Soong generates vndk-related .libraries.txt files

This is a follow-up CL of I9a24f6975bd4b226a94f61a13d43857dcdce6b88

Generated files are passed to make via MakeVars:
- SOONG_LLNDK_LIBRARIES_FILE
- SOONG_VNDKCORE_LIBRARIES_FILE
- SOONG_VNDKSP_LIBRARIES_FILE
- SOONG_VNDKPRIVATE_LIBRARIES_FILE
- SOONG_VNDKCOREVARIANT_LIBRARIES_FILE
- SOONG_VNDK_LIBRARIES_FILE

Previously filenames were "guessed" from module names. Now VndkMutator
stores filenames as well and generate those files with them.

Bug: 142963962
Bug: 141450808
Test: m && device boots && TH
Change-Id: I0c248b707188f904df60ead50059fefe90bfd17f
diff --git a/android/util.go b/android/util.go
index 71ded5e..efe12de 100644
--- a/android/util.go
+++ b/android/util.go
@@ -93,6 +93,20 @@
 	return s
 }
 
+func SortedStringMapValues(m interface{}) []string {
+	v := reflect.ValueOf(m)
+	if v.Kind() != reflect.Map {
+		panic(fmt.Sprintf("%#v is not a map", m))
+	}
+	keys := v.MapKeys()
+	s := make([]string, 0, len(keys))
+	for _, key := range keys {
+		s = append(s, v.MapIndex(key).String())
+	}
+	sort.Strings(s)
+	return s
+}
+
 func IndexList(s string, list []string) int {
 	for i, l := range list {
 		if l == s {
diff --git a/cc/cc.go b/cc/cc.go
index f90f1e8..a9ad4a9 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -745,17 +745,18 @@
 
 func (c *Module) isLlndk(config android.Config) bool {
 	// Returns true for both LLNDK (public) and LLNDK-private libs.
-	return inList(c.BaseModuleName(), *llndkLibraries(config))
+	return isLlndkLibrary(c.BaseModuleName(), config)
 }
 
 func (c *Module) isLlndkPublic(config android.Config) bool {
 	// Returns true only for LLNDK (public) libs.
-	return c.isLlndk(config) && !c.isVndkPrivate(config)
+	name := c.BaseModuleName()
+	return isLlndkLibrary(name, config) && !isVndkPrivateLibrary(name, config)
 }
 
 func (c *Module) isVndkPrivate(config android.Config) bool {
 	// Returns true for LLNDK-private, VNDK-SP-private, and VNDK-core-private.
-	return inList(c.BaseModuleName(), *vndkPrivateLibraries(config))
+	return isVndkPrivateLibrary(c.BaseModuleName(), config)
 }
 
 func (c *Module) IsVndk() bool {
@@ -1496,7 +1497,6 @@
 		// The caller can then know to add the variantLibs dependencies differently from the
 		// nonvariantLibs
 
-		llndkLibraries := llndkLibraries(actx.Config())
 		vendorPublicLibraries := vendorPublicLibraries(actx.Config())
 		rewriteNdkLibs := func(list []string) (nonvariantLibs []string, variantLibs []string) {
 			variantLibs = []string{}
@@ -1510,7 +1510,7 @@
 					} else {
 						variantLibs = append(variantLibs, name+ndkLibrarySuffix)
 					}
-				} else if ctx.useVndk() && inList(name, *llndkLibraries) {
+				} else if ctx.useVndk() && isLlndkLibrary(name, ctx.Config()) {
 					nonvariantLibs = append(nonvariantLibs, name+llndkLibrarySuffix)
 				} else if (ctx.Platform() || ctx.ProductSpecific()) && inList(name, *vendorPublicLibraries) {
 					vendorPublicLib := name + vendorPublicLibrarySuffix
@@ -1820,7 +1820,6 @@
 // it is subject to be double loaded. Such lib should be explicitly marked as double_loadable: true
 // or as vndk-sp (vndk: { enabled: true, support_system_process: true}).
 func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) {
-	llndkLibraries := llndkLibraries(ctx.Config())
 	check := func(child, parent android.Module) bool {
 		to, ok := child.(*Module)
 		if !ok {
@@ -1837,7 +1836,7 @@
 			return true
 		}
 
-		if to.isVndkSp() || inList(child.Name(), *llndkLibraries) || Bool(to.VendorProperties.Double_loadable) {
+		if to.isVndkSp() || to.isLlndk(ctx.Config()) || Bool(to.VendorProperties.Double_loadable) {
 			return false
 		}
 
@@ -1852,7 +1851,7 @@
 	}
 	if module, ok := ctx.Module().(*Module); ok {
 		if lib, ok := module.linker.(*libraryDecorator); ok && lib.shared() {
-			if inList(ctx.ModuleName(), *llndkLibraries) || Bool(module.VendorProperties.Double_loadable) {
+			if module.isLlndk(ctx.Config()) || Bool(module.VendorProperties.Double_loadable) {
 				ctx.WalkDeps(check)
 			}
 		}
@@ -1866,7 +1865,6 @@
 	directStaticDeps := []LinkableInterface{}
 	directSharedDeps := []LinkableInterface{}
 
-	llndkLibraries := llndkLibraries(ctx.Config())
 	vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
 
 	reexportExporter := func(exporter exportedFlagsProducer) {
@@ -2138,7 +2136,7 @@
 			libName := strings.TrimSuffix(depName, llndkLibrarySuffix)
 			libName = strings.TrimSuffix(libName, vendorPublicLibrarySuffix)
 			libName = strings.TrimPrefix(libName, "prebuilt_")
-			isLLndk := inList(libName, *llndkLibraries)
+			isLLndk := isLlndkLibrary(libName, ctx.Config())
 			isVendorPublicLib := inList(libName, *vendorPublicLibraries)
 			bothVendorAndCoreVariantsExist := ccDep.HasVendorVariant() || isLLndk
 
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 064b1a2..808968c 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -293,6 +293,7 @@
 				enabled: true,
 			},
 			nocrt: true,
+			stem: "libvndk-private",
 		}
 
 		cc_library {
@@ -303,6 +304,7 @@
 				support_system_process: true,
 			},
 			nocrt: true,
+			suffix: "-x",
 		}
 
 		cc_library {
@@ -313,6 +315,11 @@
 				support_system_process: true,
 			},
 			nocrt: true,
+			target: {
+				vendor: {
+					suffix: "-x",
+				},
+			},
 		}
 	`, config)
 
@@ -345,9 +352,9 @@
 	checkVndkSnapshot(t, ctx, "libvndk_sp", vndkSpLib2ndPath, variant2nd)
 
 	checkVndkOutput(t, ctx, "vndk/llndk.libraries.txt", []string{"libc.so", "libdl.so", "libft2.so", "libm.so"})
-	checkVndkOutput(t, ctx, "vndk/vndkcore.libraries.txt", []string{"libvndk.so", "libvndk_private.so"})
-	checkVndkOutput(t, ctx, "vndk/vndkprivate.libraries.txt", []string{"libft2.so", "libvndk_private.so", "libvndk_sp_private.so"})
-	checkVndkOutput(t, ctx, "vndk/vndksp.libraries.txt", []string{"libc++.so", "libvndk_sp.so", "libvndk_sp_private.so"})
+	checkVndkOutput(t, ctx, "vndk/vndkcore.libraries.txt", []string{"libvndk-private.so", "libvndk.so"})
+	checkVndkOutput(t, ctx, "vndk/vndkprivate.libraries.txt", []string{"libft2.so", "libvndk-private.so", "libvndk_sp_private-x.so"})
+	checkVndkOutput(t, ctx, "vndk/vndksp.libraries.txt", []string{"libc++.so", "libvndk_sp-x.so", "libvndk_sp_private-x.so"})
 	checkVndkOutput(t, ctx, "vndk/vndkcorevariant.libraries.txt", nil)
 	// merged & tagged & filtered-out(libclang_rt)
 	checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
@@ -356,14 +363,27 @@
 		"LLNDK: libft2.so",
 		"LLNDK: libm.so",
 		"VNDK-SP: libc++.so",
-		"VNDK-SP: libvndk_sp.so",
-		"VNDK-SP: libvndk_sp_private.so",
+		"VNDK-SP: libvndk_sp-x.so",
+		"VNDK-SP: libvndk_sp_private-x.so",
+		"VNDK-core: libvndk-private.so",
 		"VNDK-core: libvndk.so",
-		"VNDK-core: libvndk_private.so",
 		"VNDK-private: libft2.so",
-		"VNDK-private: libvndk_private.so",
-		"VNDK-private: libvndk_sp_private.so",
+		"VNDK-private: libvndk-private.so",
+		"VNDK-private: libvndk_sp_private-x.so",
 	})
+	checkVndkOutput(t, ctx, "vndk/llndk.libraries.txt", []string{
+		"libc.so", "libdl.so", "libft2.so", "libm.so",
+	})
+	checkVndkOutput(t, ctx, "vndk/vndkcore.libraries.txt", []string{
+		"libvndk-private.so", "libvndk.so",
+	})
+	checkVndkOutput(t, ctx, "vndk/vndksp.libraries.txt", []string{
+		"libc++.so", "libvndk_sp-x.so", "libvndk_sp_private-x.so",
+	})
+	checkVndkOutput(t, ctx, "vndk/vndkprivate.libraries.txt", []string{
+		"libft2.so", "libvndk-private.so", "libvndk_sp_private-x.so",
+	})
+	checkVndkOutput(t, ctx, "vndk/vndkcorevariant.libraries.txt", []string{})
 }
 
 func TestVndkUsingCoreVariant(t *testing.T) {
@@ -405,7 +425,36 @@
 	`, config)
 
 	checkVndkOutput(t, ctx, "vndk/vndkcore.libraries.txt", []string{"libvndk.so", "libvndk2.so"})
-	checkVndkOutput(t, ctx, "vndk/vndkcorevariant.libraries.txt", []string{"libvndk2.so"})
+	checkVndkOutput(t, ctx, "vndk/vndkcorevariant.libraries.txt", []string{
+		"libc++.so", "libvndk2.so", "libvndk_sp.so",
+	})
+}
+
+func TestVndkWhenVndkVersionIsNotSet(t *testing.T) {
+	config := android.TestArchConfig(buildDir, nil)
+	config.TestProductVariables.DeviceVndkVersion = nil
+	config.TestProductVariables.Platform_vndk_version = nil
+
+	ctx := testCcWithConfig(t, `
+		cc_library {
+			name: "libvndk",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+	`, config)
+
+	checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
+		"LLNDK: libc.so",
+		"LLNDK: libdl.so",
+		"LLNDK: libft2.so",
+		"LLNDK: libm.so",
+		"VNDK-SP: libc++.so",
+		"VNDK-core: libvndk.so",
+		"VNDK-private: libft2.so",
+	})
 }
 
 func TestVndkDepError(t *testing.T) {
@@ -1431,13 +1480,13 @@
 		symbol_file: "",
 	}`, config)
 
-	assertArrayString(t, *vndkCoreLibraries(config),
+	assertMapKeys(t, vndkCoreLibraries(config),
 		[]string{"libvndk", "libvndkprivate"})
-	assertArrayString(t, *vndkSpLibraries(config),
+	assertMapKeys(t, vndkSpLibraries(config),
 		[]string{"libc++", "libvndksp"})
-	assertArrayString(t, *llndkLibraries(config),
+	assertMapKeys(t, llndkLibraries(config),
 		[]string{"libc", "libdl", "libft2", "libllndk", "libllndkprivate", "libm"})
-	assertArrayString(t, *vndkPrivateLibraries(config),
+	assertMapKeys(t, vndkPrivateLibraries(config),
 		[]string{"libft2", "libllndkprivate", "libvndkprivate"})
 
 	vendorVariant27 := "android_arm64_armv8-a_vendor.27_shared"
@@ -2419,6 +2468,11 @@
 	}
 }
 
+func assertMapKeys(t *testing.T, m map[string]string, expected []string) {
+	t.Helper()
+	assertArrayString(t, android.SortedStringKeys(m), expected)
+}
+
 func TestDefaults(t *testing.T) {
 	ctx := testCc(t, `
 		cc_defaults {
diff --git a/cc/library.go b/cc/library.go
index 5a08879..8e6bed0 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -579,24 +579,28 @@
 	availableFor(string) bool
 }
 
-func (library *libraryDecorator) getLibName(ctx BaseModuleContext) string {
+func (library *libraryDecorator) getLibNameHelper(baseModuleName string, useVndk bool) string {
 	name := library.libName
 	if name == "" {
 		name = String(library.Properties.Stem)
 		if name == "" {
-			name = ctx.baseModuleName()
+			name = baseModuleName
 		}
 	}
 
 	suffix := ""
-	if ctx.useVndk() {
+	if useVndk {
 		suffix = String(library.Properties.Target.Vendor.Suffix)
 	}
 	if suffix == "" {
 		suffix = String(library.Properties.Suffix)
 	}
 
-	name += suffix
+	return name + suffix
+}
+
+func (library *libraryDecorator) getLibName(ctx BaseModuleContext) string {
+	name := library.getLibNameHelper(ctx.baseModuleName(), ctx.useVndk())
 
 	if ctx.isVndkExt() {
 		// vndk-ext lib should have the same name with original lib
diff --git a/cc/makevars.go b/cc/makevars.go
index f9c58b9..e8cedf0 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -101,35 +101,6 @@
 
 	ctx.Strict("BOARD_VNDK_VERSION", ctx.DeviceConfig().VndkVersion())
 
-	ctx.Strict("VNDK_CORE_LIBRARIES", strings.Join(*vndkCoreLibraries(ctx.Config()), " "))
-	ctx.Strict("VNDK_SAMEPROCESS_LIBRARIES", strings.Join(*vndkSpLibraries(ctx.Config()), " "))
-
-	// Make uses LLNDK_LIBRARIES to determine which libraries to install.
-	// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN.
-	// Therefore, by removing the library here, we cause it to only be installed if libc
-	// depends on it.
-	installedLlndkLibraries := []string{}
-
-	// Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to avoid installing libraries on /system if
-	// they been moved to an apex.
-	movedToApexLlndkLibraries := []string{}
-	for _, lib := range *llndkLibraries(ctx.Config()) {
-		if strings.HasPrefix(lib, "libclang_rt.hwasan-") {
-			continue
-		}
-		installedLlndkLibraries = append(installedLlndkLibraries, lib)
-
-		// Skip bionic libs, they are handled in different manner
-		if android.DirectlyInAnyApex(&notOnHostContext{}, lib) && !isBionic(lib) {
-			movedToApexLlndkLibraries = append(movedToApexLlndkLibraries, lib)
-		}
-	}
-	ctx.Strict("LLNDK_LIBRARIES", strings.Join(installedLlndkLibraries, " "))
-	ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES", strings.Join(movedToApexLlndkLibraries, " "))
-
-	ctx.Strict("VNDK_PRIVATE_LIBRARIES", strings.Join(*vndkPrivateLibraries(ctx.Config()), " "))
-	ctx.Strict("VNDK_USING_CORE_VARIANT_LIBRARIES", strings.Join(*vndkUsingCoreVariantLibraries(ctx.Config()), " "))
-
 	// Filter vendor_public_library that are exported to make
 	exportedVendorPublicLibraries := []string{}
 	ctx.VisitAllModules(func(module android.Module) {
diff --git a/cc/sabi.go b/cc/sabi.go
index 8a9eff0..4760313 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -78,7 +78,7 @@
 
 func sabiDepsMutator(mctx android.TopDownMutatorContext) {
 	if c, ok := mctx.Module().(*Module); ok &&
-		((c.IsVndk() && c.UseVndk()) || inList(c.Name(), *llndkLibraries(mctx.Config())) ||
+		((c.IsVndk() && c.UseVndk()) || c.isLlndk(mctx.Config()) ||
 			(c.sabi != nil && c.sabi.Properties.CreateSAbiDumps)) {
 		mctx.VisitDirectDeps(func(m android.Module) {
 			tag := mctx.OtherModuleDependencyTag(m)
diff --git a/cc/sanitize.go b/cc/sanitize.go
index e4c6b1c..a3b4e8e 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -873,7 +873,7 @@
 		}
 
 		if mctx.Device() && runtimeLibrary != "" {
-			if inList(runtimeLibrary, *llndkLibraries(mctx.Config())) && !c.static() && c.UseVndk() {
+			if isLlndkLibrary(runtimeLibrary, mctx.Config()) && !c.static() && c.UseVndk() {
 				runtimeLibrary = runtimeLibrary + llndkLibrarySuffix
 			}
 
diff --git a/cc/vndk.go b/cc/vndk.go
index 2805e56..f39ee50 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -17,8 +17,8 @@
 import (
 	"encoding/json"
 	"errors"
+	"fmt"
 	"path/filepath"
-	"sort"
 	"strings"
 	"sync"
 
@@ -208,34 +208,44 @@
 	headerExts = []string{".h", ".hh", ".hpp", ".hxx", ".h++", ".inl", ".inc", ".ipp", ".h.generic"}
 )
 
-func vndkCoreLibraries(config android.Config) *[]string {
+func vndkCoreLibraries(config android.Config) map[string]string {
 	return config.Once(vndkCoreLibrariesKey, func() interface{} {
-		return &[]string{}
-	}).(*[]string)
+		return make(map[string]string)
+	}).(map[string]string)
 }
 
-func vndkSpLibraries(config android.Config) *[]string {
+func vndkSpLibraries(config android.Config) map[string]string {
 	return config.Once(vndkSpLibrariesKey, func() interface{} {
-		return &[]string{}
-	}).(*[]string)
+		return make(map[string]string)
+	}).(map[string]string)
 }
 
-func llndkLibraries(config android.Config) *[]string {
+func isLlndkLibrary(baseModuleName string, config android.Config) bool {
+	_, ok := llndkLibraries(config)[baseModuleName]
+	return ok
+}
+
+func llndkLibraries(config android.Config) map[string]string {
 	return config.Once(llndkLibrariesKey, func() interface{} {
-		return &[]string{}
-	}).(*[]string)
+		return make(map[string]string)
+	}).(map[string]string)
 }
 
-func vndkPrivateLibraries(config android.Config) *[]string {
+func isVndkPrivateLibrary(baseModuleName string, config android.Config) bool {
+	_, ok := vndkPrivateLibraries(config)[baseModuleName]
+	return ok
+}
+
+func vndkPrivateLibraries(config android.Config) map[string]string {
 	return config.Once(vndkPrivateLibrariesKey, func() interface{} {
-		return &[]string{}
-	}).(*[]string)
+		return make(map[string]string)
+	}).(map[string]string)
 }
 
-func vndkUsingCoreVariantLibraries(config android.Config) *[]string {
+func vndkUsingCoreVariantLibraries(config android.Config) map[string]string {
 	return config.Once(vndkUsingCoreVariantLibrariesKey, func() interface{} {
-		return &[]string{}
-	}).(*[]string)
+		return make(map[string]string)
+	}).(map[string]string)
 }
 
 func modulePaths(config android.Config) map[string]string {
@@ -272,63 +282,44 @@
 
 func processLlndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
 	lib := m.linker.(*llndkStubDecorator)
-	name := strings.TrimSuffix(m.Name(), llndkLibrarySuffix)
+	name := m.BaseModuleName()
+	filename := m.BaseModuleName() + ".so"
 
 	vndkLibrariesLock.Lock()
 	defer vndkLibrariesLock.Unlock()
 
-	llndkLibraries := llndkLibraries(mctx.Config())
-	if !inList(name, *llndkLibraries) {
-		*llndkLibraries = append(*llndkLibraries, name)
-		sort.Strings(*llndkLibraries)
-	}
+	llndkLibraries(mctx.Config())[name] = filename
 	if !Bool(lib.Properties.Vendor_available) {
-		vndkPrivateLibraries := vndkPrivateLibraries(mctx.Config())
-		if !inList(name, *vndkPrivateLibraries) {
-			*vndkPrivateLibraries = append(*vndkPrivateLibraries, name)
-			sort.Strings(*vndkPrivateLibraries)
-		}
+		vndkPrivateLibraries(mctx.Config())[name] = filename
 	}
 }
 
 func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
-	name := strings.TrimPrefix(m.Name(), "prebuilt_")
+	name := m.BaseModuleName()
+	filename, err := getVndkFileName(m)
+	if err != nil {
+		panic(err)
+	}
 
 	vndkLibrariesLock.Lock()
 	defer vndkLibrariesLock.Unlock()
 
-	modulePaths := modulePaths(mctx.Config())
+	modulePaths(mctx.Config())[name] = mctx.ModuleDir()
+
 	if inList(name, vndkMustUseVendorVariantList(mctx.Config())) {
 		m.Properties.MustUseVendorVariant = true
 	}
-	if mctx.DeviceConfig().VndkUseCoreVariant() && !inList(name, vndkMustUseVendorVariantList(mctx.Config())) {
-		vndkUsingCoreVariantLibraries := vndkUsingCoreVariantLibraries(mctx.Config())
-		if !inList(name, *vndkUsingCoreVariantLibraries) {
-			*vndkUsingCoreVariantLibraries = append(*vndkUsingCoreVariantLibraries, name)
-			sort.Strings(*vndkUsingCoreVariantLibraries)
-		}
+	if mctx.DeviceConfig().VndkUseCoreVariant() && !m.Properties.MustUseVendorVariant {
+		vndkUsingCoreVariantLibraries(mctx.Config())[name] = filename
 	}
+
 	if m.vndkdep.isVndkSp() {
-		vndkSpLibraries := vndkSpLibraries(mctx.Config())
-		if !inList(name, *vndkSpLibraries) {
-			*vndkSpLibraries = append(*vndkSpLibraries, name)
-			sort.Strings(*vndkSpLibraries)
-			modulePaths[name] = mctx.ModuleDir()
-		}
+		vndkSpLibraries(mctx.Config())[name] = filename
 	} else {
-		vndkCoreLibraries := vndkCoreLibraries(mctx.Config())
-		if !inList(name, *vndkCoreLibraries) {
-			*vndkCoreLibraries = append(*vndkCoreLibraries, name)
-			sort.Strings(*vndkCoreLibraries)
-			modulePaths[name] = mctx.ModuleDir()
-		}
+		vndkCoreLibraries(mctx.Config())[name] = filename
 	}
 	if !Bool(m.VendorProperties.Vendor_available) {
-		vndkPrivateLibraries := vndkPrivateLibraries(mctx.Config())
-		if !inList(name, *vndkPrivateLibraries) {
-			*vndkPrivateLibraries = append(*vndkPrivateLibraries, name)
-			sort.Strings(*vndkPrivateLibraries)
-		}
+		vndkPrivateLibraries(mctx.Config())[name] = filename
 	}
 }
 
@@ -402,9 +393,20 @@
 	return &vndkSnapshotSingleton{}
 }
 
-type vndkSnapshotSingleton struct{}
+type vndkSnapshotSingleton struct {
+	installedLlndkLibraries      []string
+	llnkdLibrariesFile           android.Path
+	vndkSpLibrariesFile          android.Path
+	vndkCoreLibrariesFile        android.Path
+	vndkPrivateLibrariesFile     android.Path
+	vndkCoreVariantLibrariesFile android.Path
+	vndkLibrariesFile            android.Path
+}
 
 func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+	// build these files even if PlatformVndkVersion or BoardVndkVersion is not set
+	c.buildVndkLibrariesTxtFiles(ctx)
+
 	// BOARD_VNDK_VERSION must be set to 'current' in order to generate a VNDK snapshot.
 	if ctx.DeviceConfig().VndkVersion() != "current" {
 		return
@@ -418,8 +420,6 @@
 		return
 	}
 
-	c.buildVndkLibrariesTxtFiles(ctx)
-
 	outputs := vndkSnapshotOutputs(ctx.Config())
 
 	snapshotDir := "vndk-snapshot"
@@ -488,9 +488,9 @@
 		}
 	}
 
-	vndkCoreLibraries := vndkCoreLibraries(ctx.Config())
-	vndkSpLibraries := vndkSpLibraries(ctx.Config())
-	vndkPrivateLibraries := vndkPrivateLibraries(ctx.Config())
+	vndkCoreLibraries := android.SortedStringKeys(vndkCoreLibraries(ctx.Config()))
+	vndkSpLibraries := android.SortedStringKeys(vndkSpLibraries(ctx.Config()))
+	vndkPrivateLibraries := android.SortedStringKeys(vndkPrivateLibraries(ctx.Config()))
 
 	var generatedHeaders android.Paths
 	includeDirs := make(map[string]bool)
@@ -547,9 +547,9 @@
 			return nil, "", false
 		}
 		name := ctx.ModuleName(m)
-		if inList(name, *vndkCoreLibraries) {
+		if inList(name, vndkCoreLibraries) {
 			return l, filepath.Join("shared", "vndk-core"), true
-		} else if inList(name, *vndkSpLibraries) {
+		} else if inList(name, vndkSpLibraries) {
 			return l, filepath.Join("shared", "vndk-sp"), true
 		} else {
 			return nil, "", false
@@ -635,9 +635,9 @@
 		}
 	}
 
-	installSnapshotFileFromContent(android.JoinWithSuffix(*vndkCoreLibraries, ".so", "\\n"),
+	installSnapshotFileFromContent(android.JoinWithSuffix(vndkCoreLibraries, ".so", "\\n"),
 		filepath.Join(configsDir, "vndkcore.libraries.txt"))
-	installSnapshotFileFromContent(android.JoinWithSuffix(*vndkPrivateLibraries, ".so", "\\n"),
+	installSnapshotFileFromContent(android.JoinWithSuffix(vndkPrivateLibraries, ".so", "\\n"),
 		filepath.Join(configsDir, "vndkprivate.libraries.txt"))
 
 	var modulePathTxtBuilder strings.Builder
@@ -660,75 +660,60 @@
 		filepath.Join(configsDir, "module_paths.txt"))
 }
 
-func installListFile(ctx android.SingletonContext, list []string, pathComponents ...string) android.OutputPath {
-	out := android.PathForOutput(ctx, pathComponents...)
-	ctx.Build(pctx, android.BuildParams{
-		Rule:        android.WriteFile,
-		Output:      out,
-		Description: "Writing " + out.String(),
-		Args: map[string]string{
-			"content": strings.Join(list, "\\n"),
-		},
-	})
-	return out
+func getVndkFileName(m *Module) (string, error) {
+	if library, ok := m.linker.(*libraryDecorator); ok {
+		return library.getLibNameHelper(m.BaseModuleName(), true) + ".so", nil
+	}
+	if prebuilt, ok := m.linker.(*prebuiltLibraryLinker); ok {
+		return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true) + ".so", nil
+	}
+	return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker)
 }
 
 func (c *vndkSnapshotSingleton) buildVndkLibrariesTxtFiles(ctx android.SingletonContext) {
-	var (
-		llndk, vndkcore, vndksp, vndkprivate, vndkcorevariant, merged []string
-	)
-	vndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
-	config := ctx.Config()
-	ctx.VisitAllModules(func(m android.Module) {
-		if !m.Enabled() {
-			return
+	// Make uses LLNDK_LIBRARIES to determine which libraries to install.
+	// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN.
+	// Therefore, by removing the library here, we cause it to only be installed if libc
+	// depends on it.
+	installedLlndkLibraries := make(map[string]string)
+	for lib, filename := range llndkLibraries(ctx.Config()) {
+		if strings.HasPrefix(lib, "libclang_rt.hwasan-") {
+			continue
 		}
-		c, ok := m.(*Module)
-		if !ok || c.Os().Class != android.Device {
-			return
-		}
-		lib, ok := c.linker.(interface{ shared() bool })
-		if !ok || !lib.shared() {
-			return
-		}
+		installedLlndkLibraries[lib] = filename
+	}
 
-		if !c.OutputFile().Valid() {
-			return
-		}
+	installListFile := func(list []string, fileName string) android.Path {
+		out := android.PathForOutput(ctx, "vndk", fileName)
+		ctx.Build(pctx, android.BuildParams{
+			Rule:        android.WriteFile,
+			Output:      out,
+			Description: "Writing " + out.String(),
+			Args: map[string]string{
+				"content": strings.Join(list, "\\n"),
+			},
+		})
+		return out
+	}
 
-		filename := c.OutputFile().Path().Base()
-		if c.isLlndk(config) {
-			llndk = append(llndk, filename)
-			if c.isVndkPrivate(config) {
-				vndkprivate = append(vndkprivate, filename)
-			}
-		} else if c.vndkVersion() == vndkVersion && c.IsVndk() && !c.isVndkExt() {
-			if c.isVndkSp() {
-				vndksp = append(vndksp, filename)
-			} else {
-				vndkcore = append(vndkcore, filename)
-			}
-			if c.isVndkPrivate(config) {
-				vndkprivate = append(vndkprivate, filename)
-			}
-			if ctx.DeviceConfig().VndkUseCoreVariant() && !c.MustUseVendorVariant() {
-				vndkcorevariant = append(vndkcorevariant, filename)
-			}
-		}
-	})
-	llndk = android.SortedUniqueStrings(llndk)
-	vndkcore = android.SortedUniqueStrings(vndkcore)
-	vndksp = android.SortedUniqueStrings(vndksp)
-	vndkprivate = android.SortedUniqueStrings(vndkprivate)
-	vndkcorevariant = android.SortedUniqueStrings(vndkcorevariant)
+	c.installedLlndkLibraries = android.SortedStringKeys(installedLlndkLibraries)
 
-	installListFile(ctx, llndk, "vndk", "llndk.libraries.txt")
-	installListFile(ctx, vndkcore, "vndk", "vndkcore.libraries.txt")
-	installListFile(ctx, vndksp, "vndk", "vndksp.libraries.txt")
-	installListFile(ctx, vndkprivate, "vndk", "vndkprivate.libraries.txt")
-	installListFile(ctx, vndkcorevariant, "vndk", "vndkcorevariant.libraries.txt")
+	llndk := android.SortedStringMapValues(installedLlndkLibraries)
+	vndkcore := android.SortedStringMapValues(vndkCoreLibraries(ctx.Config()))
+	vndksp := android.SortedStringMapValues(vndkSpLibraries(ctx.Config()))
+	vndkprivate := android.SortedStringMapValues(vndkPrivateLibraries(ctx.Config()))
+	vndkcorevariant := android.SortedStringMapValues(vndkUsingCoreVariantLibraries(ctx.Config()))
+
+	c.llnkdLibrariesFile = installListFile(llndk, "llndk.libraries.txt")
+	c.vndkCoreLibrariesFile = installListFile(vndkcore, "vndkcore.libraries.txt")
+	c.vndkSpLibrariesFile = installListFile(vndksp, "vndksp.libraries.txt")
+	c.vndkPrivateLibrariesFile = installListFile(vndkprivate, "vndkprivate.libraries.txt")
+	c.vndkCoreVariantLibrariesFile = installListFile(vndkcorevariant, "vndkcorevariant.libraries.txt")
 
 	// merged & tagged & filtered-out(libclang_rt)
+	// Since each target have different set of libclang_rt.* files,
+	// keep the common set of files in vndk.libraries.txt
+	var merged []string
 	filterOutLibClangRt := func(libList []string) (filtered []string) {
 		for _, lib := range libList {
 			if !strings.HasPrefix(lib, "libclang_rt.") {
@@ -741,6 +726,31 @@
 	merged = append(merged, addPrefix(vndksp, "VNDK-SP: ")...)
 	merged = append(merged, addPrefix(filterOutLibClangRt(vndkcore), "VNDK-core: ")...)
 	merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...)
+	c.vndkLibrariesFile = installListFile(merged, "vndk.libraries.txt")
+}
 
-	installListFile(ctx, merged, "vndk", "vndk.libraries.txt")
+func (c *vndkSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
+	// Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to avoid installing libraries on /system if
+	// they been moved to an apex.
+	movedToApexLlndkLibraries := []string{}
+	for _, lib := range c.installedLlndkLibraries {
+		// Skip bionic libs, they are handled in different manner
+		if android.DirectlyInAnyApex(&notOnHostContext{}, lib) && !isBionic(lib) {
+			movedToApexLlndkLibraries = append(movedToApexLlndkLibraries, lib)
+		}
+	}
+	ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES", strings.Join(movedToApexLlndkLibraries, " "))
+	ctx.Strict("LLNDK_LIBRARIES", strings.Join(c.installedLlndkLibraries, " "))
+	ctx.Strict("VNDK_CORE_LIBRARIES", strings.Join(android.SortedStringKeys(vndkCoreLibraries(ctx.Config())), " "))
+	ctx.Strict("VNDK_SAMEPROCESS_LIBRARIES", strings.Join(android.SortedStringKeys(vndkSpLibraries(ctx.Config())), " "))
+	ctx.Strict("VNDK_PRIVATE_LIBRARIES", strings.Join(android.SortedStringKeys(vndkPrivateLibraries(ctx.Config())), " "))
+	ctx.Strict("VNDK_USING_CORE_VARIANT_LIBRARIES", strings.Join(android.SortedStringKeys(vndkUsingCoreVariantLibraries(ctx.Config())), " "))
+
+	ctx.Strict("LLNDK_LIBRARIES_FILE", c.llnkdLibrariesFile.String())
+	ctx.Strict("VNDKCORE_LIBRARIES_FILE", c.vndkCoreLibrariesFile.String())
+	ctx.Strict("VNDKSP_LIBRARIES_FILE", c.vndkSpLibrariesFile.String())
+	ctx.Strict("VNDKPRIVATE_LIBRARIES_FILE", c.vndkPrivateLibrariesFile.String())
+	ctx.Strict("VNDKCOREVARIANT_LIBRARIES_FILE", c.vndkCoreVariantLibrariesFile.String())
+
+	ctx.Strict("VNDK_LIBRARIES_FILE", c.vndkLibrariesFile.String())
 }