Merge "Replace core-junit with legacy-test"
diff --git a/android/androidmk.go b/android/androidmk.go
index 469ac7f..8f9f3bc 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -150,10 +150,6 @@
 
 	name := provider.BaseModuleName()
 	amod := mod.(Module).base()
-	data, err := provider.AndroidMk()
-	if err != nil {
-		return err
-	}
 
 	if !amod.Enabled() {
 		return nil
@@ -163,6 +159,11 @@
 		return nil
 	}
 
+	data, err := provider.AndroidMk()
+	if err != nil {
+		return err
+	}
+
 	if data.SubName != "" {
 		name += data.SubName
 	}
diff --git a/android/config.go b/android/config.go
index 725f43d..4a59bad 100644
--- a/android/config.go
+++ b/android/config.go
@@ -291,6 +291,24 @@
 	return val
 }
 
+func (c *config) GetenvWithDefault(key string, defaultValue string) string {
+	ret := c.Getenv(key)
+	if ret == "" {
+		return defaultValue
+	}
+	return ret
+}
+
+func (c *config) IsEnvTrue(key string) bool {
+	value := c.Getenv(key)
+	return value == "1" || value == "y" || value == "yes" || value == "on" || value == "true"
+}
+
+func (c *config) IsEnvFalse(key string) bool {
+	value := c.Getenv(key)
+	return value == "0" || value == "n" || value == "no" || value == "off" || value == "false"
+}
+
 func (c *config) EnvDeps() map[string]string {
 	c.envLock.Lock()
 	c.envFrozen = true
@@ -424,3 +442,10 @@
 	}
 	return arches
 }
+
+func (c *deviceConfig) VndkVersion() string {
+	if c.config.ProductVariables.DeviceVndkVersion == nil {
+		return ""
+	}
+	return *c.config.ProductVariables.DeviceVndkVersion
+}
diff --git a/android/module.go b/android/module.go
index 110f04c..c0b9c47 100644
--- a/android/module.go
+++ b/android/module.go
@@ -100,6 +100,7 @@
 	Enabled() bool
 	Target() Target
 	InstallInData() bool
+	SkipInstall()
 }
 
 type nameProperties struct {
diff --git a/android/mutator.go b/android/mutator.go
index 8114b3e..3420280 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -46,8 +46,8 @@
 
 	ctx.BottomUp("deps", depsMutator).Parallel()
 
+	ctx.TopDown("prebuilt_select", PrebuiltSelectModuleMutator).Parallel()
 	ctx.BottomUp("prebuilt_replace", PrebuiltReplaceMutator).Parallel()
-	ctx.TopDown("prebuilt_disable", PrebuiltDisableMutator).Parallel()
 
 	register(postDeps)
 }
diff --git a/android/prebuilt.go b/android/prebuilt.go
index fb9e515..5f9b4b0 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -21,20 +21,6 @@
 
 var prebuiltDependencyTag blueprint.BaseDependencyTag
 
-func SourceModuleHasPrebuilt(ctx ModuleContext) OptionalPath {
-	var path Path
-	ctx.VisitDirectDeps(func(m blueprint.Module) {
-		if ctx.OtherModuleDependencyTag(m) == prebuiltDependencyTag {
-			p := m.(PrebuiltInterface).Prebuilt()
-			if p.usePrebuilt(ctx) {
-				path = p.Path(ctx)
-			}
-		}
-	})
-
-	return OptionalPathForPath(path)
-}
-
 type Prebuilt struct {
 	Properties struct {
 		Srcs []string `android:"arch_variant"`
@@ -43,6 +29,7 @@
 		Prefer bool `android:"arch_variant"`
 
 		SourceExists bool `blueprint:"mutated"`
+		UsePrebuilt  bool `blueprint:"mutated"`
 	}
 	module Module
 }
@@ -70,10 +57,6 @@
 	Prebuilt() *Prebuilt
 }
 
-type PrebuiltSourceInterface interface {
-	SkipInstall()
-}
-
 // prebuiltMutator ensures that there is always a module with an undecorated name, and marks
 // prebuilt modules that have both a prebuilt and a source module.
 func prebuiltMutator(ctx BottomUpMutatorContext) {
@@ -89,25 +72,15 @@
 	}
 }
 
