Handle restricting to device only builds

By default, most module types are only enabled for device. Converting
this behavior and host_supported/device_supported properties allows us
to skip building incompatible targets.

Test: soong tests
Test: bp2build.sh
Change-Id: If1da523b4cc8c4cbf2bb26da063d9923b662cc32
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 0f6e139..19209f6 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -201,7 +201,7 @@
 			config := android.TestConfig(buildDir, nil, testCase.bp, nil)
 			ctx := android.NewTestContext(config)
 
-			ctx.RegisterModuleType("custom", customModuleFactory)
+			ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
 			ctx.Register()
 
 			_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
@@ -501,6 +501,215 @@
 	}
 }
 
+func TestBp2buildHostAndDevice(t *testing.T) {
+	testCases := []bp2buildTestCase{
+		{
+			description:                "host and device, device only",
+			moduleTypeUnderTest:        "custom",
+			moduleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
+			blueprint: `custom {
+		name: "foo",
+		bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				makeBazelTargetHostOrDevice("custom", "foo", attrNameToString{}, android.DeviceSupported),
+			},
+		},
+		{
+			description:                "host and device, both",
+			moduleTypeUnderTest:        "custom",
+			moduleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
+			blueprint: `custom {
+		name: "foo",
+		host_supported: true,
+		bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				makeBazelTargetNoRestrictions("custom", "foo", attrNameToString{}),
+			},
+		},
+		{
+			description:                "host and device, host explicitly disabled",
+			moduleTypeUnderTest:        "custom",
+			moduleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
+			blueprint: `custom {
+		name: "foo",
+		host_supported: false,
+		bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				makeBazelTargetHostOrDevice("custom", "foo", attrNameToString{}, android.DeviceSupported),
+			},
+		},
+		{
+			description:                "host and device, neither",
+			moduleTypeUnderTest:        "custom",
+			moduleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
+			blueprint: `custom {
+		name: "foo",
+		host_supported: false,
+		device_supported: false,
+		bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				makeBazelTargetNoRestrictions("custom", "foo", attrNameToString{
+					"target_compatible_with": `["@platforms//:incompatible"]`,
+				}),
+			},
+		},
+		{
+			description:                "host and device, neither, cannot override with product_var",
+			moduleTypeUnderTest:        "custom",
+			moduleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
+			blueprint: `custom {
+		name: "foo",
+		host_supported: false,
+		device_supported: false,
+		product_variables: { unbundled_build: { enabled: true } },
+		bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				makeBazelTargetNoRestrictions("custom", "foo", attrNameToString{
+					"target_compatible_with": `["@platforms//:incompatible"]`,
+				}),
+			},
+		},
+		{
+			description:                "host and device, both, disabled overrided with product_var",
+			moduleTypeUnderTest:        "custom",
+			moduleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
+			blueprint: `custom {
+		name: "foo",
+		host_supported: true,
+		device_supported: true,
+		enabled: false,
+		product_variables: { unbundled_build: { enabled: true } },
+		bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				makeBazelTargetNoRestrictions("custom", "foo", attrNameToString{
+					"target_compatible_with": `["//build/bazel/product_variables:unbundled_build"]`,
+				}),
+			},
+		},
+		{
+			description:                "host and device, neither, cannot override with arch enabled",
+			moduleTypeUnderTest:        "custom",
+			moduleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
+			blueprint: `custom {
+		name: "foo",
+		host_supported: false,
+		device_supported: false,
+		arch: { x86: { enabled: true } },
+		bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				makeBazelTargetNoRestrictions("custom", "foo", attrNameToString{
+					"target_compatible_with": `["@platforms//:incompatible"]`,
+				}),
+			},
+		},
+		{
+			description:                "host and device, host only",
+			moduleTypeUnderTest:        "custom",
+			moduleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
+			blueprint: `custom {
+		name: "foo",
+		host_supported: true,
+		device_supported: false,
+		bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				makeBazelTargetHostOrDevice("custom", "foo", attrNameToString{}, android.HostSupported),
+			},
+		},
+		{
+			description:                "host only",
+			moduleTypeUnderTest:        "custom",
+			moduleTypeUnderTestFactory: customModuleFactoryHostSupported,
+			blueprint: `custom {
+		name: "foo",
+		bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				makeBazelTargetHostOrDevice("custom", "foo", attrNameToString{}, android.HostSupported),
+			},
+		},
+		{
+			description:                "device only",
+			moduleTypeUnderTest:        "custom",
+			moduleTypeUnderTestFactory: customModuleFactoryDeviceSupported,
+			blueprint: `custom {
+		name: "foo",
+		bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				makeBazelTargetHostOrDevice("custom", "foo", attrNameToString{}, android.DeviceSupported),
+			},
+		},
+		{
+			description:                "host and device default, default",
+			moduleTypeUnderTest:        "custom",
+			moduleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault,
+			blueprint: `custom {
+		name: "foo",
+		bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				makeBazelTargetNoRestrictions("custom", "foo", attrNameToString{}),
+			},
+		},
+		{
+			description:                "host and device default, device only",
+			moduleTypeUnderTest:        "custom",
+			moduleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault,
+			blueprint: `custom {
+		name: "foo",
+		host_supported: false,
+		bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				makeBazelTargetHostOrDevice("custom", "foo", attrNameToString{}, android.DeviceSupported),
+			},
+		},
+		{
+			description:                "host and device default, host only",
+			moduleTypeUnderTest:        "custom",
+			moduleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault,
+			blueprint: `custom {
+		name: "foo",
+		device_supported: false,
+		bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				makeBazelTargetHostOrDevice("custom", "foo", attrNameToString{}, android.HostSupported),
+			},
+		},
+		{
+			description:                "host and device default, neither",
+			moduleTypeUnderTest:        "custom",
+			moduleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault,
+			blueprint: `custom {
+		name: "foo",
+		host_supported: false,
+		device_supported: false,
+		bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				makeBazelTargetNoRestrictions("custom", "foo", attrNameToString{
+					"target_compatible_with": `["@platforms//:incompatible"]`,
+				}),
+			},
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.description, func(t *testing.T) {
+			runBp2BuildTestCaseSimple(t, tc)
+		})
+	}
+}
+
 func TestLoadStatements(t *testing.T) {
 	testCases := []struct {
 		bazelTargets           BazelTargets
@@ -610,6 +819,7 @@
 		{
 			bp: `custom {
     name: "bar",
+    host_supported: true,
     one_to_many_prop: true,
     bazel_module: { bp2build_available: true  },
 }`,
@@ -634,7 +844,7 @@
 	for _, testCase := range testCases {
 		config := android.TestConfig(buildDir, nil, testCase.bp, nil)
 		ctx := android.NewTestContext(config)
-		ctx.RegisterModuleType("custom", customModuleFactory)
+		ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
 		ctx.RegisterForBazelConversion()
 
 		_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
@@ -680,7 +890,7 @@
     bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{
-				makeBazelTarget("filegroup", "fg_foo", map[string]string{}),
+				makeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{}),
 			},
 		},
 		{
@@ -693,7 +903,7 @@
     bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{
-				makeBazelTarget("filegroup", "fg_foo", map[string]string{}),
+				makeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{}),
 			},
 		},
 		{
@@ -706,7 +916,7 @@
     bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{
-				makeBazelTarget("filegroup", "fg_foo", map[string]string{
+				makeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
 					"srcs": `[
         "a",
         "b",
@@ -725,7 +935,7 @@
     bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{
-				makeBazelTarget("filegroup", "fg_foo", map[string]string{
+				makeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
 					"srcs": `["b"]`,
 				}),
 			},
@@ -740,7 +950,7 @@
     bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{
-				makeBazelTarget("filegroup", "fg_foo", map[string]string{
+				makeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
 					"srcs": `[
         "other/a.txt",
         "other/b.txt",
@@ -772,7 +982,7 @@
 				"other/file":         "",
 			},
 			expectedBazelTargets: []string{
-				makeBazelTarget("filegroup", "fg_foo", map[string]string{
+				makeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
 					"srcs": `[
         "a.txt",
         "b.txt",
@@ -801,7 +1011,7 @@
 }`,
 			},
 			expectedBazelTargets: []string{
-				makeBazelTarget("filegroup", "fg_foo", map[string]string{
+				makeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
 					"srcs": `[
         "//other:foo",
         "c",
@@ -884,7 +1094,7 @@
 		{
 			description:                "generates more than 1 target if needed",
 			moduleTypeUnderTest:        "custom",
-			moduleTypeUnderTestFactory: customModuleFactory,
+			moduleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
 			bp: `custom {
     name: "foo",
     one_to_many_prop: true,
@@ -1092,7 +1302,7 @@
 				"other/BUILD.bazel": `// definition for fg_bar`,
 			},
 			expectedBazelTargets: []string{
-				makeBazelTarget("filegroup", "fg_foo", map[string]string{}),
+				makeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{}),
 				`// definition for fg_bar`,
 			},
 		},
@@ -1118,7 +1328,7 @@
         },
     }`,
 			expectedBazelTargets: []string{
-				makeBazelTarget("filegroup", "fg_bar", map[string]string{}),
+				makeBazelTargetNoRestrictions("filegroup", "fg_bar", map[string]string{}),
 				`// BUILD file`,
 			},
 		},
@@ -1203,7 +1413,7 @@
 				"dir/f.txt":      "",
 			},
 			expectedBazelTargets: []string{
-				makeBazelTarget("filegroup", "fg_foo", map[string]string{
+				makeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
 					"srcs": `[
         "a.txt",
         "b.txt",
@@ -1234,7 +1444,7 @@
 				"dir/subdir/f.txt":      "",
 			},
 			expectedBazelTargets: []string{
-				makeBazelTarget("filegroup", "fg_foo", map[string]string{
+				makeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
 					"srcs": `[
         "a.txt",
         "//dir/subdir:e.txt",
@@ -1265,7 +1475,7 @@
     bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{
-				makeBazelTarget("filegroup", "fg_foo", map[string]string{
+				makeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
 					"data": `[":reqd"]`,
 				}),
 			},
@@ -1337,7 +1547,7 @@
     bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{
-				makeBazelTarget("filegroup", "fg_foo", map[string]string{
+				makeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
 					"data": `[":reqd"]`,
 				}),
 			},