Remove global state from vendor public libraries

Remove the global list of vendor public library modules used to rewrite
dependencies from the vendor module to the stubs for system modules,
and replace it with building the stubs directly in the system variant
of the vendor module.

Bug: 178231622
Test: vendor_public_library_test.go
Change-Id: I826e69ffd507d7e85fa3d4d85b5157428c642143
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 70b5259..e58d166 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -580,20 +580,6 @@
 	entries.Class = "SHARED_LIBRARIES"
 }
 
-func (c *vendorPublicLibraryStubDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
-	entries.Class = "SHARED_LIBRARIES"
-	entries.SubName = vendorPublicLibrarySuffix
-
-	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
-		c.libraryDecorator.androidMkWriteExportedFlags(entries)
-		_, _, ext := android.SplitFileExt(entries.OutputFile.Path().Base())
-
-		entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
-		entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
-		entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
-	})
-}
-
 func (p *prebuiltLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
 	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		if p.properties.Check_elf_files != nil {
diff --git a/cc/cc.go b/cc/cc.go
index 3ba5366..16a49d3 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -447,6 +447,10 @@
 
 	// IsVNDKProduct is set if a VNDK module sets the product_available property.
 	IsVNDKProduct bool `blueprint:"mutated"`
+
+	// IsVendorPublicLibrary is set for the core and product variants of a library that has
+	// vendor_public_library stubs.
+	IsVendorPublicLibrary bool `blueprint:"mutated"`
 }
 
 // ModuleContextIntf is an interface (on a module context helper) consisting of functions related
@@ -475,6 +479,7 @@
 	isVndk() bool
 	isVndkSp() bool
 	IsVndkExt() bool
+	IsVendorPublicLibrary() bool
 	inProduct() bool
 	inVendor() bool
 	inRamdisk() bool
@@ -1126,6 +1131,16 @@
 	return lib != nil && (lib.hasLLNDKStubs() || lib.hasLLNDKHeaders())
 }
 
+func (m *Module) NeedsVendorPublicLibraryVariants() bool {
+	lib := moduleLibraryInterface(m)
+	return lib != nil && (lib.hasVendorPublicLibrary())
+}
+
+// IsVendorPublicLibrary returns true for vendor public libraries.
+func (c *Module) IsVendorPublicLibrary() bool {
+	return c.VendorProperties.IsVendorPublicLibrary
+}
+
 // isImplementationForLLNDKPublic returns true for any variant of a cc_library that has LLNDK stubs
 // and does not set llndk.vendor_available: false.
 func (c *Module) isImplementationForLLNDKPublic() bool {
@@ -1437,6 +1452,10 @@
 	return ctx.mod.IsVndkExt()
 }
 
+func (ctx *moduleContextImpl) IsVendorPublicLibrary() bool {
+	return ctx.mod.IsVendorPublicLibrary()
+}
+
 func (ctx *moduleContextImpl) mustUseVendorVariant() bool {
 	return ctx.mod.MustUseVendorVariant()
 }
@@ -1599,6 +1618,8 @@
 		// added for product variant only when we have vendor and product variants with core
 		// variant. The suffix is not added for vendor-only or product-only module.
 		c.Properties.SubName += c.getNameSuffixWithVndkVersion(actx)
+	} else if c.IsVendorPublicLibrary() {
+		c.Properties.SubName += vendorPublicLibrarySuffix
 	} else 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.
@@ -2043,8 +2064,6 @@
 		// The caller can then know to add the variantLibs dependencies differently from the
 		// nonvariantLibs
 
