Merge changes from topic "revert-2457063-EKFSKANQWZ"

* changes:
  Revert "Create two sentinel api levels"
  Revert "Create EffectiveVersion* functions for ApiLevel"
  Revert "Prework for migrating min_sdk_version from (kind+level) ..."
  Revert "Always include host variants in the sdk snapshot"
  Revert "Update min_sdk_version from SdkSpec to ApiLevel"
diff --git a/android/apex.go b/android/apex.go
index 87bff74..358818f 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -845,7 +845,7 @@
 // ModuleWithMinSdkVersionCheck represents a module that implements min_sdk_version checks
 type ModuleWithMinSdkVersionCheck interface {
 	Module
-	MinSdkVersion(ctx EarlyModuleContext) ApiLevel
+	MinSdkVersion(ctx EarlyModuleContext) SdkSpec
 	CheckMinSdkVersion(ctx ModuleContext)
 }
 
diff --git a/android/api_levels.go b/android/api_levels.go
index 0c0b2b4..9440ee9 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -55,9 +55,6 @@
 }
 
 func (this ApiLevel) FinalInt() int {
-	if this.IsInvalid() {
-		panic(fmt.Errorf("%v is not a recognized api_level\n", this))
-	}
 	if this.IsPreview() {
 		panic("Requested a final int from a non-final ApiLevel")
 	} else {
@@ -66,9 +63,6 @@
 }
 
 func (this ApiLevel) FinalOrFutureInt() int {
-	if this.IsInvalid() {
-		panic(fmt.Errorf("%v is not a recognized api_level\n", this))
-	}
 	if this.IsPreview() {
 		return FutureApiLevelInt
 	} else {
@@ -82,9 +76,6 @@
 // - preview codenames -> preview base (9000) + index
 // - otherwise -> cast to int
 func (this ApiLevel) FinalOrPreviewInt() int {
-	if this.IsInvalid() {
-		panic(fmt.Errorf("%v is not a recognized api_level\n", this))
-	}
 	if this.IsCurrent() {
 		return this.number
 	}
@@ -106,11 +97,6 @@
 	return this.isPreview
 }
 
-// Returns true if the raw api level string is invalid
-func (this ApiLevel) IsInvalid() bool {
-	return this.EqualTo(InvalidApiLevel)
-}
-
 // Returns true if this is the unfinalized "current" API level. This means
 // different things across Java and native. Java APIs do not use explicit
 // codenames, so all non-final codenames are grouped into "current". For native
@@ -127,72 +113,6 @@
 	return this.number == -1
 }
 
-// Returns true if an app is compiling against private apis.
-// e.g. if sdk_version = "" in Android.bp, then the ApiLevel of that "sdk" is at PrivateApiLevel.
-func (this ApiLevel) IsPrivate() bool {
-	return this.number == PrivateApiLevel.number
-}
-
-// EffectiveVersion converts an ApiLevel into the concrete ApiLevel that the module should use. For
-// modules targeting an unreleased SDK (meaning it does not yet have a number) it returns
-// FutureApiLevel(10000).
-func (l ApiLevel) EffectiveVersion(ctx EarlyModuleContext) (ApiLevel, error) {
-	if l.EqualTo(InvalidApiLevel) {
-		return l, fmt.Errorf("invalid version in sdk_version %q", l.value)
-	}
-	if !l.IsPreview() {
-		return l, nil
-	}
-	ret := ctx.Config().DefaultAppTargetSdk(ctx)
-	if ret.IsPreview() {
-		return FutureApiLevel, nil
-	}
-	return ret, nil
-}
-
-// EffectiveVersionString converts an SdkSpec into the concrete version string that the module
-// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
-// it returns the codename (P, Q, R, etc.)
-func (l ApiLevel) EffectiveVersionString(ctx EarlyModuleContext) (string, error) {
-	if l.EqualTo(InvalidApiLevel) {
-		return l.value, fmt.Errorf("invalid version in sdk_version %q", l.value)
-	}
-	if !l.IsPreview() {
-		return l.String(), nil
-	}
-	// Determine the default sdk
-	ret := ctx.Config().DefaultAppTargetSdk(ctx)
-	if !ret.IsPreview() {
-		// If the default sdk has been finalized, return that
-		return ret.String(), nil
-	}
-	// There can be more than one active in-development sdks
-	// If an app is targeting an active sdk, but not the default one, return the requested active sdk.
-	// e.g.
-	// SETUP
-	// In-development: UpsideDownCake, VanillaIceCream
-	// Default: VanillaIceCream
-	// Android.bp
-	// min_sdk_version: `UpsideDownCake`
-	// RETURN
-	// UpsideDownCake and not VanillaIceCream
-	for _, preview := range ctx.Config().PreviewApiLevels() {
-		if l.String() == preview.String() {
-			return preview.String(), nil
-		}
-	}
-	// Otherwise return the default one
-	return ret.String(), nil
-}
-
-// Specified returns true if the module is targeting a recognzized api_level.
-// It returns false if either
-// 1. min_sdk_version is not an int or a recognized codename
-// 2. both min_sdk_version and sdk_version are empty. In this case, MinSdkVersion() defaults to SdkSpecPrivate.ApiLevel
-func (this ApiLevel) Specified() bool {
-	return !this.IsInvalid() && !this.IsPrivate()
-}
-
 // Returns -1 if the current API level is less than the argument, 0 if they
 // are equal, and 1 if it is greater than the argument.
 func (this ApiLevel) CompareTo(other ApiLevel) int {
@@ -246,19 +166,6 @@
 	isPreview: true,
 }
 
-// Sentinel ApiLevel to validate that an apiLevel is either an int or a recognized codename.
-var InvalidApiLevel = NewInvalidApiLevel("invalid")
-
-// Returns an apiLevel object at the same level as InvalidApiLevel.
-// The object contains the raw string provied in bp file, and can be used for error handling.
-func NewInvalidApiLevel(raw string) ApiLevel {
-	return ApiLevel{
-		value:     raw,
-		number:    -2, // One less than NoneApiLevel
-		isPreview: true,
-	}
-}
-
 // The first version that introduced 64-bit ABIs.
 var FirstLp64Version = uncheckedFinalApiLevel(21)
 
@@ -297,16 +204,6 @@
 	return strconv.Itoa(num)
 }
 
-// ApiLevelFrom converts the given string `raw` to an ApiLevel.
-// If `raw` is invalid (empty string, unrecognized codename etc.) it returns an invalid ApiLevel
-func ApiLevelFrom(ctx PathContext, raw string) ApiLevel {
-	ret, err := ApiLevelFromUser(ctx, raw)
-	if err != nil {
-		return NewInvalidApiLevel(raw)
-	}
-	return ret
-}
-
 // ApiLevelFromUser converts the given string `raw` to an ApiLevel, possibly returning an error.
 //
 // `raw` must be non-empty. Passing an empty string results in a panic.
diff --git a/android/config.go b/android/config.go
index 593812c..292fcf2 100644
--- a/android/config.go
+++ b/android/config.go
@@ -52,15 +52,6 @@
 // FutureApiLevelInt is a placeholder constant for unreleased API levels.
 const FutureApiLevelInt = 10000
 
-// PrivateApiLevel represents the api level of SdkSpecPrivate (sdk_version: "")
-// This api_level exists to differentiate user-provided "" from "current" sdk_version
-// The differentiation is necessary to enable different validation rules for these two possible values.
-var PrivateApiLevel = ApiLevel{
-	value:     "current",             // The value is current since aidl expects `current` as the default (TestAidlFlagsWithMinSdkVersion)
-	number:    FutureApiLevelInt + 1, // This is used to differentiate it from FutureApiLevel
-	isPreview: true,
-}
-
 // FutureApiLevel represents unreleased API levels.
 var FutureApiLevel = ApiLevel{
 	value:     "current",
diff --git a/android/sdk.go b/android/sdk.go
index 63e0bbe..8b23d63 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -25,7 +25,7 @@
 
 // minApiLevelForSdkSnapshot provides access to the min_sdk_version for MinApiLevelForSdkSnapshot
 type minApiLevelForSdkSnapshot interface {
-	MinSdkVersion(ctx EarlyModuleContext) ApiLevel
+	MinSdkVersion(ctx EarlyModuleContext) SdkSpec
 }
 
 // MinApiLevelForSdkSnapshot returns the ApiLevel of the min_sdk_version of the supplied module.
@@ -34,7 +34,7 @@
 func MinApiLevelForSdkSnapshot(ctx EarlyModuleContext, module Module) ApiLevel {
 	minApiLevel := NoneApiLevel
 	if m, ok := module.(minApiLevelForSdkSnapshot); ok {
-		minApiLevel = m.MinSdkVersion(ctx)
+		minApiLevel = m.MinSdkVersion(ctx).ApiLevel
 	}
 	if minApiLevel == NoneApiLevel {
 		// The default min API level is 1.
diff --git a/android/sdk_version.go b/android/sdk_version.go
index 18b819a..a7e03dc 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -25,9 +25,9 @@
 	SdkVersion(ctx EarlyModuleContext) SdkSpec
 	// SystemModules returns the system_modules property of the current module, or an empty string if it is not set.
 	SystemModules() string
-	// MinSdkVersion returns ApiLevel that corresponds to the min_sdk_version property of the current module,
+	// MinSdkVersion returns SdkSpec that corresponds to the min_sdk_version property of the current module,
 	// or from sdk_version if it is not set.
-	MinSdkVersion(ctx EarlyModuleContext) ApiLevel
+	MinSdkVersion(ctx EarlyModuleContext) SdkSpec
 	// ReplaceMaxSdkVersionPlaceholder returns SdkSpec to replace the maxSdkVersion property of permission and
 	// uses-permission tags if it is set.
 	ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) SdkSpec
@@ -187,7 +187,14 @@
 	if ctx.DeviceSpecific() || ctx.SocSpecific() {
 		s = s.ForVendorPartition(ctx)
 	}
-	return s.ApiLevel.EffectiveVersion(ctx)
+	if !s.ApiLevel.IsPreview() {
+		return s.ApiLevel, nil
+	}
+	ret := ctx.Config().DefaultAppTargetSdk(ctx)
+	if ret.IsPreview() {
+		return FutureApiLevel, nil
+	}
+	return ret, nil
 }
 
 // EffectiveVersionString converts an SdkSpec into the concrete version string that the module
@@ -201,12 +208,37 @@
 	if ctx.DeviceSpecific() || ctx.SocSpecific() {
 		s = s.ForVendorPartition(ctx)
 	}
-	return s.ApiLevel.EffectiveVersionString(ctx)
+	if !s.ApiLevel.IsPreview() {
+		return s.ApiLevel.String(), nil
+	}
+	// Determine the default sdk
+	ret := ctx.Config().DefaultAppTargetSdk(ctx)
+	if !ret.IsPreview() {
+		// If the default sdk has been finalized, return that
+		return ret.String(), nil
+	}
+	// There can be more than one active in-development sdks
+	// If an app is targeting an active sdk, but not the default one, return the requested active sdk.
+	// e.g.
+	// SETUP
+	// In-development: UpsideDownCake, VanillaIceCream
+	// Default: VanillaIceCream
+	// Android.bp
+	// min_sdk_version: `UpsideDownCake`
+	// RETURN
+	// UpsideDownCake and not VanillaIceCream
+	for _, preview := range ctx.Config().PreviewApiLevels() {
+		if s.ApiLevel.String() == preview.String() {
+			return preview.String(), nil
+		}
+	}
+	// Otherwise return the default one
+	return ret.String(), nil
 }
 
 var (
 	SdkSpecNone         = SdkSpec{SdkNone, NoneApiLevel, "(no version)"}
-	SdkSpecPrivate      = SdkSpec{SdkPrivate, PrivateApiLevel, ""}
+	SdkSpecPrivate      = SdkSpec{SdkPrivate, FutureApiLevel, ""}
 	SdkSpecCorePlatform = SdkSpec{SdkCorePlatform, FutureApiLevel, "core_platform"}
 )
 
@@ -229,7 +261,7 @@
 
 		var kindString string
 		if sep == 0 {
-			return SdkSpec{SdkInvalid, NewInvalidApiLevel(str), str}
+			return SdkSpec{SdkInvalid, NoneApiLevel, str}
 		} else if sep == -1 {
 			kindString = ""
 		} else {
@@ -257,7 +289,7 @@
 
 		apiLevel, err := ApiLevelFromUserWithConfig(config, versionString)
 		if err != nil {
-			return SdkSpec{SdkInvalid, NewInvalidApiLevel(versionString), str}
+			return SdkSpec{SdkInvalid, apiLevel, str}
 		}
 		return SdkSpec{kind, apiLevel, str}
 	}
diff --git a/android/sdk_version_test.go b/android/sdk_version_test.go
index ea99c4d..ec81782 100644
--- a/android/sdk_version_test.go
+++ b/android/sdk_version_test.go
@@ -37,11 +37,11 @@
 		},
 		{
 			input:    "_",
-			expected: "invalid__",
+			expected: "invalid_(no version)",
 		},
 		{
 			input:    "_31",
-			expected: "invalid__31",
+			expected: "invalid_(no version)",
 		},
 		{
 			input:    "system_R",
diff --git a/apex/apex.go b/apex/apex.go
index 68ad95e..4424b22 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2946,8 +2946,12 @@
 }
 
 // Returns apex's min_sdk_version SdkSpec, honoring overrides
