Merge "Skip native_bridge modules when installing vndk snapshot"
diff --git a/README.md b/README.md
index b0b61a8..8fdce4b 100644
--- a/README.md
+++ b/README.md
@@ -81,6 +81,8 @@
 Maps may values of any type, including nested maps.  Lists and maps may have
 trailing commas after the last value.
 
+Strings can contain double quotes using `\"`, for example `"cat \"a b\""`.
+
 ### Operators
 
 Strings, lists of strings, and maps can be appended using the `+` operator.
@@ -195,8 +197,10 @@
 * `["//visibility:legacy_public"]`: The default visibility, behaves as
 `//visibility:public` for now. It is an error if it is used in a module.
 
-The visibility rules of `//visibility:public` and `//visibility:private` can
-not be combined with any other visibility specifications.
+The visibility rules of `//visibility:public` and `//visibility:private` can not
+be combined with any other visibility specifications, except
+`//visibility:public` is allowed to override visibility specifications imported
+through the `defaults` property.
 
 Packages outside `vendor/` cannot make themselves visible to specific packages
 in `vendor/`, e.g. a module in `libcore` cannot declare that it is visible to
diff --git a/android/config.go b/android/config.go
index 1507c25..b0d8b7f 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1103,6 +1103,10 @@
 	return Bool(c.productVariables.ProductCompatibleProperty)
 }
 
+func (c *config) MissingUsesLibraries() []string {
+	return c.productVariables.MissingUsesLibraries
+}
+
 func (c *deviceConfig) BoardVndkRuntimeDisable() bool {
 	return Bool(c.config.productVariables.BoardVndkRuntimeDisable)
 }
diff --git a/android/module.go b/android/module.go
index 3906fd7..1c36279 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1740,4 +1740,5 @@
 	Jars              []string `json:"jars,omitempty"`
 	Classes           []string `json:"class,omitempty"`
 	Installed_paths   []string `json:"installed,omitempty"`
+	SrcJars           []string `json:"srcjars,omitempty"`
 }
diff --git a/android/mutator.go b/android/mutator.go
index 085c055..0e80249 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -76,6 +76,7 @@
 	registerLoadHookMutator,
 	RegisterNamespaceMutator,
 	RegisterPrebuiltsPreArchMutators,
+	registerVisibilityRuleChecker,
 	RegisterDefaultsPreArchMutators,
 	registerVisibilityRuleGatherer,
 }
diff --git a/android/variable.go b/android/variable.go
index ff3ebaf..d039a16 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -306,6 +306,8 @@
 	ProductCompatibleProperty  *bool    `json:",omitempty"`
 
 	TargetFSConfigGen []string `json:",omitempty"`
+
+	MissingUsesLibraries []string `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
diff --git a/android/visibility.go b/android/visibility.go
index 36b6f35..c7ef1da 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -71,7 +71,17 @@
 	String() string
 }
 
-// A compositeRule is a visibility rule composed from other visibility rules.
+// A compositeRule is a visibility rule composed from a list of atomic visibility rules.
+//
+// The list corresponds to the list of strings in the visibility property after defaults expansion.
+// Even though //visibility:public is not allowed together with other rules in the visibility list
+// of a single module, it is allowed here to permit a module to override an inherited visibility
+// spec with public visibility.
+//
+// //visibility:private is not allowed in the same way, since we'd need to check for it during the
+// defaults expansion to make that work. No non-private visibility rules are allowed in a
+// compositeRule containing a privateRule.
+//
 // This array will only be [] if all the rules are invalid and will behave as if visibility was
 // ["//visibility:private"].
 type compositeRule []visibilityRule
@@ -126,6 +136,28 @@
 	return fmt.Sprintf("//%s:__subpackages__", r.pkgPrefix)
 }
 
+// visibilityRule for //visibility:public
+type publicRule struct{}
+
+func (r publicRule) matches(_ qualifiedModuleName) bool {
+	return true
+}
+
+func (r publicRule) String() string {
+	return "//visibility:public"
+}
+
+// visibilityRule for //visibility:private
+type privateRule struct{}
+
+func (r privateRule) matches(_ qualifiedModuleName) bool {
+	return false
+}
+
+func (r privateRule) String() string {
+	return "//visibility:private"
+}
+
 var visibilityRuleMap = NewOnceKey("visibilityRuleMap")
 
 // The map from qualifiedModuleName to visibilityRule.
@@ -135,8 +167,15 @@
 	}).(*sync.Map)
 }
 
+// The rule checker needs to be registered before defaults expansion to correctly check that
+// //visibility:xxx isn't combined with other packages in the same list in any one module.
+func registerVisibilityRuleChecker(ctx RegisterMutatorsContext) {
+	ctx.BottomUp("visibilityRuleChecker", visibilityRuleChecker).Parallel()
+}
+
 // Visibility is not dependent on arch so this must be registered before the arch phase to avoid
-// having to process multiple variants for each module.
+// having to process multiple variants for each module. This goes after defaults expansion to gather
+// the complete visibility lists from flat lists.
 func registerVisibilityRuleGatherer(ctx RegisterMutatorsContext) {
 	ctx.BottomUp("visibilityRuleGatherer", visibilityRuleGatherer).Parallel()
 }
@@ -146,11 +185,80 @@
 	ctx.TopDown("visibilityRuleEnforcer", visibilityRuleEnforcer).Parallel()
 }
 
-// Gathers the visibility rules, parses the visibility properties, stores them in a map by
-// qualifiedModuleName for retrieval during enforcement.
+// Checks the per-module visibility rule lists before defaults expansion.
+func visibilityRuleChecker(ctx BottomUpMutatorContext) {
+	qualified := createQualifiedModuleName(ctx)
+	if d, ok := ctx.Module().(Defaults); ok {
+		// Defaults modules don't store the payload properties in m.base().
+		for _, props := range d.properties() {
+			if cp, ok := props.(*commonProperties); ok {
+				if visibility := cp.Visibility; visibility != nil {
+					checkRules(ctx, qualified.pkg, visibility)
+				}
+			}
+		}
+	} else if m, ok := ctx.Module().(Module); ok {
+		if visibility := m.base().commonProperties.Visibility; visibility != nil {
+			checkRules(ctx, qualified.pkg, visibility)
+		}
+	}
+}
+
+func checkRules(ctx BottomUpMutatorContext, currentPkg string, visibility []string) {
+	ruleCount := len(visibility)
+	if ruleCount == 0 {
+		// This prohibits an empty list as its meaning is unclear, e.g. it could mean no visibility and
+		// it could mean public visibility. Requiring at least one rule makes the owner's intent
+		// clearer.
+		ctx.PropertyErrorf("visibility", "must contain at least one visibility rule")
+		return
+	}
+
+	for _, v := range visibility {
+		ok, pkg, name := splitRule(ctx, v, currentPkg)
+		if !ok {
+			// Visibility rule is invalid so ignore it. Keep going rather than aborting straight away to
+			// ensure all the rules on this module are checked.
+			ctx.PropertyErrorf("visibility",
+				"invalid visibility pattern %q must match"+
+					" //<package>:<module>, //<package> or :<module>",
+				v)
+			continue
+		}
+
+		if pkg == "visibility" {
+			switch name {
+			case "private", "public":
+			case "legacy_public":
+				ctx.PropertyErrorf("visibility", "//visibility:legacy_public must not be used")
+				continue
+			default:
+				ctx.PropertyErrorf("visibility", "unrecognized visibility rule %q", v)
+				continue
+			}
+			if ruleCount != 1 {
+				ctx.PropertyErrorf("visibility", "cannot mix %q with any other visibility rules", v)
+				continue
+			}
+		}
+
+		// If the current directory is not in the vendor tree then there are some additional
+		// restrictions on the rules.
+		if !isAncestor("vendor", currentPkg) {
+			if !isAllowedFromOutsideVendor(pkg, name) {
+				ctx.PropertyErrorf("visibility",
+					"%q is not allowed. Packages outside //vendor cannot make themselves visible to specific"+
+						" targets within //vendor, they can only use //vendor:__subpackages__.", v)
+				continue
+			}
+		}
+	}
+}
+
+// Gathers the flattened visibility rules after defaults expansion, parses the visibility
+// properties, stores them in a map by qualifiedModuleName for retrieval during enforcement.
 //
 // See ../README.md#Visibility for information on the format of the visibility rules.
-
 func visibilityRuleGatherer(ctx BottomUpMutatorContext) {
 	m, ok := ctx.Module().(Module)
 	if !ok {
@@ -169,74 +277,51 @@
 }
 
 func parseRules(ctx BottomUpMutatorContext, currentPkg string, visibility []string) compositeRule {
-	ruleCount := len(visibility)
-	if ruleCount == 0 {
-		// This prohibits an empty list as its meaning is unclear, e.g. it could mean no visibility and
-		// it could mean public visibility. Requiring at least one rule makes the owner's intent
-		// clearer.
-		ctx.PropertyErrorf("visibility", "must contain at least one visibility rule")
-		return nil
-	}
-
-	rules := make(compositeRule, 0, ruleCount)
+	rules := make(compositeRule, 0, len(visibility))
+	hasPrivateRule := false
+	hasNonPrivateRule := false
 	for _, v := range visibility {
 		ok, pkg, name := splitRule(ctx, v, currentPkg)
 		if !ok {
-			// Visibility rule is invalid so ignore it. Keep going rather than aborting straight away to
-			// ensure all the rules on this module are checked.
-			ctx.PropertyErrorf("visibility",
-				"invalid visibility pattern %q must match"+
-					" //<package>:<module>, //<package> or :<module>",
-				v)
 			continue
 		}
 
+		var r visibilityRule
+		isPrivateRule := false
 		if pkg == "visibility" {
-			if ruleCount != 1 {
-				ctx.PropertyErrorf("visibility", "cannot mix %q with any other visibility rules", v)
-				continue
-			}
 			switch name {
 			case "private":
-				rules = append(rules, packageRule{currentPkg})
-				continue
+				r = privateRule{}
+				isPrivateRule = true
 			case "public":
-				return nil
-			case "legacy_public":
-				ctx.PropertyErrorf("visibility", "//visibility:legacy_public must not be used")
-				return nil
+				r = publicRule{}
+			}
+		} else {
+			switch name {
+			case "__pkg__":
+				r = packageRule{pkg}
+			case "__subpackages__":
+				r = subpackagesRule{pkg}
 			default:
-				ctx.PropertyErrorf("visibility", "unrecognized visibility rule %q", v)
 				continue
 			}
 		}
 
-		// If the current directory is not in the vendor tree then there are some additional
-		// restrictions on the rules.
-		if !isAncestor("vendor", currentPkg) {
-			if !isAllowedFromOutsideVendor(pkg, name) {
-				ctx.PropertyErrorf("visibility",
-					"%q is not allowed. Packages outside //vendor cannot make themselves visible to specific"+
-						" targets within //vendor, they can only use //vendor:__subpackages__.", v)
-				continue
-			}
-		}
-
-		// Create the rule
-		var r visibilityRule
-		switch name {
-		case "__pkg__":
-			r = packageRule{pkg}
-		case "__subpackages__":
-			r = subpackagesRule{pkg}
-		default:
-			ctx.PropertyErrorf("visibility", "unrecognized visibility rule %q", v)
-			continue
+		if isPrivateRule {
+			hasPrivateRule = true
+		} else {
+			hasNonPrivateRule = true
 		}
 
 		rules = append(rules, r)
 	}
 
+	if hasPrivateRule && hasNonPrivateRule {
+		ctx.PropertyErrorf("visibility",
+			"cannot mix \"//visibility:private\" with any other visibility rules")
+		return compositeRule{privateRule{}}
+	}
+
 	return rules
 }
 
@@ -274,8 +359,7 @@
 }
 
 func visibilityRuleEnforcer(ctx TopDownMutatorContext) {
-	_, ok := ctx.Module().(Module)
-	if !ok {
+	if _, ok := ctx.Module().(Module); !ok {
 		return
 	}
 
@@ -297,9 +381,7 @@
 		rule, ok := moduleToVisibilityRule.Load(depQualified)
 		if ok {
 			if !rule.(compositeRule).matches(qualified) {
-				ctx.ModuleErrorf(
-					"depends on %s which is not visible to this module; %s is only visible to %s",
-					depQualified, depQualified, rule)
+				ctx.ModuleErrorf("depends on %s which is not visible to this module", depQualified)
 			}
 		}
 	})
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 6809914..09c5b1b 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -1,10 +1,11 @@
 package android
 
 import (
-	"github.com/google/blueprint"
 	"io/ioutil"
 	"os"
 	"testing"
+
+	"github.com/google/blueprint"
 )
 
 var visibilityTests = []struct {
@@ -90,7 +91,7 @@
 		expectedErrors: []string{`unrecognized visibility rule "//visibility:unknown"`},
 	},
 	{
-		name: "//visibility:public mixed",
+		name: "//visibility:xxx mixed",
 		fs: map[string][]byte{
 			"top/Blueprints": []byte(`
 				mock_library {
@@ -104,10 +105,10 @@
 				}`),
 		},
 		expectedErrors: []string{
-			`module "libother" variant "android_common": visibility: cannot mix "//visibility:private"` +
+			`module "libother": visibility: cannot mix "//visibility:private"` +
 				` with any other visibility rules`,
-			`module "libexample" variant "android_common": visibility: cannot mix` +
-				` "//visibility:public" with any other visibility rules`,
+			`module "libexample": visibility: cannot mix "//visibility:public"` +
+				` with any other visibility rules`,
 		},
 	},
 	{
@@ -120,7 +121,7 @@
 				}`),
 		},
 		expectedErrors: []string{
-			`module "libexample" variant "android_common": visibility: //visibility:legacy_public must` +
+			`module "libexample": visibility: //visibility:legacy_public must` +
 				` not be used`,
 		},
 	},
@@ -152,33 +153,6 @@
 		},
 	},
 	{
-		// Verify that //visibility:public will allow the module to be referenced from anywhere, e.g.
-		// the current directory, a nested directory and a directory in a separate tree.
-		name: "//visibility:public",
-		fs: map[string][]byte{
-			"top/Blueprints": []byte(`
-				mock_library {
-					name: "libexample",
-					visibility: ["//visibility:public"],
-				}
-	
-				mock_library {
-					name: "libsamepackage",
-					deps: ["libexample"],
-				}`),
-			"top/nested/Blueprints": []byte(`
-				mock_library {
-					name: "libnested",
-					deps: ["libexample"],
-				}`),
-			"other/Blueprints": []byte(`
-				mock_library {
-					name: "libother",
-					deps: ["libexample"],
-				}`),
-		},
-	},
-	{
 		// Verify that //visibility:private allows the module to be referenced from the current
 		// directory only.
 		name: "//visibility:private",
@@ -198,10 +172,17 @@
 					name: "libnested",
 					deps: ["libexample"],
 				}`),
+			"other/Blueprints": []byte(`
+				mock_library {
+					name: "libother",
+					deps: ["libexample"],
+				}`),
 		},
 		expectedErrors: []string{
 			`module "libnested" variant "android_common": depends on //top:libexample which is not` +
-				` visible to this module; //top:libexample is only visible to \[//top:__pkg__\]`,
+				` visible to this module`,
+			`module "libother" variant "android_common": depends on //top:libexample which is not` +
+				` visible to this module`,
 		},
 	},
 	{
@@ -223,10 +204,17 @@
 					name: "libnested",
 					deps: ["libexample"],
 				}`),
+			"other/Blueprints": []byte(`
+				mock_library {
+					name: "libother",
+					deps: ["libexample"],
+				}`),
 		},
 		expectedErrors: []string{
 			`module "libnested" variant "android_common": depends on //top:libexample which is not` +
-				` visible to this module; //top:libexample is only visible to \[//top:__pkg__\]`,
+				` visible to this module`,
+			`module "libother" variant "android_common": depends on //top:libexample which is not` +
+				` visible to this module`,
 		},
 	},
 	{
@@ -262,9 +250,9 @@
 		},
 		expectedErrors: []string{
 			`module "libother" variant "android_common": depends on //top:libexample which is not` +
-				` visible to this module; //top:libexample is only visible to \[//top/nested:__pkg__\]`,
+				` visible to this module`,
 			`module "libnestedagain" variant "android_common": depends on //top:libexample which is not` +
-				` visible to this module; //top:libexample is only visible to \[//top/nested:__pkg__\]`,
+				` visible to this module`,
 		},
 	},
 	{
@@ -295,7 +283,7 @@
 		},
 		expectedErrors: []string{
 			`module "libother" variant "android_common": depends on //top:libexample which is not` +
-				` visible to this module; //top:libexample is only visible to \[//top:__subpackages__\]`,
+				` visible to this module`,
 		},
 	},
 	{
@@ -326,8 +314,7 @@
 		},
 		expectedErrors: []string{
 			`module "libother" variant "android_common": depends on //top:libexample which is not` +
-				` visible to this module; //top:libexample is only visible to` +
-				` \[//top/nested:__subpackages__, //other:__pkg__\]`,
+				` visible to this module`,
 		},
 	},
 	{
@@ -384,11 +371,295 @@
 				}`),
 		},
 		expectedErrors: []string{
-			`module "libsamepackage" variant "android_common": visibility: "//vendor/apps/AcmeSettings"` +
+			`module "libsamepackage": visibility: "//vendor/apps/AcmeSettings"` +
 				` is not allowed. Packages outside //vendor cannot make themselves visible to specific` +
 				` targets within //vendor, they can only use //vendor:__subpackages__.`,
 		},
 	},
+
+	// Defaults propagation tests
+	{
+		// Check that visibility is the union of the defaults modules.
+		name: "defaults union, basic",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//other"],
+				}
+				mock_library {
+					name: "libexample",
+					visibility: ["//top/nested"],
+					defaults: ["libexample_defaults"],
+				}
+				mock_library {
+					name: "libsamepackage",
+					deps: ["libexample"],
+				}`),
+			"top/nested/Blueprints": []byte(`
+				mock_library {
+					name: "libnested",
+					deps: ["libexample"],
+				}`),
+			"other/Blueprints": []byte(`
+				mock_library {
+					name: "libother",
+					deps: ["libexample"],
+				}`),
+			"outsider/Blueprints": []byte(`
+				mock_library {
+					name: "liboutsider",
+					deps: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
+				` visible to this module`,
+		},
+	},
+	{
+		name: "defaults union, multiple defaults",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults_1",
+					visibility: ["//other"],
+				}
+				mock_defaults {
+					name: "libexample_defaults_2",
+					visibility: ["//top/nested"],
+				}
+				mock_library {
+					name: "libexample",
+					defaults: ["libexample_defaults_1", "libexample_defaults_2"],
+				}
+				mock_library {
+					name: "libsamepackage",
+					deps: ["libexample"],
+				}`),
+			"top/nested/Blueprints": []byte(`
+				mock_library {
+					name: "libnested",
+					deps: ["libexample"],
+				}`),
+			"other/Blueprints": []byte(`
+				mock_library {
+					name: "libother",
+					deps: ["libexample"],
+				}`),
+			"outsider/Blueprints": []byte(`
+				mock_library {
+					name: "liboutsider",
+					deps: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
+				` visible to this module`,
+		},
+	},
+	{
+		name: "//visibility:public mixed with other in defaults",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:public", "//namespace"],
+				}
+				mock_library {
+					name: "libexample",
+					defaults: ["libexample_defaults"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "libexample_defaults": visibility: cannot mix "//visibility:public"` +
+				` with any other visibility rules`,
+		},
+	},
+	{
+		name: "//visibility:public overriding defaults",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//namespace"],
+				}
+				mock_library {
+					name: "libexample",
+					visibility: ["//visibility:public"],
+					defaults: ["libexample_defaults"],
+				}`),
+			"outsider/Blueprints": []byte(`
+				mock_library {
+					name: "liboutsider",
+					deps: ["libexample"],
+				}`),
+		},
+	},
+	{
+		name: "//visibility:public mixed with other from different defaults 1",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults_1",
+					visibility: ["//namespace"],
+				}
+				mock_defaults {
+					name: "libexample_defaults_2",
+					visibility: ["//visibility:public"],
+				}
+				mock_library {
+					name: "libexample",
+					defaults: ["libexample_defaults_1", "libexample_defaults_2"],
+				}`),
+			"outsider/Blueprints": []byte(`
+				mock_library {
+					name: "liboutsider",
+					deps: ["libexample"],
+				}`),
+		},
+	},
+	{
+		name: "//visibility:public mixed with other from different defaults 2",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults_1",
+					visibility: ["//visibility:public"],
+				}
+				mock_defaults {
+					name: "libexample_defaults_2",
+					visibility: ["//namespace"],
+				}
+				mock_library {
+					name: "libexample",
+					defaults: ["libexample_defaults_1", "libexample_defaults_2"],
+				}`),
+			"outsider/Blueprints": []byte(`
+				mock_library {
+					name: "liboutsider",
+					deps: ["libexample"],
+				}`),
+		},
+	},
+	{
+		name: "//visibility:private in defaults",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:private"],
+				}
+				mock_library {
+					name: "libexample",
+					defaults: ["libexample_defaults"],
+				}
+				mock_library {
+					name: "libsamepackage",
+					deps: ["libexample"],
+				}`),
+			"top/nested/Blueprints": []byte(`
+				mock_library {
+					name: "libnested",
+					deps: ["libexample"],
+				}`),
+			"other/Blueprints": []byte(`
+				mock_library {
+					name: "libother",
+					deps: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "libnested" variant "android_common": depends on //top:libexample which is not` +
+				` visible to this module`,
+			`module "libother" variant "android_common": depends on //top:libexample which is not` +
+				` visible to this module`,
+		},
+	},
+	{
+		name: "//visibility:private mixed with other in defaults",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:private", "//namespace"],
+				}
+				mock_library {
+					name: "libexample",
+					defaults: ["libexample_defaults"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "libexample_defaults": visibility: cannot mix "//visibility:private"` +
+				` with any other visibility rules`,
+		},
+	},
+	{
+		name: "//visibility:private overriding defaults",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//namespace"],
+				}
+				mock_library {
+					name: "libexample",
+					visibility: ["//visibility:private"],
+					defaults: ["libexample_defaults"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "libexample": visibility: cannot mix "//visibility:private"` +
+				` with any other visibility rules`,
+		},
+	},
+	{
+		name: "//visibility:private in defaults overridden",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:private"],
+				}
+				mock_library {
+					name: "libexample",
+					visibility: ["//namespace"],
+					defaults: ["libexample_defaults"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "libexample": visibility: cannot mix "//visibility:private"` +
+				` with any other visibility rules`,
+		},
+	},
+	{
+		name: "//visibility:private mixed with itself",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults_1",
+					visibility: ["//visibility:private"],
+				}
+				mock_defaults {
+					name: "libexample_defaults_2",
+					visibility: ["//visibility:private"],
+				}
+				mock_library {
+					name: "libexample",
+					visibility: ["//visibility:private"],
+					defaults: ["libexample_defaults_1", "libexample_defaults_2"],
+				}`),
+			"outsider/Blueprints": []byte(`
+				mock_library {
+					name: "liboutsider",
+					deps: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
+				` visible to this module`,
+		},
+	},
 }
 
 func TestVisibility(t *testing.T) {
@@ -430,7 +701,10 @@
 
 	ctx := NewTestArchContext()
 	ctx.RegisterModuleType("mock_library", ModuleFactoryAdaptor(newMockLibraryModule))
-	ctx.PreDepsMutators(registerVisibilityRuleGatherer)
+	ctx.RegisterModuleType("mock_defaults", ModuleFactoryAdaptor(defaultsFactory))
+	ctx.PreArchMutators(registerVisibilityRuleChecker)
+	ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
+	ctx.PreArchMutators(registerVisibilityRuleGatherer)
 	ctx.PostDepsMutators(registerVisibilityRuleEnforcer)
 	ctx.Register()
 
@@ -451,6 +725,7 @@
 
 type mockLibraryModule struct {
 	ModuleBase
+	DefaultableModuleBase
 	properties mockLibraryProperties
 }
 
@@ -458,6 +733,7 @@
 	m := &mockLibraryModule{}
 	m.AddProperties(&m.properties)
 	InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
+	InitDefaultableModule(m)
 	return m
 }
 
@@ -472,3 +748,17 @@
 
 func (p *mockLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
 }
+
+type mockDefaults struct {
+	ModuleBase
+	DefaultsModuleBase
+}
+
+func defaultsFactory() Module {
+	m := &mockDefaults{}
+	InitDefaultsModule(m)
+	return m
+}
+
+func (*mockDefaults) GenerateAndroidBuildActions(ctx ModuleContext) {
+}
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index b54ad5e..24057af 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -123,6 +123,7 @@
 			"LOCAL_SYSTEM_SHARED_LIBRARIES":       "system_shared_libs",
 			"LOCAL_ASFLAGS":                       "asflags",
 			"LOCAL_CLANG_ASFLAGS":                 "clang_asflags",
+			"LOCAL_COMPATIBILITY_SUPPORT_FILES":   "data",
 			"LOCAL_CONLYFLAGS":                    "conlyflags",
 			"LOCAL_CPPFLAGS":                      "cppflags",
 			"LOCAL_REQUIRED_MODULES":              "required",
@@ -528,7 +529,7 @@
 				ctx.file.errorf(ctx.mkvalue, "unsupported sanitize expression")
 			case *bpparser.String:
 				switch v.Value {
-				case "never", "address", "coverage", "thread", "undefined", "cfi":
+				case "never", "address", "fuzzer", "thread", "undefined", "cfi":
 					bpTrue := &bpparser.Bool{
 						Value: true,
 					}
@@ -936,6 +937,7 @@
 	"STATIC_LIBRARIES": "cc_prebuilt_library_static",
 	"EXECUTABLES":      "cc_prebuilt_binary",
 	"JAVA_LIBRARIES":   "java_import",
+	"APPS":             "android_app_import",
 	"ETC":              "prebuilt_etc",
 }
 
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index 3ec5f2e..2eab0cc 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -809,6 +809,7 @@
 LOCAL_PACKAGE_NAME := FooTest
 LOCAL_COMPATIBILITY_SUITE := cts
 LOCAL_CTS_TEST_PACKAGE := foo.bar
+LOCAL_COMPATIBILITY_SUPPORT_FILES := file1
 include $(BUILD_CTS_PACKAGE)
 `,
 		expected: `
@@ -817,6 +818,7 @@
     defaults: ["cts_defaults"],
     test_suites: ["cts"],
 
+    data: ["file1"],
 }
 `,
 	},
@@ -1235,6 +1237,32 @@
 }
 		`,
 	},
+	{
+		desc: "android_app_import",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_SRC_FILES := foo.apk
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_MODULE_CLASS := APPS
+LOCAL_MODULE_TAGS := optional
+LOCAL_DEX_PREOPT := false
+include $(BUILD_PREBUILT)
+`,
+		expected: `
+android_app_import {
+	name: "foo",
+
+	privileged: true,
+
+	dex_preopt: {
+		enabled: false,
+	},
+	apk: "foo.apk",
+
+}
+`,
+	},
 }
 
 func TestEndToEnd(t *testing.T) {
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index c898196..17cff18 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -102,6 +102,10 @@
 		name: "rewriteAndroidTest",
 		fix:  rewriteAndroidTest,
 	},
+	{
+		name: "rewriteAndroidAppImport",
+		fix:  rewriteAndroidAppImport,
+	},
 }
 
 func NewFixRequest() FixRequest {
@@ -525,27 +529,8 @@
 			continue
 		}
 
-		// The rewriter converts LOCAL_SRC_FILES to `srcs` attribute. Convert
-		// it to 'src' attribute (which is where the file is installed). If the
-		// value 'srcs' is a list, we can convert it only if it contains a single
-		// element.
-		if srcs, ok := mod.GetProperty("srcs"); ok {
-			if srcList, ok := srcs.Value.(*parser.List); ok {
-				removeProperty(mod, "srcs")
-				if len(srcList.Values) == 1 {
-					mod.Properties = append(mod.Properties,
-						&parser.Property{Name: "src", NamePos: srcs.NamePos, ColonPos: srcs.ColonPos, Value: resolveLocalModule(mod, srcList.Values[0])})
-				} else if len(srcList.Values) > 1 {
-					indicateAttributeError(mod, "src", "LOCAL_SRC_FILES should contain at most one item")
-				}
-			} else if _, ok = srcs.Value.(*parser.Variable); ok {
-				removeProperty(mod, "srcs")
-				mod.Properties = append(mod.Properties,
-					&parser.Property{Name: "src", NamePos: srcs.NamePos, ColonPos: srcs.ColonPos, Value: resolveLocalModule(mod, srcs.Value)})
-			} else {
-				renameProperty(mod, "srcs", "src")
-			}
-		}
+		// 'srcs' --> 'src' conversion
+		convertToSingleSource(mod, "src")
 
 		// The rewriter converts LOCAL_MODULE_PATH attribute into a struct attribute
 		// 'local_module_path'. Analyze its contents and create the correct sub_dir:,
@@ -603,6 +588,62 @@
 	return nil
 }
 
