Merge "Differentiate system and test apis in whitelist"
diff --git a/Android.bp b/Android.bp
index 4d73049..c0a1aeb 100644
--- a/Android.bp
+++ b/Android.bp
@@ -56,6 +56,7 @@
         "android/neverallow.go",
         "android/onceper.go",
         "android/package_ctx.go",
+        "android/path_properties.go",
         "android/paths.go",
         "android/prebuilt.go",
         "android/prebuilt_etc.go",
@@ -80,6 +81,7 @@
         "android/namespace_test.go",
         "android/neverallow_test.go",
         "android/onceper_test.go",
+        "android/path_properties_test.go",
         "android/paths_test.go",
         "android/prebuilt_test.go",
         "android/prebuilt_etc_test.go",
@@ -250,6 +252,7 @@
         "java/app_builder.go",
         "java/app.go",
         "java/builder.go",
+        "java/device_host_converter.go",
         "java/dex.go",
         "java/dexpreopt.go",
         "java/dexpreopt_bootjars.go",
@@ -275,7 +278,9 @@
     ],
     testSrcs: [
         "java/app_test.go",
+        "java/device_host_converter_test.go",
         "java/dexpreopt_test.go",
+        "java/dexpreopt_bootjars_test.go",
         "java/java_test.go",
         "java/jdeps_test.go",
         "java/kotlin_test.go",
diff --git a/README.md b/README.md
index 44a98f3..2957940 100644
--- a/README.md
+++ b/README.md
@@ -34,7 +34,7 @@
 all Android.bp files.
 
 For a list of valid module types and their properties see
-[$OUT_DIR/soong/docs/soong_build.html](http://go/Android.bp).
+[$OUT_DIR/soong/docs/soong_build.html](https://ci.android.com/builds/latest/branches/aosp-build-tools/targets/linux/view/soong_build.html).
 
 ### Globs
 
diff --git a/android/config.go b/android/config.go
index 24be10a..92879de 100644
--- a/android/config.go
+++ b/android/config.go
@@ -862,7 +862,7 @@
 func (c *deviceConfig) CoverageEnabledForPath(path string) bool {
 	coverage := false
 	if c.config.productVariables.CoveragePaths != nil {
-		if PrefixInList(path, c.config.productVariables.CoveragePaths) {
+		if InList("*", c.config.productVariables.CoveragePaths) || PrefixInList(path, c.config.productVariables.CoveragePaths) {
 			coverage = true
 		}
 	}
diff --git a/android/filegroup.go b/android/filegroup.go
index b284ce0..76af804 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -26,9 +26,9 @@
 
 type fileGroupProperties struct {
 	// srcs lists files that will be included in this filegroup
-	Srcs []string
+	Srcs []string `android:"path"`
 
-	Exclude_srcs []string
+	Exclude_srcs []string `android:"path"`
 
 	// The base path to the files.  May be used by other modules to determine which portion
 	// of the path to use.  For example, when a filegroup is used as data in a cc_test rule,
@@ -59,11 +59,6 @@
 	return module
 }
 
-func (fg *fileGroup) DepsMutator(ctx BottomUpMutatorContext) {
-	ExtractSourcesDeps(ctx, fg.properties.Srcs)
-	ExtractSourcesDeps(ctx, fg.properties.Exclude_srcs)
-}
-
 func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) {
 	fg.srcs = ctx.ExpandSourcesSubDir(fg.properties.Srcs, fg.properties.Exclude_srcs, String(fg.properties.Path))
 }
diff --git a/android/module.go b/android/module.go
index 2fa7d31..c1f3e79 100644
--- a/android/module.go
+++ b/android/module.go
@@ -88,6 +88,7 @@
 type BaseModuleContext interface {
 	ModuleName() string
 	ModuleDir() string
+	ModuleType() string
 	Config() Config
 
 	ContainsProperty(name string) bool
@@ -193,6 +194,7 @@
 	GetProperties() []interface{}
 
 	BuildParamsForTests() []BuildParams
+	RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
 	VariablesForTests() map[string]string
 }
 
@@ -258,16 +260,16 @@
 	Recovery *bool
 
 	// init.rc files to be installed if this module is installed
-	Init_rc []string
+	Init_rc []string `android:"path"`
 
 	// VINTF manifest fragments to be installed if this module is installed
-	Vintf_fragments []string
+	Vintf_fragments []string `android:"path"`
 
 	// names of other modules to install if this module is installed
 	Required []string `android:"arch_variant"`
 
 	// relative path to a file to include in the list of notices for the device
-	Notice *string
+	Notice *string `android:"path"`
 
 	Dist struct {
 		// copy the output of this module to the $DIST_DIR when `dist` is specified on the
@@ -477,6 +479,7 @@
 
 	// For tests
 	buildParams []BuildParams
+	ruleParams  map[blueprint.Rule]blueprint.RuleParams
 	variables   map[string]string
 
 	prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool
@@ -496,6 +499,10 @@
 	return a.buildParams
 }
 
+func (a *ModuleBase) RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams {
+	return a.ruleParams
+}
+
 func (a *ModuleBase) VariablesForTests() map[string]string {
 	return a.variables
 }
@@ -795,6 +802,10 @@
 		variables:              make(map[string]string),
 	}
 
+	if ctx.config.captureBuild {
+		ctx.ruleParams = make(map[blueprint.Rule]blueprint.RuleParams)
+	}
+
 	desc := "//" + ctx.ModuleDir() + ":" + ctx.ModuleName() + " "
 	var suffix []string
 	if ctx.Os().Class != Device && ctx.Os().Class != Generic {
@@ -854,6 +865,7 @@
 	}
 
 	a.buildParams = ctx.buildParams
+	a.ruleParams = ctx.ruleParams
 	a.variables = ctx.variables
 }
 
@@ -877,6 +889,7 @@
 
 	// For tests
 	buildParams []BuildParams
+	ruleParams  map[blueprint.Rule]blueprint.RuleParams
 	variables   map[string]string
 }
 
@@ -931,12 +944,12 @@
 		bparams.Implicits = append(bparams.Implicits, params.Implicit.String())
 	}
 
-	bparams.Outputs = proptools.NinjaEscape(bparams.Outputs)
-	bparams.ImplicitOutputs = proptools.NinjaEscape(bparams.ImplicitOutputs)
-	bparams.Inputs = proptools.NinjaEscape(bparams.Inputs)
-	bparams.Implicits = proptools.NinjaEscape(bparams.Implicits)
-	bparams.OrderOnly = proptools.NinjaEscape(bparams.OrderOnly)
-	bparams.Depfile = proptools.NinjaEscape([]string{bparams.Depfile})[0]
+	bparams.Outputs = proptools.NinjaEscapeList(bparams.Outputs)
+	bparams.ImplicitOutputs = proptools.NinjaEscapeList(bparams.ImplicitOutputs)
+	bparams.Inputs = proptools.NinjaEscapeList(bparams.Inputs)
+	bparams.Implicits = proptools.NinjaEscapeList(bparams.Implicits)
+	bparams.OrderOnly = proptools.NinjaEscapeList(bparams.OrderOnly)
+	bparams.Depfile = proptools.NinjaEscapeList([]string{bparams.Depfile})[0]
 
 	return bparams
 }