-// PrebuiltReplaceMutator replaces dependencies on the source module with dependencies on the prebuilt
-// when both modules exist and the prebuilt should be used.
-func PrebuiltReplaceMutator(ctx BottomUpMutatorContext) {
-	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
-		p := m.Prebuilt()
-		name := m.base().BaseModuleName()
-		if p.Properties.SourceExists && p.usePrebuilt(ctx) {
-			ctx.ReplaceDependencies(name)
-		}
-	}
-}
-
-// PrebuiltDisableMutator disables source modules that have prebuilts that should be used instead.
-func PrebuiltDisableMutator(ctx TopDownMutatorContext) {
-	if s, ok := ctx.Module().(PrebuiltSourceInterface); ok {
+// PrebuiltSelectModuleMutator marks prebuilts that are overriding source modules, and disables
+// installing the source module.
+func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) {
+	if s, ok := ctx.Module().(Module); ok {
 		ctx.VisitDirectDeps(func(m blueprint.Module) {
 			if ctx.OtherModuleDependencyTag(m) == prebuiltDependencyTag {
 				p := m.(PrebuiltInterface).Prebuilt()
-				if p.usePrebuilt(ctx) {
+				if p.usePrebuilt(ctx, s) {
+					p.Properties.UsePrebuilt = true
 					s.SkipInstall()
 				}
 			}
@@ -115,7 +88,34 @@
 	}
 }
 
-func (p *Prebuilt) usePrebuilt(ctx BaseContext) bool {
-	// TODO: use p.Properties.Name and ctx.ModuleDir to override prefer
-	return p.Properties.Prefer && len(p.Properties.Srcs) > 0
+// PrebuiltReplaceMutator replaces dependencies on the source module with dependencies on the
+// prebuilt when both modules exist and the prebuilt should be used.  When the prebuilt should not
+// be used, disable installing it.
+func PrebuiltReplaceMutator(ctx BottomUpMutatorContext) {
+	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
+		p := m.Prebuilt()
+		name := m.base().BaseModuleName()
+		if p.Properties.UsePrebuilt {
+			if p.Properties.SourceExists {
+				ctx.ReplaceDependencies(name)
+			}
+		} else {
+			m.SkipInstall()
+		}
+	}
+}
+
+// usePrebuilt returns true if a prebuilt should be used instead of the source module.  The prebuilt
+// will be used if it is marked "prefer" or if the source module is disabled.
+func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
+	if len(p.Properties.Srcs) == 0 {
+		return false
+	}
+
+	// TODO: use p.Properties.Name and ctx.ModuleDir to override preference
+	if p.Properties.Prefer {
+		return true
+	}
+
+	return !source.Enabled()
 }
diff --git a/android/variable.go b/android/variable.go
index c1948b0..3436a75 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -87,6 +87,7 @@
 	DeviceCpuVariant  *string   `json:",omitempty"`
 	DeviceAbi         *[]string `json:",omitempty"`
 	DeviceUsesClang   *bool     `json:",omitempty"`
+	DeviceVndkVersion *string   `json:",omitempty"`
 
 	DeviceSecondaryArch        *string   `json:",omitempty"`
 	DeviceSecondaryArchVariant *string   `json:",omitempty"`
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index 6387ff1..5d9f1b4 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -77,6 +77,7 @@
 	"LOCAL_NO_STANDARD_LIBRARIES":   {"no_standard_libraries", bpparser.BoolType},
 	"LOCAL_PACK_MODULE_RELOCATIONS": {"pack_relocations", bpparser.BoolType},
 	"LOCAL_TIDY":                    {"tidy", bpparser.BoolType},
+	"LOCAL_USE_VNDK":                {"use_vndk", bpparser.BoolType},
 
 	"LOCAL_EXPORT_PACKAGE_RESOURCES": {"export_package_resources", bpparser.BoolType},
 }
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 50c183e..709ac59 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -59,6 +59,9 @@
 		if c.Target().Os == android.Android && c.Properties.Sdk_version != "" {
 			fmt.Fprintln(w, "LOCAL_SDK_VERSION := "+c.Properties.Sdk_version)
 			fmt.Fprintln(w, "LOCAL_NDK_STL_VARIANT := none")
+		} else if c.Target().Os == android.Android && c.Properties.Use_vndk {
+			fmt.Fprintln(w, "LOCAL_USE_VNDK := true")
+			fmt.Fprintln(w, "LOCAL_NDK_STL_VARIANT := none")
 		} else {
 			// These are already included in LOCAL_SHARED_LIBRARIES
 			fmt.Fprintln(w, "LOCAL_CXX_STL := none")
diff --git a/cc/binary.go b/cc/binary.go
index 2b77514..1aba6eb 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -93,7 +93,7 @@
 	deps = binary.baseLinker.linkerDeps(ctx, deps)
 	if ctx.toolchain().Bionic() {
 		if !Bool(binary.baseLinker.Properties.Nocrt) {
-			if !ctx.sdk() {
+			if !ctx.sdk() && !ctx.vndk() {
 				if binary.static() {
 					deps.CrtBegin = "crtbegin_static"
 				} else {
diff --git a/cc/cc.go b/cc/cc.go
index ddeede9..fef72cc 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -125,6 +125,9 @@
 	// Minimum sdk version supported when compiling against the ndk
 	Sdk_version string
 
+	// Whether to compile against the VNDK
+	Use_vndk bool
+
 	// don't insert default compiler flags into asflags, cflags,
 	// cppflags, conlyflags, ldflags, or include_dirs
 	No_default_compiler_flags *bool
@@ -132,6 +135,7 @@
 	AndroidMkSharedLibs []string `blueprint:"mutated"`
 	HideFromMake        bool     `blueprint:"mutated"`
 	PreventInstall      bool     `blueprint:"mutated"`
+	Vndk_version        string   `blueprint:"mutated"`
 }
 
 type UnusedProperties struct {
@@ -147,6 +151,7 @@
 	noDefaultCompilerFlags() bool
 	sdk() bool
 	sdkVersion() string
+	vndk() bool
 	selectedStl() string
 	baseModuleName() string
 }
@@ -345,11 +350,22 @@
 
 func (ctx *moduleContextImpl) sdkVersion() string {
 	if ctx.ctx.Device() {
-		return ctx.mod.Properties.Sdk_version
+		if ctx.mod.Properties.Use_vndk {
+			return ctx.mod.Properties.Vndk_version
+		} else {
+			return ctx.mod.Properties.Sdk_version
+		}
 	}
 	return ""
 }
 
+func (ctx *moduleContextImpl) vndk() bool {
+	if ctx.ctx.Device() {
+		return ctx.mod.Properties.Use_vndk
+	}
+	return false
+}
+
 func (ctx *moduleContextImpl) selectedStl() string {
 	if stl := ctx.mod.stl; stl != nil {
 		return stl.Properties.SelectedStl
@@ -493,11 +509,22 @@
 		feature.begin(ctx)
 	}
 	if ctx.sdk() {
+		if ctx.vndk() {
+			ctx.PropertyErrorf("use_vndk",
+				"sdk_version and use_vndk cannot be used at the same time")
+		}
+
 		version, err := normalizeNdkApiLevel(ctx.sdkVersion(), ctx.Arch())
 		if err != nil {
 			ctx.PropertyErrorf("sdk_version", err.Error())
 		}
 		c.Properties.Sdk_version = version
+	} else if ctx.vndk() {
+		version, err := normalizeNdkApiLevel(ctx.DeviceConfig().VndkVersion(), ctx.Arch())
+		if err != nil {
+			ctx.ModuleErrorf("Bad BOARD_VNDK_VERSION: %s", err.Error())
+		}
+		c.Properties.Vndk_version = version
 	}
 }
 
@@ -579,7 +606,7 @@
 
 	variantNdkLibs := []string{}
 	variantLateNdkLibs := []string{}
-	if ctx.sdk() {
+	if ctx.sdk() || ctx.vndk() {
 		version := ctx.sdkVersion()
 
 		// Rewrites the names of shared libraries into the names of the NDK
@@ -818,8 +845,10 @@
 		}
 
 		if tag == reuseObjTag {
-			depPaths.Objs = depPaths.Objs.Append(cc.compiler.(libraryInterface).reuseObjs())
-			return
+			if l, ok := cc.compiler.(libraryInterface); ok {
+				depPaths.Objs = depPaths.Objs.Append(l.reuseObjs())
+				return
+			}
 		}
 
 		if t, ok := tag.(dependencyTag); ok && t.library {
diff --git a/cc/compiler.go b/cc/compiler.go
index 285bb69..def8d58 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -160,7 +160,7 @@
 	}
 
 	if !ctx.noDefaultCompilerFlags() {
-		if !ctx.sdk() || ctx.Host() {
+		if !(ctx.sdk() || ctx.vndk()) || ctx.Host() {
 			flags.GlobalFlags = append(flags.GlobalFlags,
 				"${config.CommonGlobalIncludes}",
 				"${config.CommonGlobalSystemIncludes}",
@@ -171,7 +171,7 @@
 		flags.GlobalFlags = append(flags.GlobalFlags, "-I"+android.PathForModuleSrc(ctx).String())
 	}
 
-	if ctx.sdk() {
+	if ctx.sdk() || ctx.vndk() {
 		// The NDK headers are installed to a common sysroot. While a more
 		// typical Soong approach would be to only make the headers for the
 		// library you're using available, we're trying to emulate the NDK
@@ -354,7 +354,7 @@
 var gnuToCReplacer = strings.NewReplacer("gnu", "c")
 
 func ndkPathDeps(ctx ModuleContext) android.Paths {
-	if ctx.sdk() {
+	if ctx.sdk() || ctx.vndk() {
 		// The NDK sysroot timestamp file depends on all the NDK sysroot files
 		// (headers and libraries).
 		return android.Paths{getNdkSysrootTimestampFile(ctx)}
diff --git a/cc/config/global.go b/cc/config/global.go
index e454c16..71c0da4 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -163,3 +163,7 @@
 		"-isystem bionic/libc/kernel/android/uapi",
 	}, " ")
 }
+
+func VndkLibraries() []string {
+	return []string{}
+}
diff --git a/cc/library.go b/cc/library.go
index 35d0089..7b7ac95 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -331,7 +331,7 @@
 		deps.SharedLibs = append(deps.SharedLibs, library.Properties.Static.Shared_libs...)
 	} else {
 		if ctx.toolchain().Bionic() && !Bool(library.baseLinker.Properties.Nocrt) {
-			if !ctx.sdk() {
+			if !ctx.sdk() && !ctx.vndk() {
 				deps.CrtBegin = "crtbegin_so"
 				deps.CrtEnd = "crtend_so"
 			} else {
diff --git a/cc/makevars.go b/cc/makevars.go
index 7f1063f..fe3440c 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -45,6 +45,13 @@
 	ctx.Strict("GLOBAL_CLANG_CPPFLAGS_NO_OVERRIDE", "")
 	ctx.Strict("NDK_PREBUILT_SHARED_LIBRARIES", strings.Join(ndkPrebuiltSharedLibs, " "))
 
+	if ctx.Config().ProductVariables.DeviceVndkVersion != nil {
+		ctx.Strict("BOARD_VNDK_VERSION", *ctx.Config().ProductVariables.DeviceVndkVersion)
+	} else {
+		ctx.Strict("BOARD_VNDK_VERSION", "")
+	}
+	ctx.Strict("VNDK_LIBRARIES", strings.Join(config.VndkLibraries(), " "))
+
 	ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", asanCflags)
 	ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS", asanLdflags)
 	ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_STATIC_LIBRARIES", asanLibs)
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 4328df8..0a54570 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -60,13 +60,14 @@
 }
 
 func prebuiltSharedLibraryFactory() (blueprint.Module, []interface{}) {
-	module, library := NewLibrary(android.HostAndDeviceSupported, true, false)
+	module, library := NewLibrary(android.HostAndDeviceSupported, true, true)
 	module.compiler = nil
 
 	prebuilt := &prebuiltLibraryLinker{
 		libraryDecorator: library,
 	}
 	module.linker = prebuilt
+	module.installer = prebuilt
 
 	return module.Init()
 }