Merge "Generate .srcjar for prebuilt_stubs_sources"
diff --git a/android/arch.go b/android/arch.go
index 131d3b9..b5b8a8f 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1602,6 +1602,15 @@
 	}
 }
 
+func getAmlAbisConfig() []archConfig {
+	return []archConfig{
+		{"arm", "armv7-a", "", []string{"armeabi-v7a"}},
+		{"arm64", "armv8-a", "", []string{"arm64-v8a"}},
+		{"x86", "", "", []string{"x86"}},
+		{"x86_64", "", "", []string{"x86_64"}},
+	}
+}
+
 func decodeArchSettings(os OsType, archConfigs []archConfig) ([]Target, error) {
 	var ret []Target
 
diff --git a/android/config.go b/android/config.go
index a9833da..101f457 100644
--- a/android/config.go
+++ b/android/config.go
@@ -364,6 +364,8 @@
 		archConfig = getMegaDeviceConfig()
 	} else if config.NdkAbis() {
 		archConfig = getNdkAbisConfig()
+	} else if config.AmlAbis() {
+		archConfig = getAmlAbisConfig()
 	}
 
 	if archConfig != nil {
@@ -946,6 +948,10 @@
 	return String(c.config.productVariables.Platform_vndk_version)
 }
 
+func (c *deviceConfig) ProductVndkVersion() string {
+	return String(c.config.productVariables.ProductVndkVersion)
+}
+
 func (c *deviceConfig) ExtraVndkVersions() []string {
 	return c.config.productVariables.ExtraVndkVersions
 }
@@ -1122,6 +1128,10 @@
 	return Bool(c.productVariables.Ndk_abis)
 }
 
+func (c *config) AmlAbis() bool {
+	return Bool(c.productVariables.Aml_abis)
+}
+
 func (c *config) ExcludeDraftNdkApis() bool {
 	return Bool(c.productVariables.Exclude_draft_ndk_apis)
 }
diff --git a/android/neverallow.go b/android/neverallow.go
index 48efb4f..cef73fb 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -136,9 +136,6 @@
 		"external/icu",
 		"external/okhttp",
 		"external/wycheproof",
-
-		// Not really a core library but still needs access to same capabilities.
-		"development",
 	}
 
 	// Core library constraints. The sdk_version: "none" can only be used in core library projects.
diff --git a/android/override_module.go b/android/override_module.go
index 45f7be0..5bc787b 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -155,11 +155,6 @@
 
 // Overrides a base module with the given OverrideModule.
 func (b *OverridableModuleBase) override(ctx BaseModuleContext, o OverrideModule) {
-	// Adds the base module to the overrides property, if exists, of the overriding module. See the
-	// comment on OverridableModuleBase.overridesProperty for details.
-	if b.overridesProperty != nil {
-		*b.overridesProperty = append(*b.overridesProperty, ctx.ModuleName())
-	}
 	for _, p := range b.overridableProperties {
 		for _, op := range o.getOverridingProperties() {
 			if proptools.TypeEqual(p, op) {
@@ -174,6 +169,11 @@
 			}
 		}
 	}
+	// Adds the base module to the overrides property, if exists, of the overriding module. See the
+	// comment on OverridableModuleBase.overridesProperty for details.
+	if b.overridesProperty != nil {
+		*b.overridesProperty = append(*b.overridesProperty, ctx.ModuleName())
+	}
 	b.properties.OverriddenBy = o.Name()
 }
 
diff --git a/android/variable.go b/android/variable.go
index 628408e..2bf84dd 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -288,6 +288,7 @@
 	Exclude_draft_ndk_apis *bool `json:",omitempty"`
 
 	Flatten_apex *bool `json:",omitempty"`
+	Aml_abis     *bool `json:",omitempty"`
 
 	DexpreoptGlobalConfig *string `json:",omitempty"`
 
@@ -306,6 +307,8 @@
 	ProductPrivateSepolicyDirs []string `json:",omitempty"`
 	ProductCompatibleProperty  *bool    `json:",omitempty"`
 
+	ProductVndkVersion *string `json:",omitempty"`
+
 	TargetFSConfigGen []string `json:",omitempty"`
 
 	MissingUsesLibraries []string `json:",omitempty"`
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 7d1a301..c42b348 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -181,7 +181,7 @@
 				fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", a.installDir.ToMakePath().String())
 				fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", name+apexType.suffix())
 				fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable())
-				fmt.Fprintln(w, "LOCAL_OVERRIDES_MODULES :=", strings.Join(a.properties.Overrides, " "))
+				fmt.Fprintln(w, "LOCAL_OVERRIDES_MODULES :=", strings.Join(a.overridableProperties.Overrides, " "))
 				if len(moduleNames) > 0 {
 					fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(moduleNames, " "))
 				}
diff --git a/apex/apex.go b/apex/apex.go
index f6997bf..e0ee1ea 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -333,13 +333,6 @@
 	// also built with the SDKs specified here.
 	Uses_sdks []string
 
-	// Names of modules to be overridden. Listed modules can only be other binaries
-	// (in Make or Soong).
-	// This does not completely prevent installation of the overridden binaries, but if both
-	// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
-	// from PRODUCT_PACKAGES.
-	Overrides []string
-
 	// Whenever apex_payload.img of the APEX should include dm-verity hashtree.
 	// Should be only used in tests#.
 	Test_only_no_hashtree *bool
@@ -376,6 +369,13 @@
 type overridableProperties struct {
 	// List of APKs to package inside APEX
 	Apps []string
+
+	// Names of modules to be overridden. Listed modules can only be other binaries
+	// (in Make or Soong).
+	// This does not completely prevent installation of the overridden binaries, but if both
+	// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
+	// from PRODUCT_PACKAGES.
+	Overrides []string
 }
 
 type apexPackaging int
@@ -884,18 +884,6 @@
 	return newApexFile(ctx, fileToCopy, lib.Name(), dirInApex, javaSharedLib, lib)
 }
 
-func apexFileForPrebuiltJavaLibrary(ctx android.BaseModuleContext, java *java.Import) apexFile {
-	dirInApex := "javalib"
-	// The output is only one, but for some reason, ImplementationJars returns Paths, not Path
-	implJars := java.ImplementationJars()
-	if len(implJars) != 1 {
-		panic(fmt.Errorf("java.ImplementationJars() must return single Path, but got: %s",
-			strings.Join(implJars.Strings(), ", ")))
-	}
-	fileToCopy := implJars[0]
-	return newApexFile(ctx, fileToCopy, java.Name(), dirInApex, javaSharedLib, java)
-}
-
 func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt android.PrebuiltEtcModule, depName string) apexFile {
 	dirInApex := filepath.Join("etc", prebuilt.SubDir())
 	fileToCopy := prebuilt.OutputFile()
@@ -1043,13 +1031,6 @@
 					}
 					filesInfo = append(filesInfo, newApexFile(ctx, pf, pf.Base(), "etc/permissions", etc, nil))
 					return true // track transitive dependencies
