apex: choose stub according to min_sdk_version

Native modules within APEX should be linked with proper stub version
according to its min_sdk_version.

For example, when min_sdk_version is set to "29", libfoo in the apex
would be linked to libbar of version 29 from platform, even if it has
a newer version like 30.

Bug: 145796956
Test: m nothing (soong tests)
Change-Id: I4a0b2002587bc24b7deeb5d59b6eeba5e1db5b1f
diff --git a/cc/cc.go b/cc/cc.go
index e5e724e..8b3c772 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -631,6 +631,15 @@
 	panic(fmt.Errorf("SetStubsVersions called on non-library module: %q", c.BaseModuleName()))
 }
 
+func (c *Module) StubsVersion() string {
+	if c.linker != nil {
+		if library, ok := c.linker.(*libraryDecorator); ok {
+			return library.MutatedProperties.StubsVersion
+		}
+	}
+	panic(fmt.Errorf("StubsVersion called on non-library module: %q", c.BaseModuleName()))
+}
+
 func (c *Module) SetStatic() {
 	if c.linker != nil {
 		if library, ok := c.linker.(libraryInterface); ok {
@@ -1821,16 +1830,17 @@
 		}
 		actx.AddVariationDependencies(variations, depTag, name)
 
-		// If the version is not specified, add dependency to the latest stubs library.
+		// If the version is not specified, add dependency to all stubs libraries.
 		// The stubs library will be used when the depending module is built for APEX and
 		// the dependent module is not in the same APEX.
-		latestVersion := LatestStubsVersionFor(actx.Config(), name)
-		if version == "" && latestVersion != "" && versionVariantAvail {
-			actx.AddVariationDependencies([]blueprint.Variation{
-				{Mutator: "link", Variation: "shared"},
-				{Mutator: "version", Variation: latestVersion},
-			}, depTag, name)
-			// Note that depTag.ExplicitlyVersioned is false in this case.
+		if version == "" && versionVariantAvail {
+			for _, ver := range stubsVersionsFor(actx.Config())[name] {
+				// Note that depTag.ExplicitlyVersioned is false in this case.
+				actx.AddVariationDependencies([]blueprint.Variation{
+					{Mutator: "link", Variation: "shared"},
+					{Mutator: "version", Variation: ver},
+				}, depTag, name)
+			}
 		}
 	}
 
@@ -2178,7 +2188,8 @@
 		}
 
 		if depTag == staticUnwinderDepTag {
-			if c.ApexProperties.Info.LegacyAndroid10Support {
+			// Use static unwinder for legacy (min_sdk_version = 29) apexes  (b/144430859)
+			if c.ShouldSupportAndroid10() {
 				depTag = StaticDepTag
 			} else {
 				return
@@ -2230,6 +2241,19 @@
 					useThisDep = (depInSameApex != depIsStubs)
 				}
 
+				// when to use (unspecified) stubs, check min_sdk_version and choose the right one
+				if useThisDep && depIsStubs && !explicitlyVersioned {
+					useLatest := c.IsForPlatform() || (c.ShouldSupportAndroid10() && !ctx.Config().UnbundledBuild())
+					versionToUse, err := c.ChooseSdkVersion(ccDep.StubsVersions(), useLatest)
+					if err != nil {
+						ctx.OtherModuleErrorf(dep, err.Error())
+						return
+					}
+					if versionToUse != ccDep.StubsVersion() {
+						useThisDep = false
+					}
+				}
+
 				if !useThisDep {
 					return // stop processing this dep
 				}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 8acc817..56b36df 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -2530,6 +2530,7 @@
 }
 
 func checkStaticLibs(t *testing.T, expected []string, module *Module) {
+	t.Helper()
 	actual := module.Properties.AndroidMkStaticLibs
 	if !reflect.DeepEqual(actual, expected) {
 		t.Errorf("incorrect static_libs"+
diff --git a/cc/linkable.go b/cc/linkable.go
index e4f034c..80cd6b8 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -26,6 +26,7 @@
 	BuildStubs() bool
 	SetBuildStubs()
 	SetStubsVersions(string)
+	StubsVersion() string
 	HasStubsVariants() bool
 	SelectedStl() string
 	ApiLevel() string