@@ -952,7 +965,13 @@
 func (a *androidModuleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
 	argNames ...string) blueprint.Rule {
 
-	return a.ModuleContext.Rule(pctx.PackageContext, name, params, argNames...)
+	rule := a.ModuleContext.Rule(pctx.PackageContext, name, params, argNames...)
+
+	if a.config.captureBuild {
+		a.ruleParams[rule] = params
+	}
+
+	return rule
 }
 
 func (a *androidModuleContext) Build(pctx PackageContext, params BuildParams) {
@@ -1339,6 +1358,8 @@
 
 // Adds necessary dependencies to satisfy filegroup or generated sources modules listed in srcFiles
 // using ":module" syntax, if any.
+//
+// Deprecated: tag the property with `android:"path"` instead.
 func ExtractSourcesDeps(ctx BottomUpMutatorContext, srcFiles []string) {
 	var deps []string
 	set := make(map[string]bool)
@@ -1359,6 +1380,8 @@
 
 // Adds necessary dependencies to satisfy filegroup or generated sources modules specified in s
 // using ":module" syntax, if any.
+//
+// Deprecated: tag the property with `android:"path"` instead.
 func ExtractSourceDeps(ctx BottomUpMutatorContext, s *string) {
 	if s != nil {
 		if m := SrcIsModule(*s); m != "" {
@@ -1371,14 +1394,14 @@
 	Srcs() Paths
 }
 
-// Returns a list of paths expanded from globs and modules referenced using ":module" syntax.
-// ExtractSourcesDeps must have already been called during the dependency resolution phase.
+// Returns a list of paths expanded from globs and modules referenced using ":module" syntax.  The property must
+// be tagged with `android:"path" to support automatic source module dependency resolution.
 func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) Paths {
 	return ctx.ExpandSourcesSubDir(srcFiles, excludes, "")
 }
 
-// Returns a single path expanded from globs and modules referenced using ":module" syntax.
-// ExtractSourceDeps must have already been called during the dependency resolution phase.
+// Returns a single path expanded from globs and modules referenced using ":module" syntax.  The property must
+// be tagged with `android:"path" to support automatic source module dependency resolution.
 func (ctx *androidModuleContext) ExpandSource(srcFile, prop string) Path {
 	srcFiles := ctx.ExpandSourcesSubDir([]string{srcFile}, nil, "")
 	if len(srcFiles) == 1 {
@@ -1397,8 +1420,8 @@
 }
 
 // Returns an optional single path expanded from globs and modules referenced using ":module" syntax if
-// the srcFile is non-nil.
-// ExtractSourceDeps must have already been called during the dependency resolution phase.
+// the srcFile is non-nil.  The property must be tagged with `android:"path" to support automatic source module
+// dependency resolution.
 func (ctx *androidModuleContext) ExpandOptionalSource(srcFile *string, prop string) OptionalPath {
 	if srcFile != nil {
 		return OptionalPathForPath(ctx.ExpandSource(*srcFile, prop))
@@ -1418,7 +1441,11 @@
 		if m := SrcIsModule(e); m != "" {
 			module := ctx.GetDirectDepWithTag(m, SourceDepTag)
 			if module == nil {
-				// Error will have been handled by ExtractSourcesDeps
+				if ctx.Config().AllowMissingDependencies() {
+					ctx.AddMissingDependencies([]string{m})
+				} else {
+					ctx.ModuleErrorf(`missing dependency on %q, is the property annotated with android:"path"?`, m)
+				}
 				continue
 			}
 			if srcProducer, ok := module.(SourceFileProducer); ok {
@@ -1435,7 +1462,11 @@
 		if m := SrcIsModule(s); m != "" {
 			module := ctx.GetDirectDepWithTag(m, SourceDepTag)
 			if module == nil {
-				// Error will have been handled by ExtractSourcesDeps
+				if ctx.Config().AllowMissingDependencies() {
+					ctx.AddMissingDependencies([]string{m})
+				} else {
+					ctx.ModuleErrorf(`missing dependency on %q, is the property annotated with android:"path"?`, m)
+				}
 				continue
 			}
 			if srcProducer, ok := module.(SourceFileProducer); ok {
diff --git a/android/mutator.go b/android/mutator.go
index e5f742f..6c9f17a 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -91,6 +91,7 @@
 }
 
 var postDeps = []RegisterMutatorFunc{
+	registerPathDepsMutator,
 	RegisterPrebuiltsPostDepsMutators,
 	registerNeverallowMutator,
 }
@@ -132,11 +133,15 @@
 	VisitDepsDepthFirst(visit func(Module))
 	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
 	WalkDeps(visit func(Module, Module) bool)
+	// GetWalkPath is supposed to be called in visit function passed in WalkDeps()
+	// and returns a top-down dependency path from a start module to current child module.
+	GetWalkPath() []Module
 }
 
 type androidTopDownMutatorContext struct {
 	blueprint.TopDownMutatorContext
 	androidBaseContextImpl
+	walkPath []Module
 }
 
 type AndroidBottomUpMutator func(BottomUpMutatorContext)
@@ -207,11 +212,6 @@
 func depsMutator(ctx BottomUpMutatorContext) {
 	if m, ok := ctx.Module().(Module); ok && m.Enabled() {
 		m.DepsMutator(ctx)
-
-		// For filegroup-based notice file references.
-		if m.base().commonProperties.Notice != nil {
-			ExtractSourceDeps(ctx, m.base().commonProperties.Notice)
-		}
 	}
 }
 
@@ -287,10 +287,16 @@
 }
 
 func (a *androidTopDownMutatorContext) WalkDeps(visit func(Module, Module) bool) {
+	a.walkPath = []Module{a.Module()}
 	a.TopDownMutatorContext.WalkDeps(func(child, parent blueprint.Module) bool {
 		childAndroidModule, _ := child.(Module)
 		parentAndroidModule, _ := parent.(Module)
 		if childAndroidModule != nil && parentAndroidModule != nil {
+			// record walkPath before visit
+			for a.walkPath[len(a.walkPath)-1] != parentAndroidModule {
+				a.walkPath = a.walkPath[0 : len(a.walkPath)-1]
+			}
+			a.walkPath = append(a.walkPath, childAndroidModule)
 			return visit(childAndroidModule, parentAndroidModule)
 		} else {
 			return false
@@ -298,6 +304,10 @@
 	})
 }
 
+func (a *androidTopDownMutatorContext) GetWalkPath() []Module {
+	return a.walkPath
+}
+
 func (a *androidTopDownMutatorContext) AppendProperties(props ...interface{}) {
 	for _, p := range props {
 		err := proptools.AppendMatchingProperties(a.Module().base().customizableProperties,
diff --git a/android/neverallow.go b/android/neverallow.go
index 18744e8..f63f461 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -51,6 +51,7 @@
 	rules := []*rule{}
 	rules = append(rules, createTrebleRules()...)
 	rules = append(rules, createLibcoreRules()...)
+	rules = append(rules, createJavaDeviceForHostRules()...)
 	return rules
 }
 
@@ -125,6 +126,20 @@
 	return rules
 }
 
+func createJavaDeviceForHostRules() []*rule {
+	javaDeviceForHostProjectsWhitelist := []string{
+		"external/robolectric-shadows",
+		"framework/layoutlib",
+	}
+
+	return []*rule{
+		neverallow().
+			notIn(javaDeviceForHostProjectsWhitelist...).
+			moduleType("java_device_for_host", "java_host_for_device").
+			because("java_device_for_host can only be used in whitelisted projects"),
+	}
+}
+
 func neverallowMutator(ctx BottomUpMutatorContext) {
 	m, ok := ctx.Module().(Module)
 	if !ok {
@@ -139,6 +154,10 @@
 			continue
 		}
 
+		if !n.appliesToModuleType(ctx.ModuleType()) {
+			continue
+		}
+
 		if !n.appliesToProperties(properties) {
 			continue
 		}
@@ -159,6 +178,9 @@
 	paths       []string
 	unlessPaths []string
 
+	moduleTypes       []string
+	unlessModuleTypes []string
+
 	props       []ruleProperty
 	unlessProps []ruleProperty
 }
@@ -166,14 +188,27 @@
 func neverallow() *rule {
 	return &rule{}
 }
+
 func (r *rule) in(path ...string) *rule {
 	r.paths = append(r.paths, cleanPaths(path)...)
 	return r
 }
+
 func (r *rule) notIn(path ...string) *rule {
 	r.unlessPaths = append(r.unlessPaths, cleanPaths(path)...)
 	return r
 }
+
+func (r *rule) moduleType(types ...string) *rule {
+	r.moduleTypes = append(r.moduleTypes, types...)
+	return r
+}
+
+func (r *rule) notModuleType(types ...string) *rule {
+	r.unlessModuleTypes = append(r.unlessModuleTypes, types...)
+	return r
+}
+
 func (r *rule) with(properties, value string) *rule {
 	r.props = append(r.props, ruleProperty{
 		fields: fieldNamesForProperties(properties),
@@ -181,6 +216,7 @@
 	})
 	return r
 }
+
 func (r *rule) without(properties, value string) *rule {
 	r.unlessProps = append(r.unlessProps, ruleProperty{
 		fields: fieldNamesForProperties(properties),
@@ -188,6 +224,7 @@
 	})
 	return r
 }
+
 func (r *rule) because(reason string) *rule {
 	r.reason = reason
 	return r
@@ -201,6 +238,12 @@
 	for _, v := range r.unlessPaths {
 		s += " -dir:" + v + "*"
 	}
+	for _, v := range r.moduleTypes {
+		s += " type:" + v
+	}
+	for _, v := range r.unlessModuleTypes {
+		s += " -type:" + v
+	}
 	for _, v := range r.props {
 		s += " " + strings.Join(v.fields, ".") + "=" + v.value
 	}
@@ -219,6 +262,10 @@
 	return includePath && !excludePath
 }
 
+func (r *rule) appliesToModuleType(moduleType string) bool {
+	return (len(r.moduleTypes) == 0 || InList(moduleType, r.moduleTypes)) && !InList(moduleType, r.unlessModuleTypes)
+}
+
 func (r *rule) appliesToProperties(properties []interface{}) bool {
 	includeProps := hasAllProperties(properties, r.props)
 	excludeProps := hasAnyProperty(properties, r.unlessProps)
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 8d53087..d55ca57 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -148,6 +148,17 @@
 		},
 		expectedError: "Only core libraries projects can depend on core-libart",
 	},
+	{
+		name: "java_device_for_host",
+		fs: map[string][]byte{
+			"Blueprints": []byte(`
+				java_device_for_host {
+					name: "device_for_host",
+					libs: ["core-libart"],
+				}`),
+		},
+		expectedError: "java_device_for_host can only be used in whitelisted projects",
+	},
 }
 
 func TestNeverallow(t *testing.T) {
@@ -176,6 +187,7 @@
 	ctx := NewTestContext()
 	ctx.RegisterModuleType("cc_library", ModuleFactoryAdaptor(newMockCcLibraryModule))
 	ctx.RegisterModuleType("java_library", ModuleFactoryAdaptor(newMockJavaLibraryModule))
+	ctx.RegisterModuleType("java_device_for_host", ModuleFactoryAdaptor(newMockJavaLibraryModule))
 	ctx.PostDepsMutators(registerNeverallowMutator)
 	ctx.Register()
 
diff --git a/android/path_properties.go b/android/path_properties.go
new file mode 100644
index 0000000..5d89709
--- /dev/null
+++ b/android/path_properties.go
@@ -0,0 +1,123 @@
+// Copyright 2019 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"
+	"reflect"
+
+	"github.com/google/blueprint/proptools"
+)
+
+func registerPathDepsMutator(ctx RegisterMutatorsContext) {
+	ctx.BottomUp("pathdeps", pathDepsMutator).Parallel()
+}
+
+// The pathDepsMutator automatically adds dependencies on any module that is listed with ":module" syntax in a
+// property that is tagged with android:"path".
+func pathDepsMutator(ctx BottomUpMutatorContext) {
+	m := ctx.Module().(Module)
+	if m == nil {
+		return
+	}
+
+	props := m.base().customizableProperties
+
+	for _, ps := range props {
+		pathProperties := pathPropertiesForPropertyStruct(ctx, ps)
+		pathProperties = FirstUniqueStrings(pathProperties)
+
+		var deps []string
+		for _, s := range pathProperties {
+			if m := SrcIsModule(s); m != "" {
+				deps = append(deps, m)
+			}
+		}
+
+		ctx.AddDependency(ctx.Module(), SourceDepTag, deps...)
+	}
+}
+
+// pathPropertiesForPropertyStruct uses the indexes of properties that are tagged with android:"path" to extract
+// all their values from a property struct, returning them as a single slice of strings..
+func pathPropertiesForPropertyStruct(ctx BottomUpMutatorContext, ps interface{}) []string {
+	v := reflect.ValueOf(ps)
+	if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
+		panic(fmt.Errorf("type %s is not a pointer to a struct", v.Type()))
+	}
+	if v.IsNil() {
+		return nil
+	}
+	v = v.Elem()
+
+	pathPropertyIndexes := pathPropertyIndexesForPropertyStruct(ps)
+
+	var ret []string
+
+	for _, i := range pathPropertyIndexes {
+		sv := fieldByIndex(v, i)
+		if !sv.IsValid() {
+			continue
+		}
+
+		if sv.Kind() == reflect.Ptr {
+			if sv.IsNil() {
+				continue
+			}
+			sv = sv.Elem()
+		}
+		switch sv.Kind() {
+		case reflect.String:
+			ret = append(ret, sv.String())
+		case reflect.Slice:
+			ret = append(ret, sv.Interface().([]string)...)
+		default:
+			panic(fmt.Errorf(`field %s in type %s has tag android:"path" but is not a string or slice of strings, it is a %s`,
+				v.Type().FieldByIndex(i).Name, v.Type(), sv.Type()))
+		}
+	}
+
+	return ret
+}
+
+// fieldByIndex is like reflect.Value.FieldByIndex, but returns an invalid reflect.Value when traversing a nil pointer
+// to a struct.
+func fieldByIndex(v reflect.Value, index []int) reflect.Value {
+	if len(index) == 1 {
+		return v.Field(index[0])
+	}
+	for _, x := range index {
+		if v.Kind() == reflect.Ptr {
+			if v.IsNil() {
+				return reflect.Value{}
+			}
+			v = v.Elem()
+		}
+		v = v.Field(x)
+	}
+	return v
+}
+
+var pathPropertyIndexesCache OncePer
+
+// pathPropertyIndexesForPropertyStruct returns a list of all of the indexes of properties in property struct type that
+// are tagged with android:"path".  Each index is a []int suitable for passing to reflect.Value.FieldByIndex.  The value
+// is cached in a global cache by type.
+func pathPropertyIndexesForPropertyStruct(ps interface{}) [][]int {
+	key := NewCustomOnceKey(reflect.TypeOf(ps))
+	return pathPropertyIndexesCache.Once(key, func() interface{} {
+		return proptools.PropertyIndexesWithTag(ps, "android", "path")
+	}).([][]int)
+}
diff --git a/android/path_properties_test.go b/android/path_properties_test.go
new file mode 100644
index 0000000..6471a3c
--- /dev/null
+++ b/android/path_properties_test.go
@@ -0,0 +1,120 @@
+// Copyright 2019 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 (
+	"io/ioutil"
+	"os"
+	"reflect"
+	"testing"
+)
+
+type pathDepsMutatorTestModule struct {
+	ModuleBase
+	props struct {
+		Foo string   `android:"path"`
+		Bar []string `android:"path"`
+		Baz *string  `android:"path"`
+		Qux string
+	}
+
+	sourceDeps []string
+}
+
+func pathDepsMutatorTestModuleFactory() Module {
+	module := &pathDepsMutatorTestModule{}
+	module.AddProperties(&module.props)
+	InitAndroidModule(module)
+	return module
+}
+
+func (p *pathDepsMutatorTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+	ctx.VisitDirectDepsWithTag(SourceDepTag, func(dep Module) {
+		p.sourceDeps = append(p.sourceDeps, ctx.OtherModuleName(dep))
+	})
+}
+
+func TestPathDepsMutator(t *testing.T) {
+	tests := []struct {
+		name string
+		bp   string
+		deps []string
+	}{
+		{
+			name: "all",
+			bp: `
+			test {
+				name: "foo",
+				foo: ":a",
+				bar: [":b"],
+				baz: ":c",
+				qux: ":d",
+			}`,
+			deps: []string{"a", "b", "c"},
+		},
+	}
+
+	buildDir, err := ioutil.TempDir("", "soong_path_properties_test")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(buildDir)
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			config := TestConfig(buildDir, nil)
+			ctx := NewTestContext()
+
+			ctx.RegisterModuleType("test", ModuleFactoryAdaptor(pathDepsMutatorTestModuleFactory))
+			ctx.RegisterModuleType("filegroup", ModuleFactoryAdaptor(FileGroupFactory))
+
+			bp := test.bp + `
+				filegroup {
+					name: "a",
+				}
+				
+				filegroup {
+					name: "b",
+				}
+    	
+				filegroup {
+					name: "c",
+				}
+    	
+				filegroup {
+					name: "d",
+				}
+			`
+
+			mockFS := map[string][]byte{
+				"Android.bp": []byte(bp),
+			}
+
+			ctx.MockFileSystem(mockFS)
+
+			ctx.Register()
+			_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+			FailIfErrored(t, errs)
+			_, errs = ctx.PrepareBuildActions(config)
+			FailIfErrored(t, errs)
+
+			m := ctx.ModuleForTests("foo", "").Module().(*pathDepsMutatorTestModule)
+
+			if g, w := m.sourceDeps, test.deps; !reflect.DeepEqual(g, w) {
+				t.Errorf("want deps %q, got %q", w, g)
+			}
+		})
+	}
+}
diff --git a/android/paths_test.go b/android/paths_test.go
index 20a00a0..cadf371 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -17,6 +17,8 @@
 import (
 	"errors"
 	"fmt"
+	"io/ioutil"
+	"os"
 	"reflect"
 	"strings"
 	"testing"
@@ -692,6 +694,147 @@
 	}
 }
 
+type expandSourcesTestModule struct {
+	ModuleBase
+	props struct {
+		Srcs         []string `android:"path"`
+		Exclude_srcs []string `android:"path"`
+	}
+
+	srcs Paths
+	rels []string
+}
+
+func expandSourcesTestModuleFactory() Module {
+	module := &expandSourcesTestModule{}
+	module.AddProperties(&module.props)
+	InitAndroidModule(module)
+	return module
+}
+
+func (p *expandSourcesTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+	p.srcs = ctx.ExpandSources(p.props.Srcs, p.props.Exclude_srcs)
+
+	for _, src := range p.srcs {
+		p.rels = append(p.rels, src.Rel())
+	}
+}
+
+func TestExpandSources(t *testing.T) {
+	tests := []struct {
+		name string
+		bp   string
+		srcs []string
+		rels []string
+	}{
+		{
+			name: "path",
+			bp: `
+			test {
+				name: "foo",
+				srcs: ["src/b"],
+			}`,
+			srcs: []string{"foo/src/b"},
+			rels: []string{"src/b"},
+		},
+		{
+			name: "glob",
+			bp: `
+			test {
+				name: "foo",
+				srcs: [
+					"src/*",
+					"src/e/*",
+				],
+			}`,
+			srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
+			rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
+		},
+		{
+			name: "recursive glob",
+			bp: `
+			test {
+				name: "foo",
+				srcs: ["src/**/*"],
+			}`,
+			srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
+			rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
+		},
+		{
+			name: "filegroup",
+			bp: `
+			test {
+				name: "foo",
+				srcs: [":a"],
+			}`,
+			srcs: []string{"fg/src/a"},
+			rels: []string{"src/a"},
+		},
+		{
+			name: "special characters glob",
+			bp: `
+			test {
+				name: "foo",
+				srcs: ["src_special/*"],
+			}`,
+			srcs: []string{"foo/src_special/$"},
+			rels: []string{"src_special/$"},
+		},
+	}
+
+	buildDir, err := ioutil.TempDir("", "soong_path_for_module_src_test")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(buildDir)
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			config := TestConfig(buildDir, nil)
+			ctx := NewTestContext()
+
+			ctx.RegisterModuleType("test", ModuleFactoryAdaptor(expandSourcesTestModuleFactory))
+			ctx.RegisterModuleType("filegroup", ModuleFactoryAdaptor(FileGroupFactory))
+
+			fgBp := `
+				filegroup {
+					name: "a",
+					srcs: ["src/a"],
+				}
+			`
+
+			mockFS := map[string][]byte{
+				"fg/Android.bp":     []byte(fgBp),
+				"foo/Android.bp":    []byte(test.bp),
+				"fg/src/a":          nil,
+				"foo/src/b":         nil,
+				"foo/src/c":         nil,
+				"foo/src/d":         nil,
+				"foo/src/e/e":       nil,
+				"foo/src_special/$": nil,
+			}
+
+			ctx.MockFileSystem(mockFS)
+
+			ctx.Register()
+			_, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp"})
+			FailIfErrored(t, errs)
+			_, errs = ctx.PrepareBuildActions(config)
+			FailIfErrored(t, errs)
+
+			m := ctx.ModuleForTests("foo", "").Module().(*expandSourcesTestModule)
+
+			if g, w := m.srcs.Strings(), test.srcs; !reflect.DeepEqual(g, w) {
+				t.Errorf("want srcs %q, got %q", w, g)
+			}
+
+			if g, w := m.rels, test.rels; !reflect.DeepEqual(g, w) {
+				t.Errorf("want rels %q, got %q", w, g)
+			}
+		})
+	}
+}
+
 func ExampleOutputPath_ReplaceExtension() {
 	ctx := &configErrorWrapper{
 		config: TestConfig("out", nil),
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 47c5cf5..ea4870d 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -137,9 +137,6 @@
 		} else {
 			m.SkipInstall()
 		}
-		if len(*p.srcs) > 0 {
-			ExtractSourceDeps(ctx, &(*p.srcs)[0])
-		}
 	}
 }
 
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
index c58cc4f..6c8fb31 100644
--- a/android/prebuilt_etc.go
+++ b/android/prebuilt_etc.go
@@ -35,7 +35,7 @@
 
 type prebuiltEtcProperties struct {
 	// Source file of this prebuilt.
-	Src *string `android:"arch_variant"`
+	Src *string `android:"path,arch_variant"`
 
 	// optional subdirectory under which this file is installed into
 	Sub_dir *string `android:"arch_variant"`
@@ -85,9 +85,6 @@
 	if p.properties.Src == nil {
 		ctx.PropertyErrorf("src", "missing prebuilt source file")
 	}
-
-	// To support ":modulename" in src
-	ExtractSourceDeps(ctx, p.properties.Src)
 }
 
 func (p *PrebuiltEtc) SourceFilePath(ctx ModuleContext) Path {
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index b30ca1a..319c15d 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -196,7 +196,7 @@
 	ModuleBase
 	prebuilt   Prebuilt
 	properties struct {
-		Srcs []string
+		Srcs []string `android:"path"`
 	}
 }
 
diff --git a/android/register.go b/android/register.go
index 93c2870..d79982a 100644
--- a/android/register.go
+++ b/android/register.go
@@ -61,7 +61,7 @@
 		if makevars, ok := singleton.(SingletonMakeVarsProvider); ok {
 			registerSingletonMakeVarsProvider(makevars)
 		}
-		return singletonAdaptor{singleton}
+		return &singletonAdaptor{Singleton: singleton}
 	}
 }
 