-				} else if javaLib, ok := child.(*java.Import); ok {
-					af := apexFileForPrebuiltJavaLibrary(ctx, javaLib)
-					if !af.Ok() {
-						ctx.PropertyErrorf("java_libs", "%q does not have a jar output", depName)
-					} else {
-						filesInfo = append(filesInfo, af)
-					}
 				} else {
 					ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
 				}
@@ -1060,6 +1041,8 @@
 					return true // track transitive dependencies
 				} else if ap, ok := child.(*java.AndroidAppImport); ok {
 					filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap, pkgName))
+				} else if ap, ok := child.(*java.AndroidTestHelperApp); ok {
+					filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap, pkgName))
 				} else {
 					ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
 				}
@@ -1267,7 +1250,7 @@
 	android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
 	android.InitSdkAwareModule(module)
-	android.InitOverridableModule(module, &module.properties.Overrides)
+	android.InitOverridableModule(module, &module.overridableProperties.Overrides)
 	return module
 }
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index e8dc9aa..97600b6 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -286,8 +286,6 @@
 	ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
 	ctx.RegisterModuleType("override_apex", overrideApexFactory)
 
-	ctx.RegisterModuleType("cc_library_shared", cc.LibrarySharedFactory)
-	ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
 	ctx.RegisterModuleType("cc_binary", cc.BinaryFactory)
 	ctx.RegisterModuleType("cc_test", cc.TestFactory)
@@ -374,7 +372,7 @@
 					binaries: ["foo",],
 				}
 			},
-			java_libs: ["myjar", "myprebuiltjar"],
+			java_libs: ["myjar"],
 		}
 
 		apex {
@@ -449,12 +447,6 @@
 			system_modules: "none",
 			compile_dex: true,
 		}
-
-		java_import {
-			name: "myprebuiltjar",
-			jars: ["prebuilt.jar"],
-			installable: true,
-		}
 	`)
 
 	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
@@ -472,7 +464,6 @@
 	// Ensure that apex variant is created for the direct dep
 	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
 	ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common_myapex")
-	ensureListContains(t, ctx.ModuleVariantsForTests("myprebuiltjar"), "android_common_myapex")
 
 	// Ensure that apex variant is created for the indirect dep
 	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
@@ -482,7 +473,6 @@
 	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
 	ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so")
 	ensureContains(t, copyCmds, "image.apex/javalib/myjar.jar")
-	ensureContains(t, copyCmds, "image.apex/javalib/myprebuiltjar.jar")
 	// .. but not for java libs
 	ensureNotContains(t, copyCmds, "image.apex/javalib/myotherjar.jar")
 
@@ -491,7 +481,6 @@
 	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared")
 	ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common")
 	ensureListContains(t, ctx.ModuleVariantsForTests("myotherjar"), "android_common")
-	ensureListContains(t, ctx.ModuleVariantsForTests("myprebuiltjar"), "android_common")
 
 	// Ensure that all symlinks are present.
 	found_foo_link_64 := false
@@ -2926,6 +2915,36 @@
 	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPrivPrebuilt/AppFooPrivPrebuilt.apk")
 }
 
+func TestApexWithTestHelperApp(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			apps: [
+				"TesterHelpAppFoo",
+			],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		android_test_helper_app {
+			name: "TesterHelpAppFoo",
+			srcs: ["foo/bar/MyClass.java"],
+		}
+
+	`)
+
+	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+	apexRule := module.Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+
+	ensureContains(t, copyCmds, "image.apex/app/TesterHelpAppFoo/TesterHelpAppFoo.apk")
+}
+
 func TestApexPropertiesShouldBeDefaultable(t *testing.T) {
 	// libfoo's apex_available comes from cc_defaults
 	testApexError(t, `"myapex" .*: requires "libfoo" that is not available for the APEX`, `
@@ -3148,12 +3167,14 @@
 			name: "myapex",
 			key: "myapex.key",
 			apps: ["app"],
+			overrides: ["oldapex"],
 		}
 
 		override_apex {
 			name: "override_myapex",
 			base: "myapex",
 			apps: ["override_app"],
+			overrides: ["unknownapex"],
 		}
 
 		apex_key {
@@ -3206,6 +3227,7 @@
 	ensureContains(t, androidMk, "LOCAL_MODULE := override_app.override_myapex")
 	ensureContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.override_myapex")
 	ensureContains(t, androidMk, "LOCAL_MODULE_STEM := override_myapex.apex")
+	ensureContains(t, androidMk, "LOCAL_OVERRIDES_MODULES := unknownapex myapex")
 	ensureNotContains(t, androidMk, "LOCAL_MODULE := app.myapex")
 	ensureNotContains(t, androidMk, "LOCAL_MODULE := override_app.myapex")
 	ensureNotContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.myapex")
diff --git a/cc/androidmk.go b/cc/androidmk.go
index c1225bc..988ebd4 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -25,6 +25,7 @@
 
 var (
 	nativeBridgeSuffix = ".native_bridge"
+	productSuffix      = ".product"
 	vendorSuffix       = ".vendor"
 	recoverySuffix     = ".recovery"
 )
@@ -37,7 +38,7 @@
 	Os() android.OsType
 	Host() bool
 	UseVndk() bool
-	vndkVersion() string
+	VndkVersion() string
 	static() bool
 	InRecovery() bool
 }
@@ -92,7 +93,7 @@
 				if c.UseVndk() {
 					fmt.Fprintln(w, "LOCAL_USE_VNDK := true")
 					if c.IsVndk() && !c.static() {
-						fmt.Fprintln(w, "LOCAL_SOONG_VNDK_VERSION := "+c.vndkVersion())
+						fmt.Fprintln(w, "LOCAL_SOONG_VNDK_VERSION := "+c.VndkVersion())
 						// VNDK libraries available to vendor are not installed because
 						// they are packaged in VNDK APEX and installed by APEX packages (apex/apex.go)
 						if !c.isVndkExt() {
diff --git a/cc/cc.go b/cc/cc.go
index 14e7122..f16bb12 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -215,8 +215,9 @@
 	PreventInstall            bool     `blueprint:"mutated"`
 	ApexesProvidingSharedLibs []string `blueprint:"mutated"`
 
-	VndkVersion string `blueprint:"mutated"`
-	SubName     string `blueprint:"mutated"`
+	ImageVariationPrefix string `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
@@ -228,7 +229,7 @@
 	// Set by imageMutator
 	CoreVariantNeeded     bool     `blueprint:"mutated"`
 	RecoveryVariantNeeded bool     `blueprint:"mutated"`
-	VendorVariants        []string `blueprint:"mutated"`
+	ExtraVariants         []string `blueprint:"mutated"`
 
 	// Allows this module to use non-APEX version of libraries. Useful
 	// for building binaries that are started before APEXes are activated.
@@ -242,20 +243,24 @@
 type VendorProperties struct {
 	// whether this module should be allowed to be directly depended by other
 	// modules with `vendor: true`, `proprietary: true`, or `vendor_available:true`.
-	// If set to true, two variants will be built separately, one like
-	// normal, and the other limited to the set of libraries and headers
-	// that are exposed to /vendor modules.
+	// In addition, this module should be allowed to be directly depended by
+	// product modules with `product_specific: true`.
+	// If set to true, three variants will be built separately, one like
+	// normal, another limited to the set of libraries and headers
+	// that are exposed to /vendor modules, and the other to /product modules.
 	//
-	// The vendor variant may be used with a different (newer) /system,
+	// The vendor and product variants may be used with a different (newer) /system,
 	// so it shouldn't have any unversioned runtime dependencies, or
 	// make assumptions about the system that may not be true in the
 	// future.
 	//
-	// If set to false, this module becomes inaccessible from /vendor modules.
+	// If set to false, this module becomes inaccessible from /vendor or /product
+	// modules.
 	//
 	// Default value is true when vndk: {enabled: true} or vendor: true.
 	//
 	// Nothing happens if BOARD_VNDK_VERSION isn't set in the BoardConfig.mk
+	// If PRODUCT_PRODUCT_VNDK_VERSION isn't set, product variant will not be used.
 	Vendor_available *bool
 
 	// whether this module is capable of being loaded with other instance
@@ -283,6 +288,8 @@
 	isVndk() bool
 	isVndkSp() bool
 	isVndkExt() bool
+	inProduct() bool
+	inVendor() bool
 	inRecovery() bool
 	shouldCreateSourceAbiDump() bool
 	selectedStl() string
@@ -417,6 +424,9 @@
 	hod      android.HostOrDeviceSupported
 	multilib android.Multilib
 
+	// Allowable SdkMemberTypes of this module type.
+	sdkMemberTypes []android.SdkMemberType
+
 	// delegates, initialize before calling Init
 	features  []feature
 	compiler  compiler
@@ -680,7 +690,7 @@
 }
 
 func (c *Module) VndkVersion() string {
-	return c.vndkVersion()
+	return c.Properties.VndkVersion
 }
 
 func (c *Module) Init() android.Module {
@@ -752,6 +762,12 @@
 	return false
 }
 
+// Returns true if the module is using VNDK libraries instead of the libraries in /system/lib or /system/lib64.
+// "product" and "vendor" variant modules return true for this function.
+// When BOARD_VNDK_VERSION is set, vendor variants of "vendor_available: true", "vendor: true",
+// "soc_specific: true" and more vendor installed modules are included here.
+// When PRODUCT_PRODUCT_VNDK_VERSION is set, product variants of "vendor_available: true" or
+// "product_specific: true" modules are included here.
 func (c *Module) UseVndk() bool {
 	return c.Properties.VndkVersion != ""
 }
@@ -787,10 +803,6 @@
 	return false
 }
 
-func (c *Module) vndkVersion() string {
-	return c.Properties.VndkVersion
-}
-
 func (c *Module) isPgoCompile() bool {
 	if pgo := c.pgo; pgo != nil {
 		return pgo.Properties.PgoCompile
@@ -830,12 +842,32 @@
 	return ""
 }
 
-// Returns true only when this module is configured to have core and vendor
+// Returns true only when this module is configured to have core, product and vendor
 // variants.
 func (c *Module) HasVendorVariant() bool {
 	return c.IsVndk() || Bool(c.VendorProperties.Vendor_available)
 }
 
+const (
+	// VendorVariationPrefix is the variant prefix used for /vendor code that compiles
+	// against the VNDK.
+	VendorVariationPrefix = "vendor."
+
+	// ProductVariationPrefix is the variant prefix used for /product code that compiles
+	// against the VNDK.
+	ProductVariationPrefix = "product."
+)
+
+// Returns true if the module is "product" variant. Usually these modules are installed in /product
+func (c *Module) inProduct() bool {
+	return c.Properties.ImageVariationPrefix == ProductVariationPrefix
+}
+
+// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
+func (c *Module) inVendor() bool {
+	return c.Properties.ImageVariationPrefix == VendorVariationPrefix
+}
+
 func (c *Module) InRecovery() bool {
 	return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery()
 }
@@ -944,9 +976,14 @@
 	moduleContextImpl
 }
 
+func (ctx *moduleContext) ProductSpecific() bool {
+	return ctx.ModuleContext.ProductSpecific() ||
+		(ctx.mod.HasVendorVariant() && ctx.mod.inProduct() && !ctx.mod.IsVndk())
+}
+
 func (ctx *moduleContext) SocSpecific() bool {
 	return ctx.ModuleContext.SocSpecific() ||
-		(ctx.mod.HasVendorVariant() && ctx.mod.UseVndk() && !ctx.mod.IsVndk())
+		(ctx.mod.HasVendorVariant() && ctx.mod.inVendor() && !ctx.mod.IsVndk())
 }
 
 type moduleContextImpl struct {
@@ -980,15 +1017,11 @@
 func (ctx *moduleContextImpl) sdkVersion() string {
 	if ctx.ctx.Device() {
 		if ctx.useVndk() {
-			vndk_ver := ctx.ctx.DeviceConfig().VndkVersion()
-			if vndk_ver == "current" {
-				platform_vndk_ver := ctx.ctx.DeviceConfig().PlatformVndkVersion()
-				if inList(platform_vndk_ver, ctx.ctx.Config().PlatformVersionCombinedCodenames()) {
-					return "current"
-				}
-				return platform_vndk_ver
+			vndkVer := ctx.mod.VndkVersion()
+			if inList(vndkVer, ctx.ctx.Config().PlatformVersionCombinedCodenames()) {
+				return "current"
 			}
-			return vndk_ver
+			return vndkVer
 		}
 		return String(ctx.mod.Properties.Sdk_version)
 	}
@@ -1039,6 +1072,14 @@
 	return ctx.mod.MustUseVendorVariant()
 }
 
+func (ctx *moduleContextImpl) inProduct() bool {
+	return ctx.mod.inProduct()
+}
+
+func (ctx *moduleContextImpl) inVendor() bool {
+	return ctx.mod.inVendor()
+}
+
 func (ctx *moduleContextImpl) inRecovery() bool {
 	return ctx.mod.InRecovery()
 }
@@ -1222,6 +1263,29 @@
 	return ok && test.isAllTestsVariation()
 }
 
+func (c *Module) getNameSuffixWithVndkVersion(ctx android.ModuleContext) string {
+	// Returns the name suffix for product and vendor variants. If the VNDK version is not
+	// "current", it will append the VNDK version to the name suffix.
+	var vndkVersion string
+	var nameSuffix string
+	if c.inProduct() {
+		vndkVersion = ctx.DeviceConfig().ProductVndkVersion()
+		nameSuffix = productSuffix
+	} else {
+		vndkVersion = ctx.DeviceConfig().VndkVersion()
+		nameSuffix = vendorSuffix
+	}
+	if vndkVersion == "current" {
+		vndkVersion = ctx.DeviceConfig().PlatformVndkVersion()
+	}
+	if c.Properties.VndkVersion != vndkVersion {
+		// add version suffix only if the module is using different vndk version than the
+		// version in product or vendor partition.
+		nameSuffix += "." + c.Properties.VndkVersion
+	}
+	return nameSuffix
+}
+
 func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
 	// Handle the case of a test module split by `test_per_src` mutator.
 	//
@@ -1241,21 +1305,17 @@
 		c.Properties.SubName += nativeBridgeSuffix
 	}
 
-	if _, ok := c.linker.(*vndkPrebuiltLibraryDecorator); ok {
+	_, llndk := c.linker.(*llndkStubDecorator)
+	_, llndkHeader := c.linker.(*llndkHeadersDecorator)
+	if llndk || llndkHeader || (c.UseVndk() && c.HasVendorVariant()) {
+		// .vendor.{version} suffix is added for vendor variant or .product.{version} suffix is
+		// 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 _, 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
 	}
@@ -2203,15 +2263,7 @@
 			} 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.
-				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
+				return libName + c.getNameSuffixWithVndkVersion(ctx)
 			} else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib {
 				return libName + vendorPublicLibrarySuffix
 			} else if ccDep.InRecovery() && !ccDep.OnlyInRecovery() {
@@ -2364,6 +2416,9 @@
 			}
 			return "native:vndk_private"
 		}
+		if c.inProduct() {
+			return "native:product"
+		}
 		return "native:vendor"
 	} else if c.InRecovery() {
 		return "native:recovery"
@@ -2489,12 +2544,6 @@
 	return module
 }
 
-const (
-	// VendorVariationPrefix is the variant prefix used for /vendor code that compiles
-	// against the VNDK.
-	VendorVariationPrefix = "vendor."
-)
-
 func squashVendorSrcs(m *Module) {
 	if lib, ok := m.compiler.(*libraryDecorator); ok {
 		lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
@@ -2566,49 +2615,65 @@
 	var recoveryVariantNeeded bool = false
 
 	var vendorVariants []string
+	var productVariants []string
 
 	platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
-	deviceVndkVersion := mctx.DeviceConfig().VndkVersion()
-	if deviceVndkVersion == "current" {
-		deviceVndkVersion = platformVndkVersion
+	boardVndkVersion := mctx.DeviceConfig().VndkVersion()
+	productVndkVersion := mctx.DeviceConfig().ProductVndkVersion()
+	if boardVndkVersion == "current" {
+		boardVndkVersion = platformVndkVersion
+	}
+	if productVndkVersion == "current" {
+		productVndkVersion = platformVndkVersion
 	}
 
-	if mctx.DeviceConfig().VndkVersion() == "" {
+	if boardVndkVersion == "" {
 		// If the device isn't compiling against the VNDK, we always
 		// use the core mode.
 		coreVariantNeeded = true
 	} 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.
+		// LL-NDK stubs only exist in the vendor and product variants,
+		// since the real libraries will be used in the core variant.
 		vendorVariants = append(vendorVariants,
 			platformVndkVersion,
-			deviceVndkVersion,
+			boardVndkVersion,
+		)
+		productVariants = append(productVariants,
+			platformVndkVersion,
+			productVndkVersion,
 		)
 	} else if _, ok := m.linker.(*llndkHeadersDecorator); ok {
 		// ... and LL-NDK headers as well
 		vendorVariants = append(vendorVariants,
 			platformVndkVersion,
-			deviceVndkVersion,
+			boardVndkVersion,
+		)
+		productVariants = append(productVariants,
+			platformVndkVersion,
+			productVndkVersion,
 		)
 	} else if lib, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
 		// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
 		// PRODUCT_EXTRA_VNDK_VERSIONS.
 		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.
+		// This will be available in /system, /vendor and /product
+		// or a /system directory that is available to vendor and product.
 		coreVariantNeeded = true
 		vendorVariants = append(vendorVariants, platformVndkVersion)
+		productVariants = append(productVariants, platformVndkVersion)
 		// VNDK modules must not create BOARD_VNDK_VERSION variant because its
 		// code is PLATFORM_VNDK_VERSION.
 		// On the other hand, vendor_available modules which are not VNDK should
 		// also build BOARD_VNDK_VERSION because it's installed in /vendor.
+		// vendor_available modules are also available to /product.
 		if !m.IsVndk() {
-			vendorVariants = append(vendorVariants, deviceVndkVersion)
+			vendorVariants = append(vendorVariants, boardVndkVersion)
+			productVariants = append(productVariants, productVndkVersion)
 		}
 	} else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
 		// This will be available in /vendor (or /odm) only
-		vendorVariants = append(vendorVariants, deviceVndkVersion)
+		vendorVariants = append(vendorVariants, boardVndkVersion)
 	} else {
 		// This is either in /system (or similar: /data), or is a
 		// modules built with the NDK. Modules built with the NDK
@@ -2616,6 +2681,19 @@
 		coreVariantNeeded = true
 	}
 
+	if boardVndkVersion != "" && productVndkVersion != "" {
+		if coreVariantNeeded && productSpecific && String(m.Properties.Sdk_version) == "" {
+			// The module has "product_specific: true" that does not create core variant.
+			coreVariantNeeded = false
+			productVariants = append(productVariants, productVndkVersion)
+		}
+	} else {
+		// Unless PRODUCT_PRODUCT_VNDK_VERSION is set, product partition has no
+		// restriction to use system libs.
+		// No product variants defined in this case.
+		productVariants = []string{}
+	}
+
 	if Bool(m.Properties.Recovery_available) {
 		recoveryVariantNeeded = true
 	}
@@ -2626,7 +2704,11 @@
 	}
 
 	for _, variant := range android.FirstUniqueStrings(vendorVariants) {
-		m.Properties.VendorVariants = append(m.Properties.VendorVariants, VendorVariationPrefix+variant)
+		m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, VendorVariationPrefix+variant)
+	}
+
+	for _, variant := range android.FirstUniqueStrings(productVariants) {
+		m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, ProductVariationPrefix+variant)
 	}
 
 	m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded
@@ -2642,7 +2724,7 @@
 }
 
 func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string {
-	return c.Properties.VendorVariants
+	return c.Properties.ExtraVariants
 }
 
 func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
@@ -2651,8 +2733,13 @@
 		m.MakeAsPlatform()
 		squashRecoverySrcs(m)
 	} else if strings.HasPrefix(variant, VendorVariationPrefix) {
+		m.Properties.ImageVariationPrefix = VendorVariationPrefix
 		m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
 		squashVendorSrcs(m)
+	} else if strings.HasPrefix(variant, ProductVariationPrefix) {
+		m.Properties.ImageVariationPrefix = ProductVariationPrefix
+		m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
+		squashVendorSrcs(m)
 	}
 }
 
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 27ff38f..1e70529 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -82,11 +82,8 @@
 	return testCcWithConfig(t, config)
 }
 
-func testCcError(t *testing.T, pattern string, bp string) {
+func testCcErrorWithConfig(t *testing.T, pattern string, config android.Config) {
 	t.Helper()
-	config := TestConfig(buildDir, android.Android, nil, bp, nil)
-	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
-	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
 
 	ctx := CreateTestContext()
 	ctx.Register(config)
@@ -106,9 +103,27 @@
 	t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
 }
 
+func testCcError(t *testing.T, pattern string, bp string) {
+	config := TestConfig(buildDir, android.Android, nil, bp, nil)
+	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+	testCcErrorWithConfig(t, pattern, config)
+	return
+}
+
+func testCcErrorProductVndk(t *testing.T, pattern string, bp string) {
+	config := TestConfig(buildDir, android.Android, nil, bp, nil)
+	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+	config.TestProductVariables.ProductVndkVersion = StringPtr("current")
+	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+	testCcErrorWithConfig(t, pattern, config)
+	return
+}
+
 const (
 	coreVariant     = "android_arm64_armv8-a_shared"
 	vendorVariant   = "android_vendor.VER_arm64_armv8-a_shared"
+	productVariant  = "android_product.VER_arm64_armv8-a_shared"
 	recoveryVariant = "android_recovery_arm64_armv8-a_shared"
 )
 
@@ -1445,6 +1460,160 @@
 	`)
 }
 
+func TestEnforceProductVndkVersion(t *testing.T) {
+	bp := `
+		cc_library {
+			name: "libllndk",
+		}
+		llndk_library {
+			name: "libllndk",
+			symbol_file: "",
+		}
+		cc_library {
+			name: "libvndk",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+		cc_library {
+			name: "libvndk_sp",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+				support_system_process: true,
+			},
+			nocrt: true,
+		}
+		cc_library {
+			name: "libva",
+			vendor_available: true,
+			nocrt: true,
+		}
+		cc_library {
+			name: "libproduct_va",
+			product_specific: true,
+			vendor_available: true,
+			nocrt: true,
+		}
+		cc_library {
+			name: "libprod",
+			product_specific: true,
+			shared_libs: [
+				"libllndk",
+				"libvndk",
+				"libvndk_sp",
+				"libva",
+				"libproduct_va",
+			],
+			nocrt: true,
+		}
+		cc_library {
+			name: "libvendor",
+			vendor: true,
+			shared_libs: [
+				"libllndk",
+				"libvndk",
+				"libvndk_sp",
+				"libva",
+				"libproduct_va",
+			],
+			nocrt: true,
+		}
+	`
+
+	config := TestConfig(buildDir, android.Android, nil, bp, nil)
+	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+	config.TestProductVariables.ProductVndkVersion = StringPtr("current")
+	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+
+	ctx := testCcWithConfig(t, config)
+
+	checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "")
+	checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "")
+}
+
+func TestEnforceProductVndkVersionErrors(t *testing.T) {
+	testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.VER", `
+		cc_library {
+			name: "libprod",
+			product_specific: true,
+			shared_libs: [
+				"libvendor",
+			],
+			nocrt: true,
+		}
+		cc_library {
+			name: "libvendor",
+			vendor: true,
+			nocrt: true,
+		}
+	`)
+	testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.VER", `
+		cc_library {
+			name: "libprod",
+			product_specific: true,
+			shared_libs: [
+				"libsystem",
+			],
+			nocrt: true,
+		}
+		cc_library {
+			name: "libsystem",
+			nocrt: true,
+		}
+	`)
+	testCcErrorProductVndk(t, "Vendor module that is not VNDK should not link to \".*\" which is marked as `vendor_available: false`", `
+		cc_library {
+			name: "libprod",
+			product_specific: true,
+			shared_libs: [
+				"libvndk_private",
+			],
+			nocrt: true,
+		}
+		cc_library {
+			name: "libvndk_private",
+			vendor_available: false,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+	`)
+	testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.VER", `
+		cc_library {
+			name: "libprod",
+			product_specific: true,
+			shared_libs: [
+				"libsystem_ext",
+			],
+			nocrt: true,
+		}
+		cc_library {
+			name: "libsystem_ext",
+			system_ext_specific: true,
+			nocrt: true,
+		}
+	`)
+	testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:", `
+		cc_library {
+			name: "libsystem",
+			shared_libs: [
+				"libproduct_va",
+			],
+			nocrt: true,
+		}
+		cc_library {
+			name: "libproduct_va",
+			product_specific: true,
+			vendor_available: true,
+			nocrt: true,
+		}
+	`)
+}
+
 func TestMakeLinkType(t *testing.T) {
 	bp := `
 		cc_library {
diff --git a/cc/genrule.go b/cc/genrule.go
index b9765a4..548d5f2 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -55,6 +55,10 @@
 		return true
 	}
 
+	if ctx.DeviceConfig().ProductVndkVersion() != "" && ctx.ProductSpecific() {
+		return false
+	}
+
 	return Bool(g.Vendor_available) || !(ctx.SocSpecific() || ctx.DeviceSpecific())
 }
 
@@ -67,16 +71,26 @@
 		return nil
 	}
 
