Merge "Integrate hiddenapi processing into boot jars test"
diff --git a/android/filegroup.go b/android/filegroup.go
index 7a6cc4f..98d0eaf 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -17,8 +17,6 @@
 import (
 	"android/soong/bazel"
 	"strings"
-
-	"github.com/google/blueprint/proptools"
 )
 
 func init() {
@@ -28,7 +26,6 @@
 
 // https://docs.bazel.build/versions/master/be/general.html#filegroup
 type bazelFilegroupAttributes struct {
-	Name *string
 	Srcs bazel.LabelList
 }
 
@@ -50,20 +47,24 @@
 
 func (bfg *bazelFilegroup) GenerateAndroidBuildActions(ctx ModuleContext) {}
 
-// TODO: Create helper functions to avoid this boilerplate.
 func FilegroupBp2Build(ctx TopDownMutatorContext) {
 	fg, ok := ctx.Module().(*fileGroup)
-	if !ok {
+	if !ok || !fg.properties.Bazel_module.Bp2build_available {
 		return
 	}
 
-	name := "__bp2build__" + fg.base().BaseModuleName()
-	ctx.CreateModule(BazelFileGroupFactory, &bazelFilegroupAttributes{
-		Name: proptools.StringPtr(name),
+	attrs := &bazelFilegroupAttributes{
 		Srcs: BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs),
-	}, &bazel.BazelTargetModuleProperties{
+	}
+
+	// Can we automate this?
+	name := "__bp2build__" + fg.Name()
+	props := bazel.BazelTargetModuleProperties{
+		Name:       &name,
 		Rule_class: "filegroup",
-	})
+	}
+
+	ctx.CreateBazelTargetModule(BazelFileGroupFactory, props, attrs)
 }
 
 type fileGroupProperties struct {
diff --git a/android/mutator.go b/android/mutator.go
index 15be65f..91753d1 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -15,6 +15,7 @@
 package android
 
 import (
+	"android/soong/bazel"
 	"reflect"
 
 	"github.com/google/blueprint"
@@ -275,6 +276,12 @@
 	// CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
 	// the specified property structs to it as if the properties were set in a blueprint file.
 	CreateModule(ModuleFactory, ...interface{}) Module
+
+	// CreateBazelTargetModule creates a BazelTargetModule by calling the
+	// factory method, just like in CreateModule, but also requires
+	// BazelTargetModuleProperties containing additional metadata for the
+	// bp2build codegenerator.
+	CreateBazelTargetModule(ModuleFactory, bazel.BazelTargetModuleProperties, interface{}) BazelTargetModule
 }
 
 type topDownMutatorContext struct {
@@ -502,6 +509,13 @@
 	ctx.BottomUp("deps", depsMutator).Parallel()
 }
 
+func (t *topDownMutatorContext) CreateBazelTargetModule(
+	factory ModuleFactory,
+	bazelProps bazel.BazelTargetModuleProperties,
+	attrs interface{}) BazelTargetModule {
+	return t.CreateModule(factory, &bazelProps, attrs).(BazelTargetModule)
+}
+
 func (t *topDownMutatorContext) AppendProperties(props ...interface{}) {
 	for _, p := range props {
 		err := proptools.AppendMatchingProperties(t.Module().base().customizableProperties,
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 3149952..041afb3 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -260,12 +260,36 @@
 	}
 }
 
+type exportedDependencyTag struct {
+	blueprint.BaseDependencyTag
+	name string
+}
+
+// Mark this tag so dependencies that use it are excluded from visibility enforcement.
+//
+// This does allow any prebuilt_apex to reference any module which does open up a small window for
+// restricted visibility modules to be referenced from the wrong prebuilt_apex. However, doing so
+// avoids opening up a much bigger window by widening the visibility of modules that need files
+// provided by the prebuilt_apex to include all the possible locations they may be defined, which
+// could include everything below vendor/.
+//
+// A prebuilt_apex that references a module via this tag will have to contain the appropriate files
+// corresponding to that module, otherwise it will fail when attempting to retrieve the files from
+// the .apex file. It will also have to be included in the module's apex_available property too.
+// That makes it highly unlikely that a prebuilt_apex would reference a restricted module
+// incorrectly.
+func (t exportedDependencyTag) ExcludeFromVisibilityEnforcement() {}
+
+var (
+	exportedJavaLibTag = exportedDependencyTag{name: "exported_java_lib"}
+)
+
 func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
 	// Add dependencies onto the java modules that represent the java libraries that are provided by
 	// and exported from this prebuilt apex.
 	for _, lib := range p.properties.Exported_java_libs {
 		dep := prebuiltApexExportedModuleName(ctx, lib)
-		ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), javaLibTag, dep)
+		ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), exportedJavaLibTag, dep)
 	}
 }
 
@@ -305,7 +329,7 @@
 	var dependencies []android.ApexModule
 	mctx.VisitDirectDeps(func(m android.Module) {
 		tag := mctx.OtherModuleDependencyTag(m)
-		if tag == javaLibTag {
+		if tag == exportedJavaLibTag {
 			depName := mctx.OtherModuleName(m)
 
 			// It is an error if the other module is not a prebuilt.
diff --git a/bazel/properties.go b/bazel/properties.go
index 5b98d15..65f37e3 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -17,6 +17,9 @@
 type bazelModuleProperties struct {
 	// The label of the Bazel target replacing this Soong module.
 	Label string
+
+	// If true, bp2build will generate the converted Bazel target for this module.
+	Bp2build_available bool
 }
 
 // Properties contains common module properties for Bazel migration purposes.
@@ -29,6 +32,8 @@
 // BazelTargetModuleProperties contain properties and metadata used for
 // Blueprint to BUILD file conversion.
 type BazelTargetModuleProperties struct {
+	Name *string
+
 	// The Bazel rule class for this target.
 	Rule_class string
 
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 2c293ea..9013377 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -173,6 +173,12 @@
 			}
 			t = generateBazelTarget(ctx, m)
 		case QueryView:
+			// Blocklist certain module types from being generated.
+			if canonicalizeModuleType(ctx.ModuleType(m)) == "package" {
+				// package module name contain slashes, and thus cannot
+				// be mapped cleanly to a bazel label.
+				return
+			}
 			t = generateSoongModuleTarget(ctx, m)
 		default:
 			panic(fmt.Errorf("Unknown code-generation mode: %s", codegenMode))
@@ -213,6 +219,8 @@
 	// Delete it from being generated in the BUILD file.
 	delete(props.Attrs, "bzl_load_location")
 
+	delete(props.Attrs, "bp2build_available")
+
 	// Return the Bazel target with rule class and attributes, ready to be
 	// code-generated.
 	attributes := propsToAttributes(props.Attrs)
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 081b0e5..27212d1 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -228,6 +228,7 @@
 	name: "foo",
     string_list_prop: ["a", "b"],
     string_prop: "a",
+    bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTarget: `custom(
     name = "foo",
@@ -382,6 +383,7 @@
 		{
 			bp: `custom {
     name: "bar",
+    bazel_module: { bp2build_available: true  },
 }`,
 			expectedBazelTarget: `my_library(
     name = "bar",
@@ -474,6 +476,7 @@
 			bp: `filegroup {
     name: "fg_foo",
     srcs: [],
+    bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{
 				`filegroup(
@@ -491,6 +494,7 @@
 			bp: `filegroup {
     name: "fg_foo",
     srcs: ["a", "b"],
+    bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{`filegroup(
     name = "fg_foo",
@@ -510,6 +514,7 @@
     name: "fg_foo",
     srcs: ["a", "b"],
     exclude_srcs: ["a"],
+    bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{`filegroup(
     name = "fg_foo",
@@ -527,6 +532,7 @@
 			bp: `filegroup {
     name: "foo",
     srcs: ["**/*.txt"],
+    bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{`filegroup(
     name = "foo",
@@ -552,6 +558,7 @@
 			bp: `filegroup {
     name: "foo",
     srcs: ["a.txt"],
+    bazel_module: { bp2build_available: true },
 }`,
 			dir: "other",
 			expectedBazelTargets: []string{`filegroup(
@@ -567,6 +574,7 @@
 				"other/Android.bp": `filegroup {
     name: "fg_foo",
     srcs: ["**/*.txt"],
+    bazel_module: { bp2build_available: true },
 }`,
 				"other/a.txt":        "",
 				"other/b.txt":        "",
@@ -585,6 +593,7 @@
       ":foo",
         "c",
     ],
+    bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{`filegroup(
     name = "foobar",
@@ -612,6 +621,7 @@
     out: ["foo_tool.out"],
     srcs: ["foo_tool.in"],
     cmd: "cp $(in) $(out)",
+    bazel_module: { bp2build_available: true },
 }
 
 genrule {
@@ -620,6 +630,7 @@
     srcs: ["foo.in"],
     tools: [":foo.tool"],
     cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)",
+    bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{
 				`genrule(
@@ -658,7 +669,8 @@
     out: ["foo_tool.out", "foo_tool2.out"],
     srcs: ["foo_tool.in"],
     cmd: "cp $(in) $(out)",
-   }
+    bazel_module: { bp2build_available: true },
+}
 
 genrule {
     name: "foo",
@@ -666,6 +678,7 @@
     srcs: ["foo.in"],
     tools: [":foo.tools"],
     cmd: "$(locations :foo.tools) -s $(out) $(in)",
+    bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{`genrule(
     name = "foo",
@@ -705,6 +718,7 @@
     srcs: ["foo.in"],
     tool_files: [":foo.tool"],
     cmd: "$(locations :foo.tool) -s $(out) $(in)",
+    bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{`genrule(
     name = "foo",
@@ -734,6 +748,7 @@
     srcs: [":other.tool"],
     tool_files: [":foo.tool"],
     cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
+    bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{`genrule(
     name = "foo",
@@ -763,6 +778,7 @@
     srcs: ["foo.in"],
     tool_files: [":foo.tool", ":other.tool"],
     cmd: "$(location) -s $(out) $(in)",
+    bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{`genrule(
     name = "foo",
@@ -793,6 +809,7 @@
     srcs: ["foo.in"],
     tools: [":foo.tool", ":other.tool"],
     cmd: "$(locations) -s $(out) $(in)",
+    bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{`genrule(
     name = "foo",
@@ -822,6 +839,7 @@
     out: ["foo.out"],
     srcs: ["foo.in"],
     cmd: "cp $(in) $(out)",
+    bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{`genrule(
     name = "foo",
@@ -927,6 +945,7 @@
     out: ["out"],
     srcs: ["in1"],
     defaults: ["gen_defaults"],
+    bazel_module: { bp2build_available: true },
 }
 `,
 			expectedBazelTarget: `genrule(
@@ -961,6 +980,7 @@
     srcs: ["in1"],
     defaults: ["gen_defaults"],
     cmd: "do-something $(in) $(out)",
+    bazel_module: { bp2build_available: true },
 }
 `,
 			expectedBazelTarget: `genrule(
@@ -999,6 +1019,7 @@
     name: "gen",
     out: ["out"],
     defaults: ["gen_defaults1", "gen_defaults2"],
+    bazel_module: { bp2build_available: true },
 }
 `,
 			expectedBazelTarget: `genrule(
@@ -1045,6 +1066,7 @@
     name: "gen",
     out: ["out"],
     defaults: ["gen_defaults1"],
+    bazel_module: { bp2build_available: true },
 }
 `,
 			expectedBazelTarget: `genrule(
@@ -1097,3 +1119,80 @@
 		}
 	}
 }
+
+func TestAllowlistingBp2buildTargets(t *testing.T) {
+	testCases := []struct {
+		moduleTypeUnderTest                string
+		moduleTypeUnderTestFactory         android.ModuleFactory
+		moduleTypeUnderTestBp2BuildMutator bp2buildMutator
+		bp                                 string
+		expectedCount                      int
+		description                        string
+	}{
+		{
+			description:                        "explicitly unavailable",
+			moduleTypeUnderTest:                "filegroup",
+			moduleTypeUnderTestFactory:         android.FileGroupFactory,
+			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+			bp: `filegroup {
+    name: "foo",
+    srcs: ["a", "b"],
+    bazel_module: { bp2build_available: false },
+}`,
+			expectedCount: 0,
+		},
+		{
+			description:                        "implicitly unavailable",
+			moduleTypeUnderTest:                "filegroup",
+			moduleTypeUnderTestFactory:         android.FileGroupFactory,
+			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+			bp: `filegroup {
+    name: "foo",
+    srcs: ["a", "b"],
+}`,
+			expectedCount: 0,
+		},
+		{
+			description:                        "explicitly available",
+			moduleTypeUnderTest:                "filegroup",
+			moduleTypeUnderTestFactory:         android.FileGroupFactory,
+			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+			bp: `filegroup {
+    name: "foo",
+    srcs: ["a", "b"],
+    bazel_module: { bp2build_available: true },
+}`,
+			expectedCount: 1,
+		},
+		{
+			description:                        "generates more than 1 target if needed",
+			moduleTypeUnderTest:                "custom",
+			moduleTypeUnderTestFactory:         customModuleFactory,
+			moduleTypeUnderTestBp2BuildMutator: customBp2BuildMutatorFromStarlark,
+			bp: `custom {
+    name: "foo",
+    bazel_module: { bp2build_available: true },
+}`,
+			expectedCount: 3,
+		},
+	}
+
+	dir := "."
+	for _, testCase := range testCases {
+		config := android.TestConfig(buildDir, nil, testCase.bp, nil)
+		ctx := android.NewTestContext(config)
+		ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
+		ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
+		ctx.RegisterForBazelConversion()
+
+		_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
+		android.FailIfErrored(t, errs)
+		_, errs = ctx.ResolveDependencies(config)
+		android.FailIfErrored(t, errs)
+
+		bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[dir]
+		if actualCount := len(bazelTargets); actualCount != testCase.expectedCount {
+			t.Fatalf("%s: Expected %d bazel target, got %d", testCase.description, testCase.expectedCount, actualCount)
+		}
+	}
+}
diff --git a/bp2build/bzl_conversion_test.go b/bp2build/bzl_conversion_test.go
index f2a4058..30c1a5b 100644
--- a/bp2build/bzl_conversion_test.go
+++ b/bp2build/bzl_conversion_test.go
@@ -86,6 +86,10 @@
         "soong_module_name": attr.string(mandatory = True),
         "soong_module_variant": attr.string(),
         "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
+        # bazel_module start
+#         "label": attr.string(),
+#         "bp2build_available": attr.bool(),
+        # bazel_module end
         "bool_prop": attr.bool(),
         "bool_ptr_prop": attr.bool(),
         "int64_ptr_prop": attr.int(),
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 5e6481b..1f0ada2 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -3,8 +3,6 @@
 import (
 	"android/soong/android"
 	"android/soong/bazel"
-
-	"github.com/google/blueprint/proptools"
 )
 
 type nestedProps struct {
@@ -29,6 +27,8 @@
 	android.ModuleBase
 
 	props customProps
+
+	bazelProps bazel.Properties
 }
 
 // OutputFiles is needed because some instances of this module use dist with a
@@ -44,6 +44,7 @@
 func customModuleFactoryBase() android.Module {
 	module := &customModule{}
 	module.AddProperties(&module.props)
+	module.AddProperties(&module.bazelProps)
 	return module
 }
 
@@ -105,7 +106,6 @@
 }
 
 type customBazelModuleAttributes struct {
-	Name             *string
 	String_prop      string
 	String_list_prop []string
 }
@@ -127,14 +127,22 @@
 
 func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
 	if m, ok := ctx.Module().(*customModule); ok {
-		name := "__bp2build__" + m.Name()
-		ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{
-			Name:             proptools.StringPtr(name),
+		if !m.bazelProps.Bazel_module.Bp2build_available {
+			return
+		}
+
+		attrs := &customBazelModuleAttributes{
 			String_prop:      m.props.String_prop,
 			String_list_prop: m.props.String_list_prop,
-		}, &bazel.BazelTargetModuleProperties{
+		}
+
+		name := "__bp2build__" + m.Name()
+		props := bazel.BazelTargetModuleProperties{
+			Name:       &name,
 			Rule_class: "custom",
-		})
+		}
+
+		ctx.CreateBazelTargetModule(customBazelModuleFactory, props, attrs)
 	}
 }
 
@@ -142,24 +150,35 @@
 // module to target.
 func customBp2BuildMutatorFromStarlark(ctx android.TopDownMutatorContext) {
 	if m, ok := ctx.Module().(*customModule); ok {
-		baseName := "__bp2build__" + m.Name()
-		ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{
-			Name: proptools.StringPtr(baseName),
-		}, &bazel.BazelTargetModuleProperties{
+		if !m.bazelProps.Bazel_module.Bp2build_available {
+			return
+		}
+
+		baseName := m.Name()
+		attrs := &customBazelModuleAttributes{}
+
+		myLibraryName := "__bp2build__" + baseName
+		myLibraryProps := bazel.BazelTargetModuleProperties{
+			Name:              &myLibraryName,
 			Rule_class:        "my_library",
 			Bzl_load_location: "//build/bazel/rules:rules.bzl",
-		})
-		ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{
-			Name: proptools.StringPtr(baseName + "_proto_library_deps"),
-		}, &bazel.BazelTargetModuleProperties{
+		}
+		ctx.CreateBazelTargetModule(customBazelModuleFactory, myLibraryProps, attrs)
+
+		protoLibraryName := "__bp2build__" + baseName + "_proto_library_deps"
+		protoLibraryProps := bazel.BazelTargetModuleProperties{
+			Name:              &protoLibraryName,
 			Rule_class:        "proto_library",
 			Bzl_load_location: "//build/bazel/rules:proto.bzl",
-		})
-		ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{
-			Name: proptools.StringPtr(baseName + "_my_proto_library_deps"),
-		}, &bazel.BazelTargetModuleProperties{
+		}
+		ctx.CreateBazelTargetModule(customBazelModuleFactory, protoLibraryProps, attrs)
+
+		myProtoLibraryName := "__bp2build__" + baseName + "_my_proto_library_deps"
+		myProtoLibraryProps := bazel.BazelTargetModuleProperties{
+			Name:              &myProtoLibraryName,
 			Rule_class:        "my_proto_library",
 			Bzl_load_location: "//build/bazel/rules:proto.bzl",
-		})
+		}
+		ctx.CreateBazelTargetModule(customBazelModuleFactory, myProtoLibraryProps, attrs)
 	}
 }
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 62aa7f8..a500c27 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -780,7 +780,6 @@
 }
 
 type bazelGenruleAttributes struct {
-	Name  *string
 	Srcs  bazel.LabelList
 	Outs  []string
 	Tools bazel.LabelList
@@ -801,10 +800,10 @@
 
 func GenruleBp2Build(ctx android.TopDownMutatorContext) {
 	m, ok := ctx.Module().(*Module)
-	if !ok {
+	if !ok || !m.properties.Bazel_module.Bp2build_available {
 		return
 	}
-	name := "__bp2build__" + m.Name()
+
 	// Bazel only has the "tools" attribute.
 	tools := android.BazelLabelForModuleDeps(ctx, m.properties.Tools)
 	tool_files := android.BazelLabelForModuleSrc(ctx, m.properties.Tool_files)
@@ -847,16 +846,22 @@
 		}
 	}
 
-	// Create the BazelTargetModule.
-	ctx.CreateModule(BazelGenruleFactory, &bazelGenruleAttributes{
-		Name:  proptools.StringPtr(name),
+	attrs := &bazelGenruleAttributes{
 		Srcs:  srcs,
 		Outs:  outs,
 		Cmd:   cmd,
 		Tools: tools,
-	}, &bazel.BazelTargetModuleProperties{
+	}
+
+	// Can we automate this?
+	name := "__bp2build__" + m.Name()
+	props := bazel.BazelTargetModuleProperties{
+		Name:       &name,
 		Rule_class: "genrule",
-	})
+	}
+
+	// Create the BazelTargetModule.
+	ctx.CreateBazelTargetModule(BazelGenruleFactory, props, attrs)
 }
 
 func (m *bazelGenrule) Name() string {