Add version to vendor variants

Vendor variant is now divided into several vendor.{version} variants,
depending on their intended usages:

vendor.{BOARD_VNDK_VERSION}: vendor and vendor_available modules
vendor.{PLATFORM_VNDK_VERSION}: VNDK modules in the source tree
vendor.{snapshot_ver}: VNDK snapshot modules

This also affects exported module names from Soong to Make. But to
maintain backward compatibility, ".{BOARD_VNDK_VERSION}" suffix will not
be emitted for modules having version BOARD_VNDK_VERSION, so that vendor
modules still can be referred as-is.

Bug: 65377115
Bug: 68123344
Test: clean build and boot blueline
Change-Id: Ib9016a0f1fe06b97e9423fd95142653a89a343fa
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 66dd838..c9d4dad 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -37,6 +37,7 @@
 	Os() android.OsType
 	Host() bool
 	useVndk() bool
+	vndkVersion() string
 	static() bool
 	inRecovery() bool
 }
@@ -109,17 +110,7 @@
 	}
 	c.subAndroidMk(&ret, c.installer)
 
-	if c.Target().NativeBridge == android.NativeBridgeEnabled {
-		ret.SubName += nativeBridgeSuffix
-	}
-
-	if c.useVndk() && c.hasVendorVariant() {
-		// .vendor suffix is added only when we will have two variants: core and vendor.
-		// The suffix is not added for vendor-only module.
-		ret.SubName += vendorSuffix
-	} else if c.inRecovery() && !c.onlyInRecovery() {
-		ret.SubName += recoverySuffix
-	}
+	ret.SubName += c.Properties.SubName
 
 	return ret
 }