+	var variants []string
 	if Bool(g.Vendor_available) || ctx.SocSpecific() || ctx.DeviceSpecific() {
-		var variants []string
 		variants = append(variants, VendorVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
 		if vndkVersion := ctx.DeviceConfig().VndkVersion(); vndkVersion != "current" {
 			variants = append(variants, VendorVariationPrefix+vndkVersion)
 		}
+	}
+
+	if ctx.DeviceConfig().ProductVndkVersion() == "" {
 		return variants
 	}
 
-	return nil
+	if Bool(g.Vendor_available) || ctx.ProductSpecific() {
+		variants = append(variants, ProductVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
+		if vndkVersion := ctx.DeviceConfig().ProductVndkVersion(); vndkVersion != "current" {
+			variants = append(variants, ProductVariationPrefix+vndkVersion)
+		}
+	}
+
+	return variants
 }
 
 func (g *GenruleExtraProperties) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
diff --git a/cc/installer.go b/cc/installer.go
index 9fdc88a..2f55ac5 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -72,7 +72,11 @@
 		dir = filepath.Join(dir, ctx.Arch().ArchType.String())
 	}
 	if installer.location == InstallInData && ctx.useVndk() {
-		dir = filepath.Join(dir, "vendor")
+		if ctx.inProduct() {
+			dir = filepath.Join(dir, "product")
+		} else {
+			dir = filepath.Join(dir, "vendor")
+		}
 	}
 	return android.PathForModuleInstall(ctx, dir, installer.subDir,
 		installer.relativeInstallPath(), installer.relative)
diff --git a/cc/library.go b/cc/library.go
index 04130c4..ae95bc5 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -174,12 +174,16 @@
 }
 
 func init() {
-	android.RegisterModuleType("cc_library_static", LibraryStaticFactory)
-	android.RegisterModuleType("cc_library_shared", LibrarySharedFactory)
-	android.RegisterModuleType("cc_library", LibraryFactory)
-	android.RegisterModuleType("cc_library_host_static", LibraryHostStaticFactory)
-	android.RegisterModuleType("cc_library_host_shared", LibraryHostSharedFactory)
-	android.RegisterModuleType("cc_library_headers", LibraryHeaderFactory)
+	RegisterLibraryBuildComponents(android.InitRegistrationContext)
+}
+
+func RegisterLibraryBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("cc_library_static", LibraryStaticFactory)
+	ctx.RegisterModuleType("cc_library_shared", LibrarySharedFactory)
+	ctx.RegisterModuleType("cc_library", LibraryFactory)
+	ctx.RegisterModuleType("cc_library_host_static", LibraryHostStaticFactory)
+	ctx.RegisterModuleType("cc_library_host_shared", LibraryHostSharedFactory)
+	ctx.RegisterModuleType("cc_library_headers", LibraryHeaderFactory)
 }
 
 // cc_library creates both static and/or shared libraries for a device and/or
@@ -188,6 +192,11 @@
 // host.
 func LibraryFactory() android.Module {
 	module, _ := NewLibrary(android.HostAndDeviceSupported)
+	// Can be used as both a static and a shared library.
+	module.sdkMemberTypes = []android.SdkMemberType{
+		sharedLibrarySdkMemberType,
+		staticLibrarySdkMemberType,
+	}
 	return module.Init()
 }
 
@@ -195,6 +204,7 @@
 func LibraryStaticFactory() android.Module {
 	module, library := NewLibrary(android.HostAndDeviceSupported)
 	library.BuildOnlyStatic()
+	module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
 	return module.Init()
 }
 
@@ -202,6 +212,7 @@
 func LibrarySharedFactory() android.Module {
 	module, library := NewLibrary(android.HostAndDeviceSupported)
 	library.BuildOnlyShared()
+	module.sdkMemberTypes = []android.SdkMemberType{sharedLibrarySdkMemberType}
 	return module.Init()
 }
 
@@ -210,6 +221,7 @@
 func LibraryHostStaticFactory() android.Module {
 	module, library := NewLibrary(android.HostSupported)
 	library.BuildOnlyStatic()
+	module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
 	return module.Init()
 }
 
@@ -217,6 +229,7 @@
 func LibraryHostSharedFactory() android.Module {
 	module, library := NewLibrary(android.HostSupported)
 	library.BuildOnlyShared()
+	module.sdkMemberTypes = []android.SdkMemberType{sharedLibrarySdkMemberType}
 	return module.Init()
 }
 
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 9319070..2c18e68 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -24,23 +24,26 @@
 
 // This file contains support for using cc library modules within an sdk.
 
+var sharedLibrarySdkMemberType = &librarySdkMemberType{
+	SdkMemberTypeBase: android.SdkMemberTypeBase{
+		PropertyName: "native_shared_libs",
+	},
+	prebuiltModuleType: "cc_prebuilt_library_shared",
+	linkTypes:          []string{"shared"},
+}
+
+var staticLibrarySdkMemberType = &librarySdkMemberType{
+	SdkMemberTypeBase: android.SdkMemberTypeBase{
+		PropertyName: "native_static_libs",
+	},
+	prebuiltModuleType: "cc_prebuilt_library_static",
+	linkTypes:          []string{"static"},
+}
+
 func init() {
 	// Register sdk member types.
-	android.RegisterSdkMemberType(&librarySdkMemberType{
-		SdkMemberTypeBase: android.SdkMemberTypeBase{
-			PropertyName: "native_shared_libs",
-		},
-		prebuiltModuleType: "cc_prebuilt_library_shared",
-		linkTypes:          []string{"shared"},
-	})
-
-	android.RegisterSdkMemberType(&librarySdkMemberType{
-		SdkMemberTypeBase: android.SdkMemberTypeBase{
-			PropertyName: "native_static_libs",
-		},
-		prebuiltModuleType: "cc_prebuilt_library_static",
-		linkTypes:          []string{"static"},
-	})
+	android.RegisterSdkMemberType(sharedLibrarySdkMemberType)
+	android.RegisterSdkMemberType(staticLibrarySdkMemberType)
 }
 
 type librarySdkMemberType struct {
@@ -72,8 +75,16 @@
 }
 
 func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
-	_, ok := module.(*Module)
-	return ok
+	// Check the module to see if it can be used with this module type.
+	if m, ok := module.(*Module); ok {
+		for _, allowableMemberType := range m.sdkMemberTypes {
+			if allowableMemberType == mt {
+				return true
+			}
+		}
+	}
+
+	return false
 }
 
 // copy exported header files and stub *.so files
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index f3ee5c1..3dee692 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -76,17 +76,12 @@
 }
 
 func (stub *llndkStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
-	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()) {
-			vndk_ver = platform_vndk_ver
-		}
-	} else if vndk_ver == "" {
-		// For non-enforcing devices, use "current"
-		vndk_ver = "current"
+	vndkVer := ctx.Module().(*Module).VndkVersion()
+	if !inList(vndkVer, ctx.Config().PlatformVersionCombinedCodenames()) || vndkVer == "" {
+		// For non-enforcing devices, vndkVer is empty. Use "current" in that case, too.
+		vndkVer = "current"
 	}
-	objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), vndk_ver, "--llndk")
+	objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), vndkVer, "--llndk")
 	stub.versionScriptPath = versionScript
 	return objs
 }
diff --git a/cc/testing.go b/cc/testing.go
index de4f1ec..bc31077 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -20,14 +20,14 @@
 
 func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
 	RegisterPrebuiltBuildComponents(ctx)
-	ctx.RegisterModuleType("toolchain_library", ToolchainLibraryFactory)
-	ctx.RegisterModuleType("cc_library", LibraryFactory)
-	ctx.RegisterModuleType("llndk_library", LlndkLibraryFactory)
-	ctx.RegisterModuleType("cc_object", ObjectFactory)
-
 	android.RegisterPrebuiltMutators(ctx)
 
 	RegisterCCBuildComponents(ctx)
+	RegisterLibraryBuildComponents(ctx)
+
+	ctx.RegisterModuleType("toolchain_library", ToolchainLibraryFactory)
+	ctx.RegisterModuleType("llndk_library", LlndkLibraryFactory)
+	ctx.RegisterModuleType("cc_object", ObjectFactory)
 }
 
 func GatherRequiredDepsForTest(os android.OsType) string {
@@ -308,9 +308,6 @@
 	ctx.RegisterModuleType("cc_binary", BinaryFactory)
 	ctx.RegisterModuleType("cc_binary_host", binaryHostFactory)
 	ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
-	ctx.RegisterModuleType("cc_library_shared", LibrarySharedFactory)
-	ctx.RegisterModuleType("cc_library_static", LibraryStaticFactory)
-	ctx.RegisterModuleType("cc_library_headers", LibraryHeaderFactory)
 	ctx.RegisterModuleType("cc_test", TestFactory)
 	ctx.RegisterModuleType("llndk_headers", llndkHeadersFactory)
 	ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
diff --git a/cc/vndk.go b/cc/vndk.go
index f531af3..e4453eb 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -132,16 +132,16 @@
 		return
 	}
 	if !vndk.isVndk() {
-		// Non-VNDK modules (those installed to /vendor) can't depend on modules marked with
-		// vendor_available: false.
+		// Non-VNDK modules (those installed to /vendor, /product, or /system/product) can't depend
+		// on modules marked with vendor_available: false.
 		violation := false
 		if lib, ok := to.linker.(*llndkStubDecorator); ok && !Bool(lib.Properties.Vendor_available) {
 			violation = true
 		} else {
 			if _, ok := to.linker.(libraryInterface); ok && to.VendorProperties.Vendor_available != nil && !Bool(to.VendorProperties.Vendor_available) {
 				// Vendor_available == nil && !Bool(Vendor_available) should be okay since
-				// it means a vendor-only library which is a valid dependency for non-VNDK
-				// modules.
+				// it means a vendor-only, or product-only library which is a valid dependency
+				// for non-VNDK modules.
 				violation = true
 			}
 		}
@@ -350,7 +350,7 @@
 	}
 
 	if lib, ok := m.linker.(libraryInterface); ok {
-		useCoreVariant := m.vndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() &&
+		useCoreVariant := m.VndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() &&
 			mctx.DeviceConfig().VndkUseCoreVariant() && !m.MustUseVendorVariant()
 		return lib.shared() && m.UseVndk() && m.IsVndk() && !m.isVndkExt() && !useCoreVariant
 	}
@@ -665,14 +665,14 @@
 		if m.Target().NativeBridge == android.NativeBridgeEnabled {
 			return nil, "", false
 		}
