Revert "Revert "Enforce min_sdk_version of apex(use_vendor:true)""

This reverts commit bacf34d986011a37dc45ebbd59d464950cd7574d.

Reason for revert: reland with fix

Change-Id: Ia03f2808353f5640597ae7ecbf2e06fc903c6977
diff --git a/cc/cc.go b/cc/cc.go
index 037b99c..4fba412 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -622,6 +622,10 @@
 			c.Properties.PreventInstall = true
 			return
 		}
+		if _, ok := c.linker.(*llndkStubDecorator); ok {
+			c.Properties.HideFromMake = true
+			return
+		}
 	}
 	panic(fmt.Errorf("SetBuildStubs called on non-library module: %q", c.BaseModuleName()))
 }
@@ -641,6 +645,10 @@
 			library.MutatedProperties.StubsVersion = version
 			return
 		}
+		if llndk, ok := c.linker.(*llndkStubDecorator); ok {
+			llndk.libraryDecorator.MutatedProperties.StubsVersion = version
+			return
+		}
 	}
 	panic(fmt.Errorf("SetStubsVersions called on non-library module: %q", c.BaseModuleName()))
 }
@@ -650,6 +658,9 @@
 		if library, ok := c.linker.(*libraryDecorator); ok {
 			return library.MutatedProperties.StubsVersion
 		}
+		if llndk, ok := c.linker.(*llndkStubDecorator); ok {
+			return llndk.libraryDecorator.MutatedProperties.StubsVersion
+		}
 	}
 	panic(fmt.Errorf("StubsVersion called on non-library module: %q", c.BaseModuleName()))
 }
@@ -1851,7 +1862,7 @@
 	addSharedLibDependencies := func(depTag DependencyTag, name string, version string) {
 		var variations []blueprint.Variation
 		variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"})
-		versionVariantAvail := !ctx.useVndk() && !c.InRecovery() && !c.InRamdisk()
+		versionVariantAvail := !c.InRecovery() && !c.InRamdisk()
 		if version != "" && versionVariantAvail {
 			// Version is explicitly specified. i.e. libFoo#30
 			variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
@@ -2186,13 +2197,17 @@
 		if depTag == android.ProtoPluginDepTag {
 			return
 		}
+		if depTag == llndkImplDep {
+			return
+		}
 
 		if dep.Target().Os != ctx.Os() {
 			ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
 			return
 		}
 		if dep.Target().Arch.ArchType != ctx.Arch().ArchType {
-			ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
+			ctx.ModuleErrorf("Arch mismatch between %q(%v) and %q(%v)",
+				ctx.ModuleName(), ctx.Arch().ArchType, depName, dep.Target().Arch.ArchType)
 			return
 		}
 
@@ -2287,6 +2302,27 @@
 					return // stop processing this dep
 				}
 			}
+			if c.UseVndk() {
+				if m, ok := ccDep.(*Module); ok && m.IsStubs() { // LLNDK
+					// by default, use current version of LLNDK
+					versionToUse := ""
+					versions := stubsVersionsFor(ctx.Config())[depName]
+					if c.ApexName() != "" && len(versions) > 0 {
+						// 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
+						useLatest := c.ShouldSupportAndroid10() && !ctx.Config().UnbundledBuild()
+						versionToUse, err = c.ChooseSdkVersion(versions, useLatest)
+						if err != nil {
+							ctx.OtherModuleErrorf(dep, err.Error())
+							return
+						}
+					}
+					if versionToUse != ccDep.StubsVersion() {
+						return
+					}
+				}
+			}
 
 			depPaths.IncludeDirs = append(depPaths.IncludeDirs, ccDep.IncludeDirs()...)
 
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 9a9678f..67eb248 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -2398,6 +2398,34 @@
 	}
 }
 