+func rewriteAndroidAppImport(f *Fixer) error {
+	for _, def := range f.tree.Defs {
+		mod, ok := def.(*parser.Module)
+		if !(ok && mod.Type == "android_app_import") {
+			continue
+		}
+		// 'srcs' --> 'apk' conversion
+		convertToSingleSource(mod, "apk")
+		// Handle special certificate value, "PRESIGNED".
+		if cert, ok := mod.GetProperty("certificate"); ok {
+			if certStr, ok := cert.Value.(*parser.String); ok {
+				if certStr.Value == "PRESIGNED" {
+					removeProperty(mod, "certificate")
+					prop := &parser.Property{
+						Name: "presigned",
+						Value: &parser.Bool{
+							Value: true,
+						},
+					}
+					mod.Properties = append(mod.Properties, prop)
+				}
+			}
+		}
+	}
+	return nil
+}
+
+// Converts the default source list property, 'srcs', to a single source property with a given name.
+// "LOCAL_MODULE" reference is also resolved during the conversion process.
+func convertToSingleSource(mod *parser.Module, srcPropertyName string) {
+	if srcs, ok := mod.GetProperty("srcs"); ok {
+		if srcList, ok := srcs.Value.(*parser.List); ok {
+			removeProperty(mod, "srcs")
+			if len(srcList.Values) == 1 {
+				mod.Properties = append(mod.Properties,
+					&parser.Property{
+						Name:     srcPropertyName,
+						NamePos:  srcs.NamePos,
+						ColonPos: srcs.ColonPos,
+						Value:    resolveLocalModule(mod, srcList.Values[0])})
+			} else if len(srcList.Values) > 1 {
+				indicateAttributeError(mod, srcPropertyName, "LOCAL_SRC_FILES should contain at most one item")
+			}
+		} else if _, ok = srcs.Value.(*parser.Variable); ok {
+			removeProperty(mod, "srcs")
+			mod.Properties = append(mod.Properties,
+				&parser.Property{Name: srcPropertyName,
+					NamePos:  srcs.NamePos,
+					ColonPos: srcs.ColonPos,
+					Value:    resolveLocalModule(mod, srcs.Value)})
+		} else {
+			renameProperty(mod, "srcs", "apk")
+		}
+	}
+}
+
 func runPatchListMod(modFunc func(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error) func(*Fixer) error {
 	return func(f *Fixer) error {
 		// Make sure all the offsets are accurate
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index 459cd36..5e0b817 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -784,3 +784,52 @@
 		})
 	}
 }
+
+func TestRewriteAndroidAppImport(t *testing.T) {
+	tests := []struct {
+		name string
+		in   string
+		out  string
+	}{
+		{
+			name: "android_app_import apk",
+			in: `
+				android_app_import {
+					name: "foo",
+					srcs: ["package.apk"],
+				}
+			`,
+			out: `
+				android_app_import {
+					name: "foo",
+					apk: "package.apk",
+				}
+			`,
+		},
+		{
+			name: "android_app_import presigned",
+			in: `
+				android_app_import {
+					name: "foo",
+					apk: "package.apk",
+					certificate: "PRESIGNED",
+				}
+			`,
+			out: `
+				android_app_import {
+					name: "foo",
+					apk: "package.apk",
+					presigned: true,
+
+				}
+			`,
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			runPass(t, test.in, test.out, func(fixer *Fixer) error {
+				return rewriteAndroidAppImport(fixer)
+			})
+		})
+	}
+}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index ae34e3d..32ccf4c 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -90,6 +90,9 @@
 				fmt.Fprintln(w, "LOCAL_SOONG_LINK_TYPE :=", c.makeLinkType)
 				if c.useVndk() {
 					fmt.Fprintln(w, "LOCAL_USE_VNDK := true")
+					if c.isVndk() && !c.static() {
+						fmt.Fprintln(w, "LOCAL_SOONG_VNDK_VERSION := "+c.vndkVersion())
+					}
 				}
 			},
 		},
diff --git a/cc/builder.go b/cc/builder.go
index 5fa0fad..7cf5c29 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -124,11 +124,11 @@
 	_ = pctx.SourcePathVariable("xzCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/xz")
 
 	// b/132822437: objcopy uses a file descriptor per .o file when called on .a files, which runs the system out of
-	// file descriptors on darwin.  Limit concurrent calls to 10 on darwin.
+	// file descriptors on darwin.  Limit concurrent calls to 5 on darwin.
 	darwinStripPool = func() blueprint.Pool {
 		if runtime.GOOS == "darwin" {
 			return pctx.StaticPool("darwinStripPool", blueprint.PoolParams{
-				Depth: 10,
+				Depth: 5,
 			})
 		} else {
 			return nil
diff --git a/cc/cc.go b/cc/cc.go
index 6c26b52..09496fc 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -52,6 +52,9 @@
 		ctx.TopDown("hwasan_deps", sanitizerDepsMutator(hwasan))
 		ctx.BottomUp("hwasan", sanitizerMutator(hwasan)).Parallel()
 
+		ctx.TopDown("fuzzer_deps", sanitizerDepsMutator(fuzzer))
+		ctx.BottomUp("fuzzer", sanitizerMutator(fuzzer)).Parallel()
+
 		ctx.TopDown("cfi_deps", sanitizerDepsMutator(cfi))
 		ctx.BottomUp("cfi", sanitizerMutator(cfi)).Parallel()
 
@@ -534,6 +537,13 @@
 	return false
 }
 
+func (c *Module) vndkVersion() string {
+	if vndkdep := c.vndkdep; vndkdep != nil {
+		return vndkdep.Properties.Vndk.Version
+	}
+	return ""
+}
+
 func (c *Module) isPgoCompile() bool {
 	if pgo := c.pgo; pgo != nil {
 		return pgo.Properties.PgoCompile
@@ -919,7 +929,7 @@
 }
 
 func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
-	c.makeLinkType = c.getMakeLinkType(actx.Config())
+	c.makeLinkType = c.getMakeLinkType(actx)
 
 	ctx := &moduleContext{
 		ModuleContext: actx,
@@ -1940,19 +1950,22 @@
 	return false
 }
 
-func (c *Module) getMakeLinkType(config android.Config) string {
+func (c *Module) getMakeLinkType(actx android.ModuleContext) string {
+	name := actx.ModuleName()
 	if c.useVndk() {
-		if inList(c.Name(), *vndkCoreLibraries(config)) ||
-			inList(c.Name(), *vndkSpLibraries(config)) ||
-			inList(c.Name(), *llndkLibraries(config)) {
-			if inList(c.Name(), *vndkPrivateLibraries(config)) {
-				return "native:vndk_private"
-			} else {
+		if lib, ok := c.linker.(*llndkStubDecorator); ok {
+			if Bool(lib.Properties.Vendor_available) {
 				return "native:vndk"
 			}
-		} else {
-			return "native:vendor"
+			return "native:vndk_private"
 		}
+		if c.isVndk() && !c.isVndkExt() {
+			if Bool(c.VendorProperties.Vendor_available) {
+				return "native:vndk"
+			}
+			return "native:vndk_private"
+		}
+		return "native:vendor"
 	} else if c.inRecovery() {
 		return "native:recovery"
 	} else if c.Target().Os == android.Android && String(c.Properties.Sdk_version) != "" {
@@ -1960,7 +1973,7 @@
 		// TODO(b/114741097): use the correct ndk stl once build errors have been fixed
 		//family, link := getNdkStlFamilyAndLinkType(c)
 		//return fmt.Sprintf("native:ndk:%s:%s", family, link)
-	} else if inList(c.Name(), *vndkUsingCoreVariantLibraries(config)) {
+	} else if inList(name, *vndkUsingCoreVariantLibraries(actx.Config())) {
 		return "native:platform_vndk"
 	} else {
 		return "native:platform"
diff --git a/cc/cc_test.go b/cc/cc_test.go
index f5bb12c..997e11e 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -1263,6 +1263,110 @@
 	`)
 }
 
+func TestMakeLinkType(t *testing.T) {
+	config := android.TestArchConfig(buildDir, nil)
+	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+	// native:vndk
+	ctx := testCcWithConfig(t, `
+	cc_library {
+		name: "libvndk",
+		vendor_available: true,
+		vndk: {
+			enabled: true,
+		},
+	}
+	cc_library {
+		name: "libvndksp",
+		vendor_available: true,
+		vndk: {
+			enabled: true,
+			support_system_process: true,
+		},
+	}
+	cc_library {
+		name: "libvndkprivate",
+		vendor_available: false,
+		vndk: {
+			enabled: true,
+		},
+	}
+	cc_library {
+		name: "libvendor",
+		vendor: true,
+	}
+	cc_library {
+		name: "libvndkext",
+		vendor: true,
+		vndk: {
+			enabled: true,
+			extends: "libvndk",
+		},
+	}
+	vndk_prebuilt_shared {
+		name: "prevndk",
+		version: "27",
+		target_arch: "arm",
+		binder32bit: true,
+		vendor_available: true,
+		vndk: {
+			enabled: true,
+		},
+		arch: {
+			arm: {
+				srcs: ["liba.so"],
+			},
+		},
+	}
+	cc_library {
+		name: "libllndk",
+	}
+	llndk_library {
+		name: "libllndk",
+		symbol_file: "",
+	}
+	cc_library {
+		name: "libllndkprivate",
+	}
+	llndk_library {
+		name: "libllndkprivate",
+		vendor_available: false,
+		symbol_file: "",
+	}`, config)
+
+	assertArrayString(t, *vndkCoreLibraries(config),
+		[]string{"libvndk", "libvndkprivate"})
+	assertArrayString(t, *vndkSpLibraries(config),
+		[]string{"libc++", "libvndksp"})
+	assertArrayString(t, *llndkLibraries(config),
+		[]string{"libc", "libdl", "libllndk", "libllndkprivate", "libm"})
+	assertArrayString(t, *vndkPrivateLibraries(config),
+		[]string{"libllndkprivate", "libvndkprivate"})
+
+	tests := []struct {
+		variant  string
+		name     string
+		expected string
+	}{
+		{vendorVariant, "libvndk", "native:vndk"},
+		{vendorVariant, "libvndksp", "native:vndk"},
+		{vendorVariant, "libvndkprivate", "native:vndk_private"},
+		{vendorVariant, "libvendor", "native:vendor"},
+		{vendorVariant, "libvndkext", "native:vendor"},
+		{vendorVariant, "prevndk.vndk.27.arm.binder32", "native:vndk"},
+		{vendorVariant, "libllndk.llndk", "native:vndk"},
+		{coreVariant, "libvndk", "native:platform"},
+		{coreVariant, "libvndkprivate", "native:platform"},
+		{coreVariant, "libllndk", "native:platform"},
+	}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			module := ctx.ModuleForTests(test.name, test.variant).Module().(*Module)
+			assertString(t, module.makeLinkType, test.expected)
+		})
+	}
+}
+
 var (
 	str11 = "01234567891"
 	str10 = str11[:10]
@@ -2159,3 +2263,25 @@
 		)
 	}
 }
+
+func assertString(t *testing.T, got, expected string) {
+	t.Helper()
+	if got != expected {
+		t.Errorf("expected %q got %q", expected, got)
+	}
+}
+
+func assertArrayString(t *testing.T, got, expected []string) {
+	t.Helper()
+	if len(got) != len(expected) {
+		t.Errorf("expected %d (%q) got (%d) %q", len(expected), expected, len(got), got)
+		return
+	}
+	for i := range got {
+		if got[i] != expected[i] {
+			t.Errorf("expected %d-th %q (%q) got %q (%q)",
+				i, expected[i], expected, got[i], got)
+			return
+		}
+	}
+}
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 94a8257..47b60e7 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -108,6 +108,9 @@
 		// Help catch common 32/64-bit errors.
 		"-Werror=int-conversion",
 
+		// Enable the new pass manager.
+		"-fexperimental-new-pass-manager",
+
 		// Disable overly aggressive warning for macros defined with a leading underscore
 		// This happens in AndroidConfig.h, which is included nearly everywhere.
 		// TODO: can we remove this now?
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 4486d2e..fdda7be 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -77,6 +77,7 @@
 	intOverflow
 	cfi
 	scs
+	fuzzer
 )
 
 // Name of the sanitizer variation for this sanitizer type
@@ -94,6 +95,8 @@
 		return "cfi"
 	case scs:
 		return "scs"
+	case fuzzer:
+		return "fuzzer"
 	default:
 		panic(fmt.Errorf("unknown sanitizerType %d", t))
 	}
@@ -114,6 +117,8 @@
 		return "cfi"
 	case scs:
 		return "shadow-call-stack"
+	case fuzzer:
+		return "fuzzer"
 	default:
 		panic(fmt.Errorf("unknown sanitizerType %d", t))
 	}
@@ -133,7 +138,7 @@
 		Undefined        *bool    `android:"arch_variant"`
 		All_undefined    *bool    `android:"arch_variant"`
 		Misc_undefined   []string `android:"arch_variant"`
-		Coverage         *bool    `android:"arch_variant"`
+		Fuzzer           *bool    `android:"arch_variant"`
 		Safestack        *bool    `android:"arch_variant"`
 		Cfi              *bool    `android:"arch_variant"`
 		Integer_overflow *bool    `android:"arch_variant"`
@@ -223,22 +228,16 @@
 			s.Undefined = boolPtr(true)
 		}
 
-		if found, globalSanitizers = removeFromList("address", globalSanitizers); found {
-			if s.Address == nil {
-				s.Address = boolPtr(true)
-			} else if *s.Address == false {
-				// Coverage w/o address is an error. If globalSanitizers includes both, and the module
-				// disables address, then disable coverage as well.
-				_, globalSanitizers = removeFromList("coverage", globalSanitizers)
-			}
+		if found, globalSanitizers = removeFromList("address", globalSanitizers); found && s.Address == nil {
+			s.Address = boolPtr(true)
 		}
 
 		if found, globalSanitizers = removeFromList("thread", globalSanitizers); found && s.Thread == nil {
 			s.Thread = boolPtr(true)
 		}
 
-		if found, globalSanitizers = removeFromList("coverage", globalSanitizers); found && s.Coverage == nil {
-			s.Coverage = boolPtr(true)
+		if found, globalSanitizers = removeFromList("fuzzer", globalSanitizers); found && s.Fuzzer == nil {
+			s.Fuzzer = boolPtr(true)
 		}
 
 		if found, globalSanitizers = removeFromList("safe-stack", globalSanitizers); found && s.Safestack == nil {
@@ -346,7 +345,7 @@
 
 	if ctx.staticBinary() {
 		s.Address = nil
-		s.Coverage = nil
+		s.Fuzzer = nil
 		s.Thread = nil
 	}
 
@@ -362,7 +361,7 @@
 	}
 
 	if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
-		Bool(s.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
+		Bool(s.Fuzzer) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
 		Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs)) {
 		sanitize.Properties.SanitizerEnabled = true
 	}
@@ -377,10 +376,10 @@
 		s.Thread = nil
 	}
 
-	if Bool(s.Coverage) {
-		if !Bool(s.Address) {
-			ctx.ModuleErrorf(`Use of "coverage" also requires "address"`)
-		}
+	// TODO(b/131771163): CFI transiently depends on LTO, and thus Fuzzer is
+	// mutually incompatible.
+	if Bool(s.Fuzzer) {
+		s.Cfi = nil
 	}
 }
 
@@ -461,8 +460,13 @@
 		flags.CFlags = append(flags.CFlags, hwasanCflags...)
 	}
 
-	if Bool(sanitize.Properties.Sanitize.Coverage) {
-		flags.CFlags = append(flags.CFlags, "-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp")
+	if Bool(sanitize.Properties.Sanitize.Fuzzer) {
+		flags.CFlags = append(flags.CFlags, "-fsanitize=fuzzer-no-link")
+		flags.LdFlags = append(flags.LdFlags, "-fsanitize=fuzzer-no-link")
+
+		// TODO(b/131771163): LTO and Fuzzer support is mutually incompatible.
+		_, flags.LdFlags = removeFromList("-flto", flags.LdFlags)
+		flags.LdFlags = append(flags.LdFlags, "-fno-lto")
 	}
 
 	if Bool(sanitize.Properties.Sanitize.Cfi) {
@@ -497,20 +501,26 @@
 		flags.CFlags = append(flags.CFlags, sanitizeArg)
 		flags.AsFlags = append(flags.AsFlags, sanitizeArg)
 		if ctx.Host() {
-			flags.CFlags = append(flags.CFlags, "-fno-sanitize-recover=all")
-			flags.LdFlags = append(flags.LdFlags, sanitizeArg)
 			// Host sanitizers only link symbols in the final executable, so
 			// there will always be undefined symbols in intermediate libraries.
 			_, flags.LdFlags = removeFromList("-Wl,--no-undefined", flags.LdFlags)
+			flags.LdFlags = append(flags.LdFlags, sanitizeArg)
 		} else {
-			flags.CFlags = append(flags.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort")
-
 			if enableMinimalRuntime(sanitize) {
 				flags.CFlags = append(flags.CFlags, strings.Join(minimalRuntimeFlags, " "))
 				flags.libFlags = append([]string{minimalRuntimePath}, flags.libFlags...)
 				flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,"+minimalRuntimeLib)
 			}
 		}
+
+		if Bool(sanitize.Properties.Sanitize.Fuzzer) {
+			// When fuzzing, we wish to crash with diagnostics on any bug.
+			flags.CFlags = append(flags.CFlags, "-fno-sanitize-trap=all", "-fno-sanitize-recover=all")
+		} else if ctx.Host() {
+			flags.CFlags = append(flags.CFlags, "-fno-sanitize-recover=all")
+		} else {
+			flags.CFlags = append(flags.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort")
+		}
 		// http://b/119329758, Android core does not boot up with this sanitizer yet.
 		if toDisableImplicitIntegerChange(flags.CFlags) {
 			flags.CFlags = append(flags.CFlags, "-fno-sanitize=implicit-integer-sign-change")
@@ -573,6 +583,8 @@
 		return sanitize.Properties.Sanitize.Cfi
 	case scs:
 		return sanitize.Properties.Sanitize.Scs
+	case fuzzer:
+		return sanitize.Properties.Sanitize.Fuzzer
 	default:
 		panic(fmt.Errorf("unknown sanitizerType %d", t))
 	}
@@ -583,22 +595,21 @@
 		!sanitize.isSanitizerEnabled(hwasan) &&
 		!sanitize.isSanitizerEnabled(tsan) &&
 		!sanitize.isSanitizerEnabled(cfi) &&
-		!sanitize.isSanitizerEnabled(scs)
+		!sanitize.isSanitizerEnabled(scs) &&
+		!sanitize.isSanitizerEnabled(fuzzer)
 }
 
 func (sanitize *sanitize) isVariantOnProductionDevice() bool {
 	return !sanitize.isSanitizerEnabled(asan) &&
 		!sanitize.isSanitizerEnabled(hwasan) &&
-		!sanitize.isSanitizerEnabled(tsan)
+		!sanitize.isSanitizerEnabled(tsan) &&
+		!sanitize.isSanitizerEnabled(fuzzer)
 }
 
 func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) {
 	switch t {
 	case asan:
 		sanitize.Properties.Sanitize.Address = boolPtr(b)
-		if !b {
-			sanitize.Properties.Sanitize.Coverage = nil
-		}
 	case hwasan:
 		sanitize.Properties.Sanitize.Hwaddress = boolPtr(b)
 	case tsan:
@@ -609,6 +620,8 @@
 		sanitize.Properties.Sanitize.Cfi = boolPtr(b)
 	case scs:
 		sanitize.Properties.Sanitize.Scs = boolPtr(b)
+	case fuzzer:
+		sanitize.Properties.Sanitize.Fuzzer = boolPtr(b)
 	default:
 		panic(fmt.Errorf("unknown sanitizerType %d", t))
 	}
@@ -793,6 +806,10 @@
 			sanitizers = append(sanitizers, "shadow-call-stack")
 		}
 
+		if Bool(c.sanitize.Properties.Sanitize.Fuzzer) {
+			sanitizers = append(sanitizers, "fuzzer-no-link")
+		}
+
 		// Save the list of sanitizers. These will be used again when generating
 		// the build rules (for Cflags, etc.)
 		c.sanitize.Properties.Sanitizers = sanitizers
@@ -931,6 +948,19 @@
 							modules[1].(*Module).Properties.HideFromMake = true
 						}
 					}
+				} else if t == fuzzer {
+					// TODO(b/131771163): CFI and fuzzer support are mutually incompatible
+					// as CFI pulls in LTO.
+					if mctx.Device() {
+						modules[1].(*Module).sanitize.SetSanitizer(cfi, false)
+					}
+					if isSanitizerEnabled {
+						modules[0].(*Module).Properties.PreventInstall = true
+						modules[0].(*Module).Properties.HideFromMake = true
+					} else {
+						modules[1].(*Module).Properties.PreventInstall = true
+						modules[1].(*Module).Properties.HideFromMake = true
+					}
 				} else if t == hwasan {
 					if mctx.Device() {
 						// CFI and HWASAN are currently mutually exclusive so disable
@@ -996,6 +1026,7 @@
 func enableMinimalRuntime(sanitize *sanitize) bool {
 	if !Bool(sanitize.Properties.Sanitize.Address) &&
 		!Bool(sanitize.Properties.Sanitize.Hwaddress) &&
+		!Bool(sanitize.Properties.Sanitize.Fuzzer) &&
 		(Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
 			len(sanitize.Properties.Sanitize.Misc_undefined) > 0) &&
 		!(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
diff --git a/cc/testing.go b/cc/testing.go
index 259fb19..d9be900 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -207,6 +207,7 @@
 	ctx.RegisterModuleType("vendor_public_library", android.ModuleFactoryAdaptor(vendorPublicLibraryFactory))
 	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(ObjectFactory))
 	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
+	ctx.RegisterModuleType("vndk_prebuilt_shared", android.ModuleFactoryAdaptor(vndkPrebuiltSharedFactory))
 	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("image", ImageMutator).Parallel()
 		ctx.BottomUp("link", LinkageMutator).Parallel()
diff --git a/cc/vndk.go b/cc/vndk.go
index 41d3fdb..5f9c686 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -49,6 +49,10 @@
 
 		// Extending another module
 		Extends *string
+
+		// for vndk_prebuilt_shared, this is set by "version" property.
+		// Otherwise, this is set as PLATFORM_VNDK_VERSION.
+		Version string `blueprint:"mutated"`
 	}
 }
 
@@ -325,6 +329,14 @@
 		return
 	}
 
+	if m.isVndk() {
+		if lib, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
+			m.vndkdep.Properties.Vndk.Version = lib.version()
+		} else {
+			m.vndkdep.Properties.Vndk.Version = mctx.DeviceConfig().PlatformVndkVersion()
+		}
+	}
+
 	if _, ok := m.linker.(*llndkStubDecorator); ok {
 		processLlndkLibrary(mctx, m)
 		return
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 1e0f862..5a1bd74 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -65,8 +65,6 @@
 	AlwaysOtherDebugInfo        bool // always generate mini debug info for non-system server modules (overrides NoDebugInfo=true)
 	NeverOtherDebugInfo         bool // never generate mini debug info for non-system server modules (overrides NoDebugInfo=true)
 
-	MissingUsesLibraries []string // libraries that may be listed in OptionalUsesLibraries but will not be installed by the product
-
 	IsEng        bool // build is a eng variant
 	SanitizeLite bool // build is the second phase of a SANITIZE_LITE build
 
@@ -95,14 +93,14 @@
 // Tools contains paths to tools possibly used by the generated commands.  If you add a new tool here you MUST add it
 // to the order-only dependency list in DEXPREOPT_GEN_DEPS.
 type Tools struct {
-	Profman  android.Path
-	Dex2oat  android.Path
-	Aapt     android.Path
-	SoongZip android.Path
-	Zip2zip  android.Path
+	Profman       android.Path
+	Dex2oat       android.Path
+	Aapt          android.Path
+	SoongZip      android.Path
+	Zip2zip       android.Path
+	ManifestCheck android.Path
 
-	VerifyUsesLibraries android.Path
-	ConstructContext    android.Path
+	ConstructContext android.Path
 }
 
 type ModuleConfig struct {
@@ -110,6 +108,7 @@
 	DexLocation     string // dex location on device
 	BuildPath       android.OutputPath
 	DexPath         android.Path
+	ManifestPath    android.Path
 	UncompressedDex bool
 	HasApkLibraries bool
 	PreoptFlags     []string
@@ -117,10 +116,10 @@
 	ProfileClassListing  android.OptionalPath
 	ProfileIsTextListing bool
 
-	EnforceUsesLibraries  bool
-	OptionalUsesLibraries []string
-	UsesLibraries         []string
-	LibraryPaths          map[string]android.Path
+	EnforceUsesLibraries         bool
+	PresentOptionalUsesLibraries []string
+	UsesLibraries                []string
+	LibraryPaths                 map[string]android.Path
 
 	Archs           []android.ArchType
 	DexPreoptImages []android.Path
@@ -187,14 +186,14 @@
 		BootImageProfiles []string
 
 		Tools struct {
-			Profman  string
-			Dex2oat  string
-			Aapt     string
-			SoongZip string
-			Zip2zip  string
+			Profman       string
+			Dex2oat       string
+			Aapt          string
+			SoongZip      string
+			Zip2zip       string
+			ManifestCheck string
 
-			VerifyUsesLibraries string
-			ConstructContext    string
+			ConstructContext string
 		}
 	}
 
@@ -214,7 +213,7 @@
 	config.GlobalConfig.Tools.Aapt = constructPath(ctx, config.Tools.Aapt)
 	config.GlobalConfig.Tools.SoongZip = constructPath(ctx, config.Tools.SoongZip)
 	config.GlobalConfig.Tools.Zip2zip = constructPath(ctx, config.Tools.Zip2zip)
-	config.GlobalConfig.Tools.VerifyUsesLibraries = constructPath(ctx, config.Tools.VerifyUsesLibraries)
+	config.GlobalConfig.Tools.ManifestCheck = constructPath(ctx, config.Tools.ManifestCheck)
 	config.GlobalConfig.Tools.ConstructContext = constructPath(ctx, config.Tools.ConstructContext)
 
 	return config.GlobalConfig, data, nil
@@ -231,6 +230,7 @@
 		// used to construct the real value manually below.
 		BuildPath                   string
 		DexPath                     string
+		ManifestPath                string
 		ProfileClassListing         string
 		LibraryPaths                map[string]string
 		DexPreoptImages             []string
@@ -249,6 +249,7 @@
 	// Construct paths that require a PathContext.
 	config.ModuleConfig.BuildPath = constructPath(ctx, config.BuildPath).(android.OutputPath)
 	config.ModuleConfig.DexPath = constructPath(ctx, config.DexPath)
+	config.ModuleConfig.ManifestPath = constructPath(ctx, config.ManifestPath)
 	config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing))
 	config.ModuleConfig.LibraryPaths = constructPathMap(ctx, config.LibraryPaths)
 	config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
@@ -307,7 +308,6 @@
 		NeverSystemServerDebugInfo:         false,
 		AlwaysOtherDebugInfo:               false,
 		NeverOtherDebugInfo:                false,
-		MissingUsesLibraries:               nil,
 		IsEng:                              false,
 		SanitizeLite:                       false,
 		DefaultAppImages:                   false,
@@ -324,13 +324,13 @@
 		Dex2oatImageXmx:                    "",
 		Dex2oatImageXms:                    "",
 		Tools: Tools{
-			Profman:             android.PathForTesting("profman"),
-			Dex2oat:             android.PathForTesting("dex2oat"),
-			Aapt:                android.PathForTesting("aapt"),
-			SoongZip:            android.PathForTesting("soong_zip"),
-			Zip2zip:             android.PathForTesting("zip2zip"),
-			VerifyUsesLibraries: android.PathForTesting("verify_uses_libraries.sh"),
-			ConstructContext:    android.PathForTesting("construct_context.sh"),
+			Profman:          android.PathForTesting("profman"),
+			Dex2oat:          android.PathForTesting("dex2oat"),
+			Aapt:             android.PathForTesting("aapt"),
+			SoongZip:         android.PathForTesting("soong_zip"),
+			Zip2zip:          android.PathForTesting("zip2zip"),
+			ManifestCheck:    android.PathForTesting("manifest_check"),
+			ConstructContext: android.PathForTesting("construct_context.sh"),
 		},
 	}
 }
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 5b658d9..0be37d0 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -226,15 +226,6 @@
 		bootImageLocation = PathToLocation(bootImage, arch)
 	}
 
-	// Lists of used and optional libraries from the build config to be verified against the manifest in the APK
-	var verifyUsesLibs []string
-	var verifyOptionalUsesLibs []string
-
-	// Lists of used and optional libraries from the build config, with optional libraries that are known to not
-	// be present in the current product removed.
-	var filteredUsesLibs []string
-	var filteredOptionalUsesLibs []string
-
 	// The class loader context using paths in the build
 	var classLoaderContextHost android.Paths
 
@@ -252,14 +243,10 @@
 	var classLoaderContextHostString string
 
 	if module.EnforceUsesLibraries {
-		verifyUsesLibs = copyOf(module.UsesLibraries)
-		verifyOptionalUsesLibs = copyOf(module.OptionalUsesLibraries)
-
-		filteredOptionalUsesLibs = filterOut(global.MissingUsesLibraries, module.OptionalUsesLibraries)
-		filteredUsesLibs = append(copyOf(module.UsesLibraries), filteredOptionalUsesLibs...)
+		usesLibs := append(copyOf(module.UsesLibraries), module.PresentOptionalUsesLibraries...)
 
 		// Create class loader context for dex2oat from uses libraries and filtered optional libraries
-		for _, l := range filteredUsesLibs {
+		for _, l := range usesLibs {
 
 			classLoaderContextHost = append(classLoaderContextHost,
 				pathForLibrary(module, l))
@@ -270,11 +257,13 @@
 		const httpLegacy = "org.apache.http.legacy"
 		const httpLegacyImpl = "org.apache.http.legacy.impl"
 
-		// Fix up org.apache.http.legacy.impl since it should be org.apache.http.legacy in the manifest.
-		replace(verifyUsesLibs, httpLegacyImpl, httpLegacy)
-		replace(verifyOptionalUsesLibs, httpLegacyImpl, httpLegacy)
+		// org.apache.http.legacy contains classes that were in the default classpath until API 28.  If the
+		// targetSdkVersion in the manifest or APK is < 28, and the module does not explicitly depend on
+		// org.apache.http.legacy, then implicitly add the classes to the classpath for dexpreopt.  One the
+		// device the classes will be in a file called org.apache.http.legacy.impl.jar.
+		module.LibraryPaths[httpLegacyImpl] = module.LibraryPaths[httpLegacy]
 
-		if !contains(verifyUsesLibs, httpLegacy) && !contains(verifyOptionalUsesLibs, httpLegacy) {
+		if !contains(module.UsesLibraries, httpLegacy) && !contains(module.PresentOptionalUsesLibraries, httpLegacy) {
 			conditionalClassLoaderContextHost28 = append(conditionalClassLoaderContextHost28,
 				pathForLibrary(module, httpLegacyImpl))
 			conditionalClassLoaderContextTarget28 = append(conditionalClassLoaderContextTarget28,
@@ -284,6 +273,9 @@
 		const hidlBase = "android.hidl.base-V1.0-java"
 		const hidlManager = "android.hidl.manager-V1.0-java"
 
+		// android.hidl.base-V1.0-java and android.hidl.manager-V1.0 contain classes that were in the default
+		// classpath until API 29.  If the targetSdkVersion in the manifest or APK is < 29 then implicitly add
+		// the classes to the classpath for dexpreopt.
 		conditionalClassLoaderContextHost29 = append(conditionalClassLoaderContextHost29,
 			pathForLibrary(module, hidlManager))
 		conditionalClassLoaderContextTarget29 = append(conditionalClassLoaderContextTarget29,
@@ -309,9 +301,21 @@
 	rule.Command().Text(`stored_class_loader_context_arg=""`)
 
 	if module.EnforceUsesLibraries {
-		rule.Command().Textf(`uses_library_names="%s"`, strings.Join(verifyUsesLibs, " "))
-		rule.Command().Textf(`optional_uses_library_names="%s"`, strings.Join(verifyOptionalUsesLibs, " "))
-		rule.Command().Textf(`aapt_binary="%s"`, global.Tools.Aapt)
+		if module.ManifestPath != nil {
+			rule.Command().Text(`target_sdk_version="$(`).
+				Tool(global.Tools.ManifestCheck).
+				Flag("--extract-target-sdk-version").
+				Input(module.ManifestPath).
+				Text(`)"`)
+		} else {
+			// No manifest to extract targetSdkVersion from, hope that DexJar is an APK
+			rule.Command().Text(`target_sdk_version="$(`).
+				Tool(global.Tools.Aapt).
+				Flag("dump badging").
+				Input(module.DexPath).
+				Text(`| grep "targetSdkVersion" | sed -n "s/targetSdkVersion:'\(.*\)'/\1/p"`).
+				Text(`)"`)
+		}
 		rule.Command().Textf(`dex_preopt_host_libraries="%s"`,
 			strings.Join(classLoaderContextHost.Strings(), " ")).
 			Implicits(classLoaderContextHost)
@@ -327,8 +331,7 @@
 			Implicits(conditionalClassLoaderContextHost29)
 		rule.Command().Textf(`conditional_target_libs_29="%s"`,
 			strings.Join(conditionalClassLoaderContextTarget29, " "))
-		rule.Command().Text("source").Tool(global.Tools.VerifyUsesLibraries).Input(module.DexPath)
-		rule.Command().Text("source").Tool(global.Tools.ConstructContext)
+		rule.Command().Text("source").Tool(global.Tools.ConstructContext).Input(module.DexPath)
 	}
 
 	// Devices that do not have a product partition use a symlink from /product to /system/product.
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 6dfa9d2..0402f87 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -33,7 +33,7 @@
 		ProfileClassListing:             android.OptionalPath{},
 		ProfileIsTextListing:            false,
 		EnforceUsesLibraries:            false,
-		OptionalUsesLibraries:           nil,
+		PresentOptionalUsesLibraries:    nil,
 		UsesLibraries:                   nil,
 		LibraryPaths:                    nil,
 		Archs:                           []android.ArchType{android.Arm},
diff --git a/java/aar.go b/java/aar.go
index 7332e76..65a7c2a 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -84,6 +84,7 @@
 	useEmbeddedNativeLibs   bool
 	useEmbeddedDex          bool
 	usesNonSdkApis          bool
+	sdkLibraries            []string
 
 	splitNames []string
 	splits     []split
@@ -194,13 +195,15 @@
 }
 
 func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, extraLinkFlags ...string) {
-	transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, libDeps, libFlags := aaptLibs(ctx, sdkContext)
+
+	transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, libDeps, libFlags, sdkLibraries :=
+		aaptLibs(ctx, sdkContext)
 
 	// App manifest file
 	manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
 	manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
 
-	manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext,
+	manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext, sdkLibraries,
 		a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex)
 
 	a.transitiveManifestPaths = append(android.Paths{manifestPath}, transitiveStaticLibManifests...)
@@ -303,7 +306,7 @@
 
 // aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
 func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, transitiveStaticLibManifests android.Paths,
-	staticRRODirs []rroDir, deps android.Paths, flags []string) {
+	staticRRODirs []rroDir, deps android.Paths, flags []string, sdkLibraries []string) {
 
 	var sharedLibs android.Paths
 
@@ -322,7 +325,16 @@
 		switch ctx.OtherModuleDependencyTag(module) {
 		case instrumentationForTag:
 			// Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2.
-		case libTag, frameworkResTag:
+		case libTag:
+			if exportPackage != nil {
+				sharedLibs = append(sharedLibs, exportPackage)
+			}
+
+			if _, ok := module.(SdkLibraryDependency); ok {
+				sdkLibraries = append(sdkLibraries, ctx.OtherModuleName(module))
+			}
+
+		case frameworkResTag:
 			if exportPackage != nil {
 				sharedLibs = append(sharedLibs, exportPackage)
 			}
@@ -331,6 +343,7 @@
 				transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
 				transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
 				transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
+				sdkLibraries = append(sdkLibraries, aarDep.ExportedSdkLibs()...)
 
 			outer:
 				for _, d := range aarDep.ExportedRRODirs() {
@@ -358,8 +371,9 @@
 
 	transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs)
 	transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests)
+	sdkLibraries = android.FirstUniqueStrings(sdkLibraries)
 
-	return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, deps, flags
+	return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, deps, flags, sdkLibraries
 }
 
 type AndroidLibrary struct {
@@ -393,6 +407,7 @@
 
 func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	a.aapt.isLibrary = true
+	a.aapt.sdkLibraries = a.exportedSdkLibs
 	a.aapt.buildActions(ctx, sdkContext(a))
 
 	ctx.CheckbuildFile(a.proguardOptionsFile)
@@ -603,10 +618,12 @@
 	linkFlags = append(linkFlags, "--manifest "+a.manifest.String())
 	linkDeps = append(linkDeps, a.manifest)
 
-	transitiveStaticLibs, staticLibManifests, staticRRODirs, libDeps, libFlags := aaptLibs(ctx, sdkContext(a))
+	transitiveStaticLibs, staticLibManifests, staticRRODirs, libDeps, libFlags, sdkLibraries :=
+		aaptLibs(ctx, sdkContext(a))
 
 	_ = staticLibManifests
 	_ = staticRRODirs
+	_ = sdkLibraries
 
 	linkDeps = append(linkDeps, libDeps...)
 	linkFlags = append(linkFlags, libFlags...)
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 5d3cfa5..b5921be 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -41,8 +41,18 @@
 	},
 	"args", "libs")
 
+// These two libs are added as optional dependencies (<uses-library> with
+// android:required set to false). This is because they haven't existed in pre-P
+// devices, but classes in them were in bootclasspath jars, etc. So making them
+// hard dependencies (android:required=true) would prevent apps from being
+// installed to such legacy devices.
+var optionalUsesLibs = []string{
+	"android.test.base",
+	"android.test.mock",
+}
+
 // Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
-func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext,
+func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext, sdkLibraries []string,
 	isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex bool) android.Path {
 
 	var args []string
@@ -69,6 +79,14 @@
 		args = append(args, "--use-embedded-dex")
 	}
 