-func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
-	return a.minSdkVersion(ctx)
+func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+	return android.SdkSpec{
+		Kind:     android.SdkNone,
+		ApiLevel: a.minSdkVersion(ctx),
+		Raw:      a.minSdkVersionValue(ctx),
+	}
 }
 
 // Returns apex's min_sdk_version ApiLevel, honoring overrides
diff --git a/apex/builder.go b/apex/builder.go
index 45c5267..ee6c473 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -1063,10 +1063,10 @@
 		} else {
 			toMinSdkVersion := "(no version)"
 			if m, ok := to.(interface {
-				MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel
+				MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec
 			}); ok {
-				if v := m.MinSdkVersion(ctx); !v.IsNone() {
-					toMinSdkVersion = v.String()
+				if v := m.MinSdkVersion(ctx); !v.ApiLevel.IsNone() {
+					toMinSdkVersion = v.ApiLevel.String()
 				}
 			} else if m, ok := to.(interface{ MinSdkVersion() string }); ok {
 				// TODO(b/175678607) eliminate the use of MinSdkVersion returning
@@ -1087,7 +1087,7 @@
 		return !externalDep
 	})
 
-	a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(ctx).String(), depInfos)
+	a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(ctx).Raw, depInfos)
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:   android.Phony,
diff --git a/java/aar.go b/java/aar.go
index 4e5ac1f..4bc5465 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -220,12 +220,12 @@
 	linkDeps = append(linkDeps, assetDeps...)
 
 	// Returns the effective version for {min|target}_sdk_version
