Add prebuilt_visibility property

Some mainline modules provide an `sdk` and one or more set of
module_exports. When the snapshots are unpacked into separate prebuilts
directories (one per snapshot) then any dependencies from a member of
one snapshot to a member of another may require the latter to have
additional visibility rules.

Previously, these rules had to be added to each source module. This
change allows additional visibility rules to be specified on the
sdk/module_exports that are added to all the prebuilts in its snapshot.

Bug: 155921753
Bug: 168301990
Test: m nothing
Change-Id: Ia3eacb5749981f04770ae9872a8013e43c5c6ef1
diff --git a/sdk/sdk.go b/sdk/sdk.go
index 7591020..50b0886 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -75,6 +75,20 @@
 
 	// True if this is a module_exports (or module_exports_snapshot) module type.
 	Module_exports bool `blueprint:"mutated"`
+
+	// The additional visibility to add to the prebuilt modules to allow them to
+	// reference each other.
+	//
+	// This can only be used to widen the visibility of the members:
+	//
+	// * Specifying //visibility:public here will make all members visible and
+	//   essentially ignore their own visibility.
+	// * Specifying //visibility:private here is an error.
+	// * Specifying any other rule here will add it to the members visibility and
+	//   be output to the member prebuilt in the snapshot. Duplicates will be
+	//   dropped. Adding a rule to members that have //visibility:private will
+	//   cause the //visibility:private to be discarded.
+	Prebuilt_visibility []string
 }
 
 // Contains information about the sdk properties that list sdk members, e.g.
@@ -211,6 +225,9 @@
 	// properties for the member type specific list properties.
 	s.dynamicMemberTypeListProperties = s.dynamicSdkMemberTypes.createMemberListProperties()
 	s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties)
+
+	// Make sure that the prebuilt visibility property is verified for errors.
+	android.AddVisibilityProperty(s, "prebuilt_visibility", &s.properties.Prebuilt_visibility)
 	android.InitCommonOSAndroidMultiTargetsArchModule(s, android.HostAndDeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(s)
 	android.AddLoadHook(s, func(ctx android.LoadHookContext) {
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index ef62b79..2e6c62a 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -108,6 +108,9 @@
 				// generated sdk_snapshot.
 				":__subpackages__",
 			],
+			prebuilt_visibility: [
+				"//prebuilts/mysdk",
+			],
 			java_header_libs: [
 				"myjavalib",
 				"mypublicjavalib",
@@ -176,6 +179,7 @@
     visibility: [
         "//other/foo",
         "//package",
+        "//prebuilts/mysdk",
     ],
     jars: ["java/myjavalib.jar"],
 }
@@ -186,6 +190,7 @@
     visibility: [
         "//other/foo",
         "//package",
+        "//prebuilts/mysdk",
     ],
     jars: ["java/myjavalib.jar"],
 }
@@ -210,6 +215,7 @@
     visibility: [
         "//other/bar",
         "//package",
+        "//prebuilts/mysdk",
     ],
     jars: ["java/mydefaultedjavalib.jar"],
 }
@@ -220,6 +226,7 @@
     visibility: [
         "//other/bar",
         "//package",
+        "//prebuilts/mysdk",
     ],
     jars: ["java/mydefaultedjavalib.jar"],
 }
@@ -227,14 +234,20 @@
 java_import {
     name: "mysdk_myprivatejavalib@current",
     sdk_member_name: "myprivatejavalib",
-    visibility: ["//package"],
+    visibility: [
+        "//package",
+        "//prebuilts/mysdk",
+    ],
     jars: ["java/myprivatejavalib.jar"],
 }
 
 java_import {
     name: "myprivatejavalib",
     prefer: false,
-    visibility: ["//package"],
+    visibility: [
+        "//package",
+        "//prebuilts/mysdk",
+    ],
     jars: ["java/myprivatejavalib.jar"],
 }
 
@@ -254,6 +267,40 @@
 `))
 }
 
+func TestPrebuiltVisibilityProperty_IsValidated(t *testing.T) {
+	testSdkError(t, `prebuilt_visibility: cannot mix "//visibility:private" with any other visibility rules`, `
+		sdk {
+			name: "mysdk",
+			prebuilt_visibility: [
+				"//foo",
+				"//visibility:private",
+			],
+		}
+`)
+}
+
+func TestPrebuiltVisibilityProperty_AddPrivate(t *testing.T) {
+	testSdkError(t, `prebuilt_visibility: "//visibility:private" does not widen the visibility`, `
+		sdk {
+			name: "mysdk",
+			prebuilt_visibility: [
+				"//visibility:private",
+			],
+			java_header_libs: [
+				"myjavalib",
+			],
+		}
+
+		java_library {
+			name: "myjavalib",
+			// Uses package default visibility
+			srcs: ["Test.java"],
+			system_modules: "none",
+			sdk_version: "none",
+		}
+`)
+}
+
 func TestSDkInstall(t *testing.T) {
 	sdk := `
 		sdk {
diff --git a/sdk/update.go b/sdk/update.go
index a10e852..f29b5a0 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -300,7 +300,7 @@
 	snapshotModule.AddProperty("name", snapshotName)
 
 	// Make sure that the snapshot has the same visibility as the sdk.
-	visibility := android.EffectiveVisibilityRules(ctx, s)
+	visibility := android.EffectiveVisibilityRules(ctx, s).Strings()
 	if len(visibility) != 0 {
 		snapshotModule.AddProperty("visibility", visibility)
 	}
@@ -719,7 +719,15 @@
 	} else {
 		// Extract visibility information from a member variant. All variants have the same
 		// visibility so it doesn't matter which one is used.
-		visibility := android.EffectiveVisibilityRules(s.ctx, variant)
+		visibilityRules := android.EffectiveVisibilityRules(s.ctx, variant)
+
+		// Add any additional visibility rules needed for the prebuilts to reference each other.
+		err := visibilityRules.Widen(s.sdk.properties.Prebuilt_visibility)
+		if err != nil {
+			s.ctx.PropertyErrorf("prebuilt_visibility", "%s", err)
+		}
+
+		visibility := visibilityRules.Strings()
 		if len(visibility) != 0 {
 			m.AddProperty("visibility", visibility)
 		}