+	for _, usesLib := range sdkLibraries {
+		if inList(usesLib, optionalUsesLibs) {
+			args = append(args, "--optional-uses-library", usesLib)
+		} else {
+			args = append(args, "--uses-library", usesLib)
+		}
+	}
+
 	var deps android.Paths
 	targetSdkVersion := sdkVersionOrDefault(ctx, sdkContext.targetSdkVersion())
 	if targetSdkVersion == ctx.Config().PlatformSdkCodename() &&
diff --git a/java/app.go b/java/app.go
index 9f37836..2d817fe 100644
--- a/java/app.go
+++ b/java/app.go
@@ -17,12 +17,13 @@
 // This file contains the module types for compiling Android apps.
 
 import (
-	"github.com/google/blueprint"
-	"github.com/google/blueprint/proptools"
 	"path/filepath"
 	"reflect"
 	"strings"
 
+	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
+
 	"android/soong/android"
 	"android/soong/cc"
 	"android/soong/tradefed"
@@ -85,6 +86,9 @@
 	// list of native libraries that will be provided in or alongside the resulting jar
 	Jni_libs []string `android:"arch_variant"`
 
+	// STL library to use for JNI libraries.
+	Stl *string `android:"arch_variant"`
+
 	// Store native libraries uncompressed in the APK and set the android:extractNativeLibs="false" manifest
 	// flag so that they are used from inside the APK at runtime.  Defaults to true for android_test modules unless
 	// sdk_version or min_sdk_version is set to a version that doesn't support it (<23), defaults to false for other
@@ -116,6 +120,8 @@
 	aapt
 	android.OverridableModuleBase
 
+	usesLibrary usesLibrary
+
 	certificate Certificate
 
 	appProperties appProperties
@@ -149,10 +155,15 @@
 func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
 	a.Module.deps(ctx)
 
+	if String(a.appProperties.Stl) == "c++_shared" && a.sdkVersion() == "" {
+		ctx.PropertyErrorf("stl", "sdk_version must be set in order to use c++_shared")
+	}
+
 	if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
 		a.aapt.deps(ctx, sdkContext(a))
 	}
 
+	embedJni := a.shouldEmbedJnis(ctx)
 	for _, jniTarget := range ctx.MultiTargets() {
 		variation := []blueprint.Variation{
 			{Mutator: "arch", Variation: jniTarget.String()},
@@ -162,7 +173,14 @@
 			target: jniTarget,
 		}
 		ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
+		if String(a.appProperties.Stl) == "c++_shared" {
+			if embedJni {
+				ctx.AddFarVariationDependencies(variation, tag, "libc++")
+			}
+		}
 	}
+
+	a.usesLibrary.deps(ctx, Bool(a.properties.No_framework_libs))
 }
 
 func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
@@ -217,6 +235,11 @@
 	return shouldUncompressDex(ctx, &a.dexpreopter)
 }
 
+func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool {
+	return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
+		a.appProperties.AlwaysPackageNativeLibs
+}
+
 func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
 	a.aapt.usesNonSdkApis = Bool(a.Module.deviceProperties.Platform_apis)
 
@@ -258,6 +281,7 @@
 	aaptLinkFlags = append(aaptLinkFlags, a.additionalAaptFlags...)
 
 	a.aapt.splitNames = a.appProperties.Package_splits
+	a.aapt.sdkLibraries = a.exportedSdkLibs
 
 	a.aapt.buildActions(ctx, sdkContext(a), aaptLinkFlags...)
 
@@ -290,9 +314,17 @@
 	} else {
 		installDir = filepath.Join("app", a.installApkName)
 	}
+
 	a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
 	a.dexpreopter.isInstallable = Bool(a.properties.Installable)
 	a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
+
+	a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
+	a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
+	a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
+	a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
+	a.dexpreopter.manifestFile = a.mergedManifestFile
+
 	a.deviceProperties.UncompressDex = a.dexpreopter.uncompressedDex
 
 	if ctx.ModuleName() != "framework-res" {
@@ -305,9 +337,7 @@
 func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext) android.WritablePath {
 	var jniJarFile android.WritablePath
 	if len(jniLibs) > 0 {
-		embedJni := ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
-			a.appProperties.AlwaysPackageNativeLibs
-		if embedJni {
+		if a.shouldEmbedJnis(ctx) {
 			jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip")
 			TransformJniLibsToJar(ctx, jniJarFile, jniLibs, a.useEmbeddedNativeLibs(ctx))
 		} else {
@@ -352,12 +382,19 @@
 }
 
 func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
+	var apkDeps android.Paths
+
 	// Check if the install APK name needs to be overridden.
 	a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Name())
 
 	// Process all building blocks, from AAPT to certificates.
 	a.aaptBuildActions(ctx)
 
+	if a.usesLibrary.enforceUsesLibraries() {
+		manifestCheckFile := a.usesLibrary.verifyUsesLibrariesManifest(ctx, a.mergedManifestFile)
+		apkDeps = append(apkDeps, manifestCheckFile)
+	}
+
 	a.proguardBuildActions(ctx)
 
 	dexJarFile := a.dexBuildActions(ctx)
@@ -375,13 +412,13 @@
 	// Build a final signed app package.
 	// TODO(jungjw): Consider changing this to installApkName.
 	packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".apk")
-	CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates)
+	CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps)
 	a.outputFile = packageFile
 
 	for _, split := range a.aapt.splits {
 		// Sign the split APKs
 		packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"_"+split.suffix+".apk")
-		CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates)
+		CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps)
 		a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
 	}
 
@@ -467,7 +504,8 @@
 		&module.Module.protoProperties,
 		&module.aaptProperties,
 		&module.appProperties,
-		&module.overridableAppProperties)
+		&module.overridableAppProperties,
+		&module.usesLibrary.usesLibraryProperties)
 
 	module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
 		return class == android.Device && ctx.Config().DevicePrefer32BitApps()
@@ -543,6 +581,7 @@
 		&module.appProperties,
 		&module.appTestProperties,
 		&module.overridableAppProperties,
+		&module.usesLibrary.usesLibraryProperties,
 		&module.testProperties)
 
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
@@ -583,7 +622,8 @@
 		&module.aaptProperties,
 		&module.appProperties,
 		&module.appTestHelperAppProperties,
-		&module.overridableAppProperties)
+		&module.overridableAppProperties,
+		&module.usesLibrary.usesLibraryProperties)
 
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
@@ -650,6 +690,8 @@
 	certificate *Certificate
 
 	dexpreopter
+
+	usesLibrary usesLibrary
 }
 
 type AndroidAppImportProperties struct {
@@ -737,6 +779,8 @@
 	if cert != "" {
 		ctx.AddDependency(ctx.Module(), certificateTag, cert)
 	}
+
+	a.usesLibrary.deps(ctx, false)
 }
 
 func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
@@ -792,7 +836,12 @@
 	// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
 	// TODO: LOCAL_PACKAGE_SPLITS
 
-	srcApk := android.PathForModuleSrc(ctx, a.getSrcApkPath(ctx))
+	var srcApk android.Path
+	srcApk = android.PathForModuleSrc(ctx, a.getSrcApkPath(ctx))
+
+	if a.usesLibrary.enforceUsesLibraries() {
+		srcApk = a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
+	}
 
 	// TODO: Install or embed JNI libraries
 
@@ -805,6 +854,12 @@
 	a.dexpreopter.isInstallable = true
 	a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
 	a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
+
+	a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
+	a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
+	a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
+	a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
+
 	dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
 	if a.dexpreopter.uncompressedDex {
 		dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk")
@@ -850,9 +905,129 @@
 	module.properties.Dpi_variants = reflect.New(dpiVariantsStruct).Interface()
 	module.AddProperties(&module.properties)
 	module.AddProperties(&module.dexpreoptProperties)
+	module.AddProperties(&module.usesLibrary.usesLibraryProperties)
 
 	InitJavaModule(module, android.DeviceSupported)
 	android.InitSingleSourcePrebuiltModule(module, &module.properties.Apk)
 
 	return module
 }
+
+type UsesLibraryProperties struct {
+	// A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file.
+	Uses_libs []string
+
+	// A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file with
+	// required=false.
+	Optional_uses_libs []string
+
+	// If true, the list of uses_libs and optional_uses_libs modules must match the AndroidManifest.xml file.  Defaults
+	// to true if either uses_libs or optional_uses_libs is set.  Will unconditionally default to true in the future.
+	Enforce_uses_libs *bool
+}
+
+// usesLibrary provides properties and helper functions for AndroidApp and AndroidAppImport to verify that the
+// <uses-library> tags that end up in the manifest of an APK match the ones known to the build system through the
+// uses_libs and optional_uses_libs properties.  The build system's values are used by dexpreopt to preopt apps
+// with knowledge of their shared libraries.
+type usesLibrary struct {
+	usesLibraryProperties UsesLibraryProperties
+}
+
+func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, noFrameworkLibs bool) {
+	ctx.AddVariationDependencies(nil, usesLibTag, u.usesLibraryProperties.Uses_libs...)
+	ctx.AddVariationDependencies(nil, usesLibTag, u.presentOptionalUsesLibs(ctx)...)
+	if !noFrameworkLibs {
+		// dexpreopt/dexpreopt.go needs the paths to the dex jars of these libraries in case construct_context.sh needs
+		// to pass them to dex2oat.  Add them as a dependency so we can determine the path to the dex jar of each
+		// library to dexpreopt.
+		ctx.AddVariationDependencies(nil, usesLibTag,
+			"org.apache.http.legacy",
+			"android.hidl.base-V1.0-java",
+			"android.hidl.manager-V1.0-java")
+	}
+}
+
+// presentOptionalUsesLibs returns optional_uses_libs after filtering out MissingUsesLibraries, which don't exist in the
+// build.
+func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []string {
+	optionalUsesLibs, _ := android.FilterList(u.usesLibraryProperties.Optional_uses_libs, ctx.Config().MissingUsesLibraries())
+	return optionalUsesLibs
+}
+
+// usesLibraryPaths returns a map of module names of shared library dependencies to the paths to their dex jars.
+func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) map[string]android.Path {
+	usesLibPaths := make(map[string]android.Path)
+
+	if !ctx.Config().UnbundledBuild() {
+		ctx.VisitDirectDepsWithTag(usesLibTag, func(m android.Module) {
+			if lib, ok := m.(Dependency); ok {
+				if dexJar := lib.DexJar(); dexJar != nil {
+					usesLibPaths[ctx.OtherModuleName(m)] = dexJar
+				} else {
+					ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must produce a dex jar, does it have installable: true?",
+						ctx.OtherModuleName(m))
+				}
+			} else if ctx.Config().AllowMissingDependencies() {
+				ctx.AddMissingDependencies([]string{ctx.OtherModuleName(m)})
+			} else {
+				ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be a java library",
+					ctx.OtherModuleName(m))
+			}
+		})
+	}
+
+	return usesLibPaths
+}
+
+// enforceUsesLibraries returns true of <uses-library> tags should be checked against uses_libs and optional_uses_libs
+// properties.  Defaults to true if either of uses_libs or optional_uses_libs is specified.  Will default to true
+// unconditionally in the future.
+func (u *usesLibrary) enforceUsesLibraries() bool {
+	defaultEnforceUsesLibs := len(u.usesLibraryProperties.Uses_libs) > 0 ||
+		len(u.usesLibraryProperties.Optional_uses_libs) > 0
+	return BoolDefault(u.usesLibraryProperties.Enforce_uses_libs, defaultEnforceUsesLibs)
+}
+
+// verifyUsesLibrariesManifest checks the <uses-library> tags in an AndroidManifest.xml against the ones specified
+// in the uses_libs and optional_uses_libs properties.  It returns the path to a copy of the manifest.
+func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path) android.Path {
+	outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
+
+	rule := android.NewRuleBuilder()
+	cmd := rule.Command().Tool(ctx.Config().HostToolPath(ctx, "manifest_check")).
+		Flag("--enforce-uses-libraries").
+		Input(manifest).
+		FlagWithOutput("-o ", outputFile)
+
+	for _, lib := range u.usesLibraryProperties.Uses_libs {
+		cmd.FlagWithArg("--uses-library ", lib)
+	}
+
+	for _, lib := range u.usesLibraryProperties.Optional_uses_libs {
+		cmd.FlagWithArg("--optional-uses-library ", lib)
+	}
+
+	rule.Build(pctx, ctx, "verify_uses_libraries", "verify <uses-library>")
+
+	return outputFile
+}
+
+// verifyUsesLibrariesAPK checks the <uses-library> tags in the manifest of an APK against the ones specified
+// in the uses_libs and optional_uses_libs properties.  It returns the path to a copy of the APK.
+func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path) android.Path {
+	outputFile := android.PathForModuleOut(ctx, "verify_uses_libraries", apk.Base())
+
+	rule := android.NewRuleBuilder()
+	aapt := ctx.Config().HostToolPath(ctx, "aapt")
+	rule.Command().
+		Textf("aapt_binary=%s", aapt.String()).Implicit(aapt).
+		Textf(`uses_library_names="%s"`, strings.Join(u.usesLibraryProperties.Uses_libs, " ")).
+		Textf(`optional_uses_library_names="%s"`, strings.Join(u.usesLibraryProperties.Optional_uses_libs, " ")).
+		Tool(android.PathForSource(ctx, "build/make/core/verify_uses_libraries.sh")).Input(apk)
+	rule.Command().Text("cp -f").Input(apk).Output(outputFile)
+
+	rule.Build(pctx, ctx, "verify_uses_libraries", "verify <uses-library>")
+
+	return outputFile
+}
diff --git a/java/app_builder.go b/java/app_builder.go
index 82a390f..fa77bbf 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -63,7 +63,7 @@
 	})
 
 func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
-	packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate) {
+	packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths) {
 
 	unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk"
 	unsignedApk := android.PathForModuleOut(ctx, unsignedApkName)
@@ -78,9 +78,10 @@
 	}
 
 	ctx.Build(pctx, android.BuildParams{
-		Rule:   combineApk,
-		Inputs: inputs,
-		Output: unsignedApk,
+		Rule:      combineApk,
+		Inputs:    inputs,
+		Output:    unsignedApk,
+		Implicits: deps,
 	})
 
 	SignAppPackage(ctx, outputFile, unsignedApk, certificates)
diff --git a/java/app_test.go b/java/app_test.go
index 347139e..559afcc 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1178,3 +1178,144 @@
 		}
 	}
 }
+
+func TestStl(t *testing.T) {
+	ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
+		cc_library {
+			name: "libjni",
+		}
+
+		android_test {
+			name: "stl",
+			jni_libs: ["libjni"],
+			compile_multilib: "both",
+			sdk_version: "current",
+			stl: "c++_shared",
+		}
+
+		android_test {
+			name: "system",
+			jni_libs: ["libjni"],
+			compile_multilib: "both",
+			sdk_version: "current",
+		}
+		`)
+
+	testCases := []struct {
+		name string
+		jnis []string
+	}{
+		{"stl",
+			[]string{
+				"libjni.so",
+				"libc++.so",
+			},
+		},
+		{"system",
+			[]string{
+				"libjni.so",
+			},
+		},
+	}
+
+	for _, test := range testCases {
+		t.Run(test.name, func(t *testing.T) {
+			app := ctx.ModuleForTests(test.name, "android_common")
+			jniLibZip := app.Output("jnilibs.zip")
+			var jnis []string
+			args := strings.Fields(jniLibZip.Args["jarArgs"])
+			for i := 0; i < len(args); i++ {
+				if args[i] == "-f" {
+					jnis = append(jnis, args[i+1])
+					i += 1
+				}
+			}
+			jnisJoined := strings.Join(jnis, " ")
+			for _, jni := range test.jnis {
+				if !strings.Contains(jnisJoined, jni) {
+					t.Errorf("missing jni %q in %q", jni, jnis)
+				}
+			}
+		})
+	}
+}
+
+func TestUsesLibraries(t *testing.T) {
+	bp := `
+		java_sdk_library {
+			name: "foo",
+			srcs: ["a.java"],
+			api_packages: ["foo"],
+		}
+
+		java_sdk_library {
+			name: "bar",
+			srcs: ["a.java"],
+			api_packages: ["bar"],
+		}
+
+		android_app {
+			name: "app",
+			srcs: ["a.java"],
+			uses_libs: ["foo"],
+			optional_uses_libs: [
+				"bar",
+				"baz",
+			],
+		}
+
+		android_app_import {
+			name: "prebuilt",
+			apk: "prebuilts/apk/app.apk",
+			certificate: "platform",
+			uses_libs: ["foo"],
+			optional_uses_libs: [
+				"bar",
+				"baz",
+			],
+		}
+	`
+
+	config := testConfig(nil)
+	config.TestProductVariables.MissingUsesLibraries = []string{"baz"}
+
+	ctx := testAppContext(config, bp, nil)
+
+	run(t, ctx, config)
+
+	app := ctx.ModuleForTests("app", "android_common")
+	prebuilt := ctx.ModuleForTests("prebuilt", "android_common")
+
+	// Test that all libraries are verified
+	cmd := app.Rule("verify_uses_libraries").RuleParams.Command
+	if w := "--uses-library foo"; !strings.Contains(cmd, w) {
+		t.Errorf("wanted %q in %q", w, cmd)
+	}
+
+	if w := "--optional-uses-library bar --optional-uses-library baz"; !strings.Contains(cmd, w) {
+		t.Errorf("wanted %q in %q", w, cmd)
+	}
+
+	cmd = prebuilt.Rule("verify_uses_libraries").RuleParams.Command
+
+	if w := `uses_library_names="foo"`; !strings.Contains(cmd, w) {
+		t.Errorf("wanted %q in %q", w, cmd)
+	}
+
+	if w := `optional_uses_library_names="bar baz"`; !strings.Contains(cmd, w) {
+		t.Errorf("wanted %q in %q", w, cmd)
+	}
+
+	// Test that only present libraries are preopted
+	cmd = app.Rule("dexpreopt").RuleParams.Command
+
+	if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) {
+		t.Errorf("wanted %q in %q", w, cmd)
+	}
+
+	cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
+
+	if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) {
+		t.Errorf("wanted %q in %q", w, cmd)
+	}
+}
diff --git a/java/config/config.go b/java/config/config.go
index 46cd361..f9552d5 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -142,7 +142,8 @@
 
 	hostBinToolVariableWithPrebuilt("Aapt2Cmd", "prebuilts/sdk/tools", "aapt2")
 
-	pctx.SourcePathVariable("ManifestFixerCmd", "build/soong/scripts/manifest_fixer.py")
+	pctx.HostBinToolVariable("ManifestCheckCmd", "manifest_check")
+	pctx.HostBinToolVariable("ManifestFixerCmd", "manifest_fixer")
 
 	pctx.HostBinToolVariable("ManifestMergerCmd", "manifest-merger")
 
diff --git a/java/config/makevars.go b/java/config/makevars.go
index 6881caf..9c78511 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -73,6 +73,7 @@
 
 	ctx.Strict("EXTRACT_JAR_PACKAGES", "${ExtractJarPackagesCmd}")
 
+	ctx.Strict("MANIFEST_CHECK", "${ManifestCheckCmd}")
 	ctx.Strict("MANIFEST_FIXER", "${ManifestFixerCmd}")
 
 	ctx.Strict("ANDROID_MANIFEST_MERGER", "${ManifestMergerCmd}")
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 08fd06e..23d2aa6 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -29,6 +29,12 @@
 	isInstallable       bool
 	isPresignedPrebuilt bool
 
+	manifestFile     android.Path
+	usesLibs         []string
+	optionalUsesLibs []string
+	enforceUsesLibs  bool
+	libraryPaths     map[string]android.Path
+
 	builtInstalled string
 }
 
@@ -154,6 +160,7 @@
 		DexLocation:     dexLocation,
 		BuildPath:       android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath,
 		DexPath:         dexJarFile,
+		ManifestPath:    d.manifestFile,
 		UncompressedDex: d.uncompressedDex,
 		HasApkLibraries: false,
 		PreoptFlags:     nil,
@@ -161,10 +168,10 @@
 		ProfileClassListing:  profileClassListing,
 		ProfileIsTextListing: profileIsTextListing,
 
-		EnforceUsesLibraries:  false,
-		OptionalUsesLibraries: nil,
-		UsesLibraries:         nil,
-		LibraryPaths:          nil,
+		EnforceUsesLibraries:         d.enforceUsesLibs,
+		PresentOptionalUsesLibraries: d.optionalUsesLibs,
+		UsesLibraries:                d.usesLibs,
+		LibraryPaths:                 d.libraryPaths,
 
 		Archs:           archs,
 		DexPreoptImages: images,
diff --git a/java/droiddoc.go b/java/droiddoc.go
index fd7e2a4..57da6b6 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -211,6 +211,7 @@
 	// Available variables for substitution:
 	//
 	//  $(location <label>): the path to the arg_files with name <label>
+	//  $$: a literal $
 	Args *string
 
 	// names of the output files used in args that will be generated
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 9627dc6..b1ddab4 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -61,7 +61,7 @@
 	stubFlagsRule(ctx)
 
 	// These rules depend on files located in frameworks/base, skip them if running in a tree that doesn't have them.
-	if ctx.Config().FrameworksBaseDirExists(ctx) {
+	if ctx.Config().FrameworksBaseDirExists(ctx) && !ctx.Config().UnbundledBuild() {
 		h.flags = flagsRule(ctx)
 		h.metadata = metadataRule(ctx)
 	} else {
diff --git a/java/java.go b/java/java.go
index 4483083..31c6afe 100644
--- a/java/java.go
+++ b/java/java.go
@@ -420,6 +420,7 @@
 	proguardRaiseTag      = dependencyTag{name: "proguard-raise"}
 	certificateTag        = dependencyTag{name: "certificate"}
 	instrumentationForTag = dependencyTag{name: "instrumentation_for"}
+	usesLibTag            = dependencyTag{name: "uses-library"}
 )
 
 type sdkDep struct {
@@ -1301,9 +1302,11 @@
 			return
 		}
 
-		// Hidden API CSV generation and dex encoding
-		dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, dexOutputFile, j.implementationJarFile,
-			j.deviceProperties.UncompressDex)
+		if !ctx.Config().UnbundledBuild() {
+			// Hidden API CSV generation and dex encoding
+			dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, dexOutputFile, j.implementationJarFile,
+				j.deviceProperties.UncompressDex)
+		}
 
 		// merge dex jar with resources if necessary
 		if j.resourceJar != nil {
@@ -1481,6 +1484,7 @@
 func (j *Module) IDEInfo(dpInfo *android.IdeInfo) {
 	dpInfo.Deps = append(dpInfo.Deps, j.CompilerDeps()...)
 	dpInfo.Srcs = append(dpInfo.Srcs, j.expandIDEInfoCompiledSrcs...)
+	dpInfo.SrcJars = append(dpInfo.SrcJars, j.compiledSrcJars.Strings()...)
 	dpInfo.Aidl_include_dirs = append(dpInfo.Aidl_include_dirs, j.deviceProperties.Aidl.Include_dirs...)
 	if j.expandJarjarRules != nil {
 		dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String())
diff --git a/java/java_test.go b/java/java_test.go
index 50b1c34..3a7ed4e 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -174,6 +174,8 @@
 
 		"build/soong/scripts/jar-wrapper.sh": nil,
 
+		"build/make/core/verify_uses_libraries.sh": nil,
+
 		"build/make/core/proguard.flags":             nil,
 		"build/make/core/proguard_basic_keeps.flags": nil,
 
diff --git a/java/jdeps.go b/java/jdeps.go
index 18498be..fccc40f 100644
--- a/java/jdeps.go
+++ b/java/jdeps.go
@@ -72,6 +72,7 @@
 		dpInfo.Aidl_include_dirs = android.FirstUniqueStrings(dpInfo.Aidl_include_dirs)
 		dpInfo.Jarjar_rules = android.FirstUniqueStrings(dpInfo.Jarjar_rules)
 		dpInfo.Jars = android.FirstUniqueStrings(dpInfo.Jars)
+		dpInfo.SrcJars = android.FirstUniqueStrings(dpInfo.SrcJars)
 		moduleInfos[name] = dpInfo
 
 		mkProvider, ok := module.(android.AndroidMkDataProvider)
diff --git a/java/robolectric.go b/java/robolectric.go
index 26f1e9d..b87ee0d 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -39,7 +39,7 @@
 
 	Test_options struct {
 		// Timeout in seconds when running the tests.
-		Timeout *string
+		Timeout *int64
 	}
 }
 
diff --git a/java/system_modules.go b/java/system_modules.go
index 9ee0307..8005360 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -87,11 +87,13 @@
 	module := &SystemModules{}
 	module.AddProperties(&module.properties)
 	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
 	return module
 }
 
 type SystemModules struct {
 	android.ModuleBase
+	android.DefaultableModuleBase
 
 	properties SystemModulesProperties
 
diff --git a/java/testing.go b/java/testing.go
index 22831c9..fc7842d 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -77,6 +77,33 @@
 			name: "framework-res",
 			no_framework_libs: true,
 		}
+
+		java_library {
+			name: "android.hidl.base-V1.0-java",
+			srcs: ["a.java"],
+			no_standard_libs: true,
+			sdk_version: "core_current",
+			system_modules: "core-platform-api-stubs-system-modules",
+			installable: true,
+		}
+
+		java_library {
+			name: "android.hidl.manager-V1.0-java",
+			srcs: ["a.java"],
+			no_standard_libs: true,
+			sdk_version: "core_current",
+			system_modules: "core-platform-api-stubs-system-modules",
+			installable: true,
+		}
+
+		java_library {
+			name: "org.apache.http.legacy",
+			srcs: ["a.java"],
+			no_standard_libs: true,
+			sdk_version: "core_current",
+			system_modules: "core-platform-api-stubs-system-modules",
+			installable: true,
+		}
 	`
 
 	systemModules := []string{
diff --git a/scripts/Android.bp b/scripts/Android.bp
new file mode 100644
index 0000000..31f5922
--- /dev/null
+++ b/scripts/Android.bp
@@ -0,0 +1,71 @@
+python_binary_host {
+    name: "manifest_fixer",
+    main: "manifest_fixer.py",
+    srcs: [
+        "manifest_fixer.py",
+        "manifest.py",
+    ],
+    version: {
+        py2: {
+            enabled: true,
+        },
+        py3: {
+            enabled: false,
+        },
+    },
+}
+
+python_test_host {
+    name: "manifest_fixer_test",
+    main: "manifest_fixer_test.py",
+    srcs: [
+        "manifest_fixer_test.py",
+        "manifest_fixer.py",
+        "manifest.py",
+    ],
+    version: {
+        py2: {
+            enabled: true,
+        },
+        py3: {
+            enabled: false,
+        },
+    },
+    test_suites: ["general-tests"],
+}
+
+python_binary_host {
+    name: "manifest_check",
+    main: "manifest_check.py",
+    srcs: [
+        "manifest_check.py",
+        "manifest.py",
+    ],
+    version: {
+        py2: {
+            enabled: true,
+        },
+        py3: {
+            enabled: false,
+        },
+    },
+}
+
+python_test_host {
+    name: "manifest_check_test",
+    main: "manifest_check_test.py",
+    srcs: [
+        "manifest_check_test.py",
+        "manifest_check.py",
+        "manifest.py",
+    ],
+    version: {
+        py2: {
+            enabled: true,
+        },
+        py3: {
+            enabled: false,
+        },
+    },
+    test_suites: ["general-tests"],
+}
diff --git a/scripts/TEST_MAPPING b/scripts/TEST_MAPPING
new file mode 100644
index 0000000..1b0a229
--- /dev/null
+++ b/scripts/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit" : [
+    {
+      "name": "manifest_check_test",
+      "host": true
+    },
+    {
+      "name": "manifest_fixer_test",
+      "host": true
+    }    
+  ]
+}
diff --git a/scripts/build_broken_logs.go b/scripts/build_broken_logs.go
index 4f3e0de..8021e55 100644
--- a/scripts/build_broken_logs.go
+++ b/scripts/build_broken_logs.go
@@ -65,18 +65,6 @@
 		warnings: []string{"overriding commands for target"},
 	},
 	{
-		name:     "BUILD_BROKEN_ANDROIDMK_EXPORTS",
-		behavior: DefaultDeprecated,
-		warnings: []string{"export_keyword"},
-	},
-	{
-		name:     "BUILD_BROKEN_ENG_DEBUG_TAGS",
-		behavior: DefaultDeprecated,
-		warnings: []string{
-			"Changes.md#LOCAL_MODULE_TAGS",
-		},
-	},
-	{
 		name:     "BUILD_BROKEN_USES_NETWORK",
 		behavior: DefaultDeprecated,
 	},
