Merge "Switch instruction_set to *string"
diff --git a/Android.bp b/Android.bp
index 1f6ebe2..3badfcd 100644
--- a/Android.bp
+++ b/Android.bp
@@ -67,6 +67,7 @@
         "android/expand_test.go",
         "android/paths_test.go",
         "android/prebuilt_test.go",
+        "android/util_test.go",
         "android/variable_test.go",
     ],
 }
diff --git a/android/defaults.go b/android/defaults.go
index 4bf872e..c704529 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -131,7 +131,7 @@
 func defaultsMutator(ctx TopDownMutatorContext) {
 	if defaultable, ok := ctx.Module().(Defaultable); ok && len(defaultable.defaults().Defaults) > 0 {
 		var defaultsList []Defaults
-		ctx.WalkDeps(func(module, parent blueprint.Module) bool {
+		ctx.WalkDeps(func(module, parent Module) bool {
 			if ctx.OtherModuleDependencyTag(module) == DefaultsDepTag {
 				if defaults, ok := module.(Defaults); ok {
 					defaultsList = append(defaultsList, defaults)
diff --git a/android/module.go b/android/module.go
index 9afc8a7..1cdc2dd 100644
--- a/android/module.go
+++ b/android/module.go
@@ -32,7 +32,7 @@
 	HostExecutable      = "host_executable"
 )
 
-type ModuleBuildParams struct {
+type BuildParams struct {
 	Rule            blueprint.Rule
 	Deps            blueprint.Deps
 	Depfile         WritablePath
@@ -50,6 +50,8 @@
 	Args            map[string]string
 }
 
+type ModuleBuildParams BuildParams
+
 type androidBaseContext interface {
 	Target() Target
 	TargetPrimary() bool
@@ -72,11 +74,10 @@
 }
 
 type ModuleContext interface {
-	blueprint.ModuleContext
 	androidBaseContext
+	blueprint.BaseModuleContext
 
-	// Similar to Build, but takes Paths instead of []string,
-	// and performs more verification.
+	// Deprecated: use ModuleContext.Build instead.
 	ModuleBuild(pctx blueprint.PackageContext, params ModuleBuildParams)
 
 	ExpandSources(srcFiles, excludes []string) Paths
@@ -94,6 +95,36 @@
 	InstallInSanitizerDir() bool
 
 	RequiredModuleNames() []string
+
+	// android.ModuleContext methods
+	// These are duplicated instead of embedded so that can eventually be wrapped to take an
+	// android.Module instead of a blueprint.Module
+	OtherModuleName(m blueprint.Module) string
+	OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
+	OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
+
+	GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
+	GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
+
+	ModuleSubDir() string
+
+	VisitDirectDeps(visit func(Module))
+	VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
+	VisitDepsDepthFirst(visit func(Module))
+	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
+	WalkDeps(visit func(Module, Module) bool)
+
+	Variable(pctx blueprint.PackageContext, name, value string)
+	Rule(pctx blueprint.PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
+	// Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
+	// and performs more verification.
+	Build(pctx blueprint.PackageContext, params BuildParams)
+
+	PrimaryModule() blueprint.Module
+	FinalModule() blueprint.Module
+	VisitAllModuleVariants(visit func(blueprint.Module))
+
+	GetMissingDependencies() []string
 }
 
 type Module interface {
@@ -116,7 +147,7 @@
 	AddProperties(props ...interface{})
 	GetProperties() []interface{}
 
-	BuildParamsForTests() []ModuleBuildParams
+	BuildParamsForTests() []BuildParams
 }
 
 type nameProperties struct {
@@ -302,7 +333,7 @@
 	registerProps []interface{}
 
 	// For tests
-	buildParams []ModuleBuildParams
+	buildParams []BuildParams
 }
 
 func (a *ModuleBase) AddProperties(props ...interface{}) {
@@ -313,7 +344,7 @@
 	return a.registerProps
 }
 
-func (a *ModuleBase) BuildParamsForTests() []ModuleBuildParams {
+func (a *ModuleBase) BuildParamsForTests() []BuildParams {
 	return a.buildParams
 }
 
@@ -558,7 +589,7 @@
 	module          Module
 
 	// For tests
-	buildParams []ModuleBuildParams
+	buildParams []BuildParams
 }
 
 func (a *androidModuleContext) ninjaError(desc string, outputs []string, err error) {
@@ -574,19 +605,11 @@
 	return
 }
 
-func (a *androidModuleContext) Build(pctx blueprint.PackageContext, params blueprint.BuildParams) {
-	if a.missingDeps != nil {
-		a.ninjaError(params.Description, params.Outputs,
-			fmt.Errorf("module %s missing dependencies: %s\n",
-				a.ModuleName(), strings.Join(a.missingDeps, ", ")))
-		return
-	}
-
-	params.Optional = true
-	a.ModuleContext.Build(pctx, params)
+func (a *androidModuleContext) ModuleBuild(pctx blueprint.PackageContext, params ModuleBuildParams) {
+	a.Build(pctx, BuildParams(params))
 }
 
-func (a *androidModuleContext) ModuleBuild(pctx blueprint.PackageContext, params ModuleBuildParams) {
+func (a *androidModuleContext) Build(pctx blueprint.PackageContext, params BuildParams) {
 	if a.config.captureBuild {
 		a.buildParams = append(a.buildParams, params)
 	}
@@ -640,9 +663,89 @@
 func (a *androidModuleContext) AddMissingDependencies(deps []string) {
 	if deps != nil {
 		a.missingDeps = append(a.missingDeps, deps...)
+		a.missingDeps = FirstUniqueStrings(a.missingDeps)
 	}
 }
 
+func (a *androidModuleContext) validateAndroidModule(module blueprint.Module) Module {
+	aModule, _ := module.(Module)
+	if aModule == nil {
+		a.ModuleErrorf("module %q not an android module", a.OtherModuleName(aModule))
+		return nil
+	}
+
+	if !aModule.Enabled() {
+		if a.AConfig().AllowMissingDependencies() {
+			a.AddMissingDependencies([]string{a.OtherModuleName(aModule)})
+		} else {
+			a.ModuleErrorf("depends on disabled module %q", a.OtherModuleName(aModule))
+		}
+		return nil
+	}
+
+	return aModule
+}
+
+func (a *androidModuleContext) VisitDirectDeps(visit func(Module)) {
+	a.ModuleContext.VisitDirectDeps(func(module blueprint.Module) {
+		if aModule := a.validateAndroidModule(module); aModule != nil {
+			visit(aModule)
+		}
+	})
+}
+
+func (a *androidModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
+	a.ModuleContext.VisitDirectDepsIf(
+		// pred
+		func(module blueprint.Module) bool {
+			if aModule := a.validateAndroidModule(module); aModule != nil {
+				return pred(aModule)
+			} else {
+				return false
+			}
+		},
+		// visit
+		func(module blueprint.Module) {
+			visit(module.(Module))
+		})
+}
+
+func (a *androidModuleContext) VisitDepsDepthFirst(visit func(Module)) {
+	a.ModuleContext.VisitDepsDepthFirst(func(module blueprint.Module) {
+		if aModule := a.validateAndroidModule(module); aModule != nil {
+			visit(aModule)
+		}
+	})
+}
+
+func (a *androidModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
+	a.ModuleContext.VisitDepsDepthFirstIf(
+		// pred
+		func(module blueprint.Module) bool {
+			if aModule := a.validateAndroidModule(module); aModule != nil {
+				return pred(aModule)
+			} else {
+				return false
+			}
+		},
+		// visit
+		func(module blueprint.Module) {
+			visit(module.(Module))
+		})
+}
+
+func (a *androidModuleContext) WalkDeps(visit func(Module, Module) bool) {
+	a.ModuleContext.WalkDeps(func(child, parent blueprint.Module) bool {
+		childAndroidModule := a.validateAndroidModule(child)
+		parentAndroidModule := a.validateAndroidModule(parent)
+		if childAndroidModule != nil && parentAndroidModule != nil {
+			return visit(childAndroidModule, parentAndroidModule)
+		} else {
+			return false
+		}
+	})
+}
+
 func (a *androidBaseContextImpl) Target() Target {
 	return a.target
 }
@@ -754,7 +857,7 @@
 			orderOnlyDeps = deps
 		}
 
-		a.ModuleBuild(pctx, ModuleBuildParams{
+		a.Build(pctx, BuildParams{
 			Rule:        rule,
 			Description: "install " + fullInstallPath.Base(),
 			Output:      fullInstallPath,
@@ -776,7 +879,7 @@
 
 	if !a.skipInstall(fullInstallPath) {
 
-		a.ModuleBuild(pctx, ModuleBuildParams{
+		a.Build(pctx, BuildParams{
 			Rule:        Symlink,
 			Description: "install symlink " + fullInstallPath.Base(),
 			Output:      fullInstallPath,
@@ -879,6 +982,10 @@
 	for _, s := range srcFiles {
 		if m := SrcIsModule(s); m != "" {
 			module := ctx.GetDirectDepWithTag(m, SourceDepTag)
+			if module == nil {
+				// Error will have been handled by ExtractSourcesDeps
+				continue
+			}
 			if srcProducer, ok := module.(SourceFileProducer); ok {
 				expandedSrcFiles = append(expandedSrcFiles, srcProducer.Srcs()...)
 			} else {
diff --git a/android/mutator.go b/android/mutator.go
index 66a1bad..afff700 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -107,8 +107,27 @@
 type AndroidTopDownMutator func(TopDownMutatorContext)
 
 type TopDownMutatorContext interface {
-	blueprint.TopDownMutatorContext
+	blueprint.BaseModuleContext
 	androidBaseContext
+
+	OtherModuleExists(name string) bool
+	Rename(name string)
+	Module() blueprint.Module
+
+	OtherModuleName(m blueprint.Module) string
+	OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
+	OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
+
+	CreateModule(blueprint.ModuleFactory, ...interface{})
+
+	GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
+	GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
+
+	VisitDirectDeps(visit func(Module))
+	VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
+	VisitDepsDepthFirst(visit func(Module))
+	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
+	WalkDeps(visit func(Module, Module) bool)
 }
 
 type androidTopDownMutatorContext struct {
@@ -172,3 +191,63 @@
 		m.DepsMutator(ctx)
 	}
 }
+
+func (a *androidTopDownMutatorContext) VisitDirectDeps(visit func(Module)) {
+	a.TopDownMutatorContext.VisitDirectDeps(func(module blueprint.Module) {
+		if aModule, _ := module.(Module); aModule != nil {
+			visit(aModule)
+		}
+	})
+}
+
+func (a *androidTopDownMutatorContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
+	a.TopDownMutatorContext.VisitDirectDepsIf(
+		// pred
+		func(module blueprint.Module) bool {
+			if aModule, _ := module.(Module); aModule != nil {
+				return pred(aModule)
+			} else {
+				return false
+			}
+		},
+		// visit
+		func(module blueprint.Module) {
+			visit(module.(Module))
+		})
+}
+
+func (a *androidTopDownMutatorContext) VisitDepsDepthFirst(visit func(Module)) {
+	a.TopDownMutatorContext.VisitDepsDepthFirst(func(module blueprint.Module) {
+		if aModule, _ := module.(Module); aModule != nil {
+			visit(aModule)
+		}
+	})
+}
+
+func (a *androidTopDownMutatorContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
+	a.TopDownMutatorContext.VisitDepsDepthFirstIf(
+		// pred
+		func(module blueprint.Module) bool {
+			if aModule, _ := module.(Module); aModule != nil {
+				return pred(aModule)
+			} else {
+				return false
+			}
+		},
+		// visit
+		func(module blueprint.Module) {
+			visit(module.(Module))
+		})
+}
+
+func (a *androidTopDownMutatorContext) WalkDeps(visit func(Module, Module) bool) {
+	a.TopDownMutatorContext.WalkDeps(func(child, parent blueprint.Module) bool {
+		childAndroidModule, _ := child.(Module)
+		parentAndroidModule, _ := parent.(Module)
+		if childAndroidModule != nil && parentAndroidModule != nil {
+			return visit(childAndroidModule, parentAndroidModule)
+		} else {
+			return false
+		}
+	})
+}
diff --git a/android/package_ctx.go b/android/package_ctx.go
index f781dd4..8e37a83 100644
--- a/android/package_ctx.go
+++ b/android/package_ctx.go
@@ -149,6 +149,15 @@
 	})
 }
 
+func (p AndroidPackageContext) HostJavaToolPath(config interface{}, path string) (Path, error) {
+	ctx := &configErrorWrapper{p, config.(Config), []error{}}
+	pa := PathForOutput(ctx, "host", ctx.config.PrebuiltOS(), "framework", path)
+	if len(ctx.errors) > 0 {
+		return nil, ctx.errors[0]
+	}
+	return pa, nil
+}
+
 // IntermediatesPathVariable returns a Variable whose value is the intermediate
 // directory appended with the supplied path. It may only be called during a Go
 // package's initialization - either from the init() function or as part of a
diff --git a/android/paths.go b/android/paths.go
index 7443547..d6a1c66 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -286,8 +286,8 @@
 	return ret
 }
 
-// FirstUniqueElements returns all unique elements of a slice, keeping the first copy of each
-// modifies the slice contents in place, and returns a subslice of the original slice
+// FirstUniquePaths returns all unique elements of a Paths, keeping the first copy of each.  It
+// modifies the Paths slice contents in place, and returns a subslice of the original slice.
 func FirstUniquePaths(list Paths) Paths {
 	k := 0
 outer:
@@ -303,6 +303,24 @@
 	return list[:k]
 }
 
+// LastUniquePaths returns all unique elements of a Paths, keeping the last copy of each.  It
+// modifies the Paths slice contents in place, and returns a subslice of the original slice.
+func LastUniquePaths(list Paths) Paths {
+	totalSkip := 0
+	for i := len(list) - 1; i >= totalSkip; i-- {
+		skip := 0
+		for j := i - 1; j >= totalSkip; j-- {
+			if list[i] == list[j] {
+				skip++
+			} else {
+				list[j+skip] = list[j]
+			}
+		}
+		totalSkip += skip
+	}
+	return list[totalSkip:]
+}
+
 func indexPathList(s Path, list []Path) int {
 	for i, l := range list {
 		if l == s {
diff --git a/android/prebuilt.go b/android/prebuilt.go
index f61a0dd..f29f865 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -109,7 +109,7 @@
 			p.properties.UsePrebuilt = p.usePrebuilt(ctx, nil)
 		}
 	} else if s, ok := ctx.Module().(Module); ok {
-		ctx.VisitDirectDeps(func(m blueprint.Module) {
+		ctx.VisitDirectDeps(func(m Module) {
 			if ctx.OtherModuleDependencyTag(m) == prebuiltDepTag {
 				p := m.(PrebuiltInterface).Prebuilt()
 				if p.usePrebuilt(ctx, s) {
diff --git a/android/testing.go b/android/testing.go
index f5777ba..e79562d 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -86,7 +86,7 @@
 	return m.module
 }
 
-func (m TestingModule) Rule(rule string) ModuleBuildParams {
+func (m TestingModule) Rule(rule string) BuildParams {
 	for _, p := range m.module.BuildParamsForTests() {
 		if strings.Contains(p.Rule.String(), rule) {
 			return p
@@ -95,7 +95,7 @@
 	panic(fmt.Errorf("couldn't find rule %q", rule))
 }
 
-func (m TestingModule) Description(desc string) ModuleBuildParams {
+func (m TestingModule) Description(desc string) BuildParams {
 	for _, p := range m.module.BuildParamsForTests() {
 		if p.Description == desc {
 			return p
@@ -104,7 +104,7 @@
 	panic(fmt.Errorf("couldn't find description %q", desc))
 }
 
-func (m TestingModule) Output(file string) ModuleBuildParams {
+func (m TestingModule) Output(file string) BuildParams {
 	for _, p := range m.module.BuildParamsForTests() {
 		outputs := append(WritablePaths(nil), p.Outputs...)
 		if p.Output != nil {
diff --git a/android/util.go b/android/util.go
index 80c7870..4d30a74 100644
--- a/android/util.go
+++ b/android/util.go
@@ -77,6 +77,41 @@
 	return false
 }
 
+// FirstUniqueStrings returns all unique elements of a slice of strings, keeping the first copy of
+// each.  It modifies the slice contents in place, and returns a subslice of the original slice.
+func FirstUniqueStrings(list []string) []string {
+	k := 0
+outer:
+	for i := 0; i < len(list); i++ {
+		for j := 0; j < k; j++ {
+			if list[i] == list[j] {
+				continue outer
+			}
+		}
+		list[k] = list[i]
+		k++
+	}
+	return list[:k]
+}
+
+// LastUniqueStrings returns all unique elements of a slice of strings, keeping the last copy of
+// each.  It modifies the slice contents in place, and returns a subslice of the original slice.
+func LastUniqueStrings(list []string) []string {
+	totalSkip := 0
+	for i := len(list) - 1; i >= totalSkip; i-- {
+		skip := 0
+		for j := i - 1; j >= totalSkip; j-- {
+			if list[i] == list[j] {
+				skip++
+			} else {
+				list[j+skip] = list[j]
+			}
+		}
+		totalSkip += skip
+	}
+	return list[totalSkip:]
+}
+
 // checkCalledFromInit panics if a Go package's init function is not on the
 // call stack.
 func checkCalledFromInit() {
diff --git a/android/util_test.go b/android/util_test.go
new file mode 100644
index 0000000..32f92b4
--- /dev/null
+++ b/android/util_test.go
@@ -0,0 +1,120 @@
+// 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 (
+	"reflect"
+	"testing"
+)
+
+var firstUniqueStringsTestCases = []struct {
+	in  []string
+	out []string
+}{
+	{
+		in:  []string{"a"},
+		out: []string{"a"},
+	},
+	{
+		in:  []string{"a", "b"},
+		out: []string{"a", "b"},
+	},
+	{
+		in:  []string{"a", "a"},
+		out: []string{"a"},
+	},
+	{
+		in:  []string{"a", "b", "a"},
+		out: []string{"a", "b"},
+	},
+	{
+		in:  []string{"b", "a", "a"},
+		out: []string{"b", "a"},
+	},
+	{
+		in:  []string{"a", "a", "b"},
+		out: []string{"a", "b"},
+	},
+	{
+		in:  []string{"a", "b", "a", "b"},
+		out: []string{"a", "b"},
+	},
+	{
+		in:  []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"},
+		out: []string{"liblog", "libdl", "libc++", "libc", "libm"},
+	},
+}
+
+func TestFirstUniqueStrings(t *testing.T) {
+	for _, testCase := range firstUniqueStringsTestCases {
+		out := FirstUniqueStrings(testCase.in)
+		if !reflect.DeepEqual(out, testCase.out) {
+			t.Errorf("incorrect output:")
+			t.Errorf("     input: %#v", testCase.in)
+			t.Errorf("  expected: %#v", testCase.out)
+			t.Errorf("       got: %#v", out)
+		}
+	}
+}
+
+var lastUniqueStringsTestCases = []struct {
+	in  []string
+	out []string
+}{
+	{
+		in:  []string{"a"},
+		out: []string{"a"},
+	},
+	{
+		in:  []string{"a", "b"},
+		out: []string{"a", "b"},
+	},
+	{
+		in:  []string{"a", "a"},
+		out: []string{"a"},
+	},
+	{
+		in:  []string{"a", "b", "a"},
+		out: []string{"b", "a"},
+	},
+	{
+		in:  []string{"b", "a", "a"},
+		out: []string{"b", "a"},
+	},
+	{
+		in:  []string{"a", "a", "b"},
+		out: []string{"a", "b"},
+	},
+	{
+		in:  []string{"a", "b", "a", "b"},
+		out: []string{"a", "b"},
+	},
+	{
+		in:  []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"},
+		out: []string{"liblog", "libc++", "libdl", "libc", "libm"},
+	},
+}
+
+func TestLastUniqueStrings(t *testing.T) {
+	for _, testCase := range lastUniqueStringsTestCases {
+		out := LastUniqueStrings(testCase.in)
+		if !reflect.DeepEqual(out, testCase.out) {
+			t.Errorf("incorrect output:")
+			t.Errorf("     input: %#v", testCase.in)
+			t.Errorf("  expected: %#v", testCase.out)
+			t.Errorf("       got: %#v", out)
+		}
+	}
+}
diff --git a/cc/builder.go b/cc/builder.go
index 742f7fb..6882e9a 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -341,7 +341,7 @@
 
 		switch srcFile.Ext() {
 		case ".asm":
-			ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+			ctx.Build(pctx, android.BuildParams{
 				Rule:        yasm,
 				Description: "yasm " + srcFile.Rel(),
 				Output:      objFile,
@@ -353,7 +353,7 @@
 			})
 			continue
 		case ".rc":
-			ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+			ctx.Build(pctx, android.BuildParams{
 				Rule:        windres,
 				Description: "windres " + srcFile.Rel(),
 				Output:      objFile,
@@ -420,7 +420,7 @@
 			coverageFiles = append(coverageFiles, gcnoFile)
 		}
 
-		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+		ctx.Build(pctx, android.BuildParams{
 			Rule:            cc,
 			Description:     ccDesc + " " + srcFile.Rel(),
 			Output:          objFile,
@@ -437,7 +437,7 @@
 			tidyFile := android.ObjPathWithExt(ctx, subdir, srcFile, "tidy")
 			tidyFiles = append(tidyFiles, tidyFile)
 
-			ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+			ctx.Build(pctx, android.BuildParams{
 				Rule:        clangTidy,
 				Description: "clang-tidy " + srcFile.Rel(),
 				Output:      tidyFile,
@@ -456,7 +456,7 @@
 			sAbiDumpFile := android.ObjPathWithExt(ctx, subdir, srcFile, "sdump")
 			sAbiDumpFiles = append(sAbiDumpFiles, sAbiDumpFile)
 
-			ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+			ctx.Build(pctx, android.BuildParams{
 				Rule:        sAbiDump,
 				Description: "header-abi-dumper " + srcFile.Rel(),
 				Output:      sAbiDumpFile,
@@ -494,7 +494,7 @@
 		arFlags += " " + flags.arFlags
 	}
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        ar,
 		Description: "static link " + outputFile.Base(),
 		Output:      outputFile,
@@ -520,14 +520,14 @@
 		dummy := android.PathForModuleOut(ctx, "dummy"+objectExtension)
 		dummyAr := android.PathForModuleOut(ctx, "dummy"+staticLibraryExtension)
 
-		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+		ctx.Build(pctx, android.BuildParams{
 			Rule:        emptyFile,
 			Description: "empty object file",
 			Output:      dummy,
 			Implicits:   deps,
 		})
 
-		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+		ctx.Build(pctx, android.BuildParams{
 			Rule:        darwinAr,
 			Description: "empty static archive",
 			Output:      dummyAr,
@@ -537,7 +537,7 @@
 			},
 		})
 
-		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+		ctx.Build(pctx, android.BuildParams{
 			Rule:        darwinAppendAr,
 			Description: "static link " + outputFile.Base(),
 			Output:      outputFile,
@@ -565,7 +565,7 @@
 			out = android.PathForModuleOut(ctx, outputFile.Base()+strconv.Itoa(i))
 		}
 
-		build := android.ModuleBuildParams{
+		build := android.BuildParams{
 			Rule:        darwinAr,
 			Description: "static link " + out.Base(),
 			Output:      out,
@@ -579,7 +579,7 @@
 			build.Rule = darwinAppendAr
 			build.Args["inAr"] = in.String()
 		}
-		ctx.ModuleBuild(pctx, build)
+		ctx.Build(pctx, build)
 	}
 }
 
@@ -639,7 +639,7 @@
 		deps = append(deps, crtBegin.Path(), crtEnd.Path())
 	}
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        ld,
 		Description: "link " + outputFile.Base(),
 		Output:      outputFile,
@@ -669,7 +669,7 @@
 		linkedDumpDep = soFile
 		symbolFilterStr = "-so " + soFile.String()
 	}
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        sAbiLink,
 		Description: "header-abi-linker " + outputFile.Base(),
 		Output:      outputFile,
@@ -687,7 +687,7 @@
 
 func UnzipRefDump(ctx android.ModuleContext, zippedRefDump android.Path, baseName string) android.Path {
 	outputFile := android.PathForModuleOut(ctx, baseName+"_ref.lsdump")
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        unzipRefSAbiDump,
 		Description: "gunzip" + outputFile.Base(),
 		Output:      outputFile,
@@ -699,7 +699,7 @@
 func SourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
 	baseName string) android.OptionalPath {
 	outputFile := android.PathForModuleOut(ctx, baseName+".abidiff")
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        sAbiDiff,
 		Description: "header-abi-diff " + outputFile.Base(),
 		Output:      outputFile,
@@ -720,7 +720,7 @@
 
 	crossCompile := gccCmd(flags.toolchain, "")
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        toc,
 		Description: "generate toc " + inputFile.Base(),
 		Output:      outputFile,
@@ -742,7 +742,7 @@
 		ldCmd = gccCmd(flags.toolchain, "g++")
 	}
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        partialLd,
 		Description: "link " + outputFile.Base(),
 		Output:      outputFile,
@@ -760,7 +760,7 @@
 
 	objcopyCmd := gccCmd(flags.toolchain, "objcopy")
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        prefixSymbols,
 		Description: "prefix symbols " + outputFile.Base(),
 		Output:      outputFile,
@@ -787,7 +787,7 @@
 		args += " --keep-symbols"
 	}
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        strip,
 		Description: "strip " + outputFile.Base(),
 		Output:      outputFile,
@@ -802,7 +802,7 @@
 func TransformDarwinStrip(ctx android.ModuleContext, inputFile android.Path,
 	outputFile android.WritablePath) {
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        darwinStrip,
 		Description: "strip " + outputFile.Base(),
 		Output:      outputFile,
@@ -827,7 +827,7 @@
 func CopyGccLib(ctx android.ModuleContext, libName string,
 	flags builderFlags, outputFile android.WritablePath) {
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        copyGccLib,
 		Description: "copy gcc library " + libName,
 		Output:      outputFile,
diff --git a/cc/cc.go b/cc/cc.go
index 7163696..cdbe43e 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -561,7 +561,7 @@
 		orderedAllDeps = append(orderedAllDeps, transitiveDeps[dep]...)
 	}
 
-	orderedAllDeps = lastUniquePaths(orderedAllDeps)
+	orderedAllDeps = android.LastUniquePaths(orderedAllDeps)
 
 	// We don't want to add any new dependencies into directDeps (to allow the caller to
 	// intentionally exclude or replace any unwanted transitive dependencies), so we limit the
@@ -763,12 +763,12 @@
 		deps = feature.deps(ctx, deps)
 	}
 
-	deps.WholeStaticLibs = lastUniqueElements(deps.WholeStaticLibs)
-	deps.StaticLibs = lastUniqueElements(deps.StaticLibs)
-	deps.LateStaticLibs = lastUniqueElements(deps.LateStaticLibs)
-	deps.SharedLibs = lastUniqueElements(deps.SharedLibs)
-	deps.LateSharedLibs = lastUniqueElements(deps.LateSharedLibs)
-	deps.HeaderLibs = lastUniqueElements(deps.HeaderLibs)
+	deps.WholeStaticLibs = android.LastUniqueStrings(deps.WholeStaticLibs)
+	deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs)
+	deps.LateStaticLibs = android.LastUniqueStrings(deps.LateStaticLibs)
+	deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs)
+	deps.LateSharedLibs = android.LastUniqueStrings(deps.LateSharedLibs)
+	deps.HeaderLibs = android.LastUniqueStrings(deps.HeaderLibs)
 
 	for _, lib := range deps.ReexportSharedLibHeaders {
 		if !inList(lib, deps.SharedLibs) {
@@ -1037,16 +1037,10 @@
 
 	directStaticDeps := []*Module{}
 
-	ctx.VisitDirectDeps(func(dep blueprint.Module) {
+	ctx.VisitDirectDeps(func(dep android.Module) {
 		depName := ctx.OtherModuleName(dep)
 		depTag := ctx.OtherModuleDependencyTag(dep)
 
-		aDep, _ := dep.(android.Module)
-		if aDep == nil {
-			ctx.ModuleErrorf("module %q not an android module", depName)
-			return
-		}
-
 		ccDep, _ := dep.(*Module)
 		if ccDep == nil {
 			// handling for a few module types that aren't cc Module but that are also supported
@@ -1096,20 +1090,11 @@
 			return
 		}
 
-		// some validation
-		if !aDep.Enabled() {
-			if ctx.AConfig().AllowMissingDependencies() {
-				ctx.AddMissingDependencies([]string{depName})
-			} else {
-				ctx.ModuleErrorf("depends on disabled module %q", depName)
-			}
-			return
-		}
-		if aDep.Target().Os != ctx.Os() {
+		if dep.Target().Os != ctx.Os() {
 			ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
 			return
 		}
-		if aDep.Target().Arch.ArchType != ctx.Arch().ArchType {
+		if dep.Target().Arch.ArchType != ctx.Arch().ArchType {
 			ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
 			return
 		}
@@ -1249,13 +1234,13 @@
 	depPaths.StaticLibs = append(depPaths.StaticLibs, orderStaticModuleDeps(c, directStaticDeps)...)
 
 	// Dedup exported flags from dependencies
-	depPaths.Flags = firstUniqueElements(depPaths.Flags)
+	depPaths.Flags = android.FirstUniqueStrings(depPaths.Flags)
 	depPaths.GeneratedHeaders = android.FirstUniquePaths(depPaths.GeneratedHeaders)
-	depPaths.ReexportedFlags = firstUniqueElements(depPaths.ReexportedFlags)
+	depPaths.ReexportedFlags = android.FirstUniqueStrings(depPaths.ReexportedFlags)
 	depPaths.ReexportedFlagsDeps = android.FirstUniquePaths(depPaths.ReexportedFlagsDeps)
 
 	if c.sabi != nil {
-		c.sabi.Properties.ReexportedIncludeFlags = firstUniqueElements(c.sabi.Properties.ReexportedIncludeFlags)
+		c.sabi.Properties.ReexportedIncludeFlags = android.FirstUniqueStrings(c.sabi.Properties.ReexportedIncludeFlags)
 	}
 
 	return depPaths
@@ -1417,6 +1402,9 @@
 		// 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 _, ok := m.linker.(*llndkHeadersDecorator); ok {
+		// ... and LL-NDK headers as well
+		mctx.CreateVariations(vendorMode)
 	} else if m.hasVendorVariant() {
 		// This will be available in both /system and /vendor
 		// or a /system directory that is available to vendor.
@@ -1438,58 +1426,6 @@
 	}
 }
 
-// firstUniqueElements returns all unique elements of a slice, keeping the first copy of each
-// modifies the slice contents in place, and returns a subslice of the original slice
-func firstUniqueElements(list []string) []string {
-	k := 0
-outer:
-	for i := 0; i < len(list); i++ {
-		for j := 0; j < k; j++ {
-			if list[i] == list[j] {
-				continue outer
-			}
-		}
-		list[k] = list[i]
-		k++
-	}
-	return list[:k]
-}
-
-// lastUniqueElements returns all unique elements of a slice, keeping the last copy of each.
-// It modifies the slice contents in place, and returns a subslice of the original slice
-func lastUniqueElements(list []string) []string {
-	totalSkip := 0
-	for i := len(list) - 1; i >= totalSkip; i-- {
-		skip := 0
-		for j := i - 1; j >= totalSkip; j-- {
-			if list[i] == list[j] {
-				skip++
-			} else {
-				list[j+skip] = list[j]
-			}
-		}
-		totalSkip += skip
-	}
-	return list[totalSkip:]
-}
-
-// lastUniquePaths is the same as lastUniqueElements but uses Path structs
-func lastUniquePaths(list []android.Path) []android.Path {
-	totalSkip := 0
-	for i := len(list) - 1; i >= totalSkip; i-- {
-		skip := 0
-		for j := i - 1; j >= totalSkip; j-- {
-			if list[i] == list[j] {
-				skip++
-			} else {
-				list[j+skip] = list[j]
-			}
-		}
-		totalSkip += skip
-	}
-	return list[totalSkip:]
-}
-
 func getCurrentNdkPrebuiltVersion(ctx DepsContext) string {
 	if ctx.AConfig().PlatformSdkVersionInt() > config.NdkMaxPrebuiltVersionInt {
 		return strconv.Itoa(config.NdkMaxPrebuiltVersionInt)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index dc04a4e..35274f0 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -156,106 +156,6 @@
 	}
 }
 
-var firstUniqueElementsTestCases = []struct {
-	in  []string
-	out []string
-}{
-	{
-		in:  []string{"a"},
-		out: []string{"a"},
-	},
-	{
-		in:  []string{"a", "b"},
-		out: []string{"a", "b"},
-	},
-	{
-		in:  []string{"a", "a"},
-		out: []string{"a"},
-	},
-	{
-		in:  []string{"a", "b", "a"},
-		out: []string{"a", "b"},
-	},
-	{
-		in:  []string{"b", "a", "a"},
-		out: []string{"b", "a"},
-	},
-	{
-		in:  []string{"a", "a", "b"},
-		out: []string{"a", "b"},
-	},
-	{
-		in:  []string{"a", "b", "a", "b"},
-		out: []string{"a", "b"},
-	},
-	{
-		in:  []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"},
-		out: []string{"liblog", "libdl", "libc++", "libc", "libm"},
-	},
-}
-
-func TestFirstUniqueElements(t *testing.T) {
-	for _, testCase := range firstUniqueElementsTestCases {
-		out := firstUniqueElements(testCase.in)
-		if !reflect.DeepEqual(out, testCase.out) {
-			t.Errorf("incorrect output:")
-			t.Errorf("     input: %#v", testCase.in)
-			t.Errorf("  expected: %#v", testCase.out)
-			t.Errorf("       got: %#v", out)
-		}
-	}
-}
-
-var lastUniqueElementsTestCases = []struct {
-	in  []string
-	out []string
-}{
-	{
-		in:  []string{"a"},
-		out: []string{"a"},
-	},
-	{
-		in:  []string{"a", "b"},
-		out: []string{"a", "b"},
-	},
-	{
-		in:  []string{"a", "a"},
-		out: []string{"a"},
-	},
-	{
-		in:  []string{"a", "b", "a"},
-		out: []string{"b", "a"},
-	},
-	{
-		in:  []string{"b", "a", "a"},
-		out: []string{"b", "a"},
-	},
-	{
-		in:  []string{"a", "a", "b"},
-		out: []string{"a", "b"},
-	},
-	{
-		in:  []string{"a", "b", "a", "b"},
-		out: []string{"a", "b"},
-	},
-	{
-		in:  []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"},
-		out: []string{"liblog", "libc++", "libdl", "libc", "libm"},
-	},
-}
-
-func TestLastUniqueElements(t *testing.T) {
-	for _, testCase := range lastUniqueElementsTestCases {
-		out := lastUniqueElements(testCase.in)
-		if !reflect.DeepEqual(out, testCase.out) {
-			t.Errorf("incorrect output:")
-			t.Errorf("     input: %#v", testCase.in)
-			t.Errorf("  expected: %#v", testCase.out)
-			t.Errorf("       got: %#v", out)
-		}
-	}
-}
-
 var (
 	str11 = "01234567891"
 	str10 = str11[:10]
diff --git a/cc/coverage.go b/cc/coverage.go
index 0b4188f..d2eede2 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -16,8 +16,6 @@
 
 import (
 	"android/soong/android"
-
-	"github.com/google/blueprint"
 )
 
 type CoverageProperties struct {
@@ -61,7 +59,7 @@
 			// For static libraries, the only thing that changes our object files
 			// are included whole static libraries, so check to see if any of
 			// those have coverage enabled.
-			ctx.VisitDirectDeps(func(m blueprint.Module) {
+			ctx.VisitDirectDeps(func(m android.Module) {
 				if ctx.OtherModuleDependencyTag(m) != wholeStaticDepTag {
 					return
 				}
@@ -75,7 +73,7 @@
 		} else {
 			// For executables and shared libraries, we need to check all of
 			// our static dependencies.
-			ctx.VisitDirectDeps(func(m blueprint.Module) {
+			ctx.VisitDirectDeps(func(m android.Module) {
 				cc, ok := m.(*Module)
 				if !ok || cc.coverage == nil {
 					return
diff --git a/cc/gen.go b/cc/gen.go
index 2280e0f..15b37b5 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -66,7 +66,7 @@
 func genYacc(ctx android.ModuleContext, yaccFile android.Path, outFile android.ModuleGenPath, yaccFlags string) (headerFile android.ModuleGenPath) {
 	headerFile = android.GenPathWithExt(ctx, "yacc", yaccFile, "h")
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:           yacc,
 		Description:    "yacc " + yaccFile.Rel(),
 		Output:         outFile,
@@ -83,7 +83,7 @@
 
 func genAidl(ctx android.ModuleContext, aidlFile android.Path, outFile android.ModuleGenPath, aidlFlags string) android.Paths {
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        aidl,
 		Description: "aidl " + aidlFile.Rel(),
 		Output:      outFile,
@@ -99,7 +99,7 @@
 }
 
 func genLex(ctx android.ModuleContext, lexFile android.Path, outFile android.ModuleGenPath) {
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        lex,
 		Description: "lex " + lexFile.Rel(),
 		Output:      outFile,
@@ -113,7 +113,7 @@
 
 	windmcCmd := gccCmd(flags.toolchain, "windmc")
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:           windmc,
 		Description:    "windmc " + srcFile.Rel(),
 		Output:         rcFile,
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 30c4d4c..de0caa5 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -23,6 +23,7 @@
 
 var (
 	llndkLibrarySuffix = ".llndk"
+	llndkHeadersSuffix = ".llndk"
 )
 
 // Creates a stub shared library based on the provided version file.
@@ -55,6 +56,9 @@
 	// 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
+
+	// list of llndk headers to re-export include directories from.
+	Export_llndk_headers []string `android:"arch_variant"`
 }
 
 type llndkStubDecorator struct {
@@ -78,7 +82,10 @@
 }
 
 func (stub *llndkStubDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
-	return Deps{}
+	headers := addSuffix(stub.Properties.Export_llndk_headers, llndkHeadersSuffix)
+	deps.HeaderLibs = append(deps.HeaderLibs, headers...)
+	deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, headers...)
+	return deps
 }
 
 func (stub *llndkStubDecorator) Name(name string) string {
@@ -173,6 +180,35 @@
 	return module
 }
 
+type llndkHeadersDecorator struct {
+	*libraryDecorator
+}
+
+func (headers *llndkHeadersDecorator) Name(name string) string {
+	return name + llndkHeadersSuffix
+}
+
+func llndkHeadersFactory() android.Module {
+	module, library := NewLibrary(android.DeviceSupported)
+	library.HeaderOnly()
+	library.setStatic()
+
+	decorator := &llndkHeadersDecorator{
+		libraryDecorator: library,
+	}
+
+	module.compiler = nil
+	module.linker = decorator
+	module.installer = nil
+
+	module.AddProperties(&library.MutatedProperties, &library.flagExporter.Properties)
+
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
+
+	return module
+}
+
 func init() {
 	android.RegisterModuleType("llndk_library", llndkLibraryFactory)
+	android.RegisterModuleType("llndk_headers", llndkHeadersFactory)
 }
diff --git a/cc/lto.go b/cc/lto.go
index 6a5ecde..fdb7688 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -15,8 +15,6 @@
 package cc
 
 import (
-	"github.com/google/blueprint"
-
 	"android/soong/android"
 )
 
@@ -104,7 +102,7 @@
 			mctx.PropertyErrorf("LTO", "FullLTO and ThinLTO are mutually exclusive")
 		}
 
-		mctx.VisitDepsDepthFirst(func(m blueprint.Module) {
+		mctx.VisitDepsDepthFirst(func(m android.Module) {
 			tag := mctx.OtherModuleDependencyTag(m)
 			switch tag {
 			case staticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag, objDepTag, reuseObjTag:
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 140cc2f..1f8c3de 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -237,7 +237,7 @@
 	}
 
 	timestampFile := android.PathForModuleOut(ctx, "versioner.timestamp")
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:            preprocessBionicHeaders,
 		Description:     "versioner preprocess " + srcDir.Rel(),
 		Output:          timestampFile,
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index a408fc5..9d96f02 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -270,7 +270,7 @@
 	versionScriptPath := android.PathForModuleGen(ctx, "stub.map")
 	symbolFilePath := android.PathForModuleSrc(ctx, symbolFile)
 	apiLevelsJson := android.GetApiLevelsJson(ctx)
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        genStubSrc,
 		Description: "generate stubs " + symbolFilePath.Rel(),
 		Outputs:     []android.WritablePath{stubSrcPath, versionScriptPath},
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 9fca053..3f277aa 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -124,7 +124,7 @@
 		fileName := p.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
 		outputFile := android.PathForModuleOut(ctx, fileName)
 
-		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+		ctx.Build(pctx, android.BuildParams{
 			Rule:        android.CpExecutable,
 			Description: "prebuilt",
 			Output:      outputFile,
diff --git a/cc/proto.go b/cc/proto.go
index 6e3cce7..a235398 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -41,7 +41,7 @@
 	ccFile = android.GenPathWithExt(ctx, "proto", protoFile, "pb.cc")
 	headerFile = android.GenPathWithExt(ctx, "proto", protoFile, "pb.h")
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        proto,
 		Description: "protoc " + protoFile.Rel(),
 		Outputs:     android.WritablePaths{ccFile, headerFile},
diff --git a/cc/relocation_packer.go b/cc/relocation_packer.go
index d9b367c..614f15c 100644
--- a/cc/relocation_packer.go
+++ b/cc/relocation_packer.go
@@ -75,7 +75,7 @@
 }
 
 func (p *relocationPacker) pack(ctx ModuleContext, in, out android.ModuleOutPath, flags builderFlags) {
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        relocationPackerRule,
 		Description: "pack relocations",
 		Output:      out,
diff --git a/cc/rs.go b/cc/rs.go
index e7eb3bb..0e411aa 100644
--- a/cc/rs.go
+++ b/cc/rs.go
@@ -64,7 +64,7 @@
 		cppFiles[i] = rsGeneratedCppFile(ctx, rsFile)
 	}
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:            rsCpp,
 		Description:     "llvm-rs-cc",
 		Output:          stampFile,
diff --git a/cc/sabi.go b/cc/sabi.go
index 8086f5b..ec1d246 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -17,8 +17,6 @@
 import (
 	"strings"
 
-	"github.com/google/blueprint"
-
 	"android/soong/android"
 	"android/soong/cc/config"
 )
@@ -81,7 +79,7 @@
 	if c, ok := mctx.Module().(*Module); ok &&
 		((c.isVndk() && c.useVndk()) || inList(c.Name(), llndkLibraries) ||
 			(c.sabi != nil && c.sabi.Properties.CreateSAbiDumps)) {
-		mctx.VisitDirectDeps(func(m blueprint.Module) {
+		mctx.VisitDirectDeps(func(m android.Module) {
 			tag := mctx.OtherModuleDependencyTag(m)
 			switch tag {
 			case staticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag:
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 74f4bdb..d5535cb 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -19,8 +19,6 @@
 	"io"
 	"strings"
 
-	"github.com/google/blueprint"
-
 	"android/soong/android"
 	"android/soong/cc/config"
 )
@@ -493,7 +491,7 @@
 func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) {
 	return func(mctx android.TopDownMutatorContext) {
 		if c, ok := mctx.Module().(*Module); ok && c.sanitize.Sanitizer(t) {
-			mctx.VisitDepsDepthFirst(func(module blueprint.Module) {
+			mctx.VisitDepsDepthFirst(func(module android.Module) {
 				if d, ok := mctx.Module().(*Module); ok && c.sanitize != nil &&
 					!c.sanitize.Properties.Sanitize.Never {
 					d.sanitize.Properties.SanitizeDep = true
diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go
index e16c00e..207b161 100644
--- a/cmd/merge_zips/merge_zips.go
+++ b/cmd/merge_zips/merge_zips.go
@@ -78,7 +78,7 @@
 	// parse args
 	flag.Parse()
 	args := flag.Args()
-	if len(args) < 2 {
+	if len(args) < 1 {
 		flag.Usage()
 		os.Exit(1)
 	}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index e470353..03e10ba 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -157,7 +157,7 @@
 	tools := map[string]android.Path{}
 
 	if len(g.properties.Tools) > 0 {
-		ctx.VisitDirectDeps(func(module blueprint.Module) {
+		ctx.VisitDirectDeps(func(module android.Module) {
 			switch ctx.OtherModuleDependencyTag(module) {
 			case android.SourceDepTag:
 				// Nothing to do
@@ -289,7 +289,7 @@
 		desc += " " + task.out[0].Base()
 	}
 
-	params := android.ModuleBuildParams{
+	params := android.BuildParams{
 		Rule:            g.rule,
 		Description:     "generate",
 		Output:          task.out[0],
@@ -304,7 +304,7 @@
 		depfile := android.GenPathWithExt(ctx, "", task.out[0], task.out[0].Ext()+".d")
 		params.Depfile = depfile
 	}
-	ctx.ModuleBuild(pctx, params)
+	ctx.Build(pctx, params)
 
 	for _, outputFile := range task.out {
 		g.outputFiles = append(g.outputFiles, outputFile)
diff --git a/java/app.go b/java/app.go
index 42ae236..e8028a0 100644
--- a/java/app.go
+++ b/java/app.go
@@ -20,7 +20,6 @@
 	"path/filepath"
 	"strings"
 
-	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
@@ -231,7 +230,7 @@
 	aaptFlags = append(aaptFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
 	aaptFlags = append(aaptFlags, android.JoinWithPrefix(resourceDirs.Strings(), "-S "))
 
-	ctx.VisitDirectDeps(func(module blueprint.Module) {
+	ctx.VisitDirectDeps(func(module android.Module) {
 		var depFiles android.Paths
 		if javaDep, ok := module.(Dependency); ok {
 			if ctx.OtherModuleName(module) == "framework-res" {
diff --git a/java/app_builder.go b/java/app_builder.go
index 55fded5..ed7abce 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -82,7 +82,7 @@
 	publicResourcesFile := android.PathForModuleOut(ctx, "public_resources.xml")
 	proguardOptionsFile := android.PathForModuleOut(ctx, "proguard.options")
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        aaptCreateResourceJavaFile,
 		Description: "aapt create R.java",
 		Outputs:     android.WritablePaths{publicResourcesFile, proguardOptionsFile, javaFileList},
@@ -102,7 +102,7 @@
 func CreateExportPackage(ctx android.ModuleContext, flags []string, deps android.Paths) android.ModuleOutPath {
 	outputFile := android.PathForModuleOut(ctx, "package-export.apk")
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        aaptCreateAssetsPackage,
 		Description: "aapt export package",
 		Output:      outputFile,
@@ -120,7 +120,7 @@
 
 	resourceApk := android.PathForModuleOut(ctx, "resources.apk")
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        aaptAddResources,
 		Description: "aapt package",
 		Output:      resourceApk,
@@ -137,7 +137,7 @@
 		certificateArgs = append(certificateArgs, c+".x509.pem", c+".pk8")
 	}
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        signapk,
 		Description: "signapk",
 		Output:      outputFile,
diff --git a/java/builder.go b/java/builder.go
index 193dfe7..deccb05 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -38,18 +38,24 @@
 	// read from directly using @<listfile>)
 	javac = pctx.AndroidGomaStaticRule("javac",
 		blueprint.RuleParams{
-			Command: `rm -rf "$outDir" "$annoDir" && mkdir -p "$outDir" "$annoDir" && ` +
+			Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
+				`${config.ExtractSrcJarsCmd} $srcJarDir $srcJarDir/list $srcJars && ` +
 				`${config.SoongJavacWrapper} ${config.JavacWrapper}${config.JavacCmd} ${config.JavacHeapFlags} ${config.CommonJdkFlags} ` +
-				`$javacFlags $sourcepath $bootClasspath $classpath ` +
+				`$javacFlags $bootClasspath $classpath ` +
 				`-source $javaVersion -target $javaVersion ` +
-				`-d $outDir -s $annoDir @$out.rsp && ` +
+				`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list && ` +
 				`${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
-			CommandDeps:      []string{"${config.JavacCmd}", "${config.SoongZipCmd}"},
+			CommandDeps: []string{
+				"${config.JavacCmd}",
+				"${config.SoongZipCmd}",
+				"${config.ExtractSrcJarsCmd}",
+			},
 			CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
 			Rspfile:          "$out.rsp",
 			RspfileContent:   "$in",
 		},
-		"javacFlags", "sourcepath", "bootClasspath", "classpath", "outDir", "annoDir", "javaVersion")
+		"javacFlags", "bootClasspath", "classpath", "srcJars", "srcJarDir",
+		"outDir", "annoDir", "javaVersion")
 
 	kotlinc = pctx.AndroidGomaStaticRule("kotlinc",
 		blueprint.RuleParams{
@@ -69,39 +75,49 @@
 
 	errorprone = pctx.AndroidStaticRule("errorprone",
 		blueprint.RuleParams{
-			Command: `rm -rf "$outDir" "$annoDir" && mkdir -p "$outDir" "$annoDir" && ` +
+			Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
+				`${config.ExtractSrcJarsCmd} $srcJarDir $srcJarDir/list $srcJars && ` +
 				`${config.SoongJavacWrapper} ${config.ErrorProneCmd} ` +
-				`$javacFlags $sourcepath $bootClasspath $classpath ` +
+				`$javacFlags $bootClasspath $classpath ` +
 				`-source $javaVersion -target $javaVersion ` +
-				`-d $outDir -s $annoDir @$out.rsp && ` +
+				`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list && ` +
 				`${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
 			CommandDeps: []string{
 				"${config.JavaCmd}",
 				"${config.ErrorProneJavacJar}",
 				"${config.ErrorProneJar}",
 				"${config.SoongZipCmd}",
+				"${config.ExtractSrcJarsCmd}",
 			},
 			CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
 			Rspfile:          "$out.rsp",
 			RspfileContent:   "$in",
 		},
-		"javacFlags", "sourcepath", "bootClasspath", "classpath", "outDir", "annoDir", "javaVersion")
+		"javacFlags", "bootClasspath", "classpath", "srcJars", "srcJarDir",
+		"outDir", "annoDir", "javaVersion")
 
 	turbine = pctx.AndroidStaticRule("turbine",
 		blueprint.RuleParams{
-			Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
+			Command: `rm -rf "$outDir" "$srcJarDir" && mkdir -p "$outDir" "$srcJarDir" && ` +
+				`${config.ExtractSrcJarsCmd} $srcJarDir $srcJarDir/list $srcJars && ` +
 				`${config.JavaCmd} -jar ${config.TurbineJar} --output $out.tmp ` +
-				`--temp_dir "$outDir" --sources @$out.rsp $sourcepath ` +
+				`--temp_dir "$outDir" --sources @$out.rsp @$srcJarDir/list ` +
 				`--javacopts ${config.CommonJdkFlags} ` +
 				`$javacFlags -source $javaVersion -target $javaVersion $bootClasspath $classpath && ` +
 				`${config.Ziptime} $out.tmp && ` +
 				`(if cmp -s $out.tmp $out ; then rm $out.tmp ; else mv $out.tmp $out ; fi )`,
-			CommandDeps:    []string{"${config.TurbineJar}", "${config.JavaCmd}", "${config.Ziptime}"},
+			CommandDeps: []string{
+				"${config.TurbineJar}",
+				"${config.JavaCmd}",
+				"${config.Ziptime}",
+				"${config.ExtractSrcJarsCmd}",
+			},
 			Rspfile:        "$out.rsp",
 			RspfileContent: "$in",
 			Restat:         true,
 		},
-		"javacFlags", "sourcepath", "bootClasspath", "classpath", "outDir", "javaVersion")
+		"javacFlags", "bootClasspath", "classpath", "srcJars", "srcJarDir",
+		"outDir", "javaVersion")
 
 	jar = pctx.AndroidStaticRule("jar",
 		blueprint.RuleParams{
@@ -173,7 +189,7 @@
 }
 
 func TransformKotlinToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
-	srcFiles android.Paths, srcJars classpath,
+	srcFiles, srcJars android.Paths,
 	flags javaBuilderFlags) {
 
 	classDir := android.PathForModuleOut(ctx, "kotlinc", "classes")
@@ -181,7 +197,7 @@
 	inputs := append(android.Paths(nil), srcFiles...)
 	inputs = append(inputs, srcJars...)
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        kotlinc,
 		Description: "kotlinc",
 		Output:      outputFile,
@@ -196,7 +212,7 @@
 }
 
 func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
-	srcFiles android.Paths, srcJars classpath,
+	srcFiles, srcJars android.Paths,
 	flags javaBuilderFlags, deps android.Paths) {
 
 	transformJavaToClasses(ctx, outputFile, srcFiles, srcJars, flags, deps,
@@ -204,7 +220,7 @@
 }
 
 func RunErrorProne(ctx android.ModuleContext, outputFile android.WritablePath,
-	srcFiles android.Paths, srcJars classpath, flags javaBuilderFlags) {
+	srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
 
 	if config.ErrorProneJar == "" {
 		ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
@@ -215,7 +231,7 @@
 }
 
 func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath,
-	srcFiles android.Paths, srcJars classpath, flags javaBuilderFlags) {
+	srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
 
 	var deps android.Paths
 	deps = append(deps, srcJars...)
@@ -230,13 +246,8 @@
 	} else {
 		bootClasspath = flags.bootClasspath.FormJavaClassPath("--bootclasspath")
 	}
-	var sourcepath string
-	if len(srcJars) > 0 {
-		sourcepath = "--sourcepath_jars" + " " + strings.Join(srcJars.Strings(), " ")
-	} else {
-		sourcepath = ""
-	}
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        turbine,
 		Description: "turbine",
 		Output:      outputFile,
@@ -245,7 +256,8 @@
 		Args: map[string]string{
 			"javacFlags":    flags.javacFlags,
 			"bootClasspath": bootClasspath,
-			"sourcepath":    sourcepath,
+			"srcJars":       strings.Join(srcJars.Strings(), " "),
+			"srcJarDir":     android.PathForModuleOut(ctx, "turbine", "srcjars").String(),
 			"classpath":     flags.classpath.FormJavaClassPath("--classpath"),
 			"outDir":        android.PathForModuleOut(ctx, "turbine", "classes").String(),
 			"javaVersion":   flags.javaVersion,
@@ -263,7 +275,7 @@
 // suffix will be appended to various intermediate files and directories to avoid collisions when
 // this function is called twice in the same module directory.
 func transformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
-	srcFiles android.Paths, srcJars classpath,
+	srcFiles, srcJars android.Paths,
 	flags javaBuilderFlags, deps android.Paths,
 	intermediatesDir, desc string, rule blueprint.Rule) {
 
@@ -286,7 +298,7 @@
 
 	deps = append(deps, flags.classpath...)
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        rule,
 		Description: desc,
 		Output:      outputFile,
@@ -295,13 +307,12 @@
 		Args: map[string]string{
 			"javacFlags":    flags.javacFlags,
 			"bootClasspath": bootClasspath,
-			// Returns a -sourcepath argument in the form javac expects.  If the list is empty returns
-			// -sourcepath "" to ensure javac does not fall back to searching the classpath for sources.
-			"sourcepath":  srcJars.FormJavaClassPath("-sourcepath"),
-			"classpath":   flags.classpath.FormJavaClassPath("-classpath"),
-			"outDir":      android.PathForModuleOut(ctx, intermediatesDir, "classes").String(),
-			"annoDir":     android.PathForModuleOut(ctx, intermediatesDir, "anno").String(),
-			"javaVersion": flags.javaVersion,
+			"classpath":     flags.classpath.FormJavaClassPath("-classpath"),
+			"srcJars":       strings.Join(srcJars.Strings(), " "),
+			"srcJarDir":     android.PathForModuleOut(ctx, intermediatesDir, "srcjars").String(),
+			"outDir":        android.PathForModuleOut(ctx, intermediatesDir, "classes").String(),
+			"annoDir":       android.PathForModuleOut(ctx, intermediatesDir, "anno").String(),
+			"javaVersion":   flags.javaVersion,
 		},
 	})
 }
@@ -309,7 +320,7 @@
 func TransformResourcesToJar(ctx android.ModuleContext, outputFile android.WritablePath,
 	jarArgs []string, deps android.Paths) {
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        jar,
 		Description: "jar",
 		Output:      outputFile,
@@ -341,7 +352,7 @@
 		jarArgs = append(jarArgs, "-D")
 	}
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        combineJar,
 		Description: desc,
 		Output:      outputFile,
@@ -371,7 +382,7 @@
 	deps = append(deps, flags.bootClasspath...)
 	deps = append(deps, flags.classpath...)
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        desugar,
 		Description: "desugar",
 		Output:      outputFile,
@@ -393,7 +404,7 @@
 
 	outDir := android.PathForModuleOut(ctx, "dex")
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        dx,
 		Description: "dx",
 		Output:      outputFile,
@@ -407,7 +418,7 @@
 
 func TransformJarJar(ctx android.ModuleContext, outputFile android.WritablePath,
 	classesJar android.Path, rulesFile android.Path) {
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        jarjar,
 		Description: "jarjar",
 		Output:      outputFile,
diff --git a/java/config/config.go b/java/config/config.go
index 94dfa19..85a753c 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -75,6 +75,7 @@
 	pctx.SourcePathVariable("JrtFsJar", "${JavaHome}/lib/jrt-fs.jar")
 	pctx.SourcePathVariable("Ziptime", "prebuilts/build-tools/${hostPrebuiltTag}/bin/ziptime")
 
+	pctx.SourcePathVariable("ExtractSrcJarsCmd", "build/soong/scripts/extract-src-jars.sh")
 	pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh")
 	pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
 	pctx.HostBinToolVariable("MergeZipsCmd", "merge_zips")
@@ -93,10 +94,21 @@
 			return path.String(), nil
 		}
 	})
+	pctx.VariableFunc("TurbineJar", func(config interface{}) (string, error) {
+		turbine := "turbine.jar"
+		if config.(android.Config).UnbundledBuild() {
+			return "prebuilts/build-tools/common/framework/" + turbine, nil
+		} else {
+			path, err := pctx.HostJavaToolPath(config, turbine)
+			if err != nil {
+				return "", err
+			}
+			return path.String(), nil
+		}
+	})
 
 	pctx.HostJavaToolVariable("JarjarCmd", "jarjar.jar")
 	pctx.HostJavaToolVariable("DesugarJar", "desugar.jar")
-	pctx.HostJavaToolVariable("TurbineJar", "turbine.jar")
 
 	pctx.HostBinToolVariable("SoongJavacWrapper", "soong_javac_wrapper")
 
diff --git a/java/gen.go b/java/gen.go
index e12a71c..8fa199e 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -57,7 +57,7 @@
 	javaFile := android.GenPathWithExt(ctx, "aidl", aidlFile, "java")
 	depFile := javaFile.String() + ".d"
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        aidl,
 		Description: "aidl " + aidlFile.Rel(),
 		Output:      javaFile,
@@ -74,7 +74,7 @@
 func genLogtags(ctx android.ModuleContext, logtagsFile android.Path) android.Path {
 	javaFile := android.GenPathWithExt(ctx, "logtags", logtagsFile, "java")
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        logtags,
 		Description: "logtags " + logtagsFile.Rel(),
 		Output:      javaFile,
@@ -85,7 +85,7 @@
 }
 
 func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths,
-	flags javaBuilderFlags) (android.Paths, classpath) {
+	flags javaBuilderFlags) (android.Paths, android.Paths) {
 
 	var protoFiles android.Paths
 	outSrcFiles := make(android.Paths, 0, len(srcFiles))
@@ -106,7 +106,7 @@
 		}
 	}
 
-	var outSrcJars classpath
+	var outSrcJars android.Paths
 
 	if len(protoFiles) > 0 {
 		protoSrcJar := android.PathForModuleGen(ctx, "proto.src.jar")
diff --git a/java/java.go b/java/java.go
index c12ada2..f5035e7 100644
--- a/java/java.go
+++ b/java/java.go
@@ -406,25 +406,10 @@
 		deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, sdkDep.aidl)
 	}
 
-	ctx.VisitDirectDeps(func(module blueprint.Module) {
+	ctx.VisitDirectDeps(func(module android.Module) {
 		otherName := ctx.OtherModuleName(module)
 		tag := ctx.OtherModuleDependencyTag(module)
 
-		aDep, _ := module.(android.Module)
-		if aDep == nil {
-			ctx.ModuleErrorf("module %q not an android module", ctx.OtherModuleName(aDep))
-			return
-		}
-
-		if !aDep.Enabled() {
-			if ctx.AConfig().AllowMissingDependencies() {
-				ctx.AddMissingDependencies([]string{ctx.OtherModuleName(aDep)})
-			} else {
-				ctx.ModuleErrorf("depends on disabled module %q", ctx.OtherModuleName(aDep))
-			}
-			return
-		}
-
 		dep, _ := module.(Dependency)
 		if dep == nil {
 			switch tag {
@@ -536,7 +521,7 @@
 		flags = protoFlags(ctx, &j.protoProperties, flags)
 	}
 
-	var srcJars classpath
+	var srcJars android.Paths
 	srcFiles, srcJars = j.genSources(ctx, srcFiles, flags)
 	srcJars = append(srcJars, deps.srcJars...)
 	srcJars = append(srcJars, j.ExtraSrcJars...)
@@ -591,7 +576,7 @@
 			}
 		}
 	}
-	if len(uniqueSrcFiles) > 0 {
+	if len(uniqueSrcFiles) > 0 || len(srcJars) > 0 {
 		var extraJarDeps android.Paths
 		if ctx.AConfig().IsEnvTrue("RUN_ERROR_PRONE") {
 			// If error-prone is enabled, add an additional rule to compile the java files into
@@ -685,11 +670,11 @@
 	j.outputFile = outputFile
 }
 
-func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles android.Paths, srcJars classpath,
+func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths,
 	deps deps, flags javaBuilderFlags, jarName string) android.Path {
 
 	var jars android.Paths
-	if len(srcFiles) > 0 {
+	if len(srcFiles) > 0 || len(srcJars) > 0 {
 		// Compile java sources into turbine.jar.
 		turbineJar := android.PathForModuleOut(ctx, "turbine", jarName)
 		TransformJavaToHeaderClasses(ctx, turbineJar, srcFiles, srcJars, flags)
@@ -704,15 +689,11 @@
 	var headerJar android.Path
 	jars = append(jars, deps.staticHeaderJars...)
 
-	if len(jars) == 0 {
-		panic("The turbine.jar is empty without any sources and static libs.")
-	} else {
-		// we cannot skip the combine step for now if there is only one jar
-		// since we have to strip META-INF/TRANSITIVE dir from turbine.jar
-		combinedJar := android.PathForModuleOut(ctx, "turbine-combined", jarName)
-		TransformJarsToJar(ctx, combinedJar, "for turbine", jars, android.OptionalPath{}, false, []string{"META-INF"})
-		headerJar = combinedJar
-	}
+	// we cannot skip the combine step for now if there is only one jar
+	// since we have to strip META-INF/TRANSITIVE dir from turbine.jar
+	combinedJar := android.PathForModuleOut(ctx, "turbine-combined", jarName)
+	TransformJarsToJar(ctx, combinedJar, "for turbine", jars, android.OptionalPath{}, false, []string{"META-INF"})
+	headerJar = combinedJar
 
 	if j.properties.Jarjar_rules != nil {
 		jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
diff --git a/java/proto.go b/java/proto.go
index fc259a5..1077fd6 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -41,7 +41,7 @@
 func genProto(ctx android.ModuleContext, outputSrcJar android.WritablePath,
 	protoFiles android.Paths, protoFlags string, protoOut, protoOutFlags string) {
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        proto,
 		Description: "protoc " + protoFiles[0].Rel(),
 		Output:      outputSrcJar,
diff --git a/java/system_modules.go b/java/system_modules.go
index ce66a7c..c3e40ca 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -67,7 +67,7 @@
 		android.PathForModuleOut(ctx, "system/release"),
 	}
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        jarsTosystemModules,
 		Description: "system modules",
 		Outputs:     outputs,
@@ -112,7 +112,7 @@
 func (system *SystemModules) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	var jars android.Paths
 
-	ctx.VisitDirectDeps(func(module blueprint.Module) {
+	ctx.VisitDirectDeps(func(module android.Module) {
 		if ctx.OtherModuleDependencyTag(module) == libTag {
 			dep, _ := module.(Dependency)
 			jars = append(jars, dep.HeaderJars()...)
@@ -138,6 +138,7 @@
 				fmt.Fprintln(w)
 				fmt.Fprintln(w, makevar, ":=", system.outputFile.String())
 				fmt.Fprintln(w, ".KATI_READONLY", ":=", makevar)
+				fmt.Fprintln(w, name+":", "$("+makevar+")")
 			}
 		},
 	}
diff --git a/python/binary.go b/python/binary.go
index b7b5056..c2e38bf 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -21,8 +21,6 @@
 	"path/filepath"
 	"strings"
 
-	"github.com/google/blueprint"
-
 	"android/soong/android"
 )
 
@@ -135,7 +133,7 @@
 
 	var launcher_path android.Path
 	if embedded_launcher {
-		ctx.VisitDirectDeps(func(m blueprint.Module) {
+		ctx.VisitDirectDeps(func(m android.Module) {
 			if ctx.OtherModuleDependencyTag(m) != launcherTag {
 				return
 			}
diff --git a/python/builder.go b/python/builder.go
index a459d3d..f194354 100644
--- a/python/builder.go
+++ b/python/builder.go
@@ -87,7 +87,7 @@
 		content = append(content, file.String())
 	}
 
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	ctx.Build(pctx, android.BuildParams{
 		Rule:        android.WriteFile,
 		Description: "generate " + fileList.Rel(),
 		Output:      fileList,
@@ -140,7 +140,7 @@
 		// added stub file to the soong_zip args.
 		parArgs = append(parArgs, `-P "" `+`-C `+strings.TrimSuffix(stub, mainFileName)+` -f `+stub)
 
-		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+		ctx.Build(pctx, android.BuildParams{
 			Rule:        host_par,
 			Description: "host python archive",
 			Output:      binFile,
@@ -169,7 +169,7 @@
 		parArgs = append(parArgs, `-P "" `+`-C `+fmt.Sprintf(
 			"%q", strings.TrimSuffix(entryPoint, entryPointFile))+` -f `+entryPoint)
 
-		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+		ctx.Build(pctx, android.BuildParams{
 			Rule:        embedded_par,
 			Description: "embedded python archive",
 			Output:      binFile,
diff --git a/python/python.go b/python/python.go
index e63c26c..1b146a8 100644
--- a/python/python.go
+++ b/python/python.go
@@ -508,7 +508,7 @@
 	}
 
 	// visit all its dependencies in depth first.
-	ctx.VisitDepsDepthFirst(func(module blueprint.Module) {
+	ctx.VisitDepsDepthFirst(func(module android.Module) {
 		if ctx.OtherModuleDependencyTag(module) != pythonLibTag {
 			return
 		}
diff --git a/scripts/extract-src-jars.sh b/scripts/extract-src-jars.sh
new file mode 100755
index 0000000..918cf8a
--- /dev/null
+++ b/scripts/extract-src-jars.sh
@@ -0,0 +1,30 @@
+#!/bin/bash -e
+
+# Extracts .java files from source jars in a specified directory and writes out a list of the files
+
+if [ -z "$1" -o -z "$2" ]; then
+  echo "usage: $0 <output dir> <output file> [<jar> ...]" >&2
+  exit 1
+fi
+
+output_dir=$1
+shift
+output_file=$1
+shift
+
+rm -f $output_file
+touch $output_file
+
+for j in "$@"; do
+  for f in $(zipinfo -1 $j '*.java'); do
+    echo $output_dir/$f >> $output_file
+  done
+  unzip -qn -d $output_dir $j '*.java'
+done
+
+duplicates=$(cat $output_file | sort | uniq -d | uniq)
+if [ -n "$duplicates" ]; then
+  echo Duplicate source files:
+  echo $duplicates
+  exit 1
+fi