Convert apex_available (for supported modules) to bazel tags.

The tags will then be read by an aspect applied from apex attributes to
validate that the deps are explicitly opt-in to the appropriate apex.

The semantics of this is the same as the Soong apex_available property.

This also adds the "base_apex_name" attr to override_apex conversion so
that apex_available checks continue to work on the non-Google and non-Go
apex names.

Test: presubmits
Fixes: 218841706
Change-Id: I19b3637da9aa47573b252d74f62b601fbdc3784d
diff --git a/android/mutator.go b/android/mutator.go
index 83d4e66..d92b87c 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -705,6 +705,28 @@
 	t.createBazelTargetModule(bazelProps, commonAttrs, attrs, enabledProperty)
 }
 
+// ApexAvailableTags converts the apex_available property value of an ApexModule
+// module and returns it as a list of keyed tags.
+func ApexAvailableTags(mod Module) bazel.StringListAttribute {
+	attr := bazel.StringListAttribute{}
+	tags := []string{}
+	// Transform specific attributes into tags.
+	if am, ok := mod.(ApexModule); ok {
+		// TODO(b/218841706): hidl_interface has the apex_available prop, but it's
+		// defined directly as a prop and not via ApexModule, so this doesn't
+		// pick those props up.
+		// TODO(b/260694842): This does not pick up aidl_interface.backend.ndk.apex_available.
+		for _, a := range am.apexModuleBase().ApexAvailable() {
+			tags = append(tags, "apex_available="+a)
+		}
+	}
+	if len(tags) > 0 {
+		// This avoids creating a tags attr with an empty list if there are no tags.
+		attr.Value = tags
+	}
+	return attr
+}
+
 func (t *topDownMutatorContext) createBazelTargetModule(
 	bazelProps bazel.BazelTargetModuleProperties,
 	commonAttrs CommonAttributes,
diff --git a/apex/apex.go b/apex/apex.go
index b1b4e47..8e1783e 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2676,6 +2676,10 @@
 	}
 	attrs, props := convertWithBp2build(a, ctx)
 
+	// We just want the name, not module reference.
+	baseApexName := strings.TrimPrefix(baseApexModuleName, ":")
+	attrs.Base_apex_name = &baseApexName
+
 	for _, p := range o.GetProperties() {
 		overridableProperties, ok := p.(*overridableProperties)
 		if !ok {
@@ -3397,6 +3401,7 @@
 	Package_name          *string
 	Logging_parent        *string
 	Tests                 bazel.LabelListAttribute
+	Base_apex_name        *string
 }
 
 type convertedNativeSharedLibs struct {
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
index b6061e4..714b848 100644
--- a/bp2build/apex_conversion_test.go
+++ b/bp2build/apex_conversion_test.go
@@ -663,6 +663,7 @@
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
 				"android_manifest": `"ApogeeAndroidManifest.xml"`,
+				"base_apex_name":   `"com.android.apogee"`,
 				"binaries": `[
         ":cc_binary_1",
         ":sh_binary_2",
@@ -729,8 +730,9 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
-				"file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
-				"manifest":      `"//a/b:apex_manifest.json"`,
+				"base_apex_name": `"com.android.apogee"`,
+				"file_contexts":  `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
+				"manifest":       `"//a/b:apex_manifest.json"`,
 			}),
 		}})
 }
@@ -763,8 +765,9 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
-				"file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
-				"manifest":      `"//a/b:apogee_manifest.json"`,
+				"base_apex_name": `"com.android.apogee"`,
+				"file_contexts":  `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
+				"manifest":       `"//a/b:apogee_manifest.json"`,
 			}),
 		}})
 }
@@ -795,8 +798,9 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
-				"file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
-				"manifest":      `"apex_manifest.json"`,
+				"base_apex_name": `"com.android.apogee"`,
+				"file_contexts":  `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
+				"manifest":       `"apex_manifest.json"`,
 			}),
 		}})
 }