-		vendorPublicLibraries := vendorPublicLibraries(actx.Config())
-
 		rewriteLibs := func(list []string) (nonvariantLibs []string, variantLibs []string) {
 			variantLibs = []string{}
 			nonvariantLibs = []string{}
@@ -2055,16 +2074,6 @@
 					nonvariantLibs = append(nonvariantLibs, rewriteSnapshotLib(entry, getSnapshot().SharedLibs))
 				} else if ctx.useSdk() && inList(name, *getNDKKnownLibs(ctx.Config())) {
 					variantLibs = append(variantLibs, name+ndkLibrarySuffix)
-				} else if (ctx.Platform() || ctx.ProductSpecific()) && inList(name, *vendorPublicLibraries) {
-					vendorPublicLib := name + vendorPublicLibrarySuffix
-					if actx.OtherModuleExists(vendorPublicLib) {
-						nonvariantLibs = append(nonvariantLibs, vendorPublicLib)
-					} else {
-						// This can happen if vendor_public_library module is defined in a
-						// namespace that isn't visible to the current module. In that case,
-						// link to the original library.
-						nonvariantLibs = append(nonvariantLibs, name)
-					}
 				} else if ctx.useVndk() {
 					nonvariantLibs = append(nonvariantLibs, rewriteSnapshotLib(entry, getSnapshot().SharedLibs))
 				} else {
@@ -2921,13 +2930,9 @@
 }
 
 func MakeLibName(ctx android.ModuleContext, c LinkableInterface, ccDep LinkableInterface, depName string) string {
-
-	vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
-
 	libName := baseLibName(depName)
 	ccDepModule, _ := ccDep.(*Module)
 	isLLndk := ccDepModule != nil && ccDepModule.IsLlndk()
-	isVendorPublicLib := inList(libName, *vendorPublicLibraries)
 	nonSystemVariantsExist := ccDep.HasNonSystemVariants() || isLLndk
 
 	if ccDepModule != nil {
@@ -2949,8 +2954,6 @@
 		// The vendor and product modules in Make will have been renamed to not conflict with the
 		// core module, so update the dependency name here accordingly.
 		return libName + ccDep.SubName()
-	} else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib {
-		return libName + vendorPublicLibrarySuffix
 	} else if ccDep.InRamdisk() && !ccDep.OnlyInRamdisk() {
 		return libName + ramdiskSuffix
 	} else if ccDep.InVendorRamdisk() && !ccDep.OnlyInVendorRamdisk() {
diff --git a/cc/image.go b/cc/image.go
index 5593afc..1a67731 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -452,6 +452,17 @@
 		if productVndkVersion != "" {
 			productVariants = append(productVariants, productVndkVersion)
 		}
+	} else if m.NeedsVendorPublicLibraryVariants() {
+		// A vendor public library has the implementation on /vendor, with stub variants
+		// for system and product.
+		coreVariantNeeded = true
+		vendorVariants = append(vendorVariants, boardVndkVersion)
+		if platformVndkVersion != "" {
+			productVariants = append(productVariants, platformVndkVersion)
+		}
+		if productVndkVersion != "" {
+			productVariants = append(productVariants, productVndkVersion)
+		}
 	} else if boardVndkVersion == "" {
 		// If the device isn't compiling against the VNDK, we always
 		// use the core mode.
@@ -677,4 +688,9 @@
 		m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
 		squashProductSrcs(m)
 	}
+
+	if c.NeedsVendorPublicLibraryVariants() &&
+		(variant == android.CoreVariation || strings.HasPrefix(variant, ProductVariationPrefix)) {
+		c.VendorProperties.IsVendorPublicLibrary = true
+	}
 }
diff --git a/cc/library.go b/cc/library.go
index b2f33a0..7ea12c9 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -120,6 +120,9 @@
 	// If this is an LLNDK library, properties to describe the LLNDK stubs.  Will be copied from
 	// the module pointed to by llndk_stubs if it is set.
 	Llndk llndkLibraryProperties
+
+	// If this is a vendor public library, properties to describe the vendor public library stubs.
+	Vendor_public_library vendorPublicLibraryProperties
 }
 
 // StaticProperties is a properties stanza to affect only attributes of the "static" variants of a
@@ -770,6 +773,13 @@
 		}
 		return objs
 	}
