Merge "Revert "Port uses-shared library verification and dexpreopting to Soong""
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/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/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 ea5316c..09c5b1b 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -91,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 {
@@ -105,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`,
 		},
 	},
 	{
@@ -121,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`,
 		},
 	},
@@ -153,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",
@@ -207,9 +180,9 @@
 		},
 		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; //top:libexample is only visible to \[//top:__pkg__\]`,
+				` visible to this module`,
 		},
 	},
 	{
@@ -239,9 +212,9 @@
 		},
 		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; //top:libexample is only visible to \[//top:__pkg__\]`,
+				` visible to this module`,
 		},
 	},
 	{
@@ -277,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`,
 		},
 	},
 	{
@@ -310,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`,
 		},
 	},
 	{
@@ -341,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`,
 		},
 	},
 	{
@@ -399,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) {
@@ -445,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()
 
@@ -466,6 +725,7 @@
 
 type mockLibraryModule struct {
 	ModuleBase
+	DefaultableModuleBase
 	properties mockLibraryProperties
 }
 
@@ -473,6 +733,7 @@
 	m := &mockLibraryModule{}
 	m.AddProperties(&m.properties)
 	InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
+	InitDefaultableModule(m)
 	return m
 }
 
@@ -487,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/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/cc.go b/cc/cc.go
index 2e551e1..4600a15 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -534,6 +534,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
diff --git a/cc/vndk.go b/cc/vndk.go
index a1d67af..60a3d78 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/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..8dbdfb6 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1301,9 +1301,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 {
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/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/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()
 		}
 	}