diff --git a/scripts/manifest.py b/scripts/manifest.py
new file mode 100755
index 0000000..4c75f8b
--- /dev/null
+++ b/scripts/manifest.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# 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.
+#
+"""A tool for inserting values from the build system into a manifest."""
+
+from __future__ import print_function
+from xml.dom import minidom
+
+
+android_ns = 'http://schemas.android.com/apk/res/android'
+
+
+def get_children_with_tag(parent, tag_name):
+  children = []
+  for child in  parent.childNodes:
+    if child.nodeType == minidom.Node.ELEMENT_NODE and \
+       child.tagName == tag_name:
+      children.append(child)
+  return children
+
+
+def find_child_with_attribute(element, tag_name, namespace_uri,
+                              attr_name, value):
+  for child in get_children_with_tag(element, tag_name):
+    attr = child.getAttributeNodeNS(namespace_uri, attr_name)
+    if attr is not None and attr.value == value:
+      return child
+  return None
+
+
+def parse_manifest(doc):
+  """Get the manifest element."""
+
+  manifest = doc.documentElement
+  if manifest.tagName != 'manifest':
+    raise RuntimeError('expected manifest tag at root')
+  return manifest
+
+
+def ensure_manifest_android_ns(doc):
+  """Make sure the manifest tag defines the android namespace."""
+
+  manifest = parse_manifest(doc)
+
+  ns = manifest.getAttributeNodeNS(minidom.XMLNS_NAMESPACE, 'android')
+  if ns is None:
+    attr = doc.createAttributeNS(minidom.XMLNS_NAMESPACE, 'xmlns:android')
+    attr.value = android_ns
+    manifest.setAttributeNode(attr)
+  elif ns.value != android_ns:
+    raise RuntimeError('manifest tag has incorrect android namespace ' +
+                       ns.value)
+
+
+def as_int(s):
+  try:
+    i = int(s)
+  except ValueError:
+    return s, False
+  return i, True
+
+
+def compare_version_gt(a, b):
+  """Compare two SDK versions.
+
+  Compares a and b, treating codenames like 'Q' as higher
+  than numerical versions like '28'.
+
+  Returns True if a > b
+
+  Args:
+    a: value to compare
+    b: value to compare
+  Returns:
+    True if a is a higher version than b
+  """
+
+  a, a_is_int = as_int(a.upper())
+  b, b_is_int = as_int(b.upper())
+
+  if a_is_int == b_is_int:
+    # Both are codenames or both are versions, compare directly
+    return a > b
+  else:
+    # One is a codename, the other is not.  Return true if
+    # b is an integer version
+    return b_is_int
+
+
+def get_indent(element, default_level):
+  indent = ''
+  if element is not None and element.nodeType == minidom.Node.TEXT_NODE:
+    text = element.nodeValue
+    indent = text[:len(text)-len(text.lstrip())]
+  if not indent or indent == '\n':
+    # 1 indent = 4 space
+    indent = '\n' + (' ' * default_level * 4)
+  return indent
+
+
+def write_xml(f, doc):
+  f.write('<?xml version="1.0" encoding="utf-8"?>\n')
+  for node in doc.childNodes:
+    f.write(node.toxml(encoding='utf-8') + '\n')
diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py
new file mode 100755
index 0000000..9122da1
--- /dev/null
+++ b/scripts/manifest_check.py
@@ -0,0 +1,215 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# 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.
+#
+"""A tool for checking that a manifest agrees with the build system."""
+
+from __future__ import print_function
+
+import argparse
+import sys
+from xml.dom import minidom
+
+
+from manifest import android_ns
+from manifest import get_children_with_tag
+from manifest import parse_manifest
+from manifest import write_xml
+
+
+class ManifestMismatchError(Exception):
+  pass
+
+
+def parse_args():
+  """Parse commandline arguments."""
+
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--uses-library', dest='uses_libraries',
+                      action='append',
+                      help='specify uses-library entries known to the build system')
+  parser.add_argument('--optional-uses-library',
+                      dest='optional_uses_libraries',
+                      action='append',
+                      help='specify uses-library entries known to the build system with required:false')
+  parser.add_argument('--enforce-uses-libraries',
+                      dest='enforce_uses_libraries',
+                      action='store_true',
+                      help='check the uses-library entries known to the build system against the manifest')
+  parser.add_argument('--extract-target-sdk-version',
+                      dest='extract_target_sdk_version',
+                      action='store_true',
+                      help='print the targetSdkVersion from the manifest')
+  parser.add_argument('--output', '-o', dest='output', help='output AndroidManifest.xml file')
+  parser.add_argument('input', help='input AndroidManifest.xml file')
+  return parser.parse_args()
+
+
+def enforce_uses_libraries(doc, uses_libraries, optional_uses_libraries):
+  """Verify that the <uses-library> tags in the manifest match those provided by the build system.
+
+  Args:
+    doc: The XML document.
+    uses_libraries: The names of <uses-library> tags known to the build system
+    optional_uses_libraries: The names of <uses-library> tags with required:fals
+      known to the build system
+  Raises:
+    RuntimeError: Invalid manifest
+    ManifestMismatchError: Manifest does not match
+  """
+
+  manifest = parse_manifest(doc)
+  elems = get_children_with_tag(manifest, 'application')
+  application = elems[0] if len(elems) == 1 else None
+  if len(elems) > 1:
+    raise RuntimeError('found multiple <application> tags')
+  elif not elems:
+    if uses_libraries or optional_uses_libraries:
+      raise ManifestMismatchError('no <application> tag found')
+    return
+
+  verify_uses_library(application, uses_libraries, optional_uses_libraries)
+
+
+def verify_uses_library(application, uses_libraries, optional_uses_libraries):
+  """Verify that the uses-library values known to the build system match the manifest.
+
+  Args:
+    application: the <application> tag in the manifest.
+    uses_libraries: the names of expected <uses-library> tags.
+    optional_uses_libraries: the names of expected <uses-library> tags with required="false".
+  Raises:
+    ManifestMismatchError: Manifest does not match
+  """
+
+  if uses_libraries is None:
+    uses_libraries = []
+
+  if optional_uses_libraries is None:
+    optional_uses_libraries = []
+
+  manifest_uses_libraries, manifest_optional_uses_libraries = parse_uses_library(application)
+
+  err = []
+  if manifest_uses_libraries != uses_libraries:
+    err.append('Expected required <uses-library> tags "%s", got "%s"' %
+               (', '.join(uses_libraries), ', '.join(manifest_uses_libraries)))
+
+  if manifest_optional_uses_libraries != optional_uses_libraries:
+    err.append('Expected optional <uses-library> tags "%s", got "%s"' %
+               (', '.join(optional_uses_libraries), ', '.join(manifest_optional_uses_libraries)))
+
+  if err:
+    raise ManifestMismatchError('\n'.join(err))
+
+
+def parse_uses_library(application):
+  """Extract uses-library tags from the manifest.
+
+  Args:
+    application: the <application> tag in the manifest.
+  """
+
+  libs = get_children_with_tag(application, 'uses-library')
+
+  uses_libraries = [uses_library_name(x) for x in libs if uses_library_required(x)]
+  optional_uses_libraries = [uses_library_name(x) for x in libs if not uses_library_required(x)]
+
+  return first_unique_elements(uses_libraries), first_unique_elements(optional_uses_libraries)
+
+
+def first_unique_elements(l):
+  result = []
+  [result.append(x) for x in l if x not in result]
+  return result
+
+
+def uses_library_name(lib):
+  """Extract the name attribute of a uses-library tag.
+
+  Args:
+    lib: a <uses-library> tag.
+  """
+  name = lib.getAttributeNodeNS(android_ns, 'name')
+  return name.value if name is not None else ""
+
+
+def uses_library_required(lib):
+  """Extract the required attribute of a uses-library tag.
+
+  Args:
+    lib: a <uses-library> tag.
+  """
+  required = lib.getAttributeNodeNS(android_ns, 'required')
+  return (required.value == 'true') if required is not None else True
+
+
+def extract_target_sdk_version(doc):
+  """Returns the targetSdkVersion from the manifest.
+
+  Args:
+    doc: The XML document.
+  Raises:
+    RuntimeError: invalid manifest
+  """
+
+  manifest = parse_manifest(doc)
+
+  # Get or insert the uses-sdk element
+  uses_sdk = get_children_with_tag(manifest, 'uses-sdk')
+  if len(uses_sdk) > 1:
+    raise RuntimeError('found multiple uses-sdk elements')
+  elif len(uses_sdk) == 0:
+    raise RuntimeError('missing uses-sdk element')
+
+  uses_sdk = uses_sdk[0]
+
+  min_attr = uses_sdk.getAttributeNodeNS(android_ns, 'minSdkVersion')
+  if min_attr is None:
+    raise RuntimeError('minSdkVersion is not specified')
+
+  target_attr = uses_sdk.getAttributeNodeNS(android_ns, 'targetSdkVersion')
+  if target_attr is None:
+    target_attr = min_attr
+
+  return target_attr.value
+
+
+def main():
+  """Program entry point."""
+  try:
+    args = parse_args()
+
+    doc = minidom.parse(args.input)
+
+    if args.enforce_uses_libraries:
+      enforce_uses_libraries(doc,
+                             args.uses_libraries,
+                             args.optional_uses_libraries)
+
+    if args.extract_target_sdk_version:
+      print(extract_target_sdk_version(doc))
+
+    if args.output:
+      with open(args.output, 'wb') as f:
+        write_xml(f, doc)
+
+  # pylint: disable=broad-except
+  except Exception as err:
+    print('error: ' + str(err), file=sys.stderr)
+    sys.exit(-1)
+
+if __name__ == '__main__':
+  main()
diff --git a/scripts/manifest_check_test.py b/scripts/manifest_check_test.py
new file mode 100755
index 0000000..7baad5d
--- /dev/null
+++ b/scripts/manifest_check_test.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# 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.
+#
+"""Unit tests for manifest_fixer.py."""
+
+import sys
+import unittest
+from xml.dom import minidom
+
+import manifest_check
+
+sys.dont_write_bytecode = True
+
+
+def uses_library(name, attr=''):
+  return '<uses-library android:name="%s"%s />' % (name, attr)
+
+
+def required(value):
+  return ' android:required="%s"' % ('true' if value else 'false')
+
+
+class EnforceUsesLibrariesTest(unittest.TestCase):
+  """Unit tests for add_extract_native_libs function."""
+
+  def run_test(self, input_manifest, uses_libraries=None, optional_uses_libraries=None):
+    doc = minidom.parseString(input_manifest)
+    try:
+      manifest_check.enforce_uses_libraries(doc, uses_libraries, optional_uses_libraries)
+      return True
+    except manifest_check.ManifestMismatchError:
+      return False
+
+  manifest_tmpl = (
+      '<?xml version="1.0" encoding="utf-8"?>\n'
+      '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
+      '    <application>\n'
+      '    %s\n'
+      '    </application>\n'
+      '</manifest>\n')
+
+  def test_uses_library(self):
+    manifest_input = self.manifest_tmpl % (uses_library('foo'))
+    matches = self.run_test(manifest_input, uses_libraries=['foo'])
+    self.assertTrue(matches)
+
+  def test_uses_library_required(self):
+    manifest_input = self.manifest_tmpl % (uses_library('foo', required(True)))
+    matches = self.run_test(manifest_input, uses_libraries=['foo'])
+    self.assertTrue(matches)
+
+  def test_optional_uses_library(self):
+    manifest_input = self.manifest_tmpl % (uses_library('foo', required(False)))
+    matches = self.run_test(manifest_input, optional_uses_libraries=['foo'])
+    self.assertTrue(matches)
+
+  def test_expected_uses_library(self):
+    manifest_input = self.manifest_tmpl % (uses_library('foo', required(False)))
+    matches = self.run_test(manifest_input, uses_libraries=['foo'])
+    self.assertFalse(matches)
+
+  def test_expected_optional_uses_library(self):
+    manifest_input = self.manifest_tmpl % (uses_library('foo'))
+    matches = self.run_test(manifest_input, optional_uses_libraries=['foo'])
+    self.assertFalse(matches)
+
+  def test_missing_uses_library(self):
+    manifest_input = self.manifest_tmpl % ('')
+    matches = self.run_test(manifest_input, uses_libraries=['foo'])
+    self.assertFalse(matches)
+
+  def test_missing_optional_uses_library(self):
+    manifest_input = self.manifest_tmpl % ('')
+    matches = self.run_test(manifest_input, optional_uses_libraries=['foo'])
+    self.assertFalse(matches)
+
+  def test_extra_uses_library(self):
+    manifest_input = self.manifest_tmpl % (uses_library('foo'))
+    matches = self.run_test(manifest_input)
+    self.assertFalse(matches)
+
+  def test_extra_optional_uses_library(self):
+    manifest_input = self.manifest_tmpl % (uses_library('foo', required(False)))
+    matches = self.run_test(manifest_input)
+    self.assertFalse(matches)
+
+  def test_multiple_uses_library(self):
+    manifest_input = self.manifest_tmpl % ('\n'.join([uses_library('foo'),
+                                                      uses_library('bar')]))
+    matches = self.run_test(manifest_input, uses_libraries=['foo', 'bar'])
+    self.assertTrue(matches)
+
+  def test_multiple_optional_uses_library(self):
+    manifest_input = self.manifest_tmpl % ('\n'.join([uses_library('foo', required(False)),
+                                                      uses_library('bar', required(False))]))
+    matches = self.run_test(manifest_input, optional_uses_libraries=['foo', 'bar'])
+    self.assertTrue(matches)
+
+  def test_order_uses_library(self):
+    manifest_input = self.manifest_tmpl % ('\n'.join([uses_library('foo'),
+                                                      uses_library('bar')]))
+    matches = self.run_test(manifest_input, uses_libraries=['bar', 'foo'])
+    self.assertFalse(matches)
+
+  def test_order_optional_uses_library(self):
+    manifest_input = self.manifest_tmpl % ('\n'.join([uses_library('foo', required(False)),
+                                                      uses_library('bar', required(False))]))
+    matches = self.run_test(manifest_input, optional_uses_libraries=['bar', 'foo'])
+    self.assertFalse(matches)
+
+  def test_duplicate_uses_library(self):
+    manifest_input = self.manifest_tmpl % ('\n'.join([uses_library('foo'),
+                                                      uses_library('foo')]))
+    matches = self.run_test(manifest_input, uses_libraries=['foo'])
+    self.assertTrue(matches)
+
+  def test_duplicate_optional_uses_library(self):
+    manifest_input = self.manifest_tmpl % ('\n'.join([uses_library('foo', required(False)),
+                                                      uses_library('foo', required(False))]))
+    matches = self.run_test(manifest_input, optional_uses_libraries=['foo'])
+    self.assertTrue(matches)
+
+  def test_mixed(self):
+    manifest_input = self.manifest_tmpl % ('\n'.join([uses_library('foo'),
+                                                      uses_library('bar', required(False))]))
+    matches = self.run_test(manifest_input, uses_libraries=['foo'],
+                            optional_uses_libraries=['bar'])
+    self.assertTrue(matches)
+
+
+class ExtractTargetSdkVersionTest(unittest.TestCase):
+  def test_target_sdk_version(self):
+    manifest = (
+      '<?xml version="1.0" encoding="utf-8"?>\n'
+      '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
+      '    <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="29" />\n'
+      '</manifest>\n')
+    doc = minidom.parseString(manifest)
+    target_sdk_version = manifest_check.extract_target_sdk_version(doc)
+    self.assertEqual(target_sdk_version, '29')
+
+  def test_min_sdk_version(self):
+    manifest = (
+      '<?xml version="1.0" encoding="utf-8"?>\n'
+      '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
+      '    <uses-sdk android:minSdkVersion="28" />\n'
+      '</manifest>\n')
+    doc = minidom.parseString(manifest)
+    target_sdk_version = manifest_check.extract_target_sdk_version(doc)
+    self.assertEqual(target_sdk_version, '28')
+
+if __name__ == '__main__':
+  unittest.main(verbosity=2)
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index 83868e6..bb14851 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -17,30 +17,20 @@
 """A tool for inserting values from the build system into a manifest."""
 
 from __future__ import print_function