-		if !m.UseVndk() || !m.IsForPlatform() || !m.installable() {
+		if !m.UseVndk() || !m.IsForPlatform() || !m.installable() || !m.inVendor() {
 			return nil, "", false
 		}
 		l, ok := m.linker.(vndkSnapshotLibraryInterface)
 		if !ok || !l.shared() {
 			return nil, "", false
 		}
-		if m.vndkVersion() == ctx.DeviceConfig().PlatformVndkVersion() && m.IsVndk() && !m.isVndkExt() {
+		if m.VndkVersion() == ctx.DeviceConfig().PlatformVndkVersion() && m.IsVndk() && !m.isVndkExt() {
 			if m.isVndkSp() {
 				return l, "vndk-sp", true
 			} else {
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index bf6043a..fefd0e6 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -32,20 +32,23 @@
 	properties     platformCompatConfigProperties
 	installDirPath android.InstallPath
 	configFile     android.OutputPath
+	metadataFile   android.OutputPath
 }
 
 func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	rule := android.NewRuleBuilder()
 
 	configFileName := p.Name() + ".xml"
+	metadataFileName := p.Name() + "_meta.xml"
 	p.configFile = android.PathForModuleOut(ctx, configFileName).OutputPath
+	p.metadataFile = android.PathForModuleOut(ctx, metadataFileName).OutputPath
 	path := android.PathForModuleSrc(ctx, String(p.properties.Src))
 
 	rule.Command().
 		BuiltTool(ctx, "process-compat-config").
-		Input(path).
-		Text(`>`).
-		Output(p.configFile)
+		FlagWithInput("--jar ", path).
+		FlagWithOutput("--device-config ", p.configFile).
+		FlagWithOutput("--merged-config ", p.metadataFile)
 
 	p.installDirPath = android.PathForModuleInstall(ctx, "etc", "compatconfig")
 	rule.Build(pctx, ctx, configFileName, "Extract compat/compat_config.xml and install it")
diff --git a/scripts/build-aml-prebuilts.sh b/scripts/build-aml-prebuilts.sh
new file mode 100755
index 0000000..7e3a82c
--- /dev/null
+++ b/scripts/build-aml-prebuilts.sh
@@ -0,0 +1,75 @@
+#!/bin/bash -e
+
+export OUT_DIR=${OUT_DIR:-out}
+
+if [ -e ${OUT_DIR}/soong/.soong.in_make ]; then
+  # If ${OUT_DIR} has been created without --skip-make, Soong will create an
+  # ${OUT_DIR}/soong/build.ninja that leaves out many targets which are
+  # expected to be supplied by the .mk files, and that might cause errors in
+  # "m --skip-make" below. We therefore default to a different out dir
+  # location in that case.
+  AML_OUT_DIR=out-aml
+  echo "Avoiding in-make OUT_DIR '${OUT_DIR}' - building in '${AML_OUT_DIR}' instead"
+  OUT_DIR=${AML_OUT_DIR}
+fi
+
+source build/envsetup.sh
+
+my_get_build_var() {
+  # get_build_var will run Soong in normal in-make mode where it creates
+  # .soong.in_make. That would clobber our real out directory, so we need to
+  # run it in a different one.
+  OUT_DIR=${OUT_DIR}/get_build_var get_build_var "$@"
+}
+
+PLATFORM_SDK_VERSION=$(my_get_build_var PLATFORM_SDK_VERSION)
+PLATFORM_VERSION=$(my_get_build_var PLATFORM_VERSION)
+PLATFORM_VERSION_ALL_CODENAMES=$(my_get_build_var PLATFORM_VERSION_ALL_CODENAMES)
+
+# PLATFORM_VERSION_ALL_CODENAMES is a comma separated list like O,P. We need to
+# turn this into ["O","P"].
+PLATFORM_VERSION_ALL_CODENAMES=${PLATFORM_VERSION_ALL_CODENAMES/,/'","'}
+PLATFORM_VERSION_ALL_CODENAMES="[\"${PLATFORM_VERSION_ALL_CODENAMES}\"]"
+
+# Logic from build/make/core/goma.mk
+if [ "${USE_GOMA}" = true ]; then
+  if [ -n "${GOMA_DIR}" ]; then
+    goma_dir="${GOMA_DIR}"
+  else
+    goma_dir="${HOME}/goma"
+  fi
+  GOMA_CC="${goma_dir}/gomacc"
+  export CC_WRAPPER="${CC_WRAPPER}${CC_WRAPPER:+ }${GOMA_CC}"
+  export CXX_WRAPPER="${CXX_WRAPPER}${CXX_WRAPPER:+ }${GOMA_CC}"
+  export JAVAC_WRAPPER="${JAVAC_WRAPPER}${JAVAC_WRAPPER:+ }${GOMA_CC}"
+else
+  USE_GOMA=false
+fi
+
+SOONG_OUT=${OUT_DIR}/soong
+mkdir -p ${SOONG_OUT}
+SOONG_VARS=${SOONG_OUT}/soong.variables
+
+cat > ${SOONG_VARS}.new << EOF
+{
+    "Platform_sdk_version": ${PLATFORM_SDK_VERSION},
+    "Platform_sdk_codename": "${PLATFORM_VERSION}",
+    "Platform_version_active_codenames": ${PLATFORM_VERSION_ALL_CODENAMES},
+
+    "DeviceName": "generic_arm64",
+    "HostArch": "x86_64",
+    "Aml_abis": true,
+
+    "UseGoma": ${USE_GOMA}
+}
+EOF
+
+if [ -f ${SOONG_VARS} ] && cmp -s ${SOONG_VARS} ${SOONG_VARS}.new; then
+  # Don't touch soong.variables if we don't have to, to avoid Soong rebuilding
+  # the ninja file when it isn't necessary.
+  rm ${SOONG_VARS}.new
+else
+  mv ${SOONG_VARS}.new ${SOONG_VARS}
+fi
+
+m --skip-make "$@"
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 08751e4..f477445 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -73,6 +73,10 @@
 			native_shared_libs: ["sdkmember"],
 		}
 
+		cc_library_shared {
+			name: "sdkmember",
+		}
+
 		sdk_snapshot {
 			name: "mysdk@1",
 			native_shared_libs: ["sdkmember_mysdk_1"],
@@ -143,6 +147,66 @@
 	ensureListContains(t, pathsToStrings(cpplibForMyApex2.Rule("ld").Implicits), sdkMemberV2.String())
 }
 
+// Make sure the sdk can use host specific cc libraries static/shared and both.
+func TestHostSdkWithCc(t *testing.T) {
+	testSdkWithCc(t, `
+		sdk {
+			name: "mysdk",
+			device_supported: false,
+			host_supported: true,
+			native_shared_libs: ["sdkshared"],
+			native_static_libs: ["sdkstatic"],
+		}
+
+		cc_library_host_shared {
+			name: "sdkshared",
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library_host_static {
+			name: "sdkstatic",
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+}
+
+// Make sure the sdk can use cc libraries static/shared and both.
+func TestSdkWithCc(t *testing.T) {
+	testSdkWithCc(t, `
+		sdk {
+			name: "mysdk",
+			native_shared_libs: ["sdkshared", "sdkboth1"],
+			native_static_libs: ["sdkstatic", "sdkboth2"],
+		}
+
+		cc_library_shared {
+			name: "sdkshared",
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library_static {
+			name: "sdkstatic",
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library {
+			name: "sdkboth1",
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library {
+			name: "sdkboth2",
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+}
+
 func TestSnapshotWithCcDuplicateHeaders(t *testing.T) {
 	result := testSdkWithCc(t, `
 		sdk {
diff --git a/sdk/testing.go b/sdk/testing.go
index 09d0247..c0d6f51 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -77,8 +77,6 @@
 
 	// from cc package
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
-	ctx.RegisterModuleType("cc_library_shared", cc.LibrarySharedFactory)
-	ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
 
 	// from apex package
 	ctx.RegisterModuleType("apex", apex.BundleFactory)
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 0c0f222..7cad3da 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -66,8 +66,6 @@
 	})
 
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
-	ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
-	ctx.RegisterModuleType("cc_library_static", cc.LibraryFactory)
 	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("sysprop_java", java.SyspropMutator).Parallel()
 	})