+	if ctx.IsVendorPublicLibrary() {
+		objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Vendor_public_library.Symbol_file), "current", "")
+		if !Bool(library.Properties.Vendor_public_library.Unversioned) {
+			library.versionScriptPath = android.OptionalPathForPath(versionScript)
+		}
+		return objs
+	}
 	if library.buildStubs() {
 		symbolFile := String(library.Properties.Stubs.Symbol_file)
 		if symbolFile != "" && !strings.HasSuffix(symbolFile, ".map.txt") {
@@ -867,6 +877,7 @@
 	implementationModuleName(name string) string
 	hasLLNDKStubs() bool
 	hasLLNDKHeaders() bool
+	hasVendorPublicLibrary() bool
 }
 
 var _ libraryInterface = (*libraryDecorator)(nil)
@@ -962,6 +973,12 @@
 		deps.ReexportHeaderLibHeaders = append([]string(nil), library.Properties.Llndk.Export_llndk_headers...)
 		return deps
 	}
+	if ctx.IsVendorPublicLibrary() {
+		headers := library.Properties.Vendor_public_library.Export_public_headers
+		deps.HeaderLibs = append([]string(nil), headers...)
+		deps.ReexportHeaderLibHeaders = append([]string(nil), headers...)
+		return deps
+	}
 
 	if library.static() {
 		// Compare with nil because an empty list needs to be propagated.
@@ -1418,6 +1435,14 @@
 		}
 	}
 
+	if ctx.IsVendorPublicLibrary() {
+		// override the module's export_include_dirs with vendor_public_library.override_export_include_dirs
+		// if it is set.
+		if override := library.Properties.Vendor_public_library.Override_export_include_dirs; override != nil {
+			library.flagExporter.Properties.Export_include_dirs = override
+		}
+	}
+
 	// Linking this library consists of linking `deps.Objs` (.o files in dependencies
 	// of this library), together with `objs` (.o files created by compiling this
 	// library).
@@ -1679,6 +1704,12 @@
 	return Bool(library.Properties.Llndk.Llndk_headers)
 }
 
+// hasVendorPublicLibrary returns true if this cc_library module has a variant that will build
+// vendor public library stubs.
+func (library *libraryDecorator) hasVendorPublicLibrary() bool {
+	return String(library.Properties.Vendor_public_library.Symbol_file) != ""
+}
+
 func (library *libraryDecorator) implementationModuleName(name string) string {
 	return name
 }
@@ -1978,11 +2009,12 @@
 
 	m := mctx.Module().(*Module)
 	isLLNDK := m.IsLlndk()