@@ -357,7 +348,6 @@
 
 func (c *llndkStubDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
 	ret.Class = "SHARED_LIBRARIES"
-	ret.SubName = vendorSuffix
 
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
 		c.libraryDecorator.androidMkWriteExportedFlags(w)
diff --git a/cc/cc.go b/cc/cc.go
index fb7fca2..cda37e8 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -36,9 +36,9 @@
 	android.RegisterModuleType("cc_defaults", defaultsFactory)
 
 	android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.BottomUp("vndk", VndkMutator).Parallel()
 		ctx.BottomUp("image", ImageMutator).Parallel()
 		ctx.BottomUp("link", LinkageMutator).Parallel()
-		ctx.BottomUp("vndk", VndkMutator).Parallel()
 		ctx.BottomUp("ndk_api", ndkApiMutator).Parallel()
 		ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
 		ctx.BottomUp("version", VersionMutator).Parallel()
@@ -200,7 +200,8 @@
 	PreventInstall            bool     `blueprint:"mutated"`
 	ApexesProvidingSharedLibs []string `blueprint:"mutated"`
 
-	UseVndk bool `blueprint:"mutated"`
+	VndkVersion string `blueprint:"mutated"`
+	SubName     string `blueprint:"mutated"`
 
 	// *.logtags files, to combine together in order to generate the /system/etc/event-log-tags
 	// file
@@ -562,7 +563,7 @@
 }
 
 func (c *Module) useVndk() bool {
-	return c.Properties.UseVndk
+	return c.Properties.VndkVersion != ""
 }
 
 func (c *Module) isCoverageVariant() bool {
@@ -596,10 +597,7 @@
 }
 
 func (c *Module) vndkVersion() string {
-	if vndkdep := c.vndkdep; vndkdep != nil {
-		return vndkdep.Properties.Vndk.Version
-	}
-	return ""
+	return c.Properties.VndkVersion
 }
 
 func (c *Module) isPgoCompile() bool {
@@ -1009,6 +1007,31 @@
 
 	c.makeLinkType = c.getMakeLinkType(actx)
 
+	c.Properties.SubName = ""
+
+	if c.Target().NativeBridge == android.NativeBridgeEnabled {
+		c.Properties.SubName += nativeBridgeSuffix
+	}
+
+	if _, ok := c.linker.(*vndkPrebuiltLibraryDecorator); ok {
+		// .vendor suffix is added for backward compatibility with VNDK snapshot whose names with
+		// such suffixes are already hard-coded in prebuilts/vndk/.../Android.bp.
+		c.Properties.SubName += vendorSuffix
+	} else if _, ok := c.linker.(*llndkStubDecorator); ok || (c.useVndk() && c.hasVendorVariant()) {
+		// .vendor.{version} suffix is added only when we will have two variants: core and vendor.
+		// The suffix is not added for vendor-only module.
+		c.Properties.SubName += vendorSuffix
+		vendorVersion := actx.DeviceConfig().VndkVersion()
+		if vendorVersion == "current" {
+			vendorVersion = actx.DeviceConfig().PlatformVndkVersion()
+		}
+		if c.Properties.VndkVersion != vendorVersion {
+			c.Properties.SubName += "." + c.Properties.VndkVersion
+		}
+	} else if c.inRecovery() && !c.onlyInRecovery() {
+		c.Properties.SubName += recoverySuffix
+	}
+
 	ctx := &moduleContext{
 		ModuleContext: actx,
 		moduleContextImpl: moduleContextImpl{
@@ -1496,9 +1519,11 @@
 
 	if vndkdep := c.vndkdep; vndkdep != nil {
 		if vndkdep.isVndkExt() {
-			baseModuleMode := vendorMode
+			var baseModuleMode string
 			if actx.DeviceConfig().VndkVersion() == "" {
 				baseModuleMode = coreMode
+			} else {
+				baseModuleMode = c.imageVariation()
 			}
 			actx.AddVariationDependencies([]blueprint.Variation{
 				{Mutator: "image", Variation: baseModuleMode},
@@ -1521,7 +1546,7 @@
 		// Host code is not restricted
 		return
 	}
-	if from.Properties.UseVndk {
+	if from.useVndk() {
 		// Though vendor code is limited by the vendor mutator,
 		// each vendor-available module needs to check
 		// link-type for VNDK.
@@ -1928,7 +1953,15 @@
 			} else if c.useVndk() && bothVendorAndCoreVariantsExist {
 				// The vendor module in Make will have been renamed to not conflict with the core
 				// module, so update the dependency name here accordingly.
-				return libName + vendorSuffix
+				ret := libName + vendorSuffix
+				vendorVersion := ctx.DeviceConfig().VndkVersion()
+				if vendorVersion == "current" {
+					vendorVersion = ctx.DeviceConfig().PlatformVndkVersion()
+				}
+				if c.Properties.VndkVersion != vendorVersion {
+					ret += "." + c.Properties.VndkVersion
+				}
+				return ret
 			} else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib {
 				return libName + vendorPublicLibrarySuffix
 			} else if ccDep.inRecovery() && !ccDep.onlyInRecovery() {
@@ -2114,13 +2147,12 @@
 }
 
 func (c *Module) imageVariation() string {
-	variation := "core"
 	if c.useVndk() {
-		variation = "vendor"
+		return vendorMode + "." + c.Properties.VndkVersion
 	} else if c.inRecovery() {
-		variation = "recovery"
+		return recoveryMode
 	}
-	return variation
+	return coreMode
 }
 
 func (c *Module) IDEInfo(dpInfo *android.IdeInfo) {
@@ -2197,7 +2229,7 @@
 	// SDK libraries. (which framework-private libraries can use)
 	coreMode = "core"
 
-	// vendorMode is the variant used for /vendor code that compiles
+	// vendorMode is the variant prefix used for /vendor code that compiles
 	// against the VNDK.
 	vendorMode = "vendor"
 
@@ -2261,7 +2293,10 @@
 				variants = append(variants, coreMode)
 			}
 			if vendorVariantNeeded {
-				variants = append(variants, vendorMode)
+				variants = append(variants, vendorMode+"."+mctx.DeviceConfig().PlatformVndkVersion())
+				if vndkVersion := mctx.DeviceConfig().VndkVersion(); vndkVersion != "current" {
+					variants = append(variants, vendorMode+"."+vndkVersion)
+				}
 			}
 			if recoveryVariantNeeded {
 				variants = append(variants, recoveryMode)
@@ -2333,9 +2368,16 @@
 	}
 
 	var coreVariantNeeded bool = false
-	var vendorVariantNeeded bool = false
 	var recoveryVariantNeeded bool = false
 
+	var vendorVariants []string
+
+	platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
+	deviceVndkVersion := mctx.DeviceConfig().VndkVersion()
+	if deviceVndkVersion == "current" {
+		deviceVndkVersion = platformVndkVersion
+	}
+
 	if mctx.DeviceConfig().VndkVersion() == "" {
 		// If the device isn't compiling against the VNDK, we always
 		// use the core mode.
@@ -2346,22 +2388,31 @@
 	} else if _, ok := m.linker.(*llndkStubDecorator); ok {
 		// LL-NDK stubs only exist in the vendor variant, since the
 		// real libraries will be used in the core variant.
-		vendorVariantNeeded = true
+		vendorVariants = append(vendorVariants,
+			platformVndkVersion,
+			deviceVndkVersion,
+		)
 	} else if _, ok := m.linker.(*llndkHeadersDecorator); ok {
 		// ... and LL-NDK headers as well
-		vendorVariantNeeded = true
-	} else if _, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
+		vendorVariants = append(vendorVariants,
+			platformVndkVersion,
+			deviceVndkVersion,
+		)
+	} else if lib, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
 		// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
 		// PRODUCT_EXTRA_VNDK_VERSIONS.
-		vendorVariantNeeded = true
+		vendorVariants = append(vendorVariants, lib.version())
 	} else if m.hasVendorVariant() && !vendorSpecific {
 		// This will be available in both /system and /vendor
 		// or a /system directory that is available to vendor.
 		coreVariantNeeded = true
-		vendorVariantNeeded = true
+		vendorVariants = append(vendorVariants, platformVndkVersion)
+		if m.isVndk() {
+			vendorVariants = append(vendorVariants, deviceVndkVersion)
+		}
 	} else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
 		// This will be available in /vendor (or /odm) only
-		vendorVariantNeeded = true
+		vendorVariants = append(vendorVariants, deviceVndkVersion)
 	} else {
 		// This is either in /system (or similar: /data), or is a
 		// modules built with the NDK. Modules built with the NDK
@@ -2390,17 +2441,17 @@
 	if coreVariantNeeded {
 		variants = append(variants, coreMode)
 	}
-	if vendorVariantNeeded {
-		variants = append(variants, vendorMode)
+	for _, variant := range android.FirstUniqueStrings(vendorVariants) {
+		variants = append(variants, vendorMode+"."+variant)
 	}
 	if recoveryVariantNeeded {
 		variants = append(variants, recoveryMode)
 	}
 	mod := mctx.CreateVariations(variants...)
 	for i, v := range variants {
-		if v == vendorMode {
+		if strings.HasPrefix(v, vendorMode+".") {
 			m := mod[i].(*Module)
-			m.Properties.UseVndk = true
+			m.Properties.VndkVersion = strings.TrimPrefix(v, vendorMode+".")
 			squashVendorSrcs(m)
 		} else if v == recoveryMode {
 			m := mod[i].(*Module)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index c9eb421..6275822 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -112,7 +112,7 @@
 
 const (
 	coreVariant     = "android_arm64_armv8-a_core_shared"
-	vendorVariant   = "android_arm64_armv8-a_vendor_shared"
+	vendorVariant   = "android_arm64_armv8-a_vendor.VER_shared"
 	recoveryVariant = "android_arm64_armv8-a_recovery_shared"
 )
 
@@ -328,8 +328,8 @@
 	vndkCoreLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-core")
 	vndkSpLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-sp")
 
-	variant := "android_arm64_armv8-a_vendor_shared"
-	variant2nd := "android_arm_armv7-a-neon_vendor_shared"
+	variant := "android_arm64_armv8-a_vendor.VER_shared"
+	variant2nd := "android_arm_armv7-a-neon_vendor.VER_shared"
 
 	checkVndkSnapshot(t, ctx, "libvndk", vndkCoreLibPath, variant)
 	checkVndkSnapshot(t, ctx, "libvndk", vndkCoreLib2ndPath, variant2nd)
@@ -1343,6 +1343,8 @@
 	assertArrayString(t, *vndkPrivateLibraries(config),
 		[]string{"libllndkprivate", "libvndkprivate"})
 
+	vendorVariant27 := "android_arm64_armv8-a_vendor.27_shared"
+
 	tests := []struct {
 		variant  string
 		name     string
@@ -1353,8 +1355,8 @@
 		{vendorVariant, "libvndkprivate", "native:vndk_private"},
 		{vendorVariant, "libvendor", "native:vendor"},
 		{vendorVariant, "libvndkext", "native:vendor"},
-		{vendorVariant, "prevndk.vndk.27.arm.binder32", "native:vndk"},
 		{vendorVariant, "libllndk.llndk", "native:vndk"},
+		{vendorVariant27, "prevndk.vndk.27.arm.binder32", "native:vndk"},
 		{coreVariant, "libvndk", "native:platform"},
 		{coreVariant, "libvndkprivate", "native:platform"},
 		{coreVariant, "libllndk", "native:platform"},
@@ -1792,7 +1794,7 @@
 	`)
 
 	// _static variant is used since _shared reuses *.o from the static variant
-	cc := ctx.ModuleForTests("libvendor", "android_arm_armv7-a-neon_vendor_static").Rule("cc")
+	cc := ctx.ModuleForTests("libvendor", "android_arm_armv7-a-neon_vendor.VER_static").Rule("cc")
 	cflags := cc.Args["cFlags"]
 	if !strings.Contains(cflags, "-Imy_include") {
 		t.Errorf("cflags for libvendor must contain -Imy_include, but was %#v.", cflags)
@@ -1878,7 +1880,7 @@
 
 	// runtime_libs for vendor variants have '.vendor' suffixes if the modules have both core
 	// and vendor variants.
-	variant = "android_arm64_armv8-a_vendor_shared"
+	variant = "android_arm64_armv8-a_vendor.VER_shared"
 
 	module = ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
 	checkRuntimeLibs(t, []string{"libvendor_available1.vendor"}, module)
@@ -1894,7 +1896,7 @@
 	module := ctx.ModuleForTests("libvendor_available3", variant).Module().(*Module)
 	checkRuntimeLibs(t, []string{"libvendor_available1"}, module)
 
-	variant = "android_arm64_armv8-a_vendor_shared"
+	variant = "android_arm64_armv8-a_vendor.VER_shared"
 	module = ctx.ModuleForTests("libvendor_available3", variant).Module().(*Module)
 	checkRuntimeLibs(t, nil, module)
 }
@@ -2091,9 +2093,9 @@
 	}
 
 	// test if libvendor is linked to the real shared lib
-	ld = ctx.ModuleForTests("libvendor", strings.Replace(variant, "_core", "_vendor", 1)).Rule("ld")
+	ld = ctx.ModuleForTests("libvendor", strings.Replace(variant, "_core", "_vendor.VER", 1)).Rule("ld")
 	libflags = ld.Args["libFlags"]
-	stubPaths = getOutputPaths(ctx, strings.Replace(variant, "_core", "_vendor", 1), []string{"libvendorpublic"})
+	stubPaths = getOutputPaths(ctx, strings.Replace(variant, "_core", "_vendor.VER", 1), []string{"libvendorpublic"})
 	if !strings.Contains(libflags, stubPaths[0].String()) {
 		t.Errorf("libflags for libvendor must contain %#v, but was %#v", stubPaths[0], libflags)
 	}
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 4d59975..9cbe800 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -76,7 +76,7 @@
 }
 
 func (stub *llndkStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
-	vndk_ver := ctx.DeviceConfig().VndkVersion()
+	vndk_ver := ctx.Module().(*Module).Properties.VndkVersion
 	if vndk_ver == "current" {
 		platform_vndk_ver := ctx.DeviceConfig().PlatformVndkVersion()
 		if !inList(platform_vndk_ver, ctx.Config().PlatformVersionCombinedCodenames()) {
@@ -177,7 +177,6 @@
 		libraryDecorator: library,
 	}
 	stub.Properties.Vendor_available = BoolPtr(true)
-	module.Properties.UseVndk = true
 	module.compiler = stub
 	module.linker = stub
 	module.installer = nil
diff --git a/cc/vndk.go b/cc/vndk.go
index 698fab5..14bbf11 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -49,10 +49,6 @@
 
 		// Extending another module
 		Extends *string
-
-		// for vndk_prebuilt_shared, this is set by "version" property.
-		// Otherwise, this is set as PLATFORM_VNDK_VERSION.
-		Version string `blueprint:"mutated"`
 	}
 }
 
@@ -129,7 +125,7 @@
 		// Other (static and LL-NDK) libraries are allowed to link.
 		return
 	}
-	if !to.Properties.UseVndk {
+	if !to.useVndk() {
 		ctx.ModuleErrorf("(%s) should not link to %q which is not a vendor-available library",
 			vndk.typeName(), to.Name())
 		return
@@ -325,14 +321,6 @@
 		return
 	}
 
-	if m.isVndk() {
-		if lib, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
-			m.vndkdep.Properties.Vndk.Version = lib.version()
-		} else {
-			m.vndkdep.Properties.Vndk.Version = mctx.DeviceConfig().PlatformVndkVersion()
-		}
-	}
-
 	if _, ok := m.linker.(*llndkStubDecorator); ok {
 		processLlndkLibrary(mctx, m)
 		return
@@ -341,8 +329,8 @@
 	lib, is_lib := m.linker.(*libraryDecorator)
 	prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker)
 
-	if (is_lib && lib.shared()) || (is_prebuilt_lib && prebuilt_lib.shared()) {
-		if m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
+	if (is_lib && lib.buildShared()) || (is_prebuilt_lib && prebuilt_lib.buildShared()) {
+		if m.vndkdep != nil && m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
 			processVndkLibrary(mctx, m)
 			return
 		}
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index b324334..8126e4a 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -167,13 +167,19 @@
 	module.stl = nil
 	module.sanitize = nil
 	library.StripProperties.Strip.None = BoolPtr(true)
-	module.Properties.UseVndk = true
 
 	prebuilt := &vndkPrebuiltLibraryDecorator{
 		libraryDecorator: library,
 	}
 
 	prebuilt.properties.Check_elf_files = BoolPtr(false)
+	prebuilt.baseLinker.Properties.No_libcrt = BoolPtr(true)
+	prebuilt.baseLinker.Properties.Nocrt = BoolPtr(true)
+
+	// Prevent default system libs (libc, libm, and libdl) from being linked
+	if prebuilt.baseLinker.Properties.System_shared_libs == nil {
+		prebuilt.baseLinker.Properties.System_shared_libs = []string{}
+	}
 
 	module.compiler = nil
 	module.linker = prebuilt