+func TestLlndkLibrary(t *testing.T) {
+	ctx := testCc(t, `
+	cc_library {
+		name: "libllndk",
+		stubs: { versions: ["1", "2"] },
+	}
+	llndk_library {
+		name: "libllndk",
+	}
+	`)
+	actual := ctx.ModuleVariantsForTests("libllndk.llndk")
+	expected := []string{
+		"android_vendor.VER_arm64_armv8-a_shared",
+		"android_vendor.VER_arm64_armv8-a_shared_1",
+		"android_vendor.VER_arm64_armv8-a_shared_2",
+		"android_vendor.VER_arm_armv7-a-neon_shared",
+		"android_vendor.VER_arm_armv7-a-neon_shared_1",
+		"android_vendor.VER_arm_armv7-a-neon_shared_2",
+	}
+	checkEquals(t, "variants for llndk stubs", expected, actual)
+
+	params := ctx.ModuleForTests("libllndk.llndk", "android_vendor.VER_arm_armv7-a-neon_shared").Description("generate stub")
+	checkEquals(t, "use VNDK version for default stubs", "current", params.Args["apiLevel"])
+
+	params = ctx.ModuleForTests("libllndk.llndk", "android_vendor.VER_arm_armv7-a-neon_shared_1").Description("generate stub")
+	checkEquals(t, "override apiLevel for versioned stubs", "1", params.Args["apiLevel"])
+}
+
 func TestLlndkHeaders(t *testing.T) {
 	ctx := testCc(t, `
 	llndk_headers {
diff --git a/cc/library.go b/cc/library.go
index 346e7d8..040e509 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1487,6 +1487,19 @@
 	}
 }
 
+func createVersionVariations(mctx android.BottomUpMutatorContext, versions []string) {
+	// "" is for the non-stubs variant
+	versions = append([]string{""}, versions...)
+
+	modules := mctx.CreateVariations(versions...)
+	for i, m := range modules {
+		if versions[i] != "" {
+			m.(LinkableInterface).SetBuildStubs()
+			m.(LinkableInterface).SetStubsVersions(versions[i])
+		}
+	}
+}
+
 // Version mutator splits a module into the mandatory non-stubs variant
 // (which is unnamed) and zero or more stubs variants.
 func VersionMutator(mctx android.BottomUpMutatorContext) {
@@ -1498,24 +1511,30 @@
 				return
 			}
 
-			// save the list of versions for later use
 			stubsVersionsLock.Lock()
 			defer stubsVersionsLock.Unlock()
+			// save the list of versions for later use
 			stubsVersionsFor(mctx.Config())[mctx.ModuleName()] = versions
 
-			// "" is for the non-stubs variant
-			versions = append([]string{""}, versions...)
-
-			modules := mctx.CreateVariations(versions...)
-			for i, m := range modules {
-				if versions[i] != "" {
-					m.(LinkableInterface).SetBuildStubs()
-					m.(LinkableInterface).SetStubsVersions(versions[i])
-				}
-			}
-		} else {
-			mctx.CreateVariations("")
+			createVersionVariations(mctx, versions)
+			return
 		}
+
+		if c, ok := library.(*Module); ok && c.IsStubs() {
+			stubsVersionsLock.Lock()
+			defer stubsVersionsLock.Unlock()
+			// For LLNDK llndk_library, we borrow vstubs.ersions from its implementation library.
+			// Since llndk_library has dependency to its implementation library,
+			// we can safely access stubsVersionsFor() with its baseModuleName.
+			versions := stubsVersionsFor(mctx.Config())[c.BaseModuleName()]
+			// save the list of versions for later use
+			stubsVersionsFor(mctx.Config())[mctx.ModuleName()] = versions
+
+			createVersionVariations(mctx, versions)
+			return
+		}
+
+		mctx.CreateVariations("")
 		return
 	}
 	if genrule, ok := mctx.Module().(*genrule.Module); ok {
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 3dee692..09050aa 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -19,8 +19,14 @@
 	"strings"
 
 	"android/soong/android"
+
+	"github.com/google/blueprint"
 )
 
+var llndkImplDep = struct {
+	blueprint.DependencyTag
+}{}
+
 var (
 	llndkLibrarySuffix = ".llndk"
 	llndkHeadersSuffix = ".llndk"
@@ -81,6 +87,9 @@
 		// For non-enforcing devices, vndkVer is empty. Use "current" in that case, too.
 		vndkVer = "current"
 	}
+	if stub.stubsVersion() != "" {
+		vndkVer = stub.stubsVersion()
+	}
 	objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), vndkVer, "--llndk")
 	stub.versionScriptPath = versionScript
 	return objs
@@ -154,6 +163,10 @@
 		stub.libraryDecorator.flagExporter.Properties.Export_include_dirs = []string{}
 	}
 
+	if stub.stubsVersion() != "" {
+		stub.reexportFlags("-D" + versioningMacroName(ctx.baseModuleName()) + "=" + stub.stubsVersion())
+	}
+
 	return stub.libraryDecorator.link(ctx, flags, deps, objs)
 }
 
diff --git a/cc/vndk.go b/cc/vndk.go
index e02e7b5..4888dcf 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -297,6 +297,9 @@
 	if !Bool(lib.Properties.Vendor_available) {
 		vndkPrivateLibraries(mctx.Config())[name] = filename
 	}
+	if mctx.OtherModuleExists(name) {
+		mctx.AddFarVariationDependencies(m.Target().Variations(), llndkImplDep, name)
+	}
 }
 
 func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {