Merge "Let tests override environment"
diff --git a/cc/androidmk.go b/cc/androidmk.go
index eb63065..2114031 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -89,7 +89,7 @@
 	}
 	c.subAndroidMk(&ret, c.installer)
 
-	if c.vndk() && Bool(c.VendorProperties.Vendor_available) {
+	if c.vndk() && c.hasVendorVariant() {
 		// .vendor suffix is added only when we will have two variants: core and vendor.
 		// The suffix is not added for vendor-only module.
 		ret.SubName += vendorSuffix
diff --git a/cc/cc.go b/cc/cc.go
index 4f10a11..0404cfb 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -168,16 +168,21 @@
 }
 
 type VendorProperties struct {
-	// whether this module should be allowed to install onto /vendor as
-	// well as /system. The 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.
+	// 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.
 	//
 	// The vendor variant 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.
+	//
+	// Default value is true when vndk: {enabled: true} or vendor: true.
+	//
 	// Nothing happens if BOARD_VNDK_VERSION isn't set in the BoardConfig.mk
 	Vendor_available *bool
 }
@@ -388,6 +393,12 @@
 	return false
 }
 
+// Returns true only when this module is configured to have core and vendor
+// variants.
+func (c *Module) hasVendorVariant() bool {
+	return c.isVndk() || Bool(c.VendorProperties.Vendor_available)
+}
+
 type baseModuleContext struct {
 	android.BaseContext
 	moduleContextImpl
@@ -1159,7 +1170,7 @@
 
 		// Export the shared libs to the make world. In doing so, .vendor suffix
 		// is added if the lib has both core and vendor variants and this module
-		// is building against vndk. This is because the vendor variant will be
+		// is building against vndk. This is because the vendor variant will
 		// have .vendor suffix in its name in the make world. However, if the
 		// lib is a vendor-only lib or this lib is not building against vndk,
 		// then the suffix is not added.
@@ -1168,7 +1179,7 @@
 			libName := strings.TrimSuffix(name, llndkLibrarySuffix)
 			libName = strings.TrimPrefix(libName, "prebuilt_")
 			isLLndk := inList(libName, llndkLibraries)
-			if c.vndk() && (Bool(cc.VendorProperties.Vendor_available) || isLLndk) {
+			if c.vndk() && (cc.hasVendorVariant() || isLLndk) {
 				libName += vendorSuffix
 			}
 			// Note: the order of libs in this list is not important because
@@ -1311,15 +1322,15 @@
 	}
 
 	// Sanity check
-	if Bool(m.VendorProperties.Vendor_available) && mctx.Vendor() {
+	if m.VendorProperties.Vendor_available != nil && mctx.Vendor() {
 		mctx.PropertyErrorf("vendor_available",
 			"doesn't make sense at the same time as `vendor: true` or `proprietary: true`")
 		return
 	}
 	if vndk := m.vndkdep; vndk != nil {
-		if vndk.isVndk() && !Bool(m.VendorProperties.Vendor_available) {
+		if vndk.isVndk() && m.VendorProperties.Vendor_available == nil {
 			mctx.PropertyErrorf("vndk",
-				"has to define `vendor_available: true` to enable vndk")
+				"vendor_available must be set to either true or false when `vndk: {enabled: true}`")
 			return
 		}
 		if !vndk.isVndk() && vndk.isVndkSp() {
@@ -1337,7 +1348,7 @@
 		// LL-NDK stubs only exist in the vendor variant, since the
 		// real libraries will be used in the core variant.
 		mctx.CreateVariations(vendorMode)
-	} else if Bool(m.VendorProperties.Vendor_available) {
+	} else if m.hasVendorVariant() {
 		// This will be available in both /system and /vendor
 		// or a /system directory that is available to vendor.
 		mod := mctx.CreateVariations(coreMode, vendorMode)
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index c3d3462..30c4d4c 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -50,6 +50,11 @@
 
 	// Whether the system library uses symbol versions.
 	Unversioned bool
+
+	// whether this module can be directly depended upon by libs that are installed to /vendor.
+	// When set to false, this module can only be depended on by VNDK libraries, not vendor
+	// libraries. This effectively hides this module from vendors. Default value is true.
+	Vendor_available bool
 }
 
 type llndkStubDecorator struct {
@@ -149,6 +154,7 @@
 	stub := &llndkStubDecorator{
 		libraryDecorator: library,
 	}
+	stub.Properties.Vendor_available = true
 	module.compiler = stub
 	module.linker = stub
 	module.installer = nil
diff --git a/cc/makevars.go b/cc/makevars.go
index 2c6af70..295b4ac 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -62,6 +62,7 @@
 	ctx.Strict("VNDK_CORE_LIBRARIES", strings.Join(vndkCoreLibraries, " "))
 	ctx.Strict("VNDK_SAMEPROCESS_LIBRARIES", strings.Join(vndkSpLibraries, " "))
 	ctx.Strict("LLNDK_LIBRARIES", strings.Join(llndkLibraries, " "))
+	ctx.Strict("VNDK_PRIVATE_LIBRARIES", strings.Join(vndkPrivateLibraries, " "))
 
 	ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(asanCflags, " "))
 	ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS", strings.Join(asanLdflags, " "))
diff --git a/cc/pgo.go b/cc/pgo.go
index a99cbad..c5e4e86 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -63,37 +63,55 @@
 	return []interface{}{&pgo.Properties}
 }
 
-func (pgo *pgo) addProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
-	if pgo.Properties.isInstrumentation() {
+func (props *PgoProperties) addProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
+	if props.isInstrumentation() {
 		flags.CFlags = append(flags.CFlags, profileInstrumentFlag)
 		// The profile runtime is added below in deps().  Add the below
 		// flag, which is the only other link-time action performed by
 		// the Clang driver during link.
 		flags.LdFlags = append(flags.LdFlags, "-u__llvm_profile_runtime")
 	}
-	if pgo.Properties.isSampling() {
+	if props.isSampling() {
 		flags.CFlags = append(flags.CFlags, profileSamplingFlag)
 		flags.LdFlags = append(flags.LdFlags, profileSamplingFlag)
 	}
 	return flags
 }
 
-func (pgo *pgo) profileUseFlag(ctx ModuleContext, file string) string {
-	if pgo.Properties.isInstrumentation() {
+func (props *PgoProperties) profileUseFlag(ctx ModuleContext, file string) string {
+	if props.isInstrumentation() {
 		return fmt.Sprintf(profileUseInstrumentFormat, file)
 	}
-	if pgo.Properties.isSampling() {
+	if props.isSampling() {
 		return fmt.Sprintf(profileUseSamplingFormat, file)
 	}
 	return ""
 }
 
-func (pgo *pgo) profileUseFlags(ctx ModuleContext, file string) []string {
-	flags := []string{pgo.profileUseFlag(ctx, file)}
+func (props *PgoProperties) profileUseFlags(ctx ModuleContext, file string) []string {
+	flags := []string{props.profileUseFlag(ctx, file)}
 	flags = append(flags, profileUseOtherFlags...)
 	return flags
 }
 
+func (props *PgoProperties) addProfileUseFlags(ctx ModuleContext, flags Flags) Flags {
+	// If the PGO profiles project is found, and this module has PGO
+	// enabled, add flags to use the profile
+	if profilesDir := getPgoProfilesDir(ctx); props.PgoPresent && profilesDir.Valid() {
+		profileFile := android.PathForSource(ctx, profilesDir.String(), *props.Pgo.Profile_file)
+		profileUseFlags := props.profileUseFlags(ctx, profileFile.String())
+
+		flags.CFlags = append(flags.CFlags, profileUseFlags...)
+		flags.LdFlags = append(flags.LdFlags, profileUseFlags...)
+
+		// Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
+		// if profileFile gets updated
+		flags.CFlagsDeps = append(flags.CFlagsDeps, profileFile)
+		flags.LdFlagsDeps = append(flags.LdFlagsDeps, profileFile)
+	}
+	return flags
+}
+
 func (props *PgoProperties) isPGO(ctx BaseModuleContext) bool {
 	isInstrumentation := props.isInstrumentation()
 	isSampling := props.isSampling()
@@ -188,22 +206,11 @@
 
 	// Add flags to profile this module based on its profile_kind
 	if props.ShouldProfileModule {
-		return pgo.addProfileGatherFlags(ctx, flags)
+		return props.addProfileGatherFlags(ctx, flags)
 	}
 
-	// If the PGO profiles project is found, and this module has PGO
-	// enabled, add flags to use the profile
-	if profilesDir := getPgoProfilesDir(ctx); props.PgoPresent && profilesDir.Valid() {
-		profileFile := android.PathForSource(ctx, profilesDir.String(), *(props.Pgo.Profile_file))
-		profileUseFlags := pgo.profileUseFlags(ctx, profileFile.String())
-
-		flags.CFlags = append(flags.CFlags, profileUseFlags...)
-		flags.LdFlags = append(flags.LdFlags, profileUseFlags...)
-
-		// Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
-		// if profileFile gets updated
-		flags.CFlagsDeps = append(flags.CFlagsDeps, profileFile)
-		flags.LdFlagsDeps = append(flags.LdFlagsDeps, profileFile)
+	if !ctx.AConfig().IsEnvTrue("ANDROID_PGO_NO_PROFILE_USE") {
+		return props.addProfileUseFlags(ctx, flags)
 	}
 
 	return flags
diff --git a/cc/vndk.go b/cc/vndk.go
index 395069b..860678d 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -27,8 +27,8 @@
 		// declared as a VNDK or VNDK-SP module. The vendor variant
 		// will be installed in /system instead of /vendor partition.
 		//
-		// `vendor_available: true` must set to together for VNDK
-		// modules.
+		// `vendor_vailable` must be explicitly set to either true or
+		// false together with `vndk: {enabled: true}`.
 		Enabled *bool
 
 		// declared as a VNDK-SP module, which is a subset of VNDK.
@@ -81,6 +81,24 @@
 	if to.linker == nil {
 		return
 	}
+	if !vndk.isVndk() {
+		// Non-VNDK modules (those installed to /vendor) can't depend on modules marked with
+		// vendor_available: false.
+		violation := false
+		if lib, ok := to.linker.(*llndkStubDecorator); ok && !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.
+				violation = true
+			}
+		}
+		if violation {
+			ctx.ModuleErrorf("Vendor module that is not VNDK should not link to %q which is marked as `vendor_available: false`", to.Name())
+		}
+	}
 	if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() {
 		// Check only shared libraries.
 		// Other (static and LL-NDK) libraries are allowed to link.
@@ -102,16 +120,17 @@
 }
 
 var (
-	vndkCoreLibraries []string
-	vndkSpLibraries   []string
-	llndkLibraries    []string
-	vndkLibrariesLock sync.Mutex
+	vndkCoreLibraries    []string
+	vndkSpLibraries      []string
+	llndkLibraries       []string
+	vndkPrivateLibraries []string
+	vndkLibrariesLock    sync.Mutex
 )
 
 // gather list of vndk-core, vndk-sp, and ll-ndk libs
 func vndkMutator(mctx android.BottomUpMutatorContext) {
 	if m, ok := mctx.Module().(*Module); ok {
-		if _, ok := m.linker.(*llndkStubDecorator); ok {
+		if lib, ok := m.linker.(*llndkStubDecorator); ok {
 			vndkLibrariesLock.Lock()
 			defer vndkLibrariesLock.Unlock()
 			name := strings.TrimSuffix(m.Name(), llndkLibrarySuffix)
@@ -119,22 +138,40 @@
 				llndkLibraries = append(llndkLibraries, name)
 				sort.Strings(llndkLibraries)
 			}
-		} else if lib, ok := m.linker.(*libraryDecorator); ok && lib.shared() {
-			if m.vndkdep.isVndk() {
-				vndkLibrariesLock.Lock()
-				defer vndkLibrariesLock.Unlock()
-				if m.vndkdep.isVndkSp() {
-					if !inList(m.Name(), vndkSpLibraries) {
-						vndkSpLibraries = append(vndkSpLibraries, m.Name())
-						sort.Strings(vndkSpLibraries)
+			if !lib.Properties.Vendor_available {
+				if !inList(name, vndkPrivateLibraries) {
+					vndkPrivateLibraries = append(vndkPrivateLibraries, name)
+					sort.Strings(vndkPrivateLibraries)
+				}
+			}
+		} else {
+			lib, is_lib := m.linker.(*libraryDecorator)
+			prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker)
+			if (is_lib && lib.shared()) || (is_prebuilt_lib && prebuilt_lib.shared()) {
+				name := strings.TrimPrefix(m.Name(), "prebuilt_")
+				if m.vndkdep.isVndk() {
+					vndkLibrariesLock.Lock()
+					defer vndkLibrariesLock.Unlock()
+					if m.vndkdep.isVndkSp() {
+						if !inList(name, vndkSpLibraries) {
+							vndkSpLibraries = append(vndkSpLibraries, name)
+							sort.Strings(vndkSpLibraries)
+						}
+					} else {
+						if !inList(name, vndkCoreLibraries) {
+							vndkCoreLibraries = append(vndkCoreLibraries, name)
+							sort.Strings(vndkCoreLibraries)
+						}
 					}
-				} else {
-					if !inList(m.Name(), vndkCoreLibraries) {
-						vndkCoreLibraries = append(vndkCoreLibraries, m.Name())
-						sort.Strings(vndkCoreLibraries)
+					if !Bool(m.VendorProperties.Vendor_available) {
+						if !inList(name, vndkPrivateLibraries) {
+							vndkPrivateLibraries = append(vndkPrivateLibraries, name)
+							sort.Strings(vndkPrivateLibraries)
+						}
 					}
 				}
 			}
 		}
+
 	}
 }