Merge "Revert "Remove java version checks""
diff --git a/Android.bp b/Android.bp
index 496dcd2..68b379c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -51,6 +51,7 @@
         "android/paths.go",
         "android/prebuilt.go",
         "android/register.go",
+        "android/testing.go",
         "android/util.go",
         "android/variable.go",
 
@@ -123,6 +124,7 @@
         "cc/strip.go",
         "cc/tidy.go",
         "cc/util.go",
+        "cc/vndk.go",
 
         "cc/cmakelists.go",
         "cc/compiler.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index b81cc2a..dabefcc 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -246,8 +246,8 @@
 		if amod.commonProperties.Vendor {
 			fmt.Fprintln(w, "LOCAL_VENDOR_MODULE := true")
 		}
-		if amod.commonProperties.Owner != "" {
-			fmt.Fprintln(w, "LOCAL_MODULE_OWNER :=", amod.commonProperties.Owner)
+		if amod.commonProperties.Owner != nil {
+			fmt.Fprintln(w, "LOCAL_MODULE_OWNER :=", *amod.commonProperties.Owner)
 		}
 	}
 
diff --git a/android/config.go b/android/config.go
index 3de1ef1..5dcc59b 100644
--- a/android/config.go
+++ b/android/config.go
@@ -84,6 +84,8 @@
 
 	inMake bool
 
+	captureBuild bool // true for tests, saves build parameters for each module
+
 	OncePer
 }
 
@@ -171,7 +173,8 @@
 			DeviceName: stringPtr("test_device"),
 		},
 
-		buildDir: buildDir,
+		buildDir:     buildDir,
+		captureBuild: true,
 	}
 	config.deviceConfig = &deviceConfig{
 		config: config,
@@ -527,20 +530,21 @@
 func (c *deviceConfig) CoverageEnabledForPath(path string) bool {
 	coverage := false
 	if c.config.ProductVariables.CoveragePaths != nil {
-		for _, prefix := range *c.config.ProductVariables.CoveragePaths {
-			if strings.HasPrefix(path, prefix) {
-				coverage = true
-				break
-			}
+		if prefixInList(path, *c.config.ProductVariables.CoveragePaths) {
+			coverage = true
 		}
 	}
 	if coverage && c.config.ProductVariables.CoverageExcludePaths != nil {
-		for _, prefix := range *c.config.ProductVariables.CoverageExcludePaths {
-			if strings.HasPrefix(path, prefix) {
-				coverage = false
-				break
-			}
+		if prefixInList(path, *c.config.ProductVariables.CoverageExcludePaths) {
+			coverage = false
 		}
 	}
 	return coverage
 }
+
+func (c *config) IntegerOverflowDisabledForPath(path string) bool {
+	if c.ProductVariables.IntegerOverflowExcludePaths == nil {
+		return false
+	}
+	return prefixInList(path, *c.ProductVariables.IntegerOverflowExcludePaths)
+}
diff --git a/android/defaults.go b/android/defaults.go
index 0776405..84f0a3d 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -113,6 +113,11 @@
 	}
 }
 
+func registerDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
+	ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
+	ctx.TopDown("defaults", defaultsMutator).Parallel()
+}
+
 func defaultsDepsMutator(ctx BottomUpMutatorContext) {
 	if defaultable, ok := ctx.Module().(Defaultable); ok {
 		ctx.AddDependency(ctx.Module(), DefaultsDepTag, defaultable.defaults().Defaults...)
diff --git a/android/module.go b/android/module.go
index 7f541be..3a3d173 100644
--- a/android/module.go
+++ b/android/module.go
@@ -111,6 +111,8 @@
 
 	AddProperties(props ...interface{})
 	GetProperties() []interface{}
+
+	BuildParamsForTests() []ModuleBuildParams
 }
 
 type nameProperties struct {
@@ -145,7 +147,7 @@
 	Proprietary bool
 
 	// vendor who owns this module
-	Owner string
+	Owner *string
 
 	// whether this module is device specific and should be installed into /vendor
 	Vendor bool
@@ -291,6 +293,9 @@
 	hooks hooks
 
 	registerProps []interface{}
+
+	// For tests
+	buildParams []ModuleBuildParams
 }
 
 func (a *ModuleBase) AddProperties(props ...interface{}) {
@@ -301,6 +306,10 @@
 	return a.registerProps
 }
 
+func (a *ModuleBase) BuildParamsForTests() []ModuleBuildParams {
+	return a.buildParams
+}
+
 // Name returns the name of the module.  It may be overridden by individual module types, for
 // example prebuilts will prepend prebuilt_ to the name.
 func (a *ModuleBase) Name() string {
@@ -520,6 +529,8 @@
 			return
 		}
 	}