+	isVendorPublicLibrary := m.IsVendorPublicLibrary()
 
 	modules := mctx.CreateLocalVariations(variants...)
 	for i, m := range modules {
 
-		if variants[i] != "" || isLLNDK {
+		if variants[i] != "" || isLLNDK || isVendorPublicLibrary {
 			// A stubs or LLNDK stubs variant.
 			c := m.(*Module)
 			c.sanitize = nil
diff --git a/cc/linkable.go b/cc/linkable.go
index 6f6410a..338137b 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -109,6 +109,9 @@
 	// NeedsLlndkVariants returns true if this module has LLNDK stubs or provides LLNDK headers.
 	NeedsLlndkVariants() bool
 
+	// NeedsVendorPublicLibraryVariants returns true if this module has vendor public library stubs.
+	NeedsVendorPublicLibraryVariants() bool
+
 	UseVndk() bool
 	MustUseVendorVariant() bool
 	IsVndk() bool
diff --git a/cc/makevars.go b/cc/makevars.go
index 923472a..fa0b2cc 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -71,8 +71,6 @@
 }
 
 func makeVarsProvider(ctx android.MakeVarsContext) {
-	vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
-
 	ctx.Strict("LLVM_RELEASE_VERSION", "${config.ClangShortVersion}")
 	ctx.Strict("LLVM_PREBUILTS_VERSION", "${config.ClangVersion}")
 	ctx.Strict("LLVM_PREBUILTS_BASE", "${config.ClangBase}")
@@ -106,7 +104,7 @@
 	ctx.VisitAllModules(func(module android.Module) {
 		if ccModule, ok := module.(*Module); ok {
 			baseName := ccModule.BaseModuleName()
-			if inList(baseName, *vendorPublicLibraries) && module.ExportedToMake() {
+			if ccModule.IsVendorPublicLibrary() && module.ExportedToMake() {
 				if !inList(baseName, exportedVendorPublicLibraries) {
 					exportedVendorPublicLibraries = append(exportedVendorPublicLibraries, baseName)
 				}
diff --git a/cc/testing.go b/cc/testing.go
index ca6a0fa..15f7ebb 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -556,7 +556,6 @@
 		ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
 		ctx.RegisterModuleType("cc_test", TestFactory)
 		ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
-		ctx.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
 		ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
 
 		RegisterVndkLibraryTxtTypes(ctx)
@@ -672,7 +671,6 @@
 	ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
 	ctx.RegisterModuleType("cc_test", TestFactory)
 	ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
-	ctx.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 	ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
 
diff --git a/cc/vendor_public_library.go b/cc/vendor_public_library.go
index 394e322..65a2b0c 100644
--- a/cc/vendor_public_library.go
+++ b/cc/vendor_public_library.go
@@ -14,26 +14,10 @@
 
 package cc
 
-import (
-	"strings"
-	"sync"
-
-	"android/soong/android"
-)
-
 var (
 	vendorPublicLibrarySuffix = ".vendorpublic"
-
-	vendorPublicLibrariesKey  = android.NewOnceKey("vendorPublicLibraries")
-	vendorPublicLibrariesLock sync.Mutex
 )
 
-func vendorPublicLibraries(config android.Config) *[]string {
-	return config.Once(vendorPublicLibrariesKey, func() interface{} {
-		return &[]string{}
-	}).(*[]string)
-}
-
 // Creates a stub shared library for a vendor public library. Vendor public libraries
 // are vendor libraries (owned by them and installed to /vendor partition) that are
 // exposed to Android apps via JNI. The libraries are made public by being listed in
@@ -64,105 +48,9 @@
 
 	// list of header libs to re-export include directories from.
 	Export_public_headers []string `android:"arch_variant"`
-}
 
-type vendorPublicLibraryStubDecorator struct {
-	*libraryDecorator
-
-	Properties vendorPublicLibraryProperties
-
-	versionScriptPath android.ModuleGenPath
-}
-
-func (stub *vendorPublicLibraryStubDecorator) Name(name string) string {
-	return name + vendorPublicLibrarySuffix
-}
-
-func (stub *vendorPublicLibraryStubDecorator) compilerInit(ctx BaseModuleContext) {
-	stub.baseCompiler.compilerInit(ctx)
-
-	name := ctx.baseModuleName()
-	if strings.HasSuffix(name, vendorPublicLibrarySuffix) {
-		ctx.PropertyErrorf("name", "Do not append %q manually, just use the base name", vendorPublicLibrarySuffix)
-	}
-
-	vendorPublicLibrariesLock.Lock()
-	defer vendorPublicLibrariesLock.Unlock()
-	vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
-	for _, lib := range *vendorPublicLibraries {
-		if lib == name {
-			return
-		}
-	}
-	*vendorPublicLibraries = append(*vendorPublicLibraries, name)
-}
-
-func (stub *vendorPublicLibraryStubDecorator) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags {
-	flags = stub.baseCompiler.compilerFlags(ctx, flags, deps)
-	return addStubLibraryCompilerFlags(flags)
-}
-
-func (stub *vendorPublicLibraryStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
-	objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), "current", "")
-	stub.versionScriptPath = versionScript
-	return objs
-}
-
-func (stub *vendorPublicLibraryStubDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
-	headers := stub.Properties.Export_public_headers
-	deps.HeaderLibs = append(deps.HeaderLibs, headers...)
-	deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, headers...)
-	return deps
-}
-
-func (stub *vendorPublicLibraryStubDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
-	stub.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), vendorPublicLibrarySuffix)
-	return stub.libraryDecorator.linkerFlags(ctx, flags)
-}
-
-func (stub *vendorPublicLibraryStubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps,
-	objs Objects) android.Path {
-	if !Bool(stub.Properties.Unversioned) {
-		linkerScriptFlag := "-Wl,--version-script," + stub.versionScriptPath.String()
-		flags.Local.LdFlags = append(flags.Local.LdFlags, linkerScriptFlag)
-		flags.LdFlagsDeps = append(flags.LdFlagsDeps, stub.versionScriptPath)
-	}
-	return stub.libraryDecorator.link(ctx, flags, deps, objs)
-}
-
-// vendor_public_library creates a stub shared library for a vendor public
-// library. This stub library is a build-time only artifact that provides
-// symbols that are exposed from a vendor public library. Example:
-//
-//    vendor_public_library {
-//        name: "libfoo",
-//        symbol_file: "libfoo.map.txt",
-//        export_public_headers: ["libfoo_headers"],
-//    }
-func vendorPublicLibraryFactory() android.Module {
-	module, library := NewLibrary(android.DeviceSupported)
-	library.BuildOnlyShared()
-	module.stl = nil
-	module.sanitize = nil
-	library.disableStripping()
-
-	stub := &vendorPublicLibraryStubDecorator{
-		libraryDecorator: library,
-	}
-	module.compiler = stub
-	module.linker = stub
-	module.installer = nil
-
-	module.AddProperties(
-		&stub.Properties,
-		&module.VendorProperties,
-		&library.MutatedProperties,
-		&library.flagExporter.Properties)
-
-	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
-	return module
-}
-
-func init() {
-	android.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
+	// list of directories relative to the Blueprints file that willbe added to the include path
+	// (using -I) for any module that links against the LLNDK variant of this module, replacing
+	// any that were listed outside the llndk clause.
+	Override_export_include_dirs []string
 }
diff --git a/cc/vendor_public_library_test.go b/cc/vendor_public_library_test.go
index 9f2accf..01959b4 100644
--- a/cc/vendor_public_library_test.go
+++ b/cc/vendor_public_library_test.go
@@ -26,18 +26,16 @@
 		product_available: true,
 		export_include_dirs: ["my_include"],
 	}
-	vendor_public_library {
-		name: "libvendorpublic",
-		product_available: true,
-		symbol_file: "",
-		export_public_headers: ["libvendorpublic_headers"],
-	}
 	cc_library {
 		name: "libvendorpublic",
 		srcs: ["foo.c"],
 		vendor: true,
 		no_libcrt: true,
 		nocrt: true,
+		vendor_public_library: {
+			symbol_file: "libvendorpublic.map.txt",
+			export_public_headers: ["libvendorpublic_headers"],
+		},
 	}
 
 	cc_library {
@@ -81,7 +79,7 @@
 	// test if libsystem is linked to the stub
 	ld := ctx.ModuleForTests("libsystem", coreVariant).Rule("ld")
 	libflags := ld.Args["libFlags"]
-	stubPaths := getOutputPaths(ctx, coreVariant, []string{"libvendorpublic" + vendorPublicLibrarySuffix})
+	stubPaths := getOutputPaths(ctx, coreVariant, []string{"libvendorpublic"})
 	if !strings.Contains(libflags, stubPaths[0].String()) {
 		t.Errorf("libflags for libsystem must contain %#v, but was %#v", stubPaths[0], libflags)
 	}
@@ -89,7 +87,7 @@
 	// test if libsystem is linked to the stub
 	ld = ctx.ModuleForTests("libproduct", productVariant).Rule("ld")
 	libflags = ld.Args["libFlags"]
-	stubPaths = getOutputPaths(ctx, productVariant, []string{"libvendorpublic" + vendorPublicLibrarySuffix})
+	stubPaths = getOutputPaths(ctx, productVariant, []string{"libvendorpublic"})
 	if !strings.Contains(libflags, stubPaths[0].String()) {
 		t.Errorf("libflags for libproduct must contain %#v, but was %#v", stubPaths[0], libflags)
 	}
diff --git a/rust/rust.go b/rust/rust.go
index 3dcd459..bb97142 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -270,6 +270,10 @@
 	return false
 }
 
+func (m *Module) NeedsVendorPublicLibraryVariants() bool {
+	return false
+}
+
 func (mod *Module) SdkVersion() string {
 	return ""
 }