-	effectiveVersionString := func(sdkVersion android.SdkSpec, minSdkVersion android.ApiLevel) string {
+	effectiveVersionString := func(sdkVersion android.SdkSpec, minSdkVersion android.SdkSpec) string {
 		// If {min|target}_sdk_version is current, use sdk_version to determine the effective level
 		// This is necessary for vendor modules.
 		// The effective version does not _only_ depend on {min|target}_sdk_version(level),
 		// but also on the sdk_version (kind+level)
-		if minSdkVersion.IsCurrent() {
+		if minSdkVersion.ApiLevel.IsCurrent() {
 			ret, err := sdkVersion.EffectiveVersionString(ctx)
 			if err != nil {
 				ctx.ModuleErrorf("invalid sdk_version: %s", err)
@@ -689,7 +689,7 @@
 	jniPackages android.Paths
 
 	sdkVersion    android.SdkSpec
-	minSdkVersion android.ApiLevel
+	minSdkVersion android.SdkSpec
 }
 
 var _ android.OutputFileProducer = (*AARImport)(nil)
@@ -714,11 +714,11 @@
 	return ""
 }
 
-func (a *AARImport) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+func (a *AARImport) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
 	if a.properties.Min_sdk_version != nil {
-		return android.ApiLevelFrom(ctx, *a.properties.Min_sdk_version)
+		return android.SdkSpecFrom(ctx, *a.properties.Min_sdk_version)
 	}
-	return a.SdkVersion(ctx).ApiLevel
+	return a.SdkVersion(ctx)
 }
 
 func (a *AARImport) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
diff --git a/java/app.go b/java/app.go
index 52caf6d..8b54bc8 100755
--- a/java/app.go
+++ b/java/app.go
@@ -752,7 +752,7 @@
 
 type appDepsInterface interface {
 	SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec
-	MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel
+	MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec
 	RequiresStableAPIs(ctx android.BaseModuleContext) bool
 }
 
@@ -865,10 +865,10 @@
 		} else {
 			toMinSdkVersion := "(no version)"
 			if m, ok := to.(interface {
-				MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel
+				MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec
 			}); ok {
-				if v := m.MinSdkVersion(ctx); !v.IsNone() {
-					toMinSdkVersion = v.String()
+				if v := m.MinSdkVersion(ctx); !v.ApiLevel.IsNone() {
+					toMinSdkVersion = v.ApiLevel.String()
 				}
 			} else if m, ok := to.(interface{ MinSdkVersion() string }); ok {
 				// TODO(b/175678607) eliminate the use of MinSdkVersion returning
@@ -1524,9 +1524,9 @@
 	manifestValues := &manifestValueAttribute{}
 	// TODO(b/274474008 ): Directly convert deviceProperties.Min_sdk_version in bp2build
 	// MinSdkVersion(ctx) calls SdkVersion(ctx) if no value for min_sdk_version is set
-	minSdkVersion := a.MinSdkVersion(ctx)
-	if !minSdkVersion.IsPreview() && !minSdkVersion.IsInvalid() {
-		minSdkStr, err := minSdkVersion.EffectiveVersionString(ctx)
+	minSdkSpec := a.MinSdkVersion(ctx)
+	if !minSdkSpec.ApiLevel.IsPreview() && minSdkSpec.Valid() {
+		minSdkStr, err := minSdkSpec.EffectiveVersionString(ctx)
 		if err == nil {
 			manifestValues.MinSdkVersion = &minSdkStr
 		}
diff --git a/java/app_import.go b/java/app_import.go
index c1de667..e24e780 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -426,8 +426,8 @@
 	return android.SdkSpecPrivate
 }
 
-func (a *AndroidAppImport) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
-	return android.SdkSpecPrivate.ApiLevel
+func (a *AndroidAppImport) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+	return android.SdkSpecPrivate
 }
 
 func (a *AndroidAppImport) LintDepSets() LintDepSets {
diff --git a/java/base.go b/java/base.go
index 75ec16d..85f4a5e 100644
--- a/java/base.go
+++ b/java/base.go
@@ -489,7 +489,7 @@
 	hideApexVariantFromMake bool
 
 	sdkVersion    android.SdkSpec
-	minSdkVersion android.ApiLevel
+	minSdkVersion android.SdkSpec
 	maxSdkVersion android.SdkSpec
 
 	sourceExtensions []string
@@ -665,11 +665,11 @@
 	return proptools.String(j.deviceProperties.System_modules)
 }
 
-func (j *Module) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+func (j *Module) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
 	if j.deviceProperties.Min_sdk_version != nil {
-		return android.ApiLevelFrom(ctx, *j.deviceProperties.Min_sdk_version)
+		return android.SdkSpecFrom(ctx, *j.deviceProperties.Min_sdk_version)
 	}
-	return j.SdkVersion(ctx).ApiLevel
+	return j.SdkVersion(ctx)
 }
 
 func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
@@ -685,7 +685,7 @@
 }
 
 func (j *Module) MinSdkVersionString() string {
-	return j.minSdkVersion.String()
+	return j.minSdkVersion.Raw
 }
 
 func (j *Module) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
@@ -881,7 +881,7 @@
 		j.ignoredAidlPermissionList = android.PathsForModuleSrcExcludes(ctx, exceptions, nil)
 	}
 
-	aidlMinSdkVersion := j.MinSdkVersion(ctx).String()
+	aidlMinSdkVersion := j.MinSdkVersion(ctx).ApiLevel.String()
 	flags = append(flags, "--min_sdk_version="+aidlMinSdkVersion)
 
 	return strings.Join(flags, " "), deps
@@ -1542,9 +1542,9 @@
 	}
 
 	if ctx.Device() {
-		lintSDKVersion := func(apiLevel android.ApiLevel) int {
-			if !apiLevel.IsPreview() {
-				return apiLevel.FinalInt()
+		lintSDKVersion := func(sdkSpec android.SdkSpec) int {
+			if v := sdkSpec.ApiLevel; !v.IsPreview() {
+				return v.FinalInt()
 			} else {
 				// When running metalava, we pass --version-codename. When that value
 				// is not REL, metalava will add 1 to the --current-version argument.
@@ -1575,8 +1575,8 @@
 		j.linter.classpath = append(append(android.Paths(nil), flags.bootClasspath...), flags.classpath...)
 		j.linter.classes = j.implementationJarFile
 		j.linter.minSdkVersion = lintSDKVersion(j.MinSdkVersion(ctx))
-		j.linter.targetSdkVersion = lintSDKVersion(j.TargetSdkVersion(ctx).ApiLevel)
-		j.linter.compileSdkVersion = lintSDKVersion(j.SdkVersion(ctx).ApiLevel)
+		j.linter.targetSdkVersion = lintSDKVersion(j.TargetSdkVersion(ctx))
+		j.linter.compileSdkVersion = lintSDKVersion(j.SdkVersion(ctx))
 		j.linter.compileSdkKind = j.SdkVersion(ctx).Kind
 		j.linter.javaLanguageLevel = flags.javaVersion.String()
 		j.linter.kotlinLanguageLevel = "1.3"
@@ -1846,14 +1846,15 @@
 // Implements android.ApexModule
 func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
 	sdkVersionSpec := j.SdkVersion(ctx)
-	minSdkVersion := j.MinSdkVersion(ctx)
-	if !minSdkVersion.Specified() {
+	minSdkVersionSpec := j.MinSdkVersion(ctx)
+	if !minSdkVersionSpec.Specified() {
 		return fmt.Errorf("min_sdk_version is not specified")
 	}
 	// If the module is compiling against core (via sdk_version), skip comparison check.
 	if sdkVersionSpec.Kind == android.SdkCore {
 		return nil
 	}
+	minSdkVersion := minSdkVersionSpec.ApiLevel
 	if minSdkVersion.GreaterThan(sdkVersion) {
 		return fmt.Errorf("newer SDK(%v)", minSdkVersion)
 	}
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index 45e6175..cf81ddb 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -130,13 +130,13 @@
 				if s, ok := m.(*SdkLibrary); ok {
 					// TODO(208456999): instead of mapping "current" to latest, min_sdk_version should never be set to "current"
 					if s.minSdkVersion.Specified() {
-						if s.minSdkVersion.IsCurrent() {
+						if s.minSdkVersion.ApiLevel.IsCurrent() {
 							jar.minSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String()
 						} else {
-							jar.minSdkVersion = s.minSdkVersion.String()
+							jar.minSdkVersion = s.minSdkVersion.ApiLevel.String()
 						}
 					}
-					if s.maxSdkVersion.ApiLevel.Specified() {
+					if s.maxSdkVersion.Specified() {
 						if s.maxSdkVersion.ApiLevel.IsCurrent() {
 							jar.maxSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String()
 						} else {
diff --git a/java/dex.go b/java/dex.go
index 4d6aa34..7b6a99a 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -343,7 +343,7 @@
 type compileDexParams struct {
 	flags         javaBuilderFlags
 	sdkVersion    android.SdkSpec
-	minSdkVersion android.ApiLevel
+	minSdkVersion android.SdkSpec
 	classesJar    android.Path
 	jarName       string
 }
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 3e21008..e98b9ea 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -248,8 +248,8 @@
 	return proptools.String(j.properties.System_modules)
 }
 
-func (j *Javadoc) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
-	return j.SdkVersion(ctx).ApiLevel
+func (j *Javadoc) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+	return j.SdkVersion(ctx)
 }
 
 func (j *Javadoc) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
@@ -304,7 +304,7 @@
 		flags = append(flags, "-I"+src.String())
 	}
 
-	minSdkVersion := j.MinSdkVersion(ctx).FinalOrFutureInt()
+	minSdkVersion := j.MinSdkVersion(ctx).ApiLevel.FinalOrFutureInt()
 	flags = append(flags, fmt.Sprintf("--min_sdk_version=%v", minSdkVersion))
 
 	return strings.Join(flags, " "), deps
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index d25096b..c4fc65f 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -73,7 +73,7 @@
 	android.Module
 	hiddenAPIIntf
 
-	MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel
+	MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec
 }
 
 type hiddenAPIIntf interface {
@@ -157,7 +157,7 @@
 	// Create a copy of the dex jar which has been encoded with hiddenapi flags.
 	flagsCSV := hiddenAPISingletonPaths(ctx).flags
 	outputDir := android.PathForModuleOut(ctx, "hiddenapi").OutputPath
-	encodedDex := hiddenAPIEncodeDex(ctx, dexJar, flagsCSV, uncompressDex, android.NoneApiLevel, outputDir)
+	encodedDex := hiddenAPIEncodeDex(ctx, dexJar, flagsCSV, uncompressDex, android.SdkSpecNone, outputDir)
 
 	// Use the encoded dex jar from here onwards.
 	return encodedDex
@@ -253,7 +253,7 @@
 // The encode dex rule requires unzipping, encoding and rezipping the classes.dex files along with
 // all the resources from the input jar. It also ensures that if it was uncompressed in the input
 // it stays uncompressed in the output.
-func hiddenAPIEncodeDex(ctx android.ModuleContext, dexInput, flagsCSV android.Path, uncompressDex bool, minSdkVersion android.ApiLevel, outputDir android.OutputPath) android.OutputPath {
+func hiddenAPIEncodeDex(ctx android.ModuleContext, dexInput, flagsCSV android.Path, uncompressDex bool, minSdkVersion android.SdkSpec, outputDir android.OutputPath) android.OutputPath {
 
 	// The output file has the same name as the input file and is in the output directory.
 	output := outputDir.Join(ctx, dexInput.Base())
@@ -283,7 +283,7 @@
 
 	// If the library is targeted for Q and/or R then make sure that they do not
 	// have any S+ flags encoded as that will break the runtime.
-	minApiLevel := minSdkVersion
+	minApiLevel := minSdkVersion.ApiLevel
 	if !minApiLevel.IsNone() {
 		if minApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(ctx, "R")) {
 			hiddenapiFlags = hiddenapiFlags + " --max-hiddenapi-level=max-target-r"
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 445ca1e..be4a48e 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -1278,7 +1278,7 @@
 	uncompressDex bool
 
 	// The minimum sdk version that the dex jar will be used on.
-	minSdkVersion android.ApiLevel
+	minSdkVersion android.SdkSpec
 }
 
 // bootDexInfoByModule is a map from module name (as returned by module.Name()) to the boot dex
diff --git a/java/java.go b/java/java.go
index 287bdac..0841dad 100644
--- a/java/java.go
+++ b/java/java.go
@@ -811,7 +811,7 @@
 	// If the min_sdk_version was set then add the canonical representation of the API level to the
 	// snapshot.
 	if j.deviceProperties.Min_sdk_version != nil {
-		canonical := android.ReplaceFinalizedCodenames(ctx.SdkModuleContext().Config(), j.minSdkVersion.String())
+		canonical := android.ReplaceFinalizedCodenames(ctx.SdkModuleContext().Config(), j.minSdkVersion.ApiLevel.String())
 		p.MinSdkVersion = proptools.StringPtr(canonical)
 	}
 
@@ -1874,7 +1874,7 @@
 	hideApexVariantFromMake bool
 
 	sdkVersion    android.SdkSpec
-	minSdkVersion android.ApiLevel
+	minSdkVersion android.SdkSpec
 }
 
 var _ PermittedPackagesForUpdatableBootJars = (*Import)(nil)
@@ -1891,11 +1891,11 @@
 	return "none"
 }
 
-func (j *Import) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+func (j *Import) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
 	if j.properties.Min_sdk_version != nil {
-		return android.ApiLevelFrom(ctx, *j.properties.Min_sdk_version)
+		return android.SdkSpecFrom(ctx, *j.properties.Min_sdk_version)
 	}
-	return j.SdkVersion(ctx).ApiLevel
+	return j.SdkVersion(ctx)
 }
 
 func (j *Import) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
@@ -2161,14 +2161,15 @@
 func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
 	sdkVersion android.ApiLevel) error {
 	sdkVersionSpec := j.SdkVersion(ctx)
-	minSdkVersion := j.MinSdkVersion(ctx)
-	if !minSdkVersion.Specified() {
+	minSdkVersionSpec := j.MinSdkVersion(ctx)
+	if !minSdkVersionSpec.Specified() {
 		return fmt.Errorf("min_sdk_version is not specified")
 	}
 	// If the module is compiling against core (via sdk_version), skip comparison check.
 	if sdkVersionSpec.Kind == android.SdkCore {
 		return nil
 	}
+	minSdkVersion := minSdkVersionSpec.ApiLevel
 	if minSdkVersion.GreaterThan(sdkVersion) {
 		return fmt.Errorf("newer SDK(%v)", minSdkVersion)
 	}
diff --git a/java/rro.go b/java/rro.go
index 49737b9..9d0667c 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -175,11 +175,11 @@
 	return ""
 }
 
-func (r *RuntimeResourceOverlay) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+func (r *RuntimeResourceOverlay) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
 	if r.properties.Min_sdk_version != nil {
-		return android.ApiLevelFrom(ctx, *r.properties.Min_sdk_version)
+		return android.SdkSpecFrom(ctx, *r.properties.Min_sdk_version)
 	}
-	return r.SdkVersion(ctx).ApiLevel
+	return r.SdkVersion(ctx)
 }
 
 func (r *RuntimeResourceOverlay) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 5477ed6..d2fbfd9 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1231,7 +1231,7 @@
 var _ android.ModuleWithMinSdkVersionCheck = (*SdkLibrary)(nil)
 
 func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) {
-	android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx), func(c android.ModuleContext, do android.PayloadDepsCallback) {
+	android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx).ApiLevel, func(c android.ModuleContext, do android.PayloadDepsCallback) {
 		ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
 			isExternal := !module.depIsInSameApex(ctx, child)
 			if am, ok := child.(android.ApexModule); ok {
@@ -1775,7 +1775,7 @@
 
 // Creates the xml file that publicizes the runtime library
 func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
-	moduleMinApiLevel := module.Library.MinSdkVersion(mctx)
+	moduleMinApiLevel := module.Library.MinSdkVersion(mctx).ApiLevel
 	var moduleMinApiLevelStr = moduleMinApiLevel.String()
 	if moduleMinApiLevel == android.NoneApiLevel {
 		moduleMinApiLevelStr = "current"
@@ -2414,8 +2414,8 @@
 }
 
 // MinSdkVersion - Implements hiddenAPIModule
-func (module *SdkLibraryImport) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
-	return android.NoneApiLevel
+func (module *SdkLibraryImport) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+	return android.SdkSpecNone
 }
 
 var _ hiddenAPIModule = (*SdkLibraryImport)(nil)
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 0d6496d..efb97be 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -839,7 +839,6 @@
 				compile_dex: true,
 				public: {enabled: true},
 				permitted_packages: ["mysdklibrary"],
-				min_sdk_version: "current",
 			}
 
 			java_sdk_library {
diff --git a/sdk/update.go b/sdk/update.go
index 5fb6f2d..0820d62 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -319,7 +319,7 @@
 	targetBuildRelease := s.targetBuildRelease(ctx)
 	targetApiLevel, err := android.ApiLevelFromUser(ctx, targetBuildRelease.name)
 	if err != nil {
-		targetApiLevel = android.InvalidApiLevel
+		targetApiLevel = android.FutureApiLevel
 	}
 
 	// Aggregate all the sdkMemberVariantDep instances from all the sdk variants.
@@ -357,12 +357,6 @@
 		// If the minApiLevel of the member is greater than the target API level then exclude it from
 		// this snapshot.
 		exclude := memberVariantDep.minApiLevel.GreaterThan(targetApiLevel)
-		// Always include host variants (e.g. host tools) in the snapshot.
-		// Host variants should not be guarded by a min_sdk_version check. In fact, host variants
-		// do not have a `min_sdk_version`.
-		if memberVariantDep.Host() {
-			exclude = false
-		}
 
 		addMember(name, export, exclude)
 
@@ -1269,11 +1263,6 @@
 	minApiLevel android.ApiLevel
 }
 
-// Host returns true if the sdk member is a host variant (e.g. host tool)
-func (s *sdkMemberVariantDep) Host() bool {
-	return s.variant.Target().Os.Class == android.Host
-}
-
 var _ android.SdkMember = (*sdkMember)(nil)
 
 // sdkMember groups all the variants of a specific member module together along with the name of the