+
+	a.buildParams = androidCtx.buildParams
 }
 
 type androidBaseContextImpl struct {
@@ -538,6 +549,9 @@
 	checkbuildFiles Paths
 	missingDeps     []string
 	module          Module
+
+	// For tests
+	buildParams []ModuleBuildParams
 }
 
 func (a *androidModuleContext) ninjaError(desc string, outputs []string, err error) {
@@ -566,6 +580,10 @@
 }
 
 func (a *androidModuleContext) ModuleBuild(pctx blueprint.PackageContext, params ModuleBuildParams) {
+	if a.config.captureBuild {
+		a.buildParams = append(a.buildParams, params)
+	}
+
 	bparams := blueprint.BuildParams{
 		Rule:            params.Rule,
 		Deps:            params.Deps,
diff --git a/android/mutator.go b/android/mutator.go
index bb49487..86a5b85 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -15,8 +15,6 @@
 package android
 
 import (
-	"sync"
-
 	"github.com/google/blueprint"
 )
 
@@ -27,9 +25,6 @@
 //   Deps
 //   PostDeps
 
-var registerMutatorsOnce sync.Once
-var registeredMutators []*mutator
-
 func registerMutatorsToContext(ctx *blueprint.Context, mutators []*mutator) {
 	for _, t := range mutators {
 		var handle blueprint.MutatorHandle
@@ -44,56 +39,24 @@
 	}
 }
 
-func registerMutators(ctx *blueprint.Context) {
-
-	registerMutatorsOnce.Do(func() {
-		ctx := &registerMutatorsContext{}
-
-		register := func(funcs []RegisterMutatorFunc) {
-			for _, f := range funcs {
-				f(ctx)
-			}
-		}
-
-		ctx.TopDown("load_hooks", loadHookMutator).Parallel()
-		ctx.BottomUp("prebuilts", prebuiltMutator).Parallel()
-		ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
-		ctx.TopDown("defaults", defaultsMutator).Parallel()
-
-		register(preArch)
-
-		ctx.BottomUp("arch", archMutator).Parallel()
-		ctx.TopDown("arch_hooks", archHookMutator).Parallel()
-
-		register(preDeps)
-
-		ctx.BottomUp("deps", depsMutator).Parallel()
-
-		ctx.TopDown("prebuilt_select", PrebuiltSelectModuleMutator).Parallel()
-		ctx.BottomUp("prebuilt_replace", PrebuiltReplaceMutator).Parallel()
-
-		register(postDeps)
-
-		registeredMutators = ctx.mutators
-	})
-
-	registerMutatorsToContext(ctx, registeredMutators)
-}
-
-func RegisterTestMutators(ctx *blueprint.Context) {
-	mutators := &registerMutatorsContext{}
+func registerMutators(ctx *blueprint.Context, preArch, preDeps, postDeps []RegisterMutatorFunc) {
+	mctx := &registerMutatorsContext{}
 
 	register := func(funcs []RegisterMutatorFunc) {
 		for _, f := range funcs {
-			f(mutators)
+			f(mctx)
 		}
 	}
 
-	register(testPreDeps)
-	mutators.BottomUp("deps", depsMutator).Parallel()
-	register(testPostDeps)
+	register(preArch)
 
-	registerMutatorsToContext(ctx, mutators.mutators)
+	register(preDeps)
+
+	mctx.BottomUp("deps", depsMutator).Parallel()
+
+	register(postDeps)
+
+	registerMutatorsToContext(ctx, mctx.mutators)
 }
 
 type registerMutatorsContext struct {
@@ -107,7 +70,24 @@
 
 type RegisterMutatorFunc func(RegisterMutatorsContext)
 
-var preArch, preDeps, postDeps, testPreDeps, testPostDeps []RegisterMutatorFunc
+var preArch = []RegisterMutatorFunc{
+	func(ctx RegisterMutatorsContext) {
+		ctx.TopDown("load_hooks", loadHookMutator).Parallel()
+	},
+	registerPrebuiltsPreArchMutators,
+	registerDefaultsPreArchMutators,
+}
+
+var preDeps = []RegisterMutatorFunc{
+	func(ctx RegisterMutatorsContext) {
+		ctx.BottomUp("arch", archMutator).Parallel()
+		ctx.TopDown("arch_hooks", archHookMutator).Parallel()
+	},
+}
+
+var postDeps = []RegisterMutatorFunc{
+	registerPrebuiltsPostDepsMutators,
+}
 
 func PreArchMutators(f RegisterMutatorFunc) {
 	preArch = append(preArch, f)
@@ -121,14 +101,6 @@
 	postDeps = append(postDeps, f)
 }
 
-func TestPreDepsMutators(f RegisterMutatorFunc) {
-	testPreDeps = append(testPreDeps, f)
-}
-
-func TeststPostDepsMutators(f RegisterMutatorFunc) {
-	testPostDeps = append(testPostDeps, f)
-}
-
 type AndroidTopDownMutator func(TopDownMutatorContext)
 
 type TopDownMutatorContext interface {
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 772df7a..080df91 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -61,6 +61,15 @@
 	Prebuilt() *Prebuilt
 }
 
+func registerPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) {
+	ctx.BottomUp("prebuilts", prebuiltMutator).Parallel()
+}
+
+func registerPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
+	ctx.TopDown("prebuilt_select", PrebuiltSelectModuleMutator).Parallel()
+	ctx.BottomUp("prebuilt_replace", PrebuiltReplaceMutator).Parallel()
+}
+
 // 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) {
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index 5fa2032..fe763ed 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -122,9 +122,12 @@
 
 	for _, test := range prebuiltsTests {
 		t.Run(test.name, func(t *testing.T) {
-			ctx := NewContext()
+			ctx := NewTestContext()
+			ctx.PreArchMutators(registerPrebuiltsPreArchMutators)
+			ctx.PostDepsMutators(registerPrebuiltsPostDepsMutators)
 			ctx.RegisterModuleType("prebuilt", ModuleFactoryAdaptor(newPrebuiltModule))
 			ctx.RegisterModuleType("source", ModuleFactoryAdaptor(newSourceModule))
+			ctx.Register()
 			ctx.MockFileSystem(map[string][]byte{
 				"Blueprints": []byte(`
 					source {
@@ -139,13 +142,10 @@
 			_, errs = ctx.PrepareBuildActions(config)
 			fail(t, errs)
 
-			foo := findModule(ctx, "foo")
-			if foo == nil {
-				t.Fatalf("failed to find module foo")
-			}
+			foo := ctx.ModuleForTests("foo", "")
 
 			var dependsOnSourceModule, dependsOnPrebuiltModule bool
-			ctx.VisitDirectDeps(foo, func(m blueprint.Module) {
+			ctx.VisitDirectDeps(foo.Module(), func(m blueprint.Module) {
 				if _, ok := m.(*sourceModule); ok {
 					dependsOnSourceModule = true
 				}
@@ -228,16 +228,6 @@
 func (s *sourceModule) GenerateAndroidBuildActions(ctx ModuleContext) {
 }
 
-func findModule(ctx *blueprint.Context, name string) blueprint.Module {
-	var ret blueprint.Module
-	ctx.VisitAllModules(func(m blueprint.Module) {
-		if ctx.ModuleName(m) == name {
-			ret = m
-		}
-	})
-	return ret
-}
-
 func fail(t *testing.T, errs []error) {
 	if len(errs) > 0 {
 		for _, err := range errs {
diff --git a/android/register.go b/android/register.go
index 76a1cc9..226e790 100644
--- a/android/register.go
+++ b/android/register.go
@@ -60,9 +60,15 @@
 	singletons = append(singletons, singleton{name, factory})
 }
 
-func NewContext() *blueprint.Context {
-	ctx := blueprint.NewContext()
+type Context struct {
+	*blueprint.Context
+}
 
+func NewContext() *Context {
+	return &Context{blueprint.NewContext()}
+}
+
+func (ctx *Context) Register() {
 	for _, t := range moduleTypes {
 		ctx.RegisterModuleType(t.name, t.factory)
 	}
@@ -71,9 +77,7 @@
 		ctx.RegisterSingletonType(t.name, t.factory)
 	}
 
-	registerMutators(ctx)
+	registerMutators(ctx.Context, preArch, preDeps, postDeps)
 
 	ctx.RegisterSingletonType("env", EnvSingleton)
-
-	return ctx
 }
diff --git a/android/testing.go b/android/testing.go
new file mode 100644
index 0000000..4144775
--- /dev/null
+++ b/android/testing.go
@@ -0,0 +1,98 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/google/blueprint"
+)
+
+func NewTestContext() *TestContext {
+	return &TestContext{
+		Context: blueprint.NewContext(),
+	}
+}
+
+type TestContext struct {
+	*blueprint.Context
+	preArch, preDeps, postDeps []RegisterMutatorFunc
+}
+
+func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
+	ctx.preArch = append(ctx.preArch, f)
+}
+
+func (ctx *TestContext) PreDepsMutators(f RegisterMutatorFunc) {
+	ctx.preDeps = append(ctx.preDeps, f)
+}
+
+func (ctx *TestContext) PostDepsMutators(f RegisterMutatorFunc) {
+	ctx.postDeps = append(ctx.postDeps, f)
+}
+
+func (ctx *TestContext) Register() {
+	registerMutators(ctx.Context, ctx.preArch, ctx.preDeps, ctx.postDeps)
+
+	ctx.RegisterSingletonType("env", EnvSingleton)
+}
+
+func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule {
+	var module Module
+	ctx.VisitAllModules(func(m blueprint.Module) {
+		if ctx.ModuleName(m) == name && ctx.ModuleSubDir(m) == variant {
+			module = m.(Module)
+		}
+	})
+
+	if module == nil {
+		panic(fmt.Errorf("failed to find module %q variant %q", name, variant))
+	}
+
+	return TestingModule{module}
+}
+
+type TestingModule struct {
+	module Module
+}
+
+func (m TestingModule) Module() Module {
+	return m.module
+}
+
+func (m TestingModule) Rule(rule string) ModuleBuildParams {
+	for _, p := range m.module.BuildParamsForTests() {
+		if strings.Contains(p.Rule.String(), rule) {
+			return p
+		}
+	}
+	panic(fmt.Errorf("couldn't find rule %q", rule))
+}
+
+func (m TestingModule) Output(file string) ModuleBuildParams {
+	for _, p := range m.module.BuildParamsForTests() {
+		outputs := append(WritablePaths(nil), p.Outputs...)
+		if p.Output != nil {
+			outputs = append(outputs, p.Output)
+		}
+		for _, f := range outputs {
+			if f.Base() == file {
+				return p
+			}
+		}
+	}
+	panic(fmt.Errorf("couldn't find output %q", file))
+}
diff --git a/android/util.go b/android/util.go
index 8cee256..80c7870 100644
--- a/android/util.go
+++ b/android/util.go
@@ -68,6 +68,15 @@
 	return indexList(s, list) != -1
 }
 
+func prefixInList(s string, list []string) bool {
+	for _, prefix := range list {
+		if strings.HasPrefix(s, prefix) {
+			return true
+		}
+	}
+	return false
+}
+
 // checkCalledFromInit panics if a Go package's init function is not on the
 // call stack.
 func checkCalledFromInit() {
diff --git a/android/variable.go b/android/variable.go
index 7ca7a55..8462d0d 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -140,6 +140,8 @@
 	Treble                     *bool `json:",omitempty"`
 	Pdk                        *bool `json:",omitempty"`
 
+	IntegerOverflowExcludePaths *[]string `json:",omitempty"`
+
 	VendorPath *string `json:",omitempty"`
 
 	ClangTidy  *bool   `json:",omitempty"`
diff --git a/build.ninja.in b/build.ninja.in
index 9449d73..27f1db0 100644
--- a/build.ninja.in
+++ b/build.ninja.in
@@ -436,7 +436,7 @@
 # Variant:
 # Type:    bootstrap_core_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
-# Defined: build/blueprint/Blueprints:130:1
+# Defined: build/blueprint/Blueprints:131:1
 
 build ${g.bootstrap.buildDir}/.bootstrap/bpglob/obj/bpglob.a: $
         g.bootstrap.compile $
@@ -464,7 +464,7 @@
 # Variant:
 # Type:    bootstrap_core_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
-# Defined: build/blueprint/Blueprints:148:1
+# Defined: build/blueprint/Blueprints:149:1
 
 build ${g.bootstrap.buildDir}/.bootstrap/gotestmain/obj/gotestmain.a: $
         g.bootstrap.compile $
@@ -484,11 +484,68 @@
 default ${g.bootstrap.BinDir}/gotestmain
 
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# Module:  gotestmain-tests
+# Variant:
+# Type:    bootstrap_go_package
+# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
+# Defined: build/blueprint/Blueprints:156:1
+
+build $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/github.com/google/blueprint/gotestmain.a $
+        : g.bootstrap.compile $
+        ${g.bootstrap.srcDir}/build/blueprint/gotestmain/dummy.go $
+        ${g.bootstrap.srcDir}/build/blueprint/gotestmain/testmain_test.go | $
+        ${g.bootstrap.compileCmd}
+    pkgPath = github.com/google/blueprint/gotestmain
+default $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/github.com/google/blueprint/gotestmain.a
+
+build ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/test.go: $
+        g.bootstrap.gotestmain $
+        ${g.bootstrap.srcDir}/build/blueprint/gotestmain/testmain_test.go | $
+        ${g.bootstrap.goTestMainCmd}
+    pkg = github.com/google/blueprint/gotestmain
+default ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/test.go
+
+build ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/test.a: $
+        g.bootstrap.compile $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/test.go | $
+        ${g.bootstrap.compileCmd} $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/github.com/google/blueprint/gotestmain.a
+    incFlags = -I ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test
+    pkgPath = main
+default ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/test.a
+
+build ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/test: $
+        g.bootstrap.link $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/test.a | $
+        ${g.bootstrap.linkCmd}
+    libDirFlags = -L ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test
+default ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/test
+
+build ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/test.passed: $
+        g.bootstrap.test $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/test | $
+        ${g.bootstrap.goTestRunnerCmd}
+    pkg = github.com/google/blueprint/gotestmain
+    pkgSrcDir = ${g.bootstrap.srcDir}/build/blueprint/gotestmain
+default ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/test.passed
+
+build $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg/github.com/google/blueprint/gotestmain.a $
+        : g.bootstrap.compile $
+        ${g.bootstrap.srcDir}/build/blueprint/gotestmain/dummy.go | $
+        ${g.bootstrap.compileCmd}
+    pkgPath = github.com/google/blueprint/gotestmain
+default $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg/github.com/google/blueprint/gotestmain.a
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 # Module:  gotestrunner
 # Variant:
 # Type:    bootstrap_core_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
-# Defined: build/blueprint/Blueprints:153:1
+# Defined: build/blueprint/Blueprints:167:1
 
 build ${g.bootstrap.buildDir}/.bootstrap/gotestrunner/obj/gotestrunner.a: $
         g.bootstrap.compile $
@@ -524,15 +581,16 @@
         ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg/github.com/google/blueprint/proptools.a $
         ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg/github.com/google/blueprint.a $
         ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg/github.com/google/blueprint/bootstrap/bpdoc.a $
-        ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a
-    incFlags = -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg
+        ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg/github.com/google/blueprint/gotestmain.a
+    incFlags = -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg -I ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg
     pkgPath = minibp
 default ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/minibp.a
 
 build ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/a.out: g.bootstrap.link $
         ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/minibp.a | $
         ${g.bootstrap.linkCmd}
-    libDirFlags = -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg
+    libDirFlags = -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg -L ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg
 default ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/a.out
 
 build ${g.bootstrap.BinDir}/minibp: g.bootstrap.cp $
@@ -540,7 +598,8 @@
         ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/test/test.passed $
         ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/test/test.passed $
         ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/test/test.passed $
-        ${g.bootstrap.buildDir}/.bootstrap/blueprint/test/test.passed
+        ${g.bootstrap.buildDir}/.bootstrap/blueprint/test/test.passed $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/test.passed
 default ${g.bootstrap.BinDir}/minibp
 
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
@@ -556,7 +615,7 @@
 build ${g.bootstrap.buildDir}/.minibootstrap/build.ninja.in: $
         g.bootstrap.build.ninja ${g.bootstrap.srcDir}/Android.bp | ${builder}
     builder = ${g.bootstrap.BinDir}/minibp
-    extra =  -t
+    extra = $ -t
 default ${g.bootstrap.buildDir}/.minibootstrap/build.ninja.in
 
 build ${g.bootstrap.buildDir}/.minibootstrap/build.ninja: $
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 2a3b344..a92a95c 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -88,6 +88,25 @@
 	return ret, nil
 }
 
+func androidMkWriteTestData(data android.Paths, ctx AndroidMkContext, ret *android.AndroidMkData) {
+	var testFiles []string
+	for _, d := range data {
+		rel := d.Rel()
+		path := d.String()
+		if !strings.HasSuffix(path, rel) {
+			panic(fmt.Errorf("path %q does not end with %q", path, rel))
+		}
+		path = strings.TrimSuffix(path, rel)
+		testFiles = append(testFiles, path+":"+rel)
+	}
+	if len(testFiles) > 0 {
+		ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) error {
+			fmt.Fprintln(w, "LOCAL_TEST_DATA := "+strings.Join(testFiles, " "))
+			return nil
+		})
+	}
+}
+
 func (library *libraryDecorator) androidMkWriteExportedFlags(w io.Writer) {
 	exportedFlags := library.exportedFlags()
 	if len(exportedFlags) > 0 {
@@ -212,6 +231,8 @@
 		}
 		return nil
 	})
+
+	androidMkWriteTestData(benchmark.data, ctx, ret)
 }
 
 func (test *testBinary) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
@@ -229,22 +250,7 @@
 		return nil
 	})
 
-	var testFiles []string
-	for _, d := range test.data {
-		rel := d.Rel()
-		path := d.String()
-		if !strings.HasSuffix(path, rel) {
-			panic(fmt.Errorf("path %q does not end with %q", path, rel))
-		}
-		path = strings.TrimSuffix(path, rel)
-		testFiles = append(testFiles, path+":"+rel)
-	}
-	if len(testFiles) > 0 {
-		ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) error {
-			fmt.Fprintln(w, "LOCAL_TEST_DATA := "+strings.Join(testFiles, " "))
-			return nil
-		})
-	}
+	androidMkWriteTestData(test.data, ctx, ret)
 }
 
 func (test *testLibrary) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
diff --git a/cc/cc.go b/cc/cc.go
index c17b95e..8fc0ebd 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -183,6 +183,8 @@
 	sdk() bool
 	sdkVersion() string
 	vndk() bool
+	isVndk() bool
+	isVndkSp() bool
 	createVndkSourceAbiDump() bool
 	selectedStl() string
 	baseModuleName() string
@@ -291,6 +293,7 @@
 	sanitize  *sanitize
 	coverage  *coverage
 	sabi      *sabi
+	vndkdep   *vndkdep
 
 	androidMkSharedLibDeps []string
 
@@ -327,6 +330,9 @@
 	if c.sabi != nil {
 		c.AddProperties(c.sabi.props()...)
 	}
+	if c.vndkdep != nil {
+		c.AddProperties(c.vndkdep.props()...)
+	}
 	for _, feature := range c.features {
 		c.AddProperties(feature.props()...)
 	}
@@ -353,6 +359,13 @@
 	return c.Properties.UseVndk
 }
 
+func (c *Module) isVndk() bool {
+	if c.vndkdep != nil {
+		return c.vndkdep.isVndk()
+	}
+	return false
+}
+
 type baseModuleContext struct {
 	android.BaseContext
 	moduleContextImpl
@@ -368,10 +381,10 @@
 	moduleContextImpl
 }
 
-// Vendor returns true for vendor modules so that they get installed onto the
-// correct partition
+// Vendor returns true for vendor modules excluding VNDK libraries so that
+// they get installed onto the correct partition
 func (ctx *moduleContext) Vendor() bool {
-	return ctx.ModuleContext.Vendor() || ctx.moduleContextImpl.mod.Properties.UseVndk
+	return ctx.ModuleContext.Vendor() || (ctx.mod.vndk() && !ctx.mod.isVndk())
 }
 
 type moduleContextImpl struct {
@@ -431,9 +444,20 @@
 	return ctx.mod.vndk()
 }
 
+func (ctx *moduleContextImpl) isVndk() bool {
+	return ctx.mod.isVndk()
+}
+
+func (ctx *moduleContextImpl) isVndkSp() bool {
+	if vndk := ctx.mod.vndkdep; vndk != nil {
+		return vndk.isVndkSp()
+	}
+	return false
+}
+
 // Create source abi dumps if the module belongs to the list of VndkLibraries.
 func (ctx *moduleContextImpl) createVndkSourceAbiDump() bool {
-	return ctx.ctx.Device() && ((Bool(ctx.mod.Properties.Vendor_available)) || (inList(ctx.baseModuleName(), config.LLndkLibraries())))
+	return ctx.ctx.Device() && (ctx.mod.isVndk() || inList(ctx.baseModuleName(), config.LLndkLibraries()))
 }
 
 func (ctx *moduleContextImpl) selectedStl() string {
@@ -463,6 +487,7 @@
 	module.sanitize = &sanitize{}
 	module.coverage = &coverage{}
 	module.sabi = &sabi{}
+	module.vndkdep = &vndkdep{}
 	return module
 }
 
@@ -591,6 +616,9 @@
 	if c.sabi != nil {
 		c.sabi.begin(ctx)
 	}
+	if c.vndkdep != nil {
+		c.vndkdep.begin(ctx)
+	}
 	for _, feature := range c.features {
 		feature.begin(ctx)
 	}
@@ -624,6 +652,9 @@
 	if c.sabi != nil {
 		deps = c.sabi.deps(ctx, deps)
 	}
+	if c.vndkdep != nil {
+		deps = c.vndkdep.deps(ctx, deps)
+	}
 	for _, feature := range c.features {
 		deps = feature.deps(ctx, deps)
 	}
@@ -828,7 +859,12 @@
 			return
 		}
 		if from.Properties.UseVndk {
-			// Vendor code is already limited by the vendor mutator
+			// Though vendor code is limited by the vendor mutator,
+			// each vendor-available module needs to check
+			// link-type for VNDK.
+			if from.vndkdep != nil {
+				from.vndkdep.vndkCheckLinkType(ctx, to)
+			}
 			return
 		}
 		if from.Properties.Sdk_version == "" {
@@ -1169,6 +1205,18 @@
 			"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.Properties.Vendor_available) {
+			mctx.PropertyErrorf("vndk",
+				"has to define `vendor_available: true` to enable vndk")
+			return
+		}
+		if !vndk.isVndk() && vndk.isVndkSp() {
+			mctx.PropertyErrorf("vndk",
+				"must set `enabled: true` to set `support_system_process: true`")
+			return
+		}
+	}
 
 	if !mctx.DeviceConfig().CompileVndk() {
 		// If the device isn't compiling against the VNDK, we always
@@ -1180,6 +1228,7 @@
 		mctx.CreateVariations(vendorMode)
 	} else if Bool(m.Properties.Vendor_available) {
 		// This will be available in both /system and /vendor
+		// or a /system directory that is available to vendor.
 		mod := mctx.CreateVariations(coreMode, vendorMode)
 		mod[1].(*Module).Properties.UseVndk = true
 	} else if mctx.Vendor() && m.Properties.Sdk_version == "" {
diff --git a/cc/config/global.go b/cc/config/global.go
index 4ae22c9..f4a1230 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -124,7 +124,7 @@
 	// This is used by non-NDK modules to get jni.h. export_include_dirs doesn't help
 	// with this, since there is no associated library.
 	pctx.PrefixedExistentPathsForSourcesVariable("CommonNativehelperInclude", "-I",
-		[]string{"libnativehelper/include/nativehelper"})
+		[]string{"libnativehelper/include_deprecated"})
 
 	pctx.SourcePathVariable("ClangDefaultBase", ClangDefaultBase)
 	pctx.VariableFunc("ClangBase", func(config interface{}) (string, error) {
diff --git a/cc/installer.go b/cc/installer.go
index 112a7ea..7bedc56 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -48,6 +48,7 @@
 
 	dir      string
 	dir64    string
+	subDir   string
 	relative string
 	location installLocation
 
@@ -61,17 +62,17 @@
 }
 
 func (installer *baseInstaller) installDir(ctx ModuleContext) android.OutputPath {
-	subDir := installer.dir
+	dir := installer.dir
 	if ctx.toolchain().Is64Bit() && installer.dir64 != "" {
-		subDir = installer.dir64
+		dir = installer.dir64
 	}
 	if !ctx.Host() && !ctx.Arch().Native {
-		subDir = filepath.Join(subDir, ctx.Arch().ArchType.String())
+		dir = filepath.Join(dir, ctx.Arch().ArchType.String())
 	}
 	if installer.location == InstallInData && ctx.vndk() {
-		subDir = filepath.Join(subDir, "vendor")
+		dir = filepath.Join(dir, "vendor")
 	}
-	return android.PathForModuleInstall(ctx, subDir, installer.Properties.Relative_install_path, installer.relative)
+	return android.PathForModuleInstall(ctx, dir, installer.subDir, installer.Properties.Relative_install_path, installer.relative)
 }
 
 func (installer *baseInstaller) install(ctx ModuleContext, file android.Path) {
diff --git a/cc/library.go b/cc/library.go
index c7c1142..3d463bd 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -156,7 +156,7 @@
 }
 
 func (f *flagExporter) exportedIncludes(ctx ModuleContext) android.Paths {
-	if ctx.Vendor() && f.Properties.Target.Vendor.Export_include_dirs != nil {
+	if ctx.vndk() && f.Properties.Target.Vendor.Export_include_dirs != nil {
 		return android.PathsForModuleSrc(ctx, f.Properties.Target.Vendor.Export_include_dirs)
 	} else {
 		return android.PathsForModuleSrc(ctx, f.Properties.Export_include_dirs)
@@ -351,7 +351,7 @@
 		}
 		return Objects{}
 	}
-	if (ctx.createVndkSourceAbiDump() || (library.sabi.Properties.CreateSAbiDumps && ctx.Device())) && !ctx.Vendor() {
+	if ctx.createVndkSourceAbiDump() {
 		exportIncludeDirs := android.PathsForModuleSrc(ctx, library.flagExporter.Properties.Export_include_dirs)
 		var SourceAbiFlags []string
 		for _, dir := range exportIncludeDirs.Strings() {
@@ -596,7 +596,7 @@
 
 func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objects, fileName string, soFile android.Path) {
 	//Also take into account object re-use.
-	if len(objs.sAbiDumpFiles) > 0 && ctx.createVndkSourceAbiDump() && !ctx.Vendor() {
+	if len(objs.sAbiDumpFiles) > 0 && ctx.createVndkSourceAbiDump() {
 		refSourceDumpFile := android.PathForVndkRefAbiDump(ctx, "current", fileName, vndkVsNdk(ctx), true)
 		versionScript := android.OptionalPathForModuleSrc(ctx, library.Properties.Version_script)
 		var symbolFile android.OptionalPath
@@ -699,6 +699,15 @@
 
 func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) {
 	if library.shared() {
+		if ctx.Device() {
+			if ctx.vndk() {
+				if ctx.isVndkSp() {
+					library.baseInstaller.subDir = "vndk-sp"
+				} else if ctx.isVndk() {
+					library.baseInstaller.subDir = "vndk"
+				}
+			}
+		}
 		library.baseInstaller.install(ctx, file)
 	}
 }
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 66ffc9f..c3d3462 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -61,6 +61,11 @@
 	versionScriptPath      android.ModuleGenPath
 }
 
+func (stub *llndkStubDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
+	flags = stub.baseCompiler.compilerFlags(ctx, flags)
+	return addStubLibraryCompilerFlags(flags)
+}
+
 func (stub *llndkStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
 	objs, versionScript := compileStubLibrary(ctx, flags, stub.Properties.Symbol_file, "current", "--vndk")
 	stub.versionScriptPath = versionScript
diff --git a/cc/makevars.go b/cc/makevars.go
index 11c3162..294f3e6 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -82,6 +82,16 @@
 
 	ctx.Strict("RS_GLOBAL_INCLUDES", "${config.RsGlobalIncludes}")
 
+	nativeHelperIncludeFlags, err := ctx.Eval("${config.CommonNativehelperInclude}")
+	if err != nil {
+		panic(err)
+	}
+	nativeHelperIncludes, nativeHelperSystemIncludes := splitSystemIncludes(ctx, nativeHelperIncludeFlags)
+	if len(nativeHelperSystemIncludes) > 0 {
+		panic("native helper may not have any system includes")
+	}
+	ctx.Strict("JNI_H_INCLUDE", strings.Join(nativeHelperIncludes, " "))
+
 	includeFlags, err := ctx.Eval("${config.CommonGlobalIncludes}")
 	if err != nil {
 		panic(err)
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 5765aa9..dbfc5be 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -242,6 +242,25 @@
 	ndkMigratedLibs = append(ndkMigratedLibs, name)
 }
 
+func addStubLibraryCompilerFlags(flags Flags) Flags {
+	flags.CFlags = append(flags.CFlags,
+		// We're knowingly doing some otherwise unsightly things with builtin
+		// functions here. We're just generating stub libraries, so ignore it.
+		"-Wno-incompatible-library-redeclaration",
+		"-Wno-builtin-requires-header",
+		"-Wno-invalid-noreturn",
+		// These libraries aren't actually used. Don't worry about unwinding
+		// (avoids the need to link an unwinder into a fake library).
+		"-fno-unwind-tables",
+	)
+	return flags
+}
+
+func (stub *stubDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
+	flags = stub.baseCompiler.compilerFlags(ctx, flags)
+	return addStubLibraryCompilerFlags(flags)
+}
+
 func compileStubLibrary(ctx ModuleContext, flags Flags, symbolFile, apiLevel, vndk string) (Objects, android.ModuleGenPath) {
 	arch := ctx.Arch().ArchType.String()
 
@@ -263,18 +282,6 @@
 		},
 	})
 
-	flags.CFlags = append(flags.CFlags,
-		// We're knowingly doing some otherwise unsightly things with builtin
-		// functions here. We're just generating stub libraries, so ignore it.
-		"-Wno-incompatible-library-redeclaration",
-		"-Wno-builtin-requires-header",
-		"-Wno-invalid-noreturn",
-
-		// These libraries aren't actually used. Don't worry about unwinding
-		// (avoids the need to link an unwinder into a fake library).
-		"-fno-unwind-tables",
-	)
-
 	subdir := ""
 	srcs := []android.Path{stubSrcPath}
 	return compileObjs(ctx, flagsToBuilderFlags(flags), subdir, srcs, nil), versionScriptPath
diff --git a/cc/sabi.go b/cc/sabi.go
index 9aff738..318d198 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -72,7 +72,7 @@
 
 func sabiDepsMutator(mctx android.TopDownMutatorContext) {
 	if c, ok := mctx.Module().(*Module); ok &&
-		(Bool(c.Properties.Vendor_available) || (inList(c.Name(), config.LLndkLibraries())) ||
+		(c.isVndk() || inList(c.Name(), config.LLndkLibraries()) ||
 			(c.sabi != nil && c.sabi.Properties.CreateSAbiDumps)) {
 		mctx.VisitDirectDeps(func(m blueprint.Module) {
 			tag := mctx.OtherModuleDependencyTag(m)
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 49bd0f3..eccd255 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -188,7 +188,9 @@
 		}
 
 		if found, globalSanitizers = removeFromList("integer_overflow", globalSanitizers); found && s.Integer_overflow == nil {
-			s.Integer_overflow = boolPtr(true)
+			if !ctx.AConfig().IntegerOverflowDisabledForPath(ctx.ModuleDir()) {
+				s.Integer_overflow = boolPtr(true)
+			}
 		}
 
 		if len(globalSanitizers) > 0 {
diff --git a/cc/test.go b/cc/test.go
index ea05ba5..a52e94a 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -298,6 +298,10 @@
 }
 
 type BenchmarkProperties struct {
+	// list of files or filegroup modules that provide data that should be installed alongside
+	// the test
+	Data []string
+
 	// list of compatibility suites (for example "cts", "vts") that the module should be
 	// installed into.
 	Test_suites []string
@@ -306,6 +310,7 @@
 type benchmarkDecorator struct {
 	*binaryDecorator
 	Properties BenchmarkProperties
+	data       android.Paths
 }
 
 func (benchmark *benchmarkDecorator) linkerInit(ctx BaseModuleContext) {
@@ -324,12 +329,14 @@
 }
 
 func (benchmark *benchmarkDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
+	android.ExtractSourcesDeps(ctx, benchmark.Properties.Data)
 	deps = benchmark.binaryDecorator.linkerDeps(ctx, deps)
 	deps.StaticLibs = append(deps.StaticLibs, "libgoogle-benchmark")
 	return deps
 }
 
 func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Path) {
+	benchmark.data = ctx.ExpandSources(benchmark.Properties.Data, nil)
 	benchmark.binaryDecorator.baseInstaller.dir = filepath.Join("nativetest", ctx.ModuleName())
 	benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("nativetest64", ctx.ModuleName())
 	benchmark.binaryDecorator.baseInstaller.install(ctx, file)
diff --git a/cc/test_data_test.go b/cc/test_data_test.go
index a798919..962bde5 100644
--- a/cc/test_data_test.go
+++ b/cc/test_data_test.go
@@ -23,8 +23,6 @@
 
 	"android/soong/android"
 	"android/soong/genrule"
-
-	"github.com/google/blueprint"
 )
 
 type dataFile struct {
@@ -123,8 +121,7 @@
 
 	for _, test := range testDataTests {
 		t.Run(test.name, func(t *testing.T) {
-			ctx := blueprint.NewContext()
-			android.RegisterTestMutators(ctx)
+			ctx := android.NewTestContext()
 			ctx.MockFileSystem(map[string][]byte{
 				"Blueprints":     []byte(`subdirs = ["dir"]`),
 				"dir/Blueprints": []byte(test.modules),
@@ -135,18 +132,16 @@
 				android.ModuleFactoryAdaptor(genrule.FileGroupFactory))
 			ctx.RegisterModuleType("test",
 				android.ModuleFactoryAdaptor(newTest))
+			ctx.Register()
 
 			_, errs := ctx.ParseBlueprintsFiles("Blueprints")
 			fail(t, errs)
 			_, errs = ctx.PrepareBuildActions(config)
 			fail(t, errs)
 
-			foo := findModule(ctx, "foo")
-			if foo == nil {
-				t.Fatalf("failed to find module foo")
-			}
+			foo := ctx.ModuleForTests("foo", "")
 
-			got := foo.(*testDataTest).data
+			got := foo.Module().(*testDataTest).data
 			if len(got) != len(test.data) {
 				t.Errorf("expected %d data files, got %d",
 					len(test.data), len(got))
@@ -192,16 +187,6 @@
 	test.data = ctx.ExpandSources(test.Properties.Data, nil)
 }
 
-func findModule(ctx *blueprint.Context, name string) blueprint.Module {
-	var ret blueprint.Module
-	ctx.VisitAllModules(func(m blueprint.Module) {
-		if ctx.ModuleName(m) == name {
-			ret = m
-		}
-	})
-	return ret
-}
-
 func fail(t *testing.T, errs []error) {
 	if len(errs) > 0 {
 		for _, err := range errs {
diff --git a/cc/vndk.go b/cc/vndk.go
new file mode 100644
index 0000000..fd1bdcb
--- /dev/null
+++ b/cc/vndk.go
@@ -0,0 +1,98 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cc
+
+import (
+	"android/soong/android"
+)
+
+type VndkProperties struct {
+	Vndk struct {
+		// 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.
+		Enabled *bool
+
+		// declared as a VNDK-SP module, which is a subset of VNDK.
+		//
+		// `vndk: { enabled: true }` must set together.
+		//
+		// All these modules are allowed to link to VNDK-SP or LL-NDK
+		// modules only. Other dependency will cause link-type errors.
+		//
+		// If `support_system_process` is not set or set to false,
+		// the module is VNDK-core and can link to other VNDK-core,
+		// VNDK-SP or LL-NDK modules only.
+		Support_system_process *bool
+	}
+}
+
+type vndkdep struct {
+	Properties VndkProperties
+}
+
+func (vndk *vndkdep) props() []interface{} {
+	return []interface{}{&vndk.Properties}
+}
+
+func (vndk *vndkdep) begin(ctx BaseModuleContext) {}
+
+func (vndk *vndkdep) deps(ctx BaseModuleContext, deps Deps) Deps {
+	return deps
+}
+
+func (vndk *vndkdep) isVndk() bool {
+	return Bool(vndk.Properties.Vndk.Enabled)
+}
+
+func (vndk *vndkdep) isVndkSp() bool {
+	return Bool(vndk.Properties.Vndk.Support_system_process)
+}
+
+func (vndk *vndkdep) typeName() string {
+	if !vndk.isVndk() {
+		return "native:vendor"
+	}
+	if !vndk.isVndkSp() {
+		return "native:vendor:vndk"
+	}
+	return "native:vendor:vndksp"
+}
+
+func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module) {
+	if to.linker == nil {
+		return
+	}
+	if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() {
+		// Check only shared libraries.
+		// Other (static and LL-NDK) libraries are allowed to link.
+		return
+	}
+	if !to.Properties.UseVndk {
+		ctx.ModuleErrorf("(%s) should not link to %q which is not a vendor-available library",
+			vndk.typeName(), to.Name())
+		return
+	}
+	if to.vndkdep == nil {
+		return
+	}
+	if (vndk.isVndk() && !to.vndkdep.isVndk()) || (vndk.isVndkSp() && !to.vndkdep.isVndkSp()) {
+		ctx.ModuleErrorf("(%s) should not link to %q(%s)",
+			vndk.typeName(), to.Name(), to.vndkdep.typeName())
+		return
+	}
+}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index ed8f2fd..e15a6bd 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -32,6 +32,7 @@
 	srcDir := filepath.Dir(flag.Arg(0))
 
 	ctx := android.NewContext()
+	ctx.Register()
 
 	configuration, err := android.NewConfig(srcDir, bootstrap.BuildDir)
 	if err != nil {
@@ -44,5 +45,5 @@
 
 	ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
 
-	bootstrap.Main(ctx, configuration, configuration.ConfigFileName, configuration.ProductVariablesFileName)
+	bootstrap.Main(ctx.Context, configuration, configuration.ConfigFileName, configuration.ProductVariablesFileName)
 }
diff --git a/java/builder.go b/java/builder.go
index 041c303..ed9d82c 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -40,7 +40,7 @@
 	javac = pctx.AndroidGomaStaticRule("javac",
 		blueprint.RuleParams{
 			Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
-				`${config.JavacWrapper}$javacCmd ` +
+				`${JavacWrapper}$javacCmd ` +
 				`-encoding UTF-8 $javacFlags $bootClasspath $classpath ` +
 				`-extdirs "" -d $outDir @$out.rsp || ( rm -rf "$outDir"; exit 41 ) && ` +
 				`find $outDir -name "*.class" > $out`,
diff --git a/java/java.go b/java/java.go
index 3cc552f..adb3d7b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -203,7 +203,9 @@
 	flags = append(flags, android.JoinWithPrefix(j.exportAidlIncludeDirs.Strings(), "-I"))
 	flags = append(flags, android.JoinWithPrefix(localAidlIncludes.Strings(), "-I"))
 	flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String())
-	flags = append(flags, "-I"+android.PathForModuleSrc(ctx, "src").String())
+	if src := android.ExistentPathForSource(ctx, "", "src"); src.Valid() {
+		flags = append(flags, "-I"+src.String())
+	}
 
 	return flags
 }
diff --git a/python/python_test.go b/python/python_test.go
index 57aaa34..4c30d95 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -26,8 +26,6 @@
 	"testing"
 
 	"android/soong/android"
-
-	"github.com/google/blueprint"
 )
 
 type pyBinary struct {
@@ -306,17 +304,17 @@
 func TestPythonModule(t *testing.T) {
 	config, buildDir := setupBuildEnv(t)
 	defer tearDownBuildEnv(buildDir)
-	android.TestPreDepsMutators(func(ctx android.RegisterMutatorsContext) {
-		ctx.BottomUp("version_split", versionSplitMutator()).Parallel()
-	})
 	for _, d := range data {
 		t.Run(d.desc, func(t *testing.T) {
-			ctx := blueprint.NewContext()
-			android.RegisterTestMutators(ctx)
+			ctx := android.NewTestContext()
+			ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+				ctx.BottomUp("version_split", versionSplitMutator()).Parallel()
+			})
 			ctx.RegisterModuleType("python_library_host",
 				android.ModuleFactoryAdaptor(PythonLibraryHostFactory))
 			ctx.RegisterModuleType("python_binary_host",
 				android.ModuleFactoryAdaptor(PythonBinaryHostFactory))
+			ctx.Register()
 			ctx.MockFileSystem(d.mockFiles)
 			_, testErrs := ctx.ParseBlueprintsFiles(bpFile)
 			fail(t, testErrs)
@@ -360,15 +358,12 @@
 	return
 }
 
-func expectModule(t *testing.T, ctx *blueprint.Context, buildDir, name, variant string,
+func expectModule(t *testing.T, ctx *android.TestContext, buildDir, name, variant string,
 	expPyRunfiles, expDepsPyRunfiles []string,
 	expParSpec string, expDepsParSpecs []string) (testErrs []error) {
-	module := findModule(ctx, name, variant)
-	if module == nil {
-		t.Fatalf("failed to find module %s!", name)
-	}
+	module := ctx.ModuleForTests(name, variant)
 
-	base, baseOk := module.(*pythonBaseModule)
+	base, baseOk := module.Module().(*pythonBaseModule)
 	if !baseOk {
 		t.Fatalf("%s is not Python module!", name)
 	}
@@ -438,16 +433,6 @@
 	os.RemoveAll(buildDir)
 }
 
-func findModule(ctx *blueprint.Context, name, variant string) blueprint.Module {
-	var ret blueprint.Module
-	ctx.VisitAllModules(func(m blueprint.Module) {
-		if ctx.ModuleName(m) == name && ctx.ModuleSubDir(m) == variant {
-			ret = m
-		}
-	})
-	return ret
-}
-
 func fail(t *testing.T, errs []error) {
 	if len(errs) > 0 {
 		for _, err := range errs {