@@ -828,8 +832,9 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
-				"file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
-				"manifest":      `"apogee_manifest.json"`,
+				"base_apex_name": `"com.android.apogee"`,
+				"file_contexts":  `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
+				"manifest":       `"apogee_manifest.json"`,
 			}),
 		}})
 }
@@ -861,9 +866,10 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
-				"file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
-				"manifest":      `"apex_manifest.json"`,
-				"package_name":  `"com.google.android.apogee"`,
+				"base_apex_name": `"com.android.apogee"`,
+				"file_contexts":  `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
+				"manifest":       `"apex_manifest.json"`,
+				"package_name":   `"com.google.android.apogee"`,
 			}),
 		}})
 }
@@ -900,9 +906,10 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
-				"file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
-				"manifest":      `"apex_manifest.json"`,
-				"prebuilts":     `[":prebuilt_file"]`,
+				"base_apex_name": `"com.android.apogee"`,
+				"file_contexts":  `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
+				"manifest":       `"apex_manifest.json"`,
+				"prebuilts":      `[":prebuilt_file"]`,
 			}),
 		}})
 }
@@ -945,9 +952,10 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
-				"file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
-				"manifest":      `"apex_manifest.json"`,
-				"prebuilts":     `[":prebuilt_file2"]`,
+				"base_apex_name": `"com.android.apogee"`,
+				"file_contexts":  `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
+				"manifest":       `"apex_manifest.json"`,
+				"prebuilts":      `[":prebuilt_file2"]`,
 			}),
 		}})
 }
@@ -985,9 +993,10 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
-				"file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
-				"manifest":      `"apex_manifest.json"`,
-				"prebuilts":     `[]`,
+				"base_apex_name": `"com.android.apogee"`,
+				"file_contexts":  `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
+				"manifest":       `"apex_manifest.json"`,
+				"prebuilts":      `[]`,
 			}),
 		}})
 }
@@ -1019,6 +1028,7 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
+				"base_apex_name": `"com.android.apogee"`,
 				"file_contexts":  `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
 				"manifest":       `"apex_manifest.json"`,
 				"logging_parent": `"foo.bar.baz"`,
@@ -1054,6 +1064,7 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
+				"base_apex_name": `"com.android.apogee"`,
 				"file_contexts":  `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
 				"manifest":       `"apex_manifest.json"`,
 				"logging_parent": `"foo.bar.baz.override"`,
@@ -1099,8 +1110,9 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
-				"file_contexts": `":com.android.apogee-file_contexts"`,
-				"manifest":      `"apogee_manifest.json"`,
+				"base_apex_name": `"com.android.apogee"`,
+				"file_contexts":  `":com.android.apogee-file_contexts"`,
+				"manifest":       `"apogee_manifest.json"`,
 			}),
 		}})
 }
@@ -1200,9 +1212,10 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
-				"file_contexts": `":com.android.apogee-file_contexts"`,
-				"certificate":   `":com.google.android.apogee.certificate"`,
-				"manifest":      `"apogee_manifest.json"`,
+				"base_apex_name": `"com.android.apogee"`,
+				"file_contexts":  `":com.android.apogee-file_contexts"`,
+				"certificate":    `":com.google.android.apogee.certificate"`,
+				"manifest":       `"apogee_manifest.json"`,
 			}),
 		}})
 }
@@ -1244,6 +1257,7 @@
 `,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
+				"base_apex_name":   `"com.android.apogee"`,
 				"file_contexts":    `":com.android.apogee-file_contexts"`,
 				"certificate_name": `"com.google.android.apogee.certificate"`,
 				"manifest":         `"apogee_manifest.json"`,
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index edb0c43..a1e83d8 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -3645,3 +3645,49 @@
 		},
 	})
 }
+
+func TestCcLibraryApexAvailable(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library apex_available converted to tags",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: soongCcLibraryPreamble + `
+cc_library {
+    name: "a",
+    srcs: ["a.cpp"],
+    apex_available: ["com.android.foo"],
+}
+`,
+		ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{
+			"tags":           `["apex_available=com.android.foo"]`,
+			"srcs":           `["a.cpp"]`,
+			"local_includes": `["."]`,
+		}),
+	},
+	)
+}
+
+func TestCcLibraryApexAvailableMultiple(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library apex_available converted to multiple tags",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: soongCcLibraryPreamble + `
+cc_library {
+    name: "a",
+    srcs: ["a.cpp"],
+    apex_available: ["com.android.foo", "//apex_available:platform", "com.android.bar"],
+}
+`,
+		ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{
+			"tags": `[
+        "apex_available=com.android.foo",
+        "apex_available=//apex_available:platform",
+        "apex_available=com.android.bar",
+    ]`,
+			"srcs":           `["a.cpp"]`,
+			"local_includes": `["."]`,
+		}),
+	},
+	)
+}
diff --git a/cc/binary.go b/cc/binary.go
index c2868e7..998934e 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -655,11 +655,12 @@
 	// shared with cc_test
 	binaryAttrs := binaryBp2buildAttrs(ctx, m)
 
+	tags := android.ApexAvailableTags(m)
 	ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
 		Rule_class:        "cc_binary",
 		Bzl_load_location: "//build/bazel/rules/cc:cc_binary.bzl",
 	},
-		android.CommonAttributes{Name: m.Name()},
+		android.CommonAttributes{Name: m.Name(), Tags: tags},
 		&binaryAttrs)
 }
 
diff --git a/cc/library.go b/cc/library.go
index 1cad6b9..6ba01eb 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -448,11 +448,18 @@
 		Bzl_load_location: "//build/bazel/rules/cc:cc_library_shared.bzl",
 	}
 
+	tags := android.ApexAvailableTags(m)
 	ctx.CreateBazelTargetModuleWithRestrictions(staticProps,
-		android.CommonAttributes{Name: m.Name() + "_bp2build_cc_library_static"},
+		android.CommonAttributes{
+			Name: m.Name() + "_bp2build_cc_library_static",
+			Tags: tags,
+		},
 		staticTargetAttrs, staticAttrs.Enabled)
 	ctx.CreateBazelTargetModuleWithRestrictions(sharedProps,
-		android.CommonAttributes{Name: m.Name()},
+		android.CommonAttributes{
+			Name: m.Name(),
+			Tags: tags,
+		},
 		sharedTargetAttrs, sharedAttrs.Enabled)
 
 	createStubsBazelTargetIfNeeded(ctx, m, compilerAttrs, exportedIncludes, baseAttributes)
@@ -2914,7 +2921,8 @@
 		Bzl_load_location: fmt.Sprintf("//build/bazel/rules/cc:%s.bzl", modType),
 	}
 
-	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
+	tags := android.ApexAvailableTags(module)
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name(), Tags: tags}, attrs)
 }
 
 // TODO(b/199902614): Can this be factored to share with the other Attributes?
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 1842e5a..2730052 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -388,7 +388,9 @@
 	if fullBuild {
 		name += "_bp2build_cc_library_static"
 	}
-	ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: name}, attrs, prebuiltAttrs.Enabled)
+
+	tags := android.ApexAvailableTags(module)
+	ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: name, Tags: tags}, attrs, prebuiltAttrs.Enabled)
 }
 
 type bazelPrebuiltLibrarySharedAttributes struct {
@@ -408,7 +410,8 @@
 	}
 
 	name := android.RemoveOptionalPrebuiltPrefix(module.Name())
-	ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: name}, attrs, prebuiltAttrs.Enabled)
+	tags := android.ApexAvailableTags(module)
+	ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: name, Tags: tags}, attrs, prebuiltAttrs.Enabled)
 }
 
 type prebuiltObjectProperties struct {
@@ -740,7 +743,8 @@
 	}
 
 	name := android.RemoveOptionalPrebuiltPrefix(module.Name())
-	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
+	tags := android.ApexAvailableTags(module)
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name, Tags: tags}, attrs)
 }
 
 type Sanitized struct {
diff --git a/cc/proto.go b/cc/proto.go
index cf5ed04..27f37cb 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -205,13 +205,13 @@
 	protoAttrs.Deps.SetValue(protoInfo.Proto_libs)
 
 	name := m.Name() + suffix
-
+	tags := android.ApexAvailableTags(m)
 	ctx.CreateBazelTargetModule(
 		bazel.BazelTargetModuleProperties{
 			Rule_class:        rule_class,
 			Bzl_load_location: "//build/bazel/rules/cc:cc_proto.bzl",
 		},
-		android.CommonAttributes{Name: name},
+		android.CommonAttributes{Name: name, Tags: tags},
 		&protoAttrs)
 
 	var privateHdrs bool