Merge "Add //visibility:override to allow control over inheritance"
diff --git a/README.md b/README.md
index 8b028a8..f1857f8 100644
--- a/README.md
+++ b/README.md
@@ -289,6 +289,9 @@
 * `["//visibility:public"]`: Anyone can use this module.
 * `["//visibility:private"]`: Only rules in the module's package (not its
 subpackages) can use this module.
+* `["//visibility:override"]`: Discards any rules inherited from defaults or a
+creating module. Can only be used at the beginning of a list of visibility
+rules.
 * `["//some/package:__pkg__", "//other/package:__pkg__"]`: Only modules in
 `some/package` and `other/package` (defined in `some/package/*.bp` and
 `other/package/*.bp`) have access to this module. Note that sub-packages do not
diff --git a/android/module.go b/android/module.go
index e431ada..71c9893 100644
--- a/android/module.go
+++ b/android/module.go
@@ -331,6 +331,8 @@
 	//  ["//visibility:public"]: Anyone can use this module.
 	//  ["//visibility:private"]: Only rules in the module's package (not its subpackages) can use
 	//      this module.
+	//  ["//visibility:override"]: Discards any rules inherited from defaults or a creating module.
+	//      Can only be used at the beginning of a list of visibility rules.
 	//  ["//some/package:__pkg__", "//other/package:__pkg__"]: Only modules in some/package and
 	//      other/package (defined in some/package/*.bp and other/package/*.bp) have access to
 	//      this module. Note that sub-packages do not have access to the rule; for example,
diff --git a/android/visibility.go b/android/visibility.go
index 1e3b91d..2cb0023 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -245,7 +245,7 @@
 		return
 	}
 
-	for _, v := range visibility {
+	for i, v := range visibility {
 		ok, pkg, name := splitRule(ctx, v, currentPkg, property)
 		if !ok {
 			continue
@@ -257,11 +257,18 @@
 			case "legacy_public":
 				ctx.PropertyErrorf(property, "//visibility:legacy_public must not be used")
 				continue
+			case "override":
+				// This keyword does not create a rule so pretend it does not exist.
+				ruleCount -= 1
 			default:
 				ctx.PropertyErrorf(property, "unrecognized visibility rule %q", v)
 				continue
 			}
-			if ruleCount != 1 {
+			if name == "override" {
+				if i != 0 {
+					ctx.PropertyErrorf(property, `"%v" may only be used at the start of the visibility rules`, v)
+				}
+			} else if ruleCount != 1 {
 				ctx.PropertyErrorf(property, "cannot mix %q with any other visibility rules", v)
 				continue
 			}
@@ -327,6 +334,14 @@
 			case "public":
 				r = publicRule{}
 				hasPublicRule = true
+			case "override":
+				// Discard all preceding rules and any state based on them.
+				rules = nil
+				hasPrivateRule = false
+				hasPublicRule = false
+				hasNonPrivateRule = false
+				// This does not actually create a rule so continue onto the next rule.
+				continue
 			}
 		} else {
 			switch name {
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 4cf41a6..ca09345 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -636,6 +636,177 @@
 		},
 	},
 	{
+		name: "//visibility:private override //visibility:public",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:public"],
+				}
+				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:public override //visibility:private",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:private"],
+				}
+				mock_library {
+					name: "libexample",
+					visibility: ["//visibility:public"],
+					defaults: ["libexample_defaults"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "libexample": visibility: cannot mix "//visibility:private" with any other visibility rules`,
+		},
+	},
+	{
+		name: "//visibility:override must be first in the list",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_library {
+					name: "libexample",
+					visibility: ["//other", "//visibility:override", "//namespace"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "libexample": visibility: "//visibility:override" may only be used at the start of the visibility rules`,
+		},
+	},
+	{
+		name: "//visibility:override discards //visibility:private",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:private"],
+				}
+				mock_library {
+					name: "libexample",
+					// Make this visibility to //other but not //visibility:private
+					visibility: ["//visibility:override", "//other"],
+					defaults: ["libexample_defaults"],
+				}`),
+			"other/Blueprints": []byte(`
+				mock_library {
+					name: "libother",
+					deps: ["libexample"],
+				}`),
+		},
+	},
+	{
+		name: "//visibility:override discards //visibility:public",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:public"],
+				}
+				mock_library {
+					name: "libexample",
+					// Make this visibility to //other but not //visibility:public
+					visibility: ["//visibility:override", "//other"],
+					defaults: ["libexample_defaults"],
+				}`),
+			"other/Blueprints": []byte(`
+				mock_library {
+					name: "libother",
+					deps: ["libexample"],
+				}`),
+			"namespace/Blueprints": []byte(`
+				mock_library {
+					name: "libnamespace",
+					deps: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`,
+		},
+	},
+	{
+		name: "//visibility:override discards defaults supplied rules",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//namespace"],
+				}
+				mock_library {
+					name: "libexample",
+					// Make this visibility to //other but not //namespace
+					visibility: ["//visibility:override", "//other"],
+					defaults: ["libexample_defaults"],
+				}`),
+			"other/Blueprints": []byte(`
+				mock_library {
+					name: "libother",
+					deps: ["libexample"],
+				}`),
+			"namespace/Blueprints": []byte(`
+				mock_library {
+					name: "libnamespace",
+					deps: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`,
+		},
+	},
+	{
+		name: "//visibility:override can override //visibility:public with //visibility:private",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:public"],
+				}
+				mock_library {
+					name: "libexample",
+					visibility: ["//visibility:override", "//visibility:private"],
+					defaults: ["libexample_defaults"],
+				}`),
+			"namespace/Blueprints": []byte(`
+				mock_library {
+					name: "libnamespace",
+					deps: ["libexample"],
+				}`),
+		},
+		expectedErrors: []string{
+			`module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`,
+		},
+	},
+	{
+		name: "//visibility:override can override //visibility:private with //visibility:public",
+		fs: map[string][]byte{
+			"top/Blueprints": []byte(`
+				mock_defaults {
+					name: "libexample_defaults",
+					visibility: ["//visibility:private"],
+				}
+				mock_library {
+					name: "libexample",
+					visibility: ["//visibility:override", "//visibility:public"],
+					defaults: ["libexample_defaults"],
+				}`),
+			"namespace/Blueprints": []byte(`
+				mock_library {
+					name: "libnamespace",
+					deps: ["libexample"],
+				}`),
+		},
+	},
+	{
 		name: "//visibility:private mixed with itself",
 		fs: map[string][]byte{
 			"top/Blueprints": []byte(`