diff --git a/android/rule_builder.go b/android/rule_builder.go
index ff43e22..a2a5366 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -240,8 +240,9 @@
 	if len(r.Commands()) > 0 {
 		ctx.Build(pctx, BuildParams{
 			Rule: ctx.Rule(pctx, name, blueprint.RuleParams{
-				Command:     strings.Join(proptools.NinjaEscape(r.Commands()), " && "),
+				Command:     strings.Join(proptools.NinjaEscapeList(r.Commands()), " && "),
 				CommandDeps: r.Tools().Strings(),
+				Restat:      r.restat,
 			}),
 			Implicits:   r.Inputs(),
 			Outputs:     r.Outputs(),
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index f738faf..01d23e5 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -331,6 +331,8 @@
 
 	rule.Command().Tool(PathForSource(ctx, "cp")).Input(in).Output(out)
 
+	rule.Restat()
+
 	rule.Build(pctx, ctx, "rule", "desc")
 }
 
@@ -364,17 +366,30 @@
 	_, errs = ctx.PrepareBuildActions(config)
 	FailIfErrored(t, errs)
 
-	foo := ctx.ModuleForTests("foo", "").Rule("rule")
+	check := func(t *testing.T, params TestingBuildParams, wantOutput string) {
+		if len(params.RuleParams.CommandDeps) != 1 || params.RuleParams.CommandDeps[0] != "cp" {
+			t.Errorf("want RuleParams.CommandDeps = [%q], got %q", "cp", params.RuleParams.CommandDeps)
+		}
 
-	// TODO: make RuleParams accessible to tests and verify rule.Command().Tools() ends up in CommandDeps
+		if len(params.Implicits) != 1 || params.Implicits[0].String() != "bar" {
+			t.Errorf("want Implicits = [%q], got %q", "bar", params.Implicits.Strings())
+		}
 
-	if len(foo.Implicits) != 1 || foo.Implicits[0].String() != "bar" {
-		t.Errorf("want foo.Implicits = [%q], got %q", "bar", foo.Implicits.Strings())
+		if len(params.Outputs) != 1 || params.Outputs[0].String() != wantOutput {
+			t.Errorf("want Outputs = [%q], got %q", wantOutput, params.Outputs.Strings())
+		}
+
+		if !params.RuleParams.Restat {
+			t.Errorf("want RuleParams.Restat = true, got %v", params.RuleParams.Restat)
+		}
 	}
 
-	wantOutput := filepath.Join(buildDir, ".intermediates", "foo", "foo")
-	if len(foo.Outputs) != 1 || foo.Outputs[0].String() != wantOutput {
-		t.Errorf("want foo.Outputs = [%q], got %q", wantOutput, foo.Outputs.Strings())
-	}
-
+	t.Run("module", func(t *testing.T) {
+		check(t, ctx.ModuleForTests("foo", "").Rule("rule"),
+			filepath.Join(buildDir, ".intermediates", "foo", "foo"))
+	})
+	t.Run("singleton", func(t *testing.T) {
+		check(t, ctx.SingletonForTests("rule_builder_test").Rule("rule"),
+			filepath.Join(buildDir, "baz"))
+	})
 }
diff --git a/android/sh_binary.go b/android/sh_binary.go
index 3915193..eaedc9f 100644
--- a/android/sh_binary.go
+++ b/android/sh_binary.go
@@ -32,7 +32,7 @@
 
 type shBinaryProperties struct {
 	// Source file of this prebuilt.
-	Src *string `android:"arch_variant"`
+	Src *string `android:"path,arch_variant"`
 
 	// optional subdirectory under which this file is installed into
 	Sub_dir *string `android:"arch_variant"`
@@ -61,9 +61,6 @@
 	if s.properties.Src == nil {
 		ctx.PropertyErrorf("src", "missing prebuilt source file")
 	}
-
-	// To support ":modulename" in src
-	ExtractSourceDeps(ctx, s.properties.Src)
 }
 
 func (s *ShBinary) SourceFilePath(ctx ModuleContext) Path {
diff --git a/android/singleton.go b/android/singleton.go
index 05ec6b5..a59d54a 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -76,10 +76,31 @@
 
 type singletonAdaptor struct {
 	Singleton
+
+	buildParams []BuildParams
+	ruleParams  map[blueprint.Rule]blueprint.RuleParams
 }
 
-func (s singletonAdaptor) GenerateBuildActions(ctx blueprint.SingletonContext) {
-	s.Singleton.GenerateBuildActions(singletonContextAdaptor{ctx})
+var _ testBuildProvider = (*singletonAdaptor)(nil)
+
+func (s *singletonAdaptor) GenerateBuildActions(ctx blueprint.SingletonContext) {
+	sctx := &singletonContextAdaptor{SingletonContext: ctx}
+	if sctx.Config().captureBuild {
+		sctx.ruleParams = make(map[blueprint.Rule]blueprint.RuleParams)
+	}
+
+	s.Singleton.GenerateBuildActions(sctx)
+
+	s.buildParams = sctx.buildParams
+	s.ruleParams = sctx.ruleParams
+}
+
+func (s *singletonAdaptor) BuildParamsForTests() []BuildParams {
+	return s.buildParams
+}
+
+func (s *singletonAdaptor) RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams {
+	return s.ruleParams
 }
 
 type Singleton interface {
@@ -88,35 +109,45 @@
 
 type singletonContextAdaptor struct {
 	blueprint.SingletonContext
+
+	buildParams []BuildParams
+	ruleParams  map[blueprint.Rule]blueprint.RuleParams
 }
 
-func (s singletonContextAdaptor) Config() Config {
+func (s *singletonContextAdaptor) Config() Config {
 	return s.SingletonContext.Config().(Config)
 }
 
-func (s singletonContextAdaptor) DeviceConfig() DeviceConfig {
+func (s *singletonContextAdaptor) DeviceConfig() DeviceConfig {
 	return DeviceConfig{s.Config().deviceConfig}
 }
 
-func (s singletonContextAdaptor) Variable(pctx PackageContext, name, value string) {
+func (s *singletonContextAdaptor) Variable(pctx PackageContext, name, value string) {
 	s.SingletonContext.Variable(pctx.PackageContext, name, value)
 }
 
-func (s singletonContextAdaptor) Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule {
-	return s.SingletonContext.Rule(pctx.PackageContext, name, params, argNames...)
+func (s *singletonContextAdaptor) Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule {
+	rule := s.SingletonContext.Rule(pctx.PackageContext, name, params, argNames...)
+	if s.Config().captureBuild {
+		s.ruleParams[rule] = params
+	}
+	return rule
 }
 
-func (s singletonContextAdaptor) Build(pctx PackageContext, params BuildParams) {
+func (s *singletonContextAdaptor) Build(pctx PackageContext, params BuildParams) {
+	if s.Config().captureBuild {
+		s.buildParams = append(s.buildParams, params)
+	}
 	bparams := convertBuildParams(params)
 	s.SingletonContext.Build(pctx.PackageContext, bparams)
 
 }
 
-func (s singletonContextAdaptor) SetNinjaBuildDir(pctx PackageContext, value string) {
+func (s *singletonContextAdaptor) SetNinjaBuildDir(pctx PackageContext, value string) {
 	s.SingletonContext.SetNinjaBuildDir(pctx.PackageContext, value)
 }
 
-func (s singletonContextAdaptor) Eval(pctx PackageContext, ninjaStr string) (string, error) {
+func (s *singletonContextAdaptor) Eval(pctx PackageContext, ninjaStr string) (string, error) {
 	return s.SingletonContext.Eval(pctx.PackageContext, ninjaStr)
 }
 
@@ -144,34 +175,34 @@
 	}
 }
 
-func (s singletonContextAdaptor) VisitAllModulesBlueprint(visit func(blueprint.Module)) {
+func (s *singletonContextAdaptor) VisitAllModulesBlueprint(visit func(blueprint.Module)) {
 	s.SingletonContext.VisitAllModules(visit)
 }
 
-func (s singletonContextAdaptor) VisitAllModules(visit func(Module)) {
+func (s *singletonContextAdaptor) VisitAllModules(visit func(Module)) {
 	s.SingletonContext.VisitAllModules(visitAdaptor(visit))
 }
 
-func (s singletonContextAdaptor) VisitAllModulesIf(pred func(Module) bool, visit func(Module)) {
+func (s *singletonContextAdaptor) VisitAllModulesIf(pred func(Module) bool, visit func(Module)) {
 	s.SingletonContext.VisitAllModulesIf(predAdaptor(pred), visitAdaptor(visit))
 }
 
-func (s singletonContextAdaptor) VisitDepsDepthFirst(module Module, visit func(Module)) {
+func (s *singletonContextAdaptor) VisitDepsDepthFirst(module Module, visit func(Module)) {
 	s.SingletonContext.VisitDepsDepthFirst(module, visitAdaptor(visit))
 }
 
-func (s singletonContextAdaptor) VisitDepsDepthFirstIf(module Module, pred func(Module) bool, visit func(Module)) {
+func (s *singletonContextAdaptor) VisitDepsDepthFirstIf(module Module, pred func(Module) bool, visit func(Module)) {
 	s.SingletonContext.VisitDepsDepthFirstIf(module, predAdaptor(pred), visitAdaptor(visit))
 }
 
-func (s singletonContextAdaptor) VisitAllModuleVariants(module Module, visit func(Module)) {
+func (s *singletonContextAdaptor) VisitAllModuleVariants(module Module, visit func(Module)) {
 	s.SingletonContext.VisitAllModuleVariants(module, visitAdaptor(visit))
 }
 
-func (s singletonContextAdaptor) PrimaryModule(module Module) Module {
+func (s *singletonContextAdaptor) PrimaryModule(module Module) Module {
 	return s.SingletonContext.PrimaryModule(module).(Module)
 }
 
-func (s singletonContextAdaptor) FinalModule(module Module) Module {
+func (s *singletonContextAdaptor) FinalModule(module Module) Module {
 	return s.SingletonContext.FinalModule(module).(Module)
 }
diff --git a/android/testing.go b/android/testing.go
index b7a043e..7f443a3 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -31,12 +31,14 @@
 
 	nameResolver := NewNameResolver(namespaceExportFilter)
 	ctx := &TestContext{
-		Context:      blueprint.NewContext(),
+		Context:      &Context{blueprint.NewContext()},
 		NameResolver: nameResolver,
 	}
 
 	ctx.SetNameInterface(nameResolver)
 
+	ctx.postDeps = append(ctx.postDeps, registerPathDepsMutator)
+
 	return ctx
 }
 
@@ -47,7 +49,7 @@
 }
 
 type TestContext struct {
-	*blueprint.Context
+	*Context
 	preArch, preDeps, postDeps []RegisterMutatorFunc
 	NameResolver               *NameResolver
 }
@@ -65,7 +67,7 @@
 }
 
 func (ctx *TestContext) Register() {
-	registerMutators(ctx.Context, ctx.preArch, ctx.preDeps, ctx.postDeps)
+	registerMutators(ctx.Context.Context, ctx.preArch, ctx.preDeps, ctx.postDeps)
 
 	ctx.RegisterSingletonType("env", SingletonFactoryAdaptor(EnvSingleton))
 }
@@ -102,6 +104,24 @@
 	return variants
 }
 
+// SingletonForTests returns a TestingSingleton for the singleton registered with the given name.
+func (ctx *TestContext) SingletonForTests(name string) TestingSingleton {
+	allSingletonNames := []string{}
+	for _, s := range ctx.Singletons() {
+		n := ctx.SingletonName(s)
+		if n == name {
+			return TestingSingleton{
+				singleton: s.(*singletonAdaptor).Singleton,
+				provider:  s.(testBuildProvider),
+			}
+		}
+		allSingletonNames = append(allSingletonNames, n)
+	}
+
+	panic(fmt.Errorf("failed to find singleton %q."+
+		"\nall singletons: %v", name, allSingletonNames))
+}
+
 // MockFileSystem causes the Context to replace all reads with accesses to the provided map of
 // filenames to contents stored as a byte slice.
 func (ctx *TestContext) MockFileSystem(files map[string][]byte) {
@@ -121,6 +141,95 @@
 	ctx.Context.MockFileSystem(files)
 }
 
+type testBuildProvider interface {
+	BuildParamsForTests() []BuildParams
+	RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
+}
+
+type TestingBuildParams struct {
+	BuildParams
+	RuleParams blueprint.RuleParams
+}
+
+func newTestingBuildParams(provider testBuildProvider, bparams BuildParams) TestingBuildParams {
+	return TestingBuildParams{
+		BuildParams: bparams,
+		RuleParams:  provider.RuleParamsForTests()[bparams.Rule],
+	}
+}
+
+func maybeBuildParamsFromRule(provider testBuildProvider, rule string) TestingBuildParams {
+	for _, p := range provider.BuildParamsForTests() {
+		if strings.Contains(p.Rule.String(), rule) {
+			return newTestingBuildParams(provider, p)
+		}
+	}
+	return TestingBuildParams{}
+}
+
+func buildParamsFromRule(provider testBuildProvider, rule string) TestingBuildParams {
+	p := maybeBuildParamsFromRule(provider, rule)
+	if p.Rule == nil {
+		panic(fmt.Errorf("couldn't find rule %q", rule))
+	}
+	return p
+}
+
+func maybeBuildParamsFromDescription(provider testBuildProvider, desc string) TestingBuildParams {
+	for _, p := range provider.BuildParamsForTests() {
+		if p.Description == desc {
+			return newTestingBuildParams(provider, p)
+		}
+	}
+	return TestingBuildParams{}
+}
+
+func buildParamsFromDescription(provider testBuildProvider, desc string) TestingBuildParams {
+	p := maybeBuildParamsFromDescription(provider, desc)
+	if p.Rule == nil {
+		panic(fmt.Errorf("couldn't find description %q", desc))
+	}
+	return p
+}
+
+func maybeBuildParamsFromOutput(provider testBuildProvider, file string) (TestingBuildParams, []string) {
+	var searchedOutputs []string
+	for _, p := range provider.BuildParamsForTests() {
+		outputs := append(WritablePaths(nil), p.Outputs...)
+		if p.Output != nil {
+			outputs = append(outputs, p.Output)
+		}
+		for _, f := range outputs {
+			if f.String() == file || f.Rel() == file {
+				return newTestingBuildParams(provider, p), nil
+			}
+			searchedOutputs = append(searchedOutputs, f.Rel())
+		}
+	}
+	return TestingBuildParams{}, searchedOutputs
+}
+
+func buildParamsFromOutput(provider testBuildProvider, file string) TestingBuildParams {
+	p, searchedOutputs := maybeBuildParamsFromOutput(provider, file)
+	if p.Rule == nil {
+		panic(fmt.Errorf("couldn't find output %q.\nall outputs: %v",
+			file, searchedOutputs))
+	}
+	return p
+}
+
+func allOutputs(provider testBuildProvider) []string {
+	var outputFullPaths []string
+	for _, p := range provider.BuildParamsForTests() {
+		outputs := append(WritablePaths(nil), p.Outputs...)
+		if p.Output != nil {
+			outputs = append(outputs, p.Output)
+		}
+		outputFullPaths = append(outputFullPaths, outputs.Strings()...)
+	}
+	return outputFullPaths
+}
+
 // TestingModule is wrapper around an android.Module that provides methods to find information about individual
 // ctx.Build parameters for verification in tests.
 type TestingModule struct {
@@ -134,91 +243,96 @@
 
 // MaybeRule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name.  Returns an empty
 // BuildParams if no rule is found.
-func (m TestingModule) MaybeRule(rule string) BuildParams {
-	for _, p := range m.module.BuildParamsForTests() {
-		if strings.Contains(p.Rule.String(), rule) {
-			return p
-		}
-	}
-	return BuildParams{}
+func (m TestingModule) MaybeRule(rule string) TestingBuildParams {
+	return maybeBuildParamsFromRule(m.module, rule)
 }
 
 // Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name.  Panics if no rule is found.
-func (m TestingModule) Rule(rule string) BuildParams {
-	p := m.MaybeRule(rule)
-	if p.Rule == nil {
-		panic(fmt.Errorf("couldn't find rule %q", rule))
-	}
-	return p
+func (m TestingModule) Rule(rule string) TestingBuildParams {
+	return buildParamsFromRule(m.module, rule)
 }
 
 // MaybeDescription finds a call to ctx.Build with BuildParams.Description set to a the given string.  Returns an empty
 // BuildParams if no rule is found.
-func (m TestingModule) MaybeDescription(desc string) BuildParams {
-	for _, p := range m.module.BuildParamsForTests() {
-		if p.Description == desc {
-			return p
-		}
-	}
-	return BuildParams{}
+func (m TestingModule) MaybeDescription(desc string) TestingBuildParams {
+	return maybeBuildParamsFromDescription(m.module, desc)
 }
 
 // Description finds a call to ctx.Build with BuildParams.Description set to a the given string.  Panics if no rule is
 // found.
-func (m TestingModule) Description(desc string) BuildParams {
-	p := m.MaybeDescription(desc)
-	if p.Rule == nil {
-		panic(fmt.Errorf("couldn't find description %q", desc))
-	}
-	return p
-}
-
-func (m TestingModule) maybeOutput(file string) (BuildParams, []string) {
-	var searchedOutputs []string
-	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.String() == file || f.Rel() == file {
-				return p, nil
-			}
-			searchedOutputs = append(searchedOutputs, f.Rel())
-		}
-	}
-	return BuildParams{}, searchedOutputs
+func (m TestingModule) Description(desc string) TestingBuildParams {
+	return buildParamsFromDescription(m.module, desc)
 }
 
 // MaybeOutput finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
 // value matches the provided string.  Returns an empty BuildParams if no rule is found.
-func (m TestingModule) MaybeOutput(file string) BuildParams {
-	p, _ := m.maybeOutput(file)
+func (m TestingModule) MaybeOutput(file string) TestingBuildParams {
+	p, _ := maybeBuildParamsFromOutput(m.module, file)
 	return p
 }
 
 // Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
 // value matches the provided string.  Panics if no rule is found.
-func (m TestingModule) Output(file string) BuildParams {
-	p, searchedOutputs := m.maybeOutput(file)
-	if p.Rule == nil {
-		panic(fmt.Errorf("couldn't find output %q.\nall outputs: %v",
-			file, searchedOutputs))
-	}
-	return p
+func (m TestingModule) Output(file string) TestingBuildParams {
+	return buildParamsFromOutput(m.module, file)
 }
 
 // AllOutputs returns all 'BuildParams.Output's and 'BuildParams.Outputs's in their full path string forms.
 func (m TestingModule) AllOutputs() []string {
-	var outputFullPaths []string
-	for _, p := range m.module.BuildParamsForTests() {
-		outputs := append(WritablePaths(nil), p.Outputs...)
-		if p.Output != nil {
-			outputs = append(outputs, p.Output)
-		}
-		outputFullPaths = append(outputFullPaths, outputs.Strings()...)
-	}
-	return outputFullPaths
+	return allOutputs(m.module)
+}
+
+// TestingSingleton is wrapper around an android.Singleton that provides methods to find information about individual
+// ctx.Build parameters for verification in tests.
+type TestingSingleton struct {
+	singleton Singleton
+	provider  testBuildProvider
+}
+
+// Singleton returns the Singleton wrapped by the TestingSingleton.
+func (s TestingSingleton) Singleton() Singleton {
+	return s.singleton
+}
+
+// MaybeRule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name.  Returns an empty
+// BuildParams if no rule is found.
+func (s TestingSingleton) MaybeRule(rule string) TestingBuildParams {
+	return maybeBuildParamsFromRule(s.provider, rule)
+}
+
+// Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name.  Panics if no rule is found.
+func (s TestingSingleton) Rule(rule string) TestingBuildParams {
+	return buildParamsFromRule(s.provider, rule)
+}
+
+// MaybeDescription finds a call to ctx.Build with BuildParams.Description set to a the given string.  Returns an empty
+// BuildParams if no rule is found.
+func (s TestingSingleton) MaybeDescription(desc string) TestingBuildParams {
+	return maybeBuildParamsFromDescription(s.provider, desc)
+}
+
+// Description finds a call to ctx.Build with BuildParams.Description set to a the given string.  Panics if no rule is
+// found.
+func (s TestingSingleton) Description(desc string) TestingBuildParams {
+	return buildParamsFromDescription(s.provider, desc)
+}
+
+// MaybeOutput finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
+// value matches the provided string.  Returns an empty BuildParams if no rule is found.
+func (s TestingSingleton) MaybeOutput(file string) TestingBuildParams {
+	p, _ := maybeBuildParamsFromOutput(s.provider, file)
+	return p
+}
+
+// Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
+// value matches the provided string.  Panics if no rule is found.
+func (s TestingSingleton) Output(file string) TestingBuildParams {
+	return buildParamsFromOutput(s.provider, file)
+}
+
+// AllOutputs returns all 'BuildParams.Output's and 'BuildParams.Outputs's in their full path string forms.
+func (s TestingSingleton) AllOutputs() []string {
+	return allOutputs(s.provider)
 }
 
 func FailIfErrored(t *testing.T, errs []error) {
diff --git a/android/variable.go b/android/variable.go
index 5ee888f..1c17e5a 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -87,6 +87,7 @@
 			Cflags   []string
 			Cppflags []string
 			Init_rc  []string
+			Required []string
 		}
 
 		// eng is true for -eng builds, and can be used to turn on additionaly heavyweight debugging
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index c66acdc..1d66ab7 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -42,26 +42,24 @@
 
 var rewriteProperties = map[string](func(variableAssignmentContext) error){
 	// custom functions
-	"LOCAL_32_BIT_ONLY":             local32BitOnly,
-	"LOCAL_ADDITIONAL_CERTIFICATES": localizePathList("additional_certificates"),
-	"LOCAL_AIDL_INCLUDES":           localAidlIncludes,
-	"LOCAL_ASSET_DIR":               localizePathList("asset_dirs"),
-	"LOCAL_C_INCLUDES":              localIncludeDirs,
-	"LOCAL_CERTIFICATE":             localizePath("certificate"),
-	"LOCAL_EXPORT_C_INCLUDE_DIRS":   exportIncludeDirs,
-	"LOCAL_JARJAR_RULES":            localizePath("jarjar_rules"),
-	"LOCAL_LDFLAGS":                 ldflags,
-	"LOCAL_MODULE_CLASS":            prebuiltClass,
-	"LOCAL_MODULE_STEM":             stem,
-	"LOCAL_MODULE_HOST_OS":          hostOs,
-	"LOCAL_RESOURCE_DIR":            localizePathList("resource_dirs"),
-	"LOCAL_SANITIZE":                sanitize(""),
-	"LOCAL_SANITIZE_DIAG":           sanitize("diag."),
-	"LOCAL_STRIP_MODULE":            strip(),
-	"LOCAL_CFLAGS":                  cflags,
-	"LOCAL_UNINSTALLABLE_MODULE":    invert("installable"),
-	"LOCAL_PROGUARD_ENABLED":        proguardEnabled,
-	"LOCAL_MODULE_PATH":             prebuiltModulePath,
+	"LOCAL_32_BIT_ONLY":           local32BitOnly,
+	"LOCAL_AIDL_INCLUDES":         localAidlIncludes,
+	"LOCAL_ASSET_DIR":             localizePathList("asset_dirs"),
+	"LOCAL_C_INCLUDES":            localIncludeDirs,
+	"LOCAL_EXPORT_C_INCLUDE_DIRS": exportIncludeDirs,
+	"LOCAL_JARJAR_RULES":          localizePath("jarjar_rules"),
+	"LOCAL_LDFLAGS":               ldflags,
+	"LOCAL_MODULE_CLASS":          prebuiltClass,
+	"LOCAL_MODULE_STEM":           stem,
+	"LOCAL_MODULE_HOST_OS":        hostOs,
+	"LOCAL_RESOURCE_DIR":          localizePathList("resource_dirs"),
+	"LOCAL_SANITIZE":              sanitize(""),
+	"LOCAL_SANITIZE_DIAG":         sanitize("diag."),
+	"LOCAL_STRIP_MODULE":          strip(),
+	"LOCAL_CFLAGS":                cflags,
+	"LOCAL_UNINSTALLABLE_MODULE":  invert("installable"),
+	"LOCAL_PROGUARD_ENABLED":      proguardEnabled,
+	"LOCAL_MODULE_PATH":           prebuiltModulePath,
 
 	// composite functions
 	"LOCAL_MODULE_TAGS": includeVariableIf(bpVariable{"tags", bpparser.ListType}, not(valueDumpEquals("optional"))),
@@ -98,6 +96,7 @@
 			"LOCAL_MIN_SDK_VERSION":         "min_sdk_version",
 			"LOCAL_NDK_STL_VARIANT":         "stl",
 			"LOCAL_JAR_MANIFEST":            "manifest",
+			"LOCAL_CERTIFICATE":             "certificate",
 			"LOCAL_PACKAGE_NAME":            "name",
 			"LOCAL_MODULE_RELATIVE_PATH":    "relative_install_path",
 			"LOCAL_PROTOC_OPTIMIZE_TYPE":    "proto.type",
@@ -163,6 +162,7 @@
 			// java_library_static to android_library.
 			"LOCAL_SHARED_ANDROID_LIBRARIES": "android_libs",
 			"LOCAL_STATIC_ANDROID_LIBRARIES": "android_static_libs",
+			"LOCAL_ADDITIONAL_CERTIFICATES":  "additional_certificates",
 
 			// Jacoco filters:
 			"LOCAL_JACK_COVERAGE_INCLUDE_FILTER": "jacoco.include_filter",
@@ -918,6 +918,7 @@
 	"BUILD_HOST_DALVIK_JAVA_LIBRARY": "java_library_host_dalvik",
 	"BUILD_PACKAGE":                  "android_app",
 
+	"BUILD_CTS_EXECUTABLE":          "cc_binary",               // will be further massaged by bpfix depending on the output path
 	"BUILD_CTS_SUPPORT_PACKAGE":     "cts_support_package",     // will be rewritten to android_test by bpfix
 	"BUILD_CTS_PACKAGE":             "cts_package",             // will be rewritten to android_test by bpfix
 	"BUILD_CTS_TARGET_JAVA_LIBRARY": "cts_target_java_library", // will be rewritten to java_library by bpfix
diff --git a/androidmk/cmd/androidmk/androidmk.go b/androidmk/cmd/androidmk/androidmk.go
index 0426b43..d2a84d1 100644
--- a/androidmk/cmd/androidmk/androidmk.go
+++ b/androidmk/cmd/androidmk/androidmk.go
@@ -208,7 +208,7 @@
 					file.errorf(x, "missing if before else")
 					continue
 				} else if conds[len(conds)-1] == nil {
-					file.errorf(x, "else from unsupported contitional")
+					file.errorf(x, "else from unsupported conditional")
 					continue
 				}
 				conds[len(conds)-1].eq = !conds[len(conds)-1].eq
@@ -217,7 +217,7 @@
 					file.errorf(x, "missing if before endif")
 					continue
 				} else if conds[len(conds)-1] == nil {
-					file.errorf(x, "endif from unsupported contitional")
+					file.errorf(x, "endif from unsupported conditional")
 					conds = conds[:len(conds)-1]
 				} else {
 					if assignmentCond == conds[len(conds)-1] {
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index bc249d0..98d4506 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -118,8 +118,6 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res $(LOCAL_PATH)/res2
 LOCAL_ASSET_DIR := $(LOCAL_PATH)/asset
 LOCAL_JARJAR_RULES := $(LOCAL_PATH)/jarjar-rules.txt
-LOCAL_CERTIFICATE := $(LOCAL_PATH)/cert
-LOCAL_ADDITIONAL_CERTIFICATES := $(LOCAL_PATH)/cert1 $(LOCAL_PATH)/cert2
 include $(BUILD_PACKAGE)
 	`,
 		expected: `
@@ -130,11 +128,6 @@
 	],
 	asset_dirs: ["asset"],
 	jarjar_rules: "jarjar-rules.txt",
-	certificate: "cert",
-	additional_certificates: [
-		"cert1",
-		"cert2",
-	],
 }`,
 	},
 	{
@@ -511,9 +504,9 @@
 //  # b==false
 // echo end
 //
-// ANDROIDMK TRANSLATION ERROR: endif from unsupported contitional
+// ANDROIDMK TRANSLATION ERROR: endif from unsupported conditional
 // endif
-// ANDROIDMK TRANSLATION ERROR: endif from unsupported contitional
+// ANDROIDMK TRANSLATION ERROR: endif from unsupported conditional
 // endif
 		`,
 	},
@@ -1071,6 +1064,17 @@
 }
 `,
 	},
+	{
+		desc: "comment with ESC",
+		in: `
+# Comment line 1 \
+# Comment line 2
+`,
+		expected: `
+// Comment line 1 \
+// Comment line 2
+`,
+	},
 }
 
 func TestEndToEnd(t *testing.T) {
diff --git a/androidmk/parser/parser.go b/androidmk/parser/parser.go
index 89c1af9..86dabf9 100644
--- a/androidmk/parser/parser.go
+++ b/androidmk/parser/parser.go
@@ -485,10 +485,12 @@
 		case '\\':
 			p.parseEscape()
 			if p.tok == '\n' {
-				comment += "\n"
-			} else {
-				comment += "\\" + p.scanner.TokenText()
+				// Special case: '\' does not "escape" newline in comment (b/127521510)
+				comment += "\\"
+				p.accept(p.tok)
+				break loop
 			}
+			comment += "\\" + p.scanner.TokenText()
 			p.accept(p.tok)
 		case '\n':
 			p.accept('\n')
diff --git a/apex/apex.go b/apex/apex.go
index f72eef3..341968b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -212,11 +212,11 @@
 type apexBundleProperties struct {
 	// Json manifest file describing meta info of this APEX bundle. Default:
 	// "apex_manifest.json"
-	Manifest *string
+	Manifest *string `android:"path"`
 
 	// AndroidManifest.xml file used for the zip container of this APEX bundle.
 	// If unspecified, a default one is automatically generated.
-	AndroidManifest *string
+	AndroidManifest *string `android:"path"`
 
 	// Determines the file contexts file for setting security context to each file in this APEX bundle.
 	// Specifically, when this is set to <value>, /system/sepolicy/apex/<value>_file_contexts file is
@@ -525,14 +525,6 @@
 	if cert != "" {
 		ctx.AddDependency(ctx.Module(), certificateTag, cert)
 	}
-
-	if String(a.properties.Manifest) != "" {
-		android.ExtractSourceDeps(ctx, a.properties.Manifest)
-	}
-
-	if String(a.properties.AndroidManifest) != "" {
-		android.ExtractSourceDeps(ctx, a.properties.AndroidManifest)
-	}
 }
 
 func (a *apexBundle) getCertString(ctx android.BaseContext) string {
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 4b0d510..01e98f1 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -44,7 +44,7 @@
 )
 
 type BpfProperties struct {
-	Srcs         []string
+	Srcs         []string `android:"path"`
 	Cflags       []string
 	Include_dirs []string
 }
@@ -95,10 +95,6 @@
 	}
 }
 
-func (bpf *bpf) DepsMutator(ctx android.BottomUpMutatorContext) {
-	android.ExtractSourcesDeps(ctx, bpf.properties.Srcs)
-}
-
 func (bpf *bpf) AndroidMk() android.AndroidMkData {
 	return android.AndroidMkData{
 		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
diff --git a/cc/cc.go b/cc/cc.go
index ddc47ea..284b58d 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -68,6 +68,8 @@
 
 		ctx.TopDown("lto_deps", ltoDepsMutator)
 		ctx.BottomUp("lto", ltoMutator).Parallel()
+
+		ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
 	})
 
 	pctx.Import("android/soong/cc/config")
@@ -1469,30 +1471,44 @@
 }
 
 // Tests whether the dependent library is okay to be double loaded inside a single process.
-// If a library is a member of VNDK and at the same time dependencies of an LLNDK library,
-// it is subject to be double loaded. Such lib should be explicitly marked as double_loaded: true
+// If a library has a vendor variant and is a (transitive) dependency of an LLNDK library,
+// it is subject to be double loaded. Such lib should be explicitly marked as double_loadable: true
 // or as vndk-sp (vndk: { enabled: true, support_system_process: true}).
-func checkDoubleLoadableLibries(ctx android.ModuleContext, from *Module, to *Module) {
-	if _, ok := from.linker.(*libraryDecorator); !ok {
-		return
-	}
+func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) {
+	check := func(child, parent android.Module) bool {
+		to, ok := child.(*Module)
+		if !ok {
+			// follow thru cc.Defaults, etc.
+			return true
+		}
 
-	if inList(ctx.ModuleName(), llndkLibraries) ||
-		(from.useVndk() && Bool(from.VendorProperties.Double_loadable)) {
-		_, depIsLlndk := to.linker.(*llndkStubDecorator)
-		depIsVndkSp := false
-		if to.vndkdep != nil && to.vndkdep.isVndkSp() {
-			depIsVndkSp = true
+		if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() {
+			return false
 		}
-		depIsVndk := false
-		if to.vndkdep != nil && to.vndkdep.isVndk() {
-			depIsVndk = true
+
+		// if target lib has no vendor variant, keep checking dependency graph
+		if !to.hasVendorVariant() {
+			return true
 		}
-		depIsDoubleLoadable := Bool(to.VendorProperties.Double_loadable)
-		if !depIsLlndk && !depIsVndkSp && !depIsDoubleLoadable && depIsVndk {
-			ctx.ModuleErrorf("links VNDK library %q that isn't double loadable (not also LL-NDK, "+
-				"VNDK-SP, or explicitly marked as 'double_loadable').",
-				ctx.OtherModuleName(to))
+
+		if to.isVndkSp() || inList(child.Name(), llndkLibraries) || Bool(to.VendorProperties.Double_loadable) {
+			return false
+		}
+
+		var stringPath []string
+		for _, m := range ctx.GetWalkPath() {
+			stringPath = append(stringPath, m.Name())
+		}
+		ctx.ModuleErrorf("links a library %q which is not LL-NDK, "+
+			"VNDK-SP, or explicitly marked as 'double_loadable:true'. "+
+			"(dependency: %s)", ctx.OtherModuleName(to), strings.Join(stringPath, " -> "))
+		return false
+	}
+	if module, ok := ctx.Module().(*Module); ok {
+		if lib, ok := module.linker.(*libraryDecorator); ok && lib.shared() {
+			if inList(ctx.ModuleName(), llndkLibraries) || Bool(module.VendorProperties.Double_loadable) {
+				ctx.WalkDeps(check)
+			}
 		}
 	}
 }
@@ -1648,7 +1664,6 @@
 			}
 
 			checkLinkType(ctx, c, ccDep, t)
-			checkDoubleLoadableLibries(ctx, c, ccDep)
 		}
 
 		var ptr *android.Paths
@@ -1911,6 +1926,10 @@
 	return variation
 }
 
+func (c *Module) IDEInfo(dpInfo *android.IdeInfo) {
+	dpInfo.Srcs = append(dpInfo.Srcs, c.Srcs().Strings()...)
+}
+
 //
 // Defaults
 //
diff --git a/cc/cc_test.go b/cc/cc_test.go
index a0914c8..8c0bcfe 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -71,6 +71,9 @@
 		ctx.BottomUp("version", VersionMutator).Parallel()
 		ctx.BottomUp("begin", BeginMutator).Parallel()
 	})
+	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
+	})
 	ctx.Register()
 
 	// add some modules that are required by the compiler and/or linker
@@ -428,6 +431,309 @@
 			nocrt: true,
 		}
 	`)
+
+	// Check whether an error is emitted when a VNDK lib depends on a non-VNDK lib.
+	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
+		cc_library {
+			name: "libvndk",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			shared_libs: ["libnonvndk"],
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libnonvndk",
+			vendor_available: true,
+			nocrt: true,
+		}
+	`)
+
+	// Check whether an error is emitted when a VNDK-private lib depends on a non-VNDK lib.
+	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
+		cc_library {
+			name: "libvndkprivate",
+			vendor_available: false,
+			vndk: {
+				enabled: true,
+			},
+			shared_libs: ["libnonvndk"],
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libnonvndk",
+			vendor_available: true,
+			nocrt: true,
+		}
+	`)
+
+	// Check whether an error is emitted when a VNDK-sp lib depends on a non-VNDK lib.
+	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
+		cc_library {
+			name: "libvndksp",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+				support_system_process: true,
+			},
+			shared_libs: ["libnonvndk"],
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libnonvndk",
+			vendor_available: true,
+			nocrt: true,
+		}
+	`)
+
+	// Check whether an error is emitted when a VNDK-sp-private lib depends on a non-VNDK lib.
+	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
+		cc_library {
+			name: "libvndkspprivate",
+			vendor_available: false,
+			vndk: {
+				enabled: true,
+				support_system_process: true,
+			},
+			shared_libs: ["libnonvndk"],
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libnonvndk",
+			vendor_available: true,
+			nocrt: true,
+		}
+	`)
+}
+
+func TestDoubleLoadbleDep(t *testing.T) {
+	// okay to link : LLNDK -> double_loadable VNDK
+	testCc(t, `
+		cc_library {
+			name: "libllndk",
+			shared_libs: ["libdoubleloadable"],
+		}
+
+		llndk_library {
+			name: "libllndk",
+			symbol_file: "",
+		}
+
+		cc_library {
+			name: "libdoubleloadable",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			double_loadable: true,
+		}
+	`)
+	// okay to link : LLNDK -> VNDK-SP
+	testCc(t, `
+		cc_library {
+			name: "libllndk",
+			shared_libs: ["libvndksp"],
+		}
+
+		llndk_library {
+			name: "libllndk",
+			symbol_file: "",
+		}
+
+		cc_library {
+			name: "libvndksp",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+				support_system_process: true,
+			},
+		}
+	`)
+	// okay to link : double_loadable -> double_loadable
+	testCc(t, `
+		cc_library {
+			name: "libdoubleloadable1",
+			shared_libs: ["libdoubleloadable2"],
+			vendor_available: true,
+			double_loadable: true,
+		}
+
+		cc_library {
+			name: "libdoubleloadable2",
+			vendor_available: true,
+			double_loadable: true,
+		}
+	`)
+	// okay to link : double_loadable VNDK -> double_loadable VNDK private
+	testCc(t, `
+		cc_library {
+			name: "libdoubleloadable",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			double_loadable: true,
+			shared_libs: ["libnondoubleloadable"],
+		}
+
+		cc_library {
+			name: "libnondoubleloadable",
+			vendor_available: false,
+			vndk: {
+				enabled: true,
+			},
+			double_loadable: true,
+		}
+	`)
+	// okay to link : LLNDK -> core-only -> vendor_available & double_loadable
+	testCc(t, `
+		cc_library {
+			name: "libllndk",
+			shared_libs: ["libcoreonly"],
+		}
+
+		llndk_library {
+			name: "libllndk",
+			symbol_file: "",
+		}
+
+		cc_library {
+			name: "libcoreonly",
+			shared_libs: ["libvendoravailable"],
+		}
+
+		// indirect dependency of LLNDK
+		cc_library {
+			name: "libvendoravailable",
+			vendor_available: true,
+			double_loadable: true,
+		}
+	`)
+}
+
+func TestDoubleLoadableDepError(t *testing.T) {
+	// Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
+	testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
+		cc_library {
+			name: "libllndk",
+			shared_libs: ["libnondoubleloadable"],
+		}
+
+		llndk_library {
+			name: "libllndk",
+			symbol_file: "",
+		}
+
+		cc_library {
+			name: "libnondoubleloadable",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+		}
+	`)
+
+	// Check whether an error is emitted when a LLNDK depends on a non-double_loadable vendor_available lib.
+	testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
+		cc_library {
+			name: "libllndk",
+			no_libgcc: true,
+			shared_libs: ["libnondoubleloadable"],
+		}
+
+		llndk_library {
+			name: "libllndk",
+			symbol_file: "",
+		}
+
+		cc_library {
+			name: "libnondoubleloadable",
+			vendor_available: true,
+		}
+	`)
+
+	// Check whether an error is emitted when a double_loadable lib depends on a non-double_loadable vendor_available lib.
+	testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
+		cc_library {
+			name: "libdoubleloadable",
+			vendor_available: true,
+			double_loadable: true,
+			shared_libs: ["libnondoubleloadable"],
+		}
+
+		cc_library {
+			name: "libnondoubleloadable",
+			vendor_available: true,
+		}
+	`)
+
+	// Check whether an error is emitted when a double_loadable lib depends on a non-double_loadable VNDK lib.
+	testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
+		cc_library {
+			name: "libdoubleloadable",
+			vendor_available: true,
+			double_loadable: true,
+			shared_libs: ["libnondoubleloadable"],
+		}
+
+		cc_library {
+			name: "libnondoubleloadable",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+		}
+	`)
+
+	// Check whether an error is emitted when a double_loadable VNDK depends on a non-double_loadable VNDK private lib.
+	testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
+		cc_library {
+			name: "libdoubleloadable",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			double_loadable: true,
+			shared_libs: ["libnondoubleloadable"],
+		}
+
+		cc_library {
+			name: "libnondoubleloadable",
+			vendor_available: false,
+			vndk: {
+				enabled: true,
+			},
+		}
+	`)
+
+	// Check whether an error is emitted when a LLNDK depends on a non-double_loadable indirectly.
+	testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
+		cc_library {
+			name: "libllndk",
+			shared_libs: ["libcoreonly"],
+		}
+
+		llndk_library {
+			name: "libllndk",
+			symbol_file: "",
+		}
+
+		cc_library {
+			name: "libcoreonly",
+			shared_libs: ["libvendoravailable"],
+		}
+
+		// indirect dependency of LLNDK
+		cc_library {
+			name: "libvendoravailable",
+			vendor_available: true,
+		}
+	`)
 }
 
 func TestVndkMustNotBeProductSpecific(t *testing.T) {
diff --git a/cc/compiler.go b/cc/compiler.go
index 0aee0bd..df396e8 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -31,11 +31,11 @@
 	// list of source files used to compile the C/C++ module.  May be .c, .cpp, or .S files.
 	// srcs may reference the outputs of other modules that produce source files like genrule
 	// or filegroup using the syntax ":module".
-	Srcs []string `android:"arch_variant"`
+	Srcs []string `android:"path,arch_variant"`
 
 	// list of source files that should not be used to build the C/C++ module.
 	// This is most useful in the arch/multilib variants to remove non-common files
-	Exclude_srcs []string `android:"arch_variant"`
+	Exclude_srcs []string `android:"path,arch_variant"`
 
 	// list of module-specific flags that will be used for C and C++ compiles.
 	Cflags []string `android:"arch_variant"`
@@ -136,11 +136,11 @@
 		Vendor struct {
 			// list of source files that should only be used in the
 			// vendor variant of the C/C++ module.
-			Srcs []string
+			Srcs []string `android:"path"`
 
 			// list of source files that should not be used to
 			// build the vendor variant of the C/C++ module.
-			Exclude_srcs []string
+			Exclude_srcs []string `android:"path"`
 
 			// List of additional cflags that should be used to build the vendor
 			// variant of the C/C++ module.
@@ -149,11 +149,11 @@
 		Recovery struct {
 			// list of source files that should only be used in the
 			// recovery variant of the C/C++ module.
-			Srcs []string
+			Srcs []string `android:"path"`
 
 			// list of source files that should not be used to
 			// build the recovery variant of the C/C++ module.
-			Exclude_srcs []string
+			Exclude_srcs []string `android:"path"`
 
 			// List of additional cflags that should be used to build the recovery
 			// variant of the C/C++ module.
@@ -221,9 +221,6 @@
 	deps.GeneratedSources = append(deps.GeneratedSources, compiler.Properties.Generated_sources...)
 	deps.GeneratedHeaders = append(deps.GeneratedHeaders, compiler.Properties.Generated_headers...)
 
-	android.ExtractSourcesDeps(ctx, compiler.Properties.Srcs)
-	android.ExtractSourcesDeps(ctx, compiler.Properties.Exclude_srcs)
-
 	if compiler.hasSrcExt(".proto") {
 		deps = protoDeps(ctx, deps, &compiler.Proto, Bool(compiler.Properties.Proto.Static))
 	}
@@ -269,7 +266,7 @@
 	CheckBadCompilerFlags(ctx, "vendor.cflags", compiler.Properties.Target.Vendor.Cflags)
 	CheckBadCompilerFlags(ctx, "recovery.cflags", compiler.Properties.Target.Recovery.Cflags)
 
-	esc := proptools.NinjaAndShellEscape
+	esc := proptools.NinjaAndShellEscapeList
 
 	flags.CFlags = append(flags.CFlags, esc(compiler.Properties.Cflags)...)
 	flags.CppFlags = append(flags.CppFlags, esc(compiler.Properties.Cppflags)...)
diff --git a/cc/library.go b/cc/library.go
index c23f26b..71a9df6 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -30,8 +30,8 @@
 )
 
 type StaticSharedLibraryProperties struct {
-	Srcs   []string `android:"arch_variant"`
-	Cflags []string `android:"arch_variant"`
+	Srcs   []string `android:"path,arch_variant"`
+	Cflags []string `android:"path,arch_variant"`
 
 	Enabled            *bool    `android:"arch_variant"`
 	Whole_static_libs  []string `android:"arch_variant"`
@@ -48,11 +48,11 @@
 	Shared StaticSharedLibraryProperties `android:"arch_variant"`
 
 	// local file name to pass to the linker as -unexported_symbols_list
-	Unexported_symbols_list *string `android:"arch_variant"`
+	Unexported_symbols_list *string `android:"path,arch_variant"`
 	// local file name to pass to the linker as -force_symbols_not_weak_list
-	Force_symbols_not_weak_list *string `android:"arch_variant"`
+	Force_symbols_not_weak_list *string `android:"path,arch_variant"`
 	// local file name to pass to the linker as -force_symbols_weak_list
-	Force_symbols_weak_list *string `android:"arch_variant"`
+	Force_symbols_weak_list *string `android:"path,arch_variant"`
 
 	// rename host libraries to prevent overlap with system installed libraries
 	Unique_host_soname *bool
@@ -70,14 +70,14 @@
 	Sysprop struct {
 		// Whether platform owns this sysprop library.
 		Platform *bool
-	}
+	} `blueprint:"mutated"`
 
 	Static_ndk_lib *bool
 
 	Stubs struct {
 		// Relative path to the symbol map. The symbol map provides the list of
 		// symbols that are exported for stubs variant of this library.
-		Symbol_file *string
+		Symbol_file *string `android:"path"`
 
 		// List versions to generate stubs libs for.
 		Versions []string
@@ -97,7 +97,7 @@
 	Header_abi_checker struct {
 		// Path to a symbol file that specifies the symbols to be included in the generated
 		// ABI dump file
-		Symbol_file *string
+		Symbol_file *string `android:"path"`
 
 		// Symbol versions that should be ignored from the symbol file
 		Exclude_symbol_versions []string
@@ -526,12 +526,6 @@
 func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
 	deps = library.baseCompiler.compilerDeps(ctx, deps)
 
-	if library.static() {
-		android.ExtractSourcesDeps(ctx, library.Properties.Static.Srcs)
-	} else if library.shared() {
-		android.ExtractSourcesDeps(ctx, library.Properties.Shared.Srcs)
-	}
-
 	return deps
 }
 
@@ -596,10 +590,6 @@
 		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, library.baseLinker.Properties.Target.Recovery.Exclude_static_libs)
 	}
 
-	android.ExtractSourceDeps(ctx, library.Properties.Unexported_symbols_list)
-	android.ExtractSourceDeps(ctx, library.Properties.Force_symbols_not_weak_list)
-	android.ExtractSourceDeps(ctx, library.Properties.Force_symbols_weak_list)
-
 	return deps
 }
 
diff --git a/cc/linker.go b/cc/linker.go
index 25aedd0..fd958ba 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -149,7 +149,7 @@
 	Pack_relocations *bool `android:"arch_variant"`
 
 	// local file name to pass to the linker as --version_script
-	Version_script *string `android:"arch_variant"`
+	Version_script *string `android:"path,arch_variant"`
 
 	// Local file name to pass to the linker as --symbol-ordering-file
 	Symbol_ordering_file *string `android:"arch_variant"`
@@ -281,16 +281,6 @@
 		deps.LateStaticLibs = append(deps.LateStaticLibs, "libwinpthread")
 	}
 
-	// Version_script is not needed when linking stubs lib where the version
-	// script is created from the symbol map file.
-	if !linker.dynamicProperties.BuildStubs {
-		android.ExtractSourceDeps(ctx, linker.Properties.Version_script)
-		android.ExtractSourceDeps(ctx,
-			linker.Properties.Target.Vendor.Version_script)
-	}
-
-	android.ExtractSourceDeps(ctx, linker.Properties.Symbol_ordering_file)
-
 	return deps
 }
 
@@ -392,7 +382,7 @@
 
 	CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags)
 
-	flags.LdFlags = append(flags.LdFlags, proptools.NinjaAndShellEscape(linker.Properties.Ldflags)...)
+	flags.LdFlags = append(flags.LdFlags, proptools.NinjaAndShellEscapeList(linker.Properties.Ldflags)...)
 
 	if ctx.Host() {
 		rpath_prefix := `\$$ORIGIN/`
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index c0ce9c3..2024180 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -70,13 +70,13 @@
 	To *string
 
 	// List of headers to install. Glob compatible. Common case is "include/**/*.h".
-	Srcs []string
+	Srcs []string `android:"path"`
 
 	// Source paths that should be excluded from the srcs glob.
-	Exclude_srcs []string
+	Exclude_srcs []string `android:"path"`
 
 	// Path to the NOTICE file associated with the headers.
-	License *string
+	License *string `android:"path"`
 
 	// True if this API is not yet ready to be shipped in the NDK. It will be
 	// available in the platform for testing, but will be excluded from the
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 686a85a..4c893d4 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -33,7 +33,7 @@
 	android.Prebuilt
 
 	properties struct {
-		Srcs []string `android:"arch_variant"`
+		Srcs []string `android:"path,arch_variant"`
 
 		// Check the prebuilt ELF files (e.g. DT_SONAME, DT_NEEDED, resolution of undefined
 		// symbols, etc), default true.
diff --git a/cc/test.go b/cc/test.go
index e9f0944..f0274e9 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -42,7 +42,7 @@
 
 	// list of files or filegroup modules that provide data that should be installed alongside
 	// the test
-	Data []string
+	Data []string `android:"path"`
 
 	// list of compatibility suites (for example "cts", "vts") that the module should be
 	// installed into.
@@ -50,11 +50,11 @@
 
 	// the name of the test configuration (for example "AndroidTest.xml") that should be
 	// installed with the module.
-	Test_config *string `android:"arch_variant"`
+	Test_config *string `android:"path,arch_variant"`
 
 	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
 	// should be installed with the module.
-	Test_config_template *string `android:"arch_variant"`
+	Test_config_template *string `android:"path,arch_variant"`
 }
 
 func init() {
@@ -120,6 +120,10 @@
 	if m, ok := mctx.Module().(*Module); ok {
 		if test, ok := m.linker.(testPerSrc); ok {
 			if test.testPerSrc() && len(test.srcs()) > 0 {
+				if duplicate, found := checkDuplicate(test.srcs()); found {
+					mctx.PropertyErrorf("srcs", "found a duplicate entry %q", duplicate)
+					return
+				}
 				testNames := make([]string, len(test.srcs()))
 				for i, src := range test.srcs() {
 					testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
@@ -133,6 +137,17 @@
 	}
 }
 
+func checkDuplicate(values []string) (duplicate string, found bool) {
+	seen := make(map[string]string)
+	for _, v := range values {
+		if duplicate, found = seen[v]; found {
+			return
+		}
+		seen[v] = v
+	}
+	return
+}
+
 type testDecorator struct {
 	Properties TestProperties
 	linker     *baseLinker
@@ -226,10 +241,6 @@
 }
 
 func (test *testBinary) linkerDeps(ctx DepsContext, deps Deps) Deps {
-	android.ExtractSourcesDeps(ctx, test.Properties.Data)
-	android.ExtractSourceDeps(ctx, test.Properties.Test_config)
-	android.ExtractSourceDeps(ctx, test.Properties.Test_config_template)
-
 	deps = test.testDecorator.linkerDeps(ctx, deps)
 	deps = test.binaryDecorator.linkerDeps(ctx, deps)
 	return deps
@@ -243,8 +254,13 @@
 
 func (test *testBinary) install(ctx ModuleContext, file android.Path) {
 	test.data = ctx.ExpandSources(test.Properties.Data, nil)
+	optionsMap := map[string]string{}
+	if Bool(test.testDecorator.Properties.Isolated) {
+		optionsMap["not-shardable"] = "true"
+	}
 	test.testConfig = tradefed.AutoGenNativeTestConfig(ctx, test.Properties.Test_config,
-		test.Properties.Test_config_template, test.Properties.Test_suites)
+		test.Properties.Test_config_template,
+		test.Properties.Test_suites, optionsMap)
 
 	test.binaryDecorator.baseInstaller.dir = "nativetest"
 	test.binaryDecorator.baseInstaller.dir64 = "nativetest64"
@@ -318,7 +334,7 @@
 type BenchmarkProperties struct {
 	// list of files or filegroup modules that provide data that should be installed alongside
 	// the test
-	Data []string
+	Data []string `android:"path"`
 
 	// list of compatibility suites (for example "cts", "vts") that the module should be
 	// installed into.
@@ -326,11 +342,11 @@
 
 	// the name of the test configuration (for example "AndroidTest.xml") that should be
 	// installed with the module.
-	Test_config *string `android:"arch_variant"`
+	Test_config *string `android:"path,arch_variant"`
 
 	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
 	// should be installed with the module.
-	Test_config_template *string `android:"arch_variant"`
+	Test_config_template *string `android:"path,arch_variant"`
 }
 
 type benchmarkDecorator struct {
@@ -356,10 +372,6 @@
 }
 
 func (benchmark *benchmarkDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
-	android.ExtractSourcesDeps(ctx, benchmark.Properties.Data)
-	android.ExtractSourceDeps(ctx, benchmark.Properties.Test_config)
-	android.ExtractSourceDeps(ctx, benchmark.Properties.Test_config_template)
-
 	deps = benchmark.binaryDecorator.linkerDeps(ctx, deps)
 	deps.StaticLibs = append(deps.StaticLibs, "libgoogle-benchmark")
 	return deps
diff --git a/cc/test_data_test.go b/cc/test_data_test.go
index eead25b..7ba244e 100644
--- a/cc/test_data_test.go
+++ b/cc/test_data_test.go
@@ -166,7 +166,7 @@
 	android.ModuleBase
 	data       android.Paths
 	Properties struct {
-		Data []string
+		Data []string `android:"path"`
 	}
 }
 
@@ -177,10 +177,6 @@
 	return m
 }
 
-func (test *testDataTest) DepsMutator(ctx android.BottomUpMutatorContext) {
-	android.ExtractSourcesDeps(ctx, test.Properties.Data)
-}
-
 func (test *testDataTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	test.data = ctx.ExpandSources(test.Properties.Data, nil)
 }
diff --git a/cc/tidy.go b/cc/tidy.go
index 6bac846..0b78d6f 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -69,7 +69,7 @@
 	if len(withTidyFlags) > 0 {
 		flags.TidyFlags = append(flags.TidyFlags, withTidyFlags)
 	}
-	esc := proptools.NinjaAndShellEscape
+	esc := proptools.NinjaAndShellEscapeList
 	flags.TidyFlags = append(flags.TidyFlags, esc(tidy.Properties.Tidy_flags)...)
 	// If TidyFlags is empty, add default header filter.
 	if len(flags.TidyFlags) == 0 {
diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go
index a79c84f..a399b28 100644
--- a/cmd/pom2bp/pom2bp.go
+++ b/cmd/pom2bp/pom2bp.go
@@ -605,7 +605,7 @@
 	buf := &bytes.Buffer{}
 
 	fmt.Fprintln(buf, "// Automatically generated with:")
-	fmt.Fprintln(buf, "// pom2bp", strings.Join(proptools.ShellEscape(os.Args[1:]), " "))
+	fmt.Fprintln(buf, "// pom2bp", strings.Join(proptools.ShellEscapeList(os.Args[1:]), " "))
 
 	for _, pom := range poms {
 		var err error
diff --git a/cmd/pom2mk/pom2mk.go b/cmd/pom2mk/pom2mk.go
index fc83641..94e5619 100644
--- a/cmd/pom2mk/pom2mk.go
+++ b/cmd/pom2mk/pom2mk.go
@@ -483,7 +483,7 @@
 	}
 
 	fmt.Println("# Automatically generated with:")
-	fmt.Println("# pom2mk", strings.Join(proptools.ShellEscape(os.Args[1:]), " "))
+	fmt.Println("# pom2mk", strings.Join(proptools.ShellEscapeList(os.Args[1:]), " "))
 	fmt.Println("LOCAL_PATH := $(call my-dir)")
 
 	for _, pom := range poms {
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 9e333c1..01ee15e 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -331,6 +331,14 @@
 		rule.Command().Text("source").Tool(global.Tools.ConstructContext)
 	}
 
+	// Devices that do not have a product partition use a symlink from /product to /system/product.
+	// Because on-device dexopt will see dex locations starting with /product, we change the paths
+	// to mimic this behavior.
+	dexLocationArg := module.DexLocation
+	if strings.HasPrefix(dexLocationArg, "/system/product/") {
+		dexLocationArg = strings.TrimPrefix(dexLocationArg, "/system")
+	}
+
 	cmd := rule.Command().
 		Text(`ANDROID_LOG_TAGS="*:e"`).
 		Tool(global.Tools.Dex2oat).
@@ -344,7 +352,7 @@
 		Flag("${stored_class_loader_context_arg}").
 		FlagWithArg("--boot-image=", bootImageLocation).Implicit(bootImage).
 		FlagWithInput("--dex-file=", module.DexPath).
-		FlagWithArg("--dex-location=", module.DexLocation).
+		FlagWithArg("--dex-location=", dexLocationArg).
 		FlagWithOutput("--oat-file=", odexPath).ImplicitOutput(vdexPath).
 		// Pass an empty directory, dex2oat shouldn't be reading arbitrary files
 		FlagWithArg("--android-root=", global.EmptyDirectory).
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 7695ffb..f265eb6 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -83,16 +83,16 @@
 	Tools []string
 
 	// Local file that is used as the tool
-	Tool_files []string
+	Tool_files []string `android:"path"`
 
 	// List of directories to export generated headers from
 	Export_include_dirs []string
 
 	// list of input files
-	Srcs []string `android:"arch_variant"`
+	Srcs []string `android:"path,arch_variant"`
 
 	// input files to exclude
-	Exclude_srcs []string `android:"arch_variant"`
+	Exclude_srcs []string `android:"path,arch_variant"`
 }
 
 type Module struct {
@@ -143,8 +143,6 @@
 }
 
 func (g *Module) DepsMutator(ctx android.BottomUpMutatorContext) {
-	android.ExtractSourcesDeps(ctx, g.properties.Srcs)
-	android.ExtractSourcesDeps(ctx, g.properties.Tool_files)
 	if g, ok := ctx.Module().(*Module); ok {
 		for _, tool := range g.properties.Tools {
 			tag := hostToolDependencyTag{label: tool}
@@ -453,7 +451,7 @@
 			}
 
 			// escape the command in case for example it contains '#', an odd number of '"', etc
-			command = fmt.Sprintf("bash -c %v", proptools.ShellEscape([]string{command})[0])
+			command = fmt.Sprintf("bash -c %v", proptools.ShellEscape(command))
 			commands = append(commands, command)
 		}
 		fullCommand := strings.Join(commands, " && ")
diff --git a/java/aar.go b/java/aar.go
index 9eb2b27..3f13e59 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -64,10 +64,10 @@
 	Resource_dirs []string
 
 	// list of zip files containing Android resources.
-	Resource_zips []string
+	Resource_zips []string `android:"path"`
 
 	// path to AndroidManifest.xml.  If unset, defaults to "AndroidManifest.xml".
-	Manifest *string
+	Manifest *string `android:"path"`
 }
 
 type aapt struct {
@@ -168,7 +168,7 @@
 		} else {
 			versionName = ctx.Config().AppsDefaultVersionName()
 		}
-		versionName = proptools.NinjaEscape([]string{versionName})[0]
+		versionName = proptools.NinjaEscape(versionName)
 		linkFlags = append(linkFlags, "--version-name ", versionName)
 	}
 
@@ -180,8 +180,6 @@
 	if sdkDep.frameworkResModule != "" {
 		ctx.AddVariationDependencies(nil, frameworkResTag, sdkDep.frameworkResModule)
 	}
-
-	android.ExtractSourcesDeps(ctx, a.aaptProperties.Resource_zips)
 }
 
 func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, extraLinkFlags ...string) {
@@ -406,7 +404,7 @@
 //
 
 type AARImportProperties struct {
-	Aars []string
+	Aars []string `android:"path"`
 
 	Sdk_version     *string
 	Min_sdk_version *string
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 3cca4f7..d72476d 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -21,7 +21,6 @@
 	"github.com/google/blueprint"
 
 	"android/soong/android"
-	"android/soong/java/config"
 )
 
 var manifestFixerRule = pctx.AndroidStaticRule("manifestFixer",
@@ -37,9 +36,8 @@
 
 var manifestMergerRule = pctx.AndroidStaticRule("manifestMerger",
 	blueprint.RuleParams{
-		Command: `${config.JavaCmd} -classpath ${config.ManifestMergerClasspath} com.android.manifmerger.Merger ` +
-			`--main $in $libs --out $out`,
-		CommandDeps: config.ManifestMergerClasspath,
+		Command:     `${config.ManifestMergerCmd} --main $in $libs --out $out`,
+		CommandDeps: []string{"${config.ManifestMergerCmd}"},
 	},
 	"libs")
 
diff --git a/java/app.go b/java/app.go
index 2ff6c98..8a422fc 100644
--- a/java/app.go
+++ b/java/app.go
@@ -459,9 +459,6 @@
 }
 
 func (a *AndroidTest) DepsMutator(ctx android.BottomUpMutatorContext) {
-	android.ExtractSourceDeps(ctx, a.testProperties.Test_config)
-	android.ExtractSourceDeps(ctx, a.testProperties.Test_config_template)
-	android.ExtractSourcesDeps(ctx, a.testProperties.Data)
 	a.AndroidApp.DepsMutator(ctx)
 	if a.appTestProperties.Instrumentation_for != nil {
 		// The android_app dependency listed in instrumentation_for needs to be added to the classpath for javac,
diff --git a/java/app_builder.go b/java/app_builder.go
index 6cc2159..bc91d55 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -224,7 +224,7 @@
 		Output:      outputFile,
 		Implicits:   deps,
 		Args: map[string]string{
-			"jarArgs": strings.Join(proptools.NinjaAndShellEscape(jarArgs), " "),
+			"jarArgs": strings.Join(proptools.NinjaAndShellEscapeList(jarArgs), " "),
 		},
 	})
 }
diff --git a/java/builder.go b/java/builder.go
index aa61a85..d8b303e 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -300,7 +300,7 @@
 		Output:      outputFile,
 		Implicits:   deps,
 		Args: map[string]string{
-			"jarArgs": strings.Join(proptools.NinjaAndShellEscape(jarArgs), " "),
+			"jarArgs": strings.Join(proptools.NinjaAndShellEscapeList(jarArgs), " "),
 		},
 	})
 }
diff --git a/java/config/config.go b/java/config/config.go
index 7cc249c..2762a4d 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -44,16 +44,6 @@
 		"core-oj",
 		"core-libart",
 	}
-
-	ManifestMergerClasspath = []string{
-		"prebuilts/gradle-plugin/com/android/tools/build/manifest-merger/26.1.0/manifest-merger-26.1.0.jar",
-		"prebuilts/gradle-plugin/com/android/tools/common/26.1.0/common-26.1.0.jar",
-		"prebuilts/gradle-plugin/com/android/tools/sdk-common/26.1.0/sdk-common-26.1.0.jar",
-		"prebuilts/gradle-plugin/com/android/tools/sdklib/26.1.0/sdklib-26.1.0.jar",
-		"prebuilts/gradle-plugin/org/jetbrains/kotlin/kotlin-runtime/1.0.5/kotlin-runtime-1.0.5.jar",
-		"prebuilts/gradle-plugin/org/jetbrains/kotlin/kotlin-stdlib/1.1.3/kotlin-stdlib-1.1.3.jar",
-		"prebuilts/misc/common/guava/guava-21.0.jar",
-	}
 )
 
 func init() {
@@ -61,6 +51,7 @@
 
 	pctx.StaticVariable("JavacHeapSize", "2048M")
 	pctx.StaticVariable("JavacHeapFlags", "-J-Xmx${JavacHeapSize}")
+	pctx.StaticVariable("DexFlags", "-JXX:+TieredCompilation -JXX:TieredStopAtLevel=1")
 
 	pctx.StaticVariable("CommonJdkFlags", strings.Join([]string{
 		`-Xmaxerrs 9999999`,
@@ -151,8 +142,7 @@
 
 	pctx.SourcePathVariable("ManifestFixerCmd", "build/soong/scripts/manifest_fixer.py")
 
-	pctx.SourcePathsVariable("ManifestMergerJars", " ", ManifestMergerClasspath...)
-	pctx.SourcePathsVariable("ManifestMergerClasspath", ":", ManifestMergerClasspath...)
+	pctx.HostBinToolVariable("ManifestMergerCmd", "manifest-merger")
 
 	pctx.HostBinToolVariable("ZipAlign", "zipalign")
 
diff --git a/java/config/makevars.go b/java/config/makevars.go
index 156ee26..6881caf 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -75,10 +75,10 @@
 
 	ctx.Strict("MANIFEST_FIXER", "${ManifestFixerCmd}")
 
-	ctx.Strict("ANDROID_MANIFEST_MERGER_DEPS", "${ManifestMergerJars}")
-	ctx.Strict("ANDROID_MANIFEST_MERGER",
-		"${JavaCmd} -classpath ${ManifestMergerClasspath} com.android.manifmerger.Merger")
+	ctx.Strict("ANDROID_MANIFEST_MERGER", "${ManifestMergerCmd}")
 
 	ctx.Strict("CLASS2GREYLIST", "${Class2Greylist}")
 	ctx.Strict("HIDDENAPI", "${HiddenAPI}")
+
+	ctx.Strict("DEX_FLAGS", "${DexFlags}")
 }
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
new file mode 100644
index 0000000..9f40a6c
--- /dev/null
+++ b/java/device_host_converter.go
@@ -0,0 +1,131 @@
+// Copyright 2019 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 java
+
+import (
+	"android/soong/android"
+
+	"github.com/google/blueprint"
+)
+
+type DeviceHostConverter struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	properties DeviceHostConverterProperties
+
+	headerJars                    android.Paths
+	implementationJars            android.Paths
+	implementationAndResourceJars android.Paths
+	resourceJars                  android.Paths
+}
+
+type DeviceHostConverterProperties struct {
+	// List of modules whose contents will be visible to modules that depend on this module.
+	Libs []string
+}
+
+type DeviceForHost struct {
+	DeviceHostConverter
+}
+
+// java_device_for_host makes the classes.jar output of a device java_library module available to host
+// java_library modules.
+//
+// It is rarely necessary, and its used is restricted to a few whitelisted projects.
+func DeviceForHostFactory() android.Module {
+	module := &DeviceForHost{}
+
+	module.AddProperties(&module.properties)
+
+	InitJavaModule(module, android.HostSupported)
+	return module
+}
+
+type HostForDevice struct {
+	DeviceHostConverter
+}
+
+// java_host_for_device makes the classes.jar output of a host java_library module available to device
+// java_library modules.
+//
+// It is rarely necessary, and its used is restricted to a few whitelisted projects.
+func HostForDeviceFactory() android.Module {
+	module := &HostForDevice{}
+
+	module.AddProperties(&module.properties)
+
+	InitJavaModule(module, android.DeviceSupported)
+	return module
+}
+
+var deviceHostConverterDepTag = dependencyTag{name: "device_host_converter"}
+
+func (d *DeviceForHost) DepsMutator(ctx android.BottomUpMutatorContext) {
+	variation := []blueprint.Variation{{Mutator: "arch", Variation: "android_common"}}
+	ctx.AddFarVariationDependencies(variation, deviceHostConverterDepTag, d.properties.Libs...)
+}
+
+func (d *HostForDevice) DepsMutator(ctx android.BottomUpMutatorContext) {
+	variation := []blueprint.Variation{{Mutator: "arch", Variation: ctx.Config().BuildOsCommonVariant}}
+	ctx.AddFarVariationDependencies(variation, deviceHostConverterDepTag, d.properties.Libs...)
+}
+
+func (d *DeviceHostConverter) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	if len(d.properties.Libs) < 1 {
+		ctx.PropertyErrorf("libs", "at least one dependency is required")
+	}
+
+	ctx.VisitDirectDepsWithTag(deviceHostConverterDepTag, func(m android.Module) {
+		if dep, ok := m.(Dependency); ok {
+			d.headerJars = append(d.headerJars, dep.HeaderJars()...)
+			d.implementationJars = append(d.implementationJars, dep.ImplementationJars()...)
+			d.implementationAndResourceJars = append(d.implementationAndResourceJars, dep.ImplementationAndResourcesJars()...)
+			d.resourceJars = append(d.resourceJars, dep.ResourceJars()...)
+		} else {
+			ctx.PropertyErrorf("libs", "module %q cannot be used as a dependency", ctx.OtherModuleName(m))
+		}
+	})
+}
+
+var _ Dependency = (*DeviceHostConverter)(nil)
+
+func (d *DeviceHostConverter) HeaderJars() android.Paths {
+	return d.headerJars
+}
+
+func (d *DeviceHostConverter) ImplementationJars() android.Paths {
+	return d.implementationJars
+}
+
+func (d *DeviceHostConverter) ResourceJars() android.Paths {
+	return d.resourceJars
+}
+
+func (d *DeviceHostConverter) ImplementationAndResourcesJars() android.Paths {
+	return d.implementationAndResourceJars
+}
+
+func (d *DeviceHostConverter) DexJar() android.Path {
+	return nil
+}
+
+func (d *DeviceHostConverter) AidlIncludeDirs() android.Paths {
+	return nil
+}
+
+func (d *DeviceHostConverter) ExportedSdkLibs() []string {
+	return nil
+}
diff --git a/java/device_host_converter_test.go b/java/device_host_converter_test.go
new file mode 100644
index 0000000..146bf6f
--- /dev/null
+++ b/java/device_host_converter_test.go
@@ -0,0 +1,186 @@
+// Copyright 2019 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 java
+
+import (
+	"android/soong/android"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+func TestDeviceForHost(t *testing.T) {
+	bp := `
+		java_library {
+			name: "device_module",
+			srcs: ["a.java"],
+			java_resources: ["java-res/a/a"],
+		}
+
+		java_import {
+			name: "device_import_module",
+			jars: ["a.jar"],
+		}
+
+		java_device_for_host {
+			name: "device_for_host_module",
+			libs: [
+				"device_module",
+				"device_import_module",
+			],
+		}
+
+		java_library_host {
+			name: "host_module",
+			srcs: ["b.java"],
+			java_resources: ["java-res/b/b"],
+			static_libs: ["device_for_host_module"],
+		}
+	`
+
+	config := testConfig(nil)
+	ctx := testContext(config, bp, nil)
+	run(t, ctx, config)
+
+	deviceModule := ctx.ModuleForTests("device_module", "android_common")
+	deviceTurbineCombined := deviceModule.Output("turbine-combined/device_module.jar")
+	deviceJavac := deviceModule.Output("javac/device_module.jar")
+	deviceRes := deviceModule.Output("res/device_module.jar")
+
+	deviceImportModule := ctx.ModuleForTests("device_import_module", "android_common")
+	deviceImportCombined := deviceImportModule.Output("combined/device_import_module.jar")
+
+	hostModule := ctx.ModuleForTests("host_module", config.BuildOsCommonVariant)
+	hostJavac := hostModule.Output("javac/host_module.jar")
+	hostRes := hostModule.Output("res/host_module.jar")
+	combined := hostModule.Output("combined/host_module.jar")
+	resCombined := hostModule.Output("res-combined/host_module.jar")
+
+	// check classpath of host module with dependency on device_for_host_module
+	expectedClasspath := "-classpath " + strings.Join(android.Paths{
+		deviceTurbineCombined.Output,
+		deviceImportCombined.Output,
+	}.Strings(), ":")
+
+	if hostJavac.Args["classpath"] != expectedClasspath {
+		t.Errorf("expected host_module javac classpath:\n%s\ngot:\n%s",
+			expectedClasspath, hostJavac.Args["classpath"])
+	}
+
+	// check host module merged with static dependency implementation jars from device_for_host module
+	expectedInputs := android.Paths{
+		hostJavac.Output,
+		deviceJavac.Output,
+		deviceImportCombined.Output,
+	}
+
+	if !reflect.DeepEqual(combined.Inputs, expectedInputs) {
+		t.Errorf("expected host_module combined inputs:\n%q\ngot:\n%q",
+			expectedInputs, combined.Inputs)
+	}
+
+	// check host module merged with static dependency resource jars from device_for_host module
+	expectedInputs = android.Paths{
+		hostRes.Output,
+		deviceRes.Output,
+	}
+
+	if !reflect.DeepEqual(resCombined.Inputs, expectedInputs) {
+		t.Errorf("expected host_module res combined inputs:\n%q\ngot:\n%q",
+			expectedInputs, resCombined.Inputs)
+	}
+}
+
+func TestHostForDevice(t *testing.T) {
+	bp := `
+		java_library_host {
+			name: "host_module",
+			srcs: ["a.java"],
+			java_resources: ["java-res/a/a"],
+		}
+
+		java_import_host {
+			name: "host_import_module",
+			jars: ["a.jar"],
+		}
+
+		java_host_for_device {
+			name: "host_for_device_module",
+			libs: [
+				"host_module",
+				"host_import_module",
+			],
+		}
+
+		java_library {
+			name: "device_module",
+			no_framework_libs: true,
+			srcs: ["b.java"],
+			java_resources: ["java-res/b/b"],
+			static_libs: ["host_for_device_module"],
+		}
+	`
+
+	config := testConfig(nil)
+	ctx := testContext(config, bp, nil)
+	run(t, ctx, config)
+
+	hostModule := ctx.ModuleForTests("host_module", config.BuildOsCommonVariant)
+	hostJavac := hostModule.Output("javac/host_module.jar")
+	hostRes := hostModule.Output("res/host_module.jar")
+
+	hostImportModule := ctx.ModuleForTests("host_import_module", config.BuildOsCommonVariant)
+	hostImportCombined := hostImportModule.Output("combined/host_import_module.jar")
+
+	deviceModule := ctx.ModuleForTests("device_module", "android_common")
+	deviceJavac := deviceModule.Output("javac/device_module.jar")
+	deviceRes := deviceModule.Output("res/device_module.jar")
+	combined := deviceModule.Output("combined/device_module.jar")
+	resCombined := deviceModule.Output("res-combined/device_module.jar")
+
+	// check classpath of device module with dependency on host_for_device_module
+	expectedClasspath := "-classpath " + strings.Join(android.Paths{
+		hostJavac.Output,
+		hostImportCombined.Output,
+	}.Strings(), ":")
+
+	if deviceJavac.Args["classpath"] != expectedClasspath {
+		t.Errorf("expected device_module javac classpath:\n%s\ngot:\n%s",
+			expectedClasspath, deviceJavac.Args["classpath"])
+	}
+
+	// check device module merged with static dependency implementation jars from host_for_device module
+	expectedInputs := android.Paths{
+		deviceJavac.Output,
+		hostJavac.Output,
+		hostImportCombined.Output,
+	}
+
+	if !reflect.DeepEqual(combined.Inputs, expectedInputs) {
+		t.Errorf("expected device_module combined inputs:\n%q\ngot:\n%q",
+			expectedInputs, combined.Inputs)
+	}
+
+	// check device module merged with static dependency resource jars from host_for_device module
+	expectedInputs = android.Paths{
+		deviceRes.Output,
+		hostRes.Output,
+	}
+
+	if !reflect.DeepEqual(resCombined.Inputs, expectedInputs) {
+		t.Errorf("expected device_module res combined inputs:\n%q\ngot:\n%q",
+			expectedInputs, resCombined.Inputs)
+	}
+}
diff --git a/java/dex.go b/java/dex.go
index 54b7bfc..987129e 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -25,7 +25,7 @@
 var d8 = pctx.AndroidStaticRule("d8",
 	blueprint.RuleParams{
 		Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
-			`${config.D8Cmd} --output $outDir $d8Flags $in && ` +
+			`${config.D8Cmd} ${config.DexFlags} --output $outDir $d8Flags $in && ` +
 			`${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
 			`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
 		CommandDeps: []string{
@@ -40,7 +40,7 @@
 	blueprint.RuleParams{
 		Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
 			`rm -f "$outDict" && ` +
-			`${config.R8Cmd} -injars $in --output $outDir ` +
+			`${config.R8Cmd} ${config.DexFlags} -injars $in --output $outDir ` +
 			`--force-proguard-compatibility ` +
 			`--no-data-resources ` +
 			`-printmapping $outDict ` +
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index a35e011..64de21a 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -16,6 +16,7 @@
 
 import (
 	"path/filepath"
+	"sort"
 	"strings"
 
 	"android/soong/android"
@@ -137,6 +138,8 @@
 	if global.GenerateApexImage {
 		d.otherImages = append(d.otherImages, buildBootImage(ctx, apexBootImageConfig(ctx)))
 	}
+
+	dumpOatRules(ctx, d.defaultBootImage)
 }
 
 // buildBootImage takes a bootImageConfig, creates rules to build it, and returns a *bootImage.
@@ -278,7 +281,7 @@
 		cmd.Flag(extraFlags)
 	}
 
-	cmd.Textf(`|| ( echo %s ; false )`, proptools.ShellEscape([]string{failureMessage})[0])
+	cmd.Textf(`|| ( echo %s ; false )`, proptools.ShellEscape(failureMessage))
 
 	installDir := filepath.Join("/system/framework", arch.String())
 	vdexInstallDir := filepath.Join("/system/framework")
@@ -389,6 +392,50 @@
 
 var bootImageProfileRuleKey = android.NewOnceKey("bootImageProfileRule")
 
+func dumpOatRules(ctx android.SingletonContext, image *bootImage) {
+	var archs []android.ArchType
+	for arch := range image.images {
+		archs = append(archs, arch)
+	}
+	sort.Slice(archs, func(i, j int) bool { return archs[i].String() < archs[j].String() })
+
+	var allPhonies android.Paths
+	for _, arch := range archs {
+		// Create a rule to call oatdump.
+		output := android.PathForOutput(ctx, "boot."+arch.String()+".oatdump.txt")
+		rule := android.NewRuleBuilder()
+		rule.Command().
+			// TODO: for now, use the debug version for better error reporting
+			Tool(ctx.Config().HostToolPath(ctx, "oatdumpd")).
+			FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPaths.Paths(), ":").
+			FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocations, ":").
+			FlagWithArg("--image=", dexpreopt.PathToLocation(image.images[arch], arch)).Implicit(image.images[arch]).
+			FlagWithOutput("--output=", output).
+			FlagWithArg("--instruction-set=", arch.String())
+		rule.Build(pctx, ctx, "dump-oat-boot-"+arch.String(), "dump oat boot "+arch.String())
+
+		// Create a phony rule that depends on the output file and prints the path.
+		phony := android.PathForPhony(ctx, "dump-oat-boot-"+arch.String())
+		rule = android.NewRuleBuilder()
+		rule.Command().
+			Implicit(output).
+			ImplicitOutput(phony).
+			Text("echo").FlagWithArg("Output in ", output.String())
+		rule.Build(pctx, ctx, "phony-dump-oat-boot-"+arch.String(), "dump oat boot "+arch.String())
+
+		allPhonies = append(allPhonies, phony)
+	}
+
+	phony := android.PathForPhony(ctx, "dump-oat-boot")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        android.Phony,
+		Output:      phony,
+		Inputs:      allPhonies,
+		Description: "dump-oat-boot",
+	})
+
+}
+
 // Export paths for default boot image to Make
 func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
 	image := d.defaultBootImage
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
new file mode 100644
index 0000000..c99540d
--- /dev/null
+++ b/java/dexpreopt_bootjars_test.go
@@ -0,0 +1,103 @@
+// Copyright 2019 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 java
+
+import (
+	"path/filepath"
+	"reflect"
+	"sort"
+	"testing"
+
+	"android/soong/android"
+	"android/soong/dexpreopt"
+)
+
+func TestDexpreoptBootJars(t *testing.T) {
+	bp := `
+		java_sdk_library {
+			name: "foo",
+			srcs: ["a.java"],
+			api_packages: ["foo"],
+		}
+
+		java_library {
+			name: "bar",
+			srcs: ["b.java"],
+			installable: true,
+		}
+	`
+
+	config := testConfig(nil)
+
+	pathCtx := android.PathContextForTesting(config, nil)
+	dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
+	dexpreoptConfig.RuntimeApexJars = []string{"foo", "bar"}
+	setDexpreoptTestGlobalConfig(config, dexpreoptConfig)
+
+	ctx := testContext(config, bp, nil)
+
+	ctx.RegisterSingletonType("dex_bootjars", android.SingletonFactoryAdaptor(dexpreoptBootJarsFactory))
+
+	run(t, ctx, config)
+
+	dexpreoptBootJars := ctx.SingletonForTests("dex_bootjars")
+
+	bootArt := dexpreoptBootJars.Output("boot.art")
+
+	expectedInputs := []string{
+		"dex_bootjars_input/foo.jar",
+		"dex_bootjars_input/bar.jar",
+	}
+
+	for i := range expectedInputs {
+		expectedInputs[i] = filepath.Join(buildDir, "test_device", expectedInputs[i])
+	}
+
+	inputs := bootArt.Implicits.Strings()
+	sort.Strings(inputs)
+	sort.Strings(expectedInputs)
+
+	if !reflect.DeepEqual(inputs, expectedInputs) {
+		t.Errorf("want inputs %q\n got inputs %q", expectedInputs, inputs)
+	}
+
+	expectedOutputs := []string{
+		"dex_bootjars/system/framework/arm64/boot.invocation",
+
+		"dex_bootjars/system/framework/arm64/boot.art",
+		"dex_bootjars/system/framework/arm64/boot-bar.art",
+
+		"dex_bootjars/system/framework/arm64/boot.oat",
+		"dex_bootjars/system/framework/arm64/boot-bar.oat",
+
+		"dex_bootjars/system/framework/arm64/boot.vdex",
+		"dex_bootjars/system/framework/arm64/boot-bar.vdex",
+
+		"dex_bootjars_unstripped/system/framework/arm64/boot.oat",
+		"dex_bootjars_unstripped/system/framework/arm64/boot-bar.oat",
+	}
+
+	for i := range expectedOutputs {
+		expectedOutputs[i] = filepath.Join(buildDir, "test_device", expectedOutputs[i])
+	}
+
+	outputs := bootArt.Outputs.Strings()
+	sort.Strings(outputs)
+	sort.Strings(expectedOutputs)
+
+	if !reflect.DeepEqual(outputs, expectedOutputs) {
+		t.Errorf("want outputs %q\n got outputs %q", expectedOutputs, outputs)
+	}
+}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 85e4797..777cd9c 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -157,7 +157,7 @@
 type JavadocProperties struct {
 	// list of source files used to compile the Java module.  May be .java, .logtags, .proto,
 	// or .aidl files.
-	Srcs []string `android:"arch_variant"`
+	Srcs []string `android:"path,arch_variant"`
 
 	// list of directories rooted at the Android.bp file that will
 	// be added to the search paths for finding source files when passing package names.
@@ -166,7 +166,7 @@
 	// list of source files that should not be used to build the Java module.
 	// This is most useful in the arch/multilib variants to remove non-common files
 	// filegroup or genrule can be included within this property.
-	Exclude_srcs []string `android:"arch_variant"`
+	Exclude_srcs []string `android:"path,arch_variant"`
 
 	// list of java libraries that will be in the classpath.
 	Libs []string `android:"arch_variant"`
@@ -205,7 +205,7 @@
 	Java_version *string
 
 	// local files that are used within user customized droiddoc options.
-	Arg_files []string
+	Arg_files []string `android:"path"`
 
 	// user customized droiddoc args.
 	// Available variables for substitution:
@@ -220,12 +220,12 @@
 type ApiToCheck struct {
 	// path to the API txt file that the new API extracted from source code is checked
 	// against. The path can be local to the module or from other module (via :module syntax).
-	Api_file *string
+	Api_file *string `android:"path"`
 
 	// path to the API txt file that the new @removed API extractd from source code is
 	// checked against. The path can be local to the module or from other module (via
 	// :module syntax).
-	Removed_api_file *string
+	Removed_api_file *string `android:"path"`
 
 	// Arguments to the apicheck tool.
 	Args *string
@@ -243,11 +243,11 @@
 
 	// proofread file contains all of the text content of the javadocs concatenated into one file,
 	// suitable for spell-checking and other goodness.
-	Proofread_file *string
+	Proofread_file *string `android:"path"`
 
 	// a todo file lists the program elements that are missing documentation.
 	// At some point, this might be improved to show more warnings.
-	Todo_file *string
+	Todo_file *string `android:"path"`
 
 	// directory under current module source that provide additional resources (images).
 	Resourcesdir *string
@@ -260,14 +260,14 @@
 	Write_sdk_values *bool
 
 	// index.html under current module will be copied to docs out dir, if not null.
-	Static_doc_index_redirect *string
+	Static_doc_index_redirect *string `android:"path"`
 
 	// source.properties under current module will be copied to docs out dir, if not null.
-	Static_doc_properties *string
+	Static_doc_properties *string `android:"path"`
 
 	// a list of files under current module source dir which contains known tags in Java sources.
 	// filegroup or genrule can be included within this property.
-	Knowntags []string
+	Knowntags []string `android:"path"`
 
 	// the tag name used to distinguish if the API files belong to public/system/test.
 	Api_tag_name *string
@@ -307,6 +307,10 @@
 		Last_released ApiToCheck
 
 		Current ApiToCheck
+
+		// do not perform API check against Last_released, in the case that both two specified API
+		// files by Last_released are modules which don't exist.
+		Ignore_missing_latest_api *bool `blueprint:"mutated"`
 	}
 
 	// if set to true, generate docs through Dokka instead of Doclava.
@@ -349,10 +353,14 @@
 		Last_released ApiToCheck
 
 		Current ApiToCheck
+
+		// do not perform API check against Last_released, in the case that both two specified API
+		// files by Last_released are modules which don't exist.
+		Ignore_missing_latest_api *bool `blueprint:"mutated"`
 	}
 
 	// user can specify the version of previous released API file in order to do compatibility check.
-	Previous_api *string
+	Previous_api *string `android:"path"`
 
 	// is set to true, Metalava will allow framework SDK to contain annotations.
 	Annotations_enabled *bool
@@ -427,6 +435,25 @@
 	return false
 }
 
+func ignoreMissingModules(ctx android.BottomUpMutatorContext, apiToCheck *ApiToCheck) {
+	api_file := String(apiToCheck.Api_file)
+	removed_api_file := String(apiToCheck.Removed_api_file)
+
+	api_module := android.SrcIsModule(api_file)
+	removed_api_module := android.SrcIsModule(removed_api_file)
+
+	if api_module == "" || removed_api_module == "" {
+		return
+	}
+
+	if ctx.OtherModuleExists(api_module) || ctx.OtherModuleExists(removed_api_module) {
+		return
+	}
+
+	apiToCheck.Api_file = nil
+	apiToCheck.Removed_api_file = nil
+}
+
 type ApiFilePath interface {
 	ApiFilePath() android.Path
 }
@@ -529,14 +556,6 @@
 	if j.properties.Srcs_lib != nil {
 		ctx.AddVariationDependencies(nil, srcsLibTag, *j.properties.Srcs_lib)
 	}
-
-	android.ExtractSourcesDeps(ctx, j.properties.Srcs)
-
-	// exclude_srcs may contain filegroup or genrule.
-	android.ExtractSourcesDeps(ctx, j.properties.Exclude_srcs)
-
-	// arg_files may contains filegroup or genrule.
-	android.ExtractSourcesDeps(ctx, j.properties.Arg_files)
 }
 
 func (j *Javadoc) genWhitelistPathPrefixes(whitelistPathPrefixes map[string]bool) {
@@ -839,30 +858,13 @@
 func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) {
 	d.Javadoc.addDeps(ctx)
 
+	if Bool(d.properties.Check_api.Ignore_missing_latest_api) {
+		ignoreMissingModules(ctx, &d.properties.Check_api.Last_released)
+	}
+
 	if String(d.properties.Custom_template) != "" {
 		ctx.AddDependency(ctx.Module(), droiddocTemplateTag, String(d.properties.Custom_template))
 	}
-
-	// knowntags may contain filegroup or genrule.
-	android.ExtractSourcesDeps(ctx, d.properties.Knowntags)
-
-	if String(d.properties.Static_doc_index_redirect) != "" {
-		android.ExtractSourceDeps(ctx, d.properties.Static_doc_index_redirect)
-	}
-
-	if String(d.properties.Static_doc_properties) != "" {
-		android.ExtractSourceDeps(ctx, d.properties.Static_doc_properties)
-	}
-
-	if apiCheckEnabled(d.properties.Check_api.Current, "current") {
-		android.ExtractSourceDeps(ctx, d.properties.Check_api.Current.Api_file)
-		android.ExtractSourceDeps(ctx, d.properties.Check_api.Current.Removed_api_file)
-	}
-
-	if apiCheckEnabled(d.properties.Check_api.Last_released, "last_released") {
-		android.ExtractSourceDeps(ctx, d.properties.Check_api.Last_released.Api_file)
-		android.ExtractSourceDeps(ctx, d.properties.Check_api.Last_released.Removed_api_file)
-	}
 }
 
 func (d *Droiddoc) initBuilderFlags(ctx android.ModuleContext, implicits *android.Paths,
@@ -1283,18 +1285,8 @@
 func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
 	d.Javadoc.addDeps(ctx)
 
-	if apiCheckEnabled(d.properties.Check_api.Current, "current") {
-		android.ExtractSourceDeps(ctx, d.properties.Check_api.Current.Api_file)
-		android.ExtractSourceDeps(ctx, d.properties.Check_api.Current.Removed_api_file)
-	}
-
-	if apiCheckEnabled(d.properties.Check_api.Last_released, "last_released") {
-		android.ExtractSourceDeps(ctx, d.properties.Check_api.Last_released.Api_file)
-		android.ExtractSourceDeps(ctx, d.properties.Check_api.Last_released.Removed_api_file)
-	}
-
-	if String(d.properties.Previous_api) != "" {
-		android.ExtractSourceDeps(ctx, d.properties.Previous_api)
+	if Bool(d.properties.Check_api.Ignore_missing_latest_api) {
+		ignoreMissingModules(ctx, &d.properties.Check_api.Last_released)
 	}
 
 	if len(d.properties.Merge_annotations_dirs) != 0 {
@@ -1309,13 +1301,6 @@
 		}
 	}
 
-	if String(d.properties.Validate_nullability_from_list) != "" {
-		android.ExtractSourceDeps(ctx, d.properties.Validate_nullability_from_list)
-	}
-	if String(d.properties.Check_nullability_warnings) != "" {
-		android.ExtractSourceDeps(ctx, d.properties.Check_nullability_warnings)
-	}
-
 	if len(d.properties.Api_levels_annotations_dirs) != 0 {
 		for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
 			ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
diff --git a/java/jacoco.go b/java/jacoco.go
index 541a84a..8b6d4ac 100644
--- a/java/jacoco.go
+++ b/java/jacoco.go
@@ -106,7 +106,7 @@
 			return nil, err
 		}
 	}
-	return proptools.NinjaAndShellEscape(specs), nil
+	return proptools.NinjaAndShellEscapeList(specs), nil
 }
 
 func jacocoFilterToSpec(filter string) (string, error) {
diff --git a/java/java.go b/java/java.go
index ecc3608..dcd6dbe 100644
--- a/java/java.go
+++ b/java/java.go
@@ -44,6 +44,8 @@
 	android.RegisterModuleType("java_test_host", TestHostFactory)
 	android.RegisterModuleType("java_import", ImportFactory)
 	android.RegisterModuleType("java_import_host", ImportFactoryHost)
+	android.RegisterModuleType("java_device_for_host", DeviceForHostFactory)
+	android.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
 
 	android.RegisterSingletonType("logtags", LogtagsSingleton)
 }
@@ -60,11 +62,11 @@
 type CompilerProperties struct {
 	// list of source files used to compile the Java module.  May be .java, .logtags, .proto,
 	// or .aidl files.
-	Srcs []string `android:"arch_variant"`
+	Srcs []string `android:"path,arch_variant"`
 
 	// list of source files that should not be used to build the Java module.
 	// This is most useful in the arch/multilib variants to remove non-common files
-	Exclude_srcs []string `android:"arch_variant"`
+	Exclude_srcs []string `android:"path,arch_variant"`
 
 	// list of directories containing Java resources
 	Java_resource_dirs []string `android:"arch_variant"`
@@ -73,10 +75,10 @@
 	Exclude_java_resource_dirs []string `android:"arch_variant"`
 
 	// list of files to use as Java resources
-	Java_resources []string `android:"arch_variant"`
+	Java_resources []string `android:"path,arch_variant"`
 
 	// list of files that should be excluded from java_resources and java_resource_dirs
-	Exclude_java_resources []string `android:"arch_variant"`
+	Exclude_java_resources []string `android:"path,arch_variant"`
 
 	// don't build against the default libraries (bootclasspath, ext, and framework for device
 	// targets)
@@ -98,10 +100,10 @@
 	Static_libs []string `android:"arch_variant"`
 
 	// manifest file to be included in resulting jar
-	Manifest *string
+	Manifest *string `android:"path"`
 
 	// if not blank, run jarjar using the specified rules file
-	Jarjar_rules *string `android:"arch_variant"`
+	Jarjar_rules *string `android:"path,arch_variant"`
 
 	// If not blank, set the java version passed to javac as -source and -target
 	Java_version *string
@@ -124,7 +126,7 @@
 
 	Openjdk9 struct {
 		// List of source files that should only be used when passing -source 1.9
-		Srcs []string
+		Srcs []string `android:"path"`
 
 		// List of javac flags that should only be used when passing -source 1.9
 		Javacflags []string
@@ -170,7 +172,7 @@
 	Instrument bool `blueprint:"mutated"`
 
 	// List of files to include in the META-INF/services folder of the resulting jar.
-	Services []string `android:"arch_variant"`
+	Services []string `android:"path,arch_variant"`
 }
 
 type CompilerDeviceProperties struct {
@@ -239,7 +241,7 @@
 		Proguard_flags []string
 
 		// Specifies the locations of files containing proguard flags.
-		Proguard_flags_files []string
+		Proguard_flags_files []string `android:"path"`
 	}
 
 	// When targeting 1.9, override the modules to use with --system
@@ -476,13 +478,6 @@
 		{Mutator: "arch", Variation: ctx.Config().BuildOsCommonVariant},
 	}, pluginTag, j.properties.Plugins...)
 
-	android.ExtractSourcesDeps(ctx, j.properties.Srcs)
-	android.ExtractSourcesDeps(ctx, j.properties.Exclude_srcs)
-	android.ExtractSourcesDeps(ctx, j.properties.Java_resources)
-	android.ExtractSourceDeps(ctx, j.properties.Manifest)
-	android.ExtractSourceDeps(ctx, j.properties.Jarjar_rules)
-	android.ExtractSourcesDeps(ctx, j.properties.Services)
-
 	if j.hasSrcExt(".proto") {
 		protoDeps(ctx, &j.protoProperties)
 	}
@@ -1133,7 +1128,6 @@
 	}
 
 	jars = append(jars, deps.staticJars...)
-	jars = append(jars, deps.staticResourceJars...)
 
 	manifest := j.overrideManifest
 	if !manifest.Valid() && j.properties.Manifest != nil {
@@ -1153,7 +1147,7 @@
 			Output:    servicesJar,
 			Implicits: services,
 			Args: map[string]string{
-				"jarArgs": "-P META-INF/services/ " + strings.Join(proptools.NinjaAndShellEscape(zipargs), " "),
+				"jarArgs": "-P META-INF/services/ " + strings.Join(proptools.NinjaAndShellEscapeList(zipargs), " "),
 			},
 		})
 		jars = append(jars, servicesJar)
@@ -1529,15 +1523,15 @@
 
 	// the name of the test configuration (for example "AndroidTest.xml") that should be
 	// installed with the module.
-	Test_config *string `android:"arch_variant"`
+	Test_config *string `android:"path,arch_variant"`
 
 	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
 	// should be installed with the module.
-	Test_config_template *string `android:"arch_variant"`
+	Test_config_template *string `android:"path,arch_variant"`
 
 	// list of files or filegroup modules that provide data that should be installed alongside
 	// the test
-	Data []string
+	Data []string `android:"path"`
 }
 
 type Test struct {
@@ -1556,13 +1550,6 @@
 	j.Library.GenerateAndroidBuildActions(ctx)
 }
 
-func (j *Test) DepsMutator(ctx android.BottomUpMutatorContext) {
-	j.deps(ctx)
-	android.ExtractSourceDeps(ctx, j.testProperties.Test_config)
-	android.ExtractSourceDeps(ctx, j.testProperties.Test_config_template)
-	android.ExtractSourcesDeps(ctx, j.testProperties.Data)
-}
-
 // java_test builds a and links sources into a `.jar` file for the device, and possibly for the host as well, and
 // creates an `AndroidTest.xml` file to allow running the test with `atest` or a `TEST_MAPPING` file.
 //
@@ -1613,7 +1600,7 @@
 
 type binaryProperties struct {
 	// installable script to execute the resulting jar
-	Wrapper *string
+	Wrapper *string `android:"path"`
 
 	// Name of the class containing main to be inserted into the manifest as Main-Class.
 	Main_class *string
@@ -1669,8 +1656,6 @@
 func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) {
 	if ctx.Arch().ArchType == android.Common {
 		j.deps(ctx)
-	} else {
-		android.ExtractSourceDeps(ctx, j.binaryProperties.Wrapper)
 	}
 }
 
@@ -1723,7 +1708,7 @@
 //
 
 type ImportProperties struct {
-	Jars []string
+	Jars []string `android:"path"`
 
 	Sdk_version *string
 
@@ -1774,7 +1759,6 @@
 }
 
 func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
-	android.ExtractSourcesDeps(ctx, j.properties.Jars)
 	ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
 }
 
diff --git a/java/java_test.go b/java/java_test.go
index 8d3efcb..952da11 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -24,6 +24,7 @@
 
 	"android/soong/android"
 	"android/soong/cc"
+	"android/soong/dexpreopt"
 	"android/soong/genrule"
 )
 
@@ -67,10 +68,13 @@
 	ctx.RegisterModuleType("android_test_helper_app", android.ModuleFactoryAdaptor(AndroidTestHelperAppFactory))
 	ctx.RegisterModuleType("java_binary", android.ModuleFactoryAdaptor(BinaryFactory))
 	ctx.RegisterModuleType("java_binary_host", android.ModuleFactoryAdaptor(BinaryHostFactory))
+	ctx.RegisterModuleType("java_device_for_host", android.ModuleFactoryAdaptor(DeviceForHostFactory))
+	ctx.RegisterModuleType("java_host_for_device", android.ModuleFactoryAdaptor(HostForDeviceFactory))
 	ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(LibraryFactory))
 	ctx.RegisterModuleType("java_library_host", android.ModuleFactoryAdaptor(LibraryHostFactory))
 	ctx.RegisterModuleType("java_test", android.ModuleFactoryAdaptor(TestFactory))
 	ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(ImportFactory))
+	ctx.RegisterModuleType("java_import_host", android.ModuleFactoryAdaptor(ImportFactoryHost))
 	ctx.RegisterModuleType("java_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
 	ctx.RegisterModuleType("java_system_modules", android.ModuleFactoryAdaptor(SystemModulesFactory))
 	ctx.RegisterModuleType("java_genrule", android.ModuleFactoryAdaptor(genRuleFactory))
@@ -101,8 +105,6 @@
 		ctx.BottomUp("begin", cc.BeginMutator).Parallel()
 	})
 
-	ctx.Register()
-
 	bp += GatherRequiredDepsForTest()
 
 	mockFS := map[string][]byte{
@@ -187,6 +189,11 @@
 
 func run(t *testing.T, ctx *android.TestContext, config android.Config) {
 	t.Helper()
+
+	pathCtx := android.PathContextForTesting(config, nil)
+	setDexpreoptTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
+
+	ctx.Register()
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp", "prebuilts/sdk/Android.bp"})
 	android.FailIfErrored(t, errs)
 	_, errs = ctx.PrepareBuildActions(config)
diff --git a/java/sdk_library.go b/java/sdk_library.go
index df4e08b..6441c63 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -454,8 +454,9 @@
 		Merge_annotations_dirs           []string
 		Merge_inclusion_annotations_dirs []string
 		Check_api                        struct {
-			Current       ApiToCheck
-			Last_released ApiToCheck
+			Current                   ApiToCheck
+			Last_released             ApiToCheck
+			Ignore_missing_latest_api *bool
 		}
 		Aidl struct {
 			Include_dirs       []string
@@ -524,6 +525,7 @@
 		module.latestApiFilegroupName(apiScope))
 	props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
 		module.latestRemovedApiFilegroupName(apiScope))
+	props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(true)
 	props.Srcs_lib = module.sdkLibraryProperties.Srcs_lib
 	props.Srcs_lib_whitelist_dirs = module.sdkLibraryProperties.Srcs_lib_whitelist_dirs
 	props.Srcs_lib_whitelist_pkgs = module.sdkLibraryProperties.Srcs_lib_whitelist_pkgs
diff --git a/java/testing.go b/java/testing.go
index 6c4020c..6febfa1 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -18,7 +18,6 @@
 	"fmt"
 
 	"android/soong/android"
-	"android/soong/dexpreopt"
 )
 
 func TestConfig(buildDir string, env map[string]string) android.Config {
@@ -31,9 +30,6 @@
 	config := android.TestArchConfig(buildDir, env)
 	config.TestProductVariables.DeviceSystemSdkVersions = []string{"14", "15"}
 
-	pathCtx := android.PathContextForTesting(config, nil)
-	setDexpreoptTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
-
 	return config
 }
 
diff --git a/python/python.go b/python/python.go
index 4445f40..6d16020 100644
--- a/python/python.go
+++ b/python/python.go
@@ -43,11 +43,11 @@
 	// non-empty list of .py files under this strict Python version.
 	// srcs may reference the outputs of other modules that produce source files like genrule
 	// or filegroup using the syntax ":module".
-	Srcs []string `android:"arch_variant"`
+	Srcs []string `android:"path,arch_variant"`
 
 	// list of source files that should not be used to build the Python module.
 	// This is most useful in the arch/multilib variants to remove non-common files
-	Exclude_srcs []string `android:"arch_variant"`
+	Exclude_srcs []string `android:"path,arch_variant"`
 
 	// list of the Python libraries under this Python version.
 	Libs []string `android:"arch_variant"`
@@ -74,15 +74,15 @@
 	// srcs may reference the outputs of other modules that produce source files like genrule
 	// or filegroup using the syntax ":module".
 	// Srcs has to be non-empty.
-	Srcs []string `android:"arch_variant"`
+	Srcs []string `android:"path,arch_variant"`
 
 	// list of source files that should not be used to build the C/C++ module.
 	// This is most useful in the arch/multilib variants to remove non-common files
-	Exclude_srcs []string `android:"arch_variant"`
+	Exclude_srcs []string `android:"path,arch_variant"`
 
 	// list of files or filegroup modules that provide data that should be installed alongside
 	// the test. the file extension can be arbitrary except for (.py).
-	Data []string `android:"arch_variant"`
+	Data []string `android:"path,arch_variant"`
 
 	// list of the Python libraries compatible both with Python2 and Python3.
 	Libs []string `android:"arch_variant"`
@@ -288,21 +288,11 @@
 }
 
 func (p *Module) DepsMutator(ctx android.BottomUpMutatorContext) {
-	// deps from "data".
-	android.ExtractSourcesDeps(ctx, p.properties.Data)
-	// deps from "srcs".
-	android.ExtractSourcesDeps(ctx, p.properties.Srcs)
-	android.ExtractSourcesDeps(ctx, p.properties.Exclude_srcs)
-
 	if p.hasSrcExt(ctx, protoExt) && p.Name() != "libprotobuf-python" {
 		ctx.AddVariationDependencies(nil, pythonLibTag, "libprotobuf-python")
 	}
 	switch p.properties.Actual_version {
 	case pyVersion2:
-		// deps from "version.py2.srcs" property.
-		android.ExtractSourcesDeps(ctx, p.properties.Version.Py2.Srcs)
-		android.ExtractSourcesDeps(ctx, p.properties.Version.Py2.Exclude_srcs)
-
 		ctx.AddVariationDependencies(nil, pythonLibTag,
 			uniqueLibs(ctx, p.properties.Libs, "version.py2.libs",
 				p.properties.Version.Py2.Libs)...)
@@ -334,10 +324,6 @@
 		}
 
 	case pyVersion3:
-		// deps from "version.py3.srcs" property.
-		android.ExtractSourcesDeps(ctx, p.properties.Version.Py3.Srcs)
-		android.ExtractSourcesDeps(ctx, p.properties.Version.Py3.Exclude_srcs)
-
 		ctx.AddVariationDependencies(nil, pythonLibTag,
 			uniqueLibs(ctx, p.properties.Libs, "version.py3.libs",
 				p.properties.Version.Py3.Libs)...)
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 643fe8e..6e8e306 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -38,7 +38,9 @@
 	// Determine who owns this sysprop library. Possible values are
 	// "Platform", "Vendor", or "Odm"
 	Property_owner string
-	Api_packages   []string
+
+	// list of package names that will be documented and publicized as API
+	Api_packages []string
 }
 
 type commonProperties struct {
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index cfa7164..da5dabe 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -15,7 +15,12 @@
 package tradefed
 
 import (
+	"fmt"
+	"sort"
+	"strings"
+
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
 )
@@ -34,9 +39,9 @@
 }
 
 var autogenTestConfig = pctx.StaticRule("autogenTestConfig", blueprint.RuleParams{
-	Command:     "sed 's&{MODULE}&${name}&g' $template > $out",
+	Command:     "sed 's&{MODULE}&${name}&g;s&{EXTRA_OPTIONS}&'${extraOptions}'&g' $template > $out",
 	CommandDeps: []string{"$template"},
-}, "name", "template")
+}, "name", "template", "extraOptions")
 
 func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string) (path android.Path, autogenPath android.WritablePath) {
 	if p := getTestConfig(ctx, prop); p != nil {
@@ -52,30 +57,45 @@
 	}
 }
 
-func autogenTemplate(ctx android.ModuleContext, output android.WritablePath, template string) {
+func autogenTemplate(ctx android.ModuleContext, output android.WritablePath, template string, optionsMap map[string]string) {
+	// If no test option found, delete {EXTRA_OPTIONS} line.
+	var options []string
+	for optionName, value := range optionsMap {
+		if value != "" {
+			options = append(options, fmt.Sprintf(`<option name="%s" value="%s" />`, optionName, value))
+		}
+	}
+	sort.Strings(options)
+	extraOptions := strings.Join(options, "\n        ")
+	extraOptions = proptools.NinjaAndShellEscape(extraOptions)
+
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        autogenTestConfig,
 		Description: "test config",
 		Output:      output,
 		Args: map[string]string{
-			"name":     ctx.ModuleName(),
-			"template": template,
+			"name":         ctx.ModuleName(),
+			"template":     template,
+			"extraOptions": extraOptions,
 		},
 	})
 }
 
 func AutoGenNativeTestConfig(ctx android.ModuleContext, testConfigProp *string,
-	testConfigTemplateProp *string, testSuites []string) android.Path {
+	testConfigTemplateProp *string, testSuites []string,
+	optionsMap map[string]string) android.Path {
 	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
 	if autogenPath != nil {
 		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
 		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String())
+			autogenTemplate(ctx, autogenPath, templatePath.String(), optionsMap)
 		} else {
 			if ctx.Device() {
-				autogenTemplate(ctx, autogenPath, "${NativeTestConfigTemplate}")
+				autogenTemplate(ctx, autogenPath, "${NativeTestConfigTemplate}",
+					optionsMap)
 			} else {
-				autogenTemplate(ctx, autogenPath, "${NativeHostTestConfigTemplate}")
+				autogenTemplate(ctx, autogenPath, "${NativeHostTestConfigTemplate}",
+					optionsMap)
 			}
 		}
 		return autogenPath
@@ -89,9 +109,9 @@
 	if autogenPath != nil {
 		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
 		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String())
+			autogenTemplate(ctx, autogenPath, templatePath.String(), nil)
 		} else {
-			autogenTemplate(ctx, autogenPath, "${NativeBenchmarkTestConfigTemplate}")
+			autogenTemplate(ctx, autogenPath, "${NativeBenchmarkTestConfigTemplate}", nil)
 		}
 		return autogenPath
 	}
@@ -103,12 +123,12 @@
 	if autogenPath != nil {
 		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
 		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String())
+			autogenTemplate(ctx, autogenPath, templatePath.String(), nil)
 		} else {
 			if ctx.Device() {
-				autogenTemplate(ctx, autogenPath, "${JavaTestConfigTemplate}")
+				autogenTemplate(ctx, autogenPath, "${JavaTestConfigTemplate}", nil)
 			} else {
-				autogenTemplate(ctx, autogenPath, "${JavaHostTestConfigTemplate}")
+				autogenTemplate(ctx, autogenPath, "${JavaHostTestConfigTemplate}", nil)
 			}
 		}
 		return autogenPath
@@ -123,9 +143,9 @@
 	if autogenPath != nil {
 		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
 		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String())
+			autogenTemplate(ctx, autogenPath, templatePath.String(), nil)
 		} else {
-			autogenTemplate(ctx, autogenPath, "${PythonBinaryHostTestConfigTemplate}")
+			autogenTemplate(ctx, autogenPath, "${PythonBinaryHostTestConfigTemplate}", nil)
 		}
 		return autogenPath
 	}
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index d644f5f..7f0b784 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -204,6 +204,7 @@
 		"BUILD_BROKEN_PHONY_TARGETS",
 
 		// Not used, but useful to be in the soong.log
+		"BOARD_VNDK_VERSION",
 		"BUILD_BROKEN_ANDROIDMK_EXPORTS",
 		"BUILD_BROKEN_DUP_COPY_HEADERS",
 		"BUILD_BROKEN_ENG_DEBUG_TAGS",
diff --git a/xml/xml.go b/xml/xml.go
index 218d73c..d89327f 100644
--- a/xml/xml.go
+++ b/xml/xml.go
@@ -58,7 +58,7 @@
 
 type prebuiltEtcXmlProperties struct {
 	// Optional DTD that will be used to validate the xml file.
-	Schema *string
+	Schema *string `android:"path"`
 }
 
 type prebuiltEtcXml struct {
@@ -73,9 +73,6 @@
 
 func (p *prebuiltEtcXml) DepsMutator(ctx android.BottomUpMutatorContext) {
 	p.PrebuiltEtc.DepsMutator(ctx)
-
-	// To support ":modulename" in schema
-	android.ExtractSourceDeps(ctx, p.properties.Schema)
 }
 
 func (p *prebuiltEtcXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {