Replace ApiStrToNum uses with ApiLevel.

Test: treehugger
Bug: http://b/154667674
Change-Id: I2954bb21c1cfdeb305f25cfb6c8711c930f6ed50
diff --git a/cc/cc.go b/cc/cc.go
index b5a0261..e0e6a2f 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -353,7 +353,7 @@
 	useClangLld(actx ModuleContext) bool
 	isForPlatform() bool
 	apexVariationName() string
-	apexSdkVersion() int
+	apexSdkVersion() android.ApiLevel
 	hasStubsVariants() bool
 	isStubs() bool
 	bootstrap() bool
@@ -614,7 +614,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 {
@@ -1306,7 +1306,7 @@
 	return ctx.mod.ApexVariationName()
 }
 
-func (ctx *moduleContextImpl) apexSdkVersion() int {
+func (ctx *moduleContextImpl) apexSdkVersion() android.ApiLevel {
 	return ctx.mod.apexSdkVersion
 }
 
@@ -2291,16 +2291,16 @@
 	}
 
 	// For the dependency from platform to apex, use the latest stubs
-	c.apexSdkVersion = android.FutureApiLevel
+	c.apexSdkVersion = android.CurrentApiLevel
 	if !c.IsForPlatform() {
-		c.apexSdkVersion = c.ApexProperties.Info.MinSdkVersion
+		c.apexSdkVersion = c.ApexProperties.Info.MinSdkVersion(ctx)
 	}
 
 	if android.InList("hwaddress", ctx.Config().SanitizeDevice()) {
 		// In hwasan build, we override apexSdkVersion to the FutureApiLevel(10000)
 		// so that even Q(29/Android10) apexes could use the dynamic unwinder by linking the newer stubs(e.g libc(R+)).
 		// (b/144430859)
-		c.apexSdkVersion = android.FutureApiLevel
+		c.apexSdkVersion = android.CurrentApiLevel
 	}
 
 	ctx.VisitDirectDeps(func(dep android.Module) {
@@ -2397,7 +2397,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
 			}
 
@@ -2441,7 +2441,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
@@ -2464,7 +2464,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
@@ -2988,21 +2988,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
@@ -3026,11 +3013,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..18a2f62 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()))
 		}
 	}
 
diff --git a/cc/library.go b/cc/library.go
index 92853b5..8d0c578 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -19,8 +19,6 @@
 	"io"
 	"path/filepath"
 	"regexp"
-	"sort"
-	"strconv"
 	"strings"
 	"sync"
 
@@ -1538,20 +1536,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)
 }