+
 import argparse
 import sys
 from xml.dom import minidom
 
 
-android_ns = 'http://schemas.android.com/apk/res/android'
-
-
-def get_children_with_tag(parent, tag_name):
-  children = []
-  for child in  parent.childNodes:
-    if child.nodeType == minidom.Node.ELEMENT_NODE and \
-       child.tagName == tag_name:
-      children.append(child)
-  return children
-
-
-def find_child_with_attribute(element, tag_name, namespace_uri,
-                              attr_name, value):
-  for child in get_children_with_tag(element, tag_name):
-    attr = child.getAttributeNodeNS(namespace_uri, attr_name)
-    if attr is not None and attr.value == value:
-      return child
-  return None
+from manifest import android_ns
+from manifest import compare_version_gt
+from manifest import ensure_manifest_android_ns
+from manifest import find_child_with_attribute
+from manifest import get_children_with_tag
+from manifest import get_indent
+from manifest import parse_manifest
+from manifest import write_xml
 
 
 def parse_args():
@@ -74,76 +64,6 @@
   return parser.parse_args()
 
 
-def parse_manifest(doc):
-  """Get the manifest element."""
-
-  manifest = doc.documentElement
-  if manifest.tagName != 'manifest':
-    raise RuntimeError('expected manifest tag at root')
-  return manifest
-
-
-def ensure_manifest_android_ns(doc):
-  """Make sure the manifest tag defines the android namespace."""
-
-  manifest = parse_manifest(doc)
-
-  ns = manifest.getAttributeNodeNS(minidom.XMLNS_NAMESPACE, 'android')
-  if ns is None:
-    attr = doc.createAttributeNS(minidom.XMLNS_NAMESPACE, 'xmlns:android')
-    attr.value = android_ns
-    manifest.setAttributeNode(attr)
-  elif ns.value != android_ns:
-    raise RuntimeError('manifest tag has incorrect android namespace ' +
-                       ns.value)
-
-
-def as_int(s):
-  try:
-    i = int(s)
-  except ValueError:
-    return s, False
-  return i, True
-
-
-def compare_version_gt(a, b):
-  """Compare two SDK versions.
-
-  Compares a and b, treating codenames like 'Q' as higher
-  than numerical versions like '28'.
-
-  Returns True if a > b
-
-  Args:
-    a: value to compare
-    b: value to compare
-  Returns:
-    True if a is a higher version than b
-  """
-
-  a, a_is_int = as_int(a.upper())
-  b, b_is_int = as_int(b.upper())
-
-  if a_is_int == b_is_int:
-    # Both are codenames or both are versions, compare directly
-    return a > b
-  else:
-    # One is a codename, the other is not.  Return true if
-    # b is an integer version
-    return b_is_int
-
-
-def get_indent(element, default_level):
-  indent = ''
-  if element is not None and element.nodeType == minidom.Node.TEXT_NODE:
-    text = element.nodeValue
-    indent = text[:len(text)-len(text.lstrip())]
-  if not indent or indent == '\n':
-    # 1 indent = 4 space
-    indent = '\n' + (' ' * default_level * 4)
-  return indent
-
-
 def raise_min_sdk_version(doc, min_sdk_version, target_sdk_version, library):
   """Ensure the manifest contains a <uses-sdk> tag with a minSdkVersion.
 
@@ -151,6 +71,7 @@
     doc: The XML document.  May be modified by this function.
     min_sdk_version: The requested minSdkVersion attribute.
     target_sdk_version: The requested targetSdkVersion attribute.
+    library: True if the manifest is for a library.
   Raises:
     RuntimeError: invalid manifest
   """
@@ -249,6 +170,7 @@
     indent = get_indent(application.previousSibling, 1)
     application.appendChild(doc.createTextNode(indent))
 
+
 def add_uses_non_sdk_api(doc):
   """Add android:usesNonSdkApi=true attribute to <application>.
 
@@ -323,12 +245,6 @@
                        (attr.value, value))
 
 
-def write_xml(f, doc):
-  f.write('<?xml version="1.0" encoding="utf-8"?>\n')
-  for node in doc.childNodes:
-    f.write(node.toxml(encoding='utf-8') + '\n')
-
-
 def main():
   """Program entry point."""
   try:
diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py
index 7ec8999..2035421 100755
--- a/scripts/manifest_fixer_test.py
+++ b/scripts/manifest_fixer_test.py
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-"""Unit tests for manifest_fixer_test.py."""
+"""Unit tests for manifest_fixer.py."""
 
 import StringIO
 import sys
@@ -393,10 +393,10 @@
     return output.getvalue()
 
   manifest_tmpl = (
-    '<?xml version="1.0" encoding="utf-8"?>\n'
-    '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
-    '    <application%s/>\n'
-    '</manifest>\n')
+      '<?xml version="1.0" encoding="utf-8"?>\n'
+      '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
+      '    <application%s/>\n'
+      '</manifest>\n')
 
   def extract_native_libs(self, value):
     return ' android:extractNativeLibs="%s"' % value
@@ -425,4 +425,4 @@
 
 
 if __name__ == '__main__':
-  unittest.main()
+  unittest.main(verbosity=2)
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index c6e5ddc..4335667 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -205,8 +205,6 @@
 
 		// Not used, but useful to be in the soong.log
 		"BOARD_VNDK_VERSION",
-		"BUILD_BROKEN_ANDROIDMK_EXPORTS",
-		"BUILD_BROKEN_ENG_DEBUG_TAGS",
 
 		"DEFAULT_WARNING_BUILD_MODULE_TYPES",
 		"DEFAULT_ERROR_BUILD_MODULE_TYPES",
diff --git a/ui/build/proc_sync.go b/ui/build/proc_sync.go
index 857786d..0cfe798 100644
--- a/ui/build/proc_sync.go
+++ b/ui/build/proc_sync.go
@@ -34,6 +34,14 @@
 	if err != nil {
 		ctx.Logger.Fatal(err)
 	}
+	lockfilePollDuration := time.Second
+	lockfileTimeout := time.Second * 10
+	if envTimeout := os.Getenv("SOONG_LOCK_TIMEOUT"); envTimeout != "" {
+		lockfileTimeout, err = time.ParseDuration(envTimeout)
+		if err != nil {
+			ctx.Logger.Fatalf("failure parsing SOONG_LOCK_TIMEOUT %q: %s", envTimeout, err)
+		}
+	}
 	err = lockSynchronous(*lockingInfo, newSleepWaiter(lockfilePollDuration, lockfileTimeout), ctx.Logger)
 	if err != nil {
 		ctx.Logger.Fatal(err)
@@ -41,9 +49,6 @@
 	return lockingInfo
 }
 
-var lockfileTimeout = time.Second * 10
-var lockfilePollDuration = time.Second
-
 type lockable interface {
 	tryLock() error
 	Unlock() error
@@ -80,15 +85,18 @@
 			return nil
 		}
 
-		waited = true
-
 		done, description := waiter.checkDeadline()
 
+		if !waited {
+			logger.Printf("Waiting up to %s to lock %v to ensure no other Soong process is running in the same output directory\n", description, lock.description())
+		}
+
+		waited = true
+
 		if done {
 			return fmt.Errorf("Tried to lock %s, but timed out %s . Make sure no other Soong process is using it",
 				lock.description(), waiter.summarize())
 		} else {
-			logger.Printf("Waiting up to %s to lock %v to ensure no other Soong process is running in the same output directory\n", description, lock.description())
 			waiter.wait()
 		}
 	}