Add neverallow rules for java_device_for_host

java_device_for_host and java_host_for_device should rarely be
used and could cause problems if used incorrectly, so restrict them
to only the necessary projects through a neverallow whitelist.

Bug: 117920228
Test: neverallow_test.go
Change-Id: I37dce489c2fb8bca71bd46dbabaaa514bf6f7eee
Merged-In: I37dce489c2fb8bca71bd46dbabaaa514bf6f7eee
diff --git a/android/neverallow.go b/android/neverallow.go
index 18744e8..f63f461 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -51,6 +51,7 @@
 	rules := []*rule{}
 	rules = append(rules, createTrebleRules()...)
 	rules = append(rules, createLibcoreRules()...)
+	rules = append(rules, createJavaDeviceForHostRules()...)
 	return rules
 }
 
@@ -125,6 +126,20 @@
 	return rules
 }
 
+func createJavaDeviceForHostRules() []*rule {
+	javaDeviceForHostProjectsWhitelist := []string{
+		"external/robolectric-shadows",
+		"framework/layoutlib",
+	}
+
+	return []*rule{
+		neverallow().
+			notIn(javaDeviceForHostProjectsWhitelist...).
+			moduleType("java_device_for_host", "java_host_for_device").
+			because("java_device_for_host can only be used in whitelisted projects"),
+	}
+}
+
 func neverallowMutator(ctx BottomUpMutatorContext) {
 	m, ok := ctx.Module().(Module)
 	if !ok {
@@ -139,6 +154,10 @@
 			continue
 		}
 
+		if !n.appliesToModuleType(ctx.ModuleType()) {
+			continue
+		}
+
 		if !n.appliesToProperties(properties) {
 			continue
 		}
@@ -159,6 +178,9 @@
 	paths       []string
 	unlessPaths []string
 
+	moduleTypes       []string
+	unlessModuleTypes []string
+
 	props       []ruleProperty
 	unlessProps []ruleProperty
 }
@@ -166,14 +188,27 @@
 func neverallow() *rule {
 	return &rule{}
 }
+
 func (r *rule) in(path ...string) *rule {
 	r.paths = append(r.paths, cleanPaths(path)...)
 	return r
 }
+
 func (r *rule) notIn(path ...string) *rule {
 	r.unlessPaths = append(r.unlessPaths, cleanPaths(path)...)
 	return r
 }
+
+func (r *rule) moduleType(types ...string) *rule {
+	r.moduleTypes = append(r.moduleTypes, types...)
+	return r
+}
+
+func (r *rule) notModuleType(types ...string) *rule {
+	r.unlessModuleTypes = append(r.unlessModuleTypes, types...)
+	return r
+}
+
 func (r *rule) with(properties, value string) *rule {
 	r.props = append(r.props, ruleProperty{
 		fields: fieldNamesForProperties(properties),
@@ -181,6 +216,7 @@
 	})
 	return r
 }
+
 func (r *rule) without(properties, value string) *rule {
 	r.unlessProps = append(r.unlessProps, ruleProperty{
 		fields: fieldNamesForProperties(properties),
@@ -188,6 +224,7 @@
 	})
 	return r
 }
+
 func (r *rule) because(reason string) *rule {
 	r.reason = reason
 	return r
@@ -201,6 +238,12 @@
 	for _, v := range r.unlessPaths {
 		s += " -dir:" + v + "*"
 	}
+	for _, v := range r.moduleTypes {
+		s += " type:" + v
+	}
+	for _, v := range r.unlessModuleTypes {
+		s += " -type:" + v
+	}
 	for _, v := range r.props {
 		s += " " + strings.Join(v.fields, ".") + "=" + v.value
 	}
@@ -219,6 +262,10 @@
 	return includePath && !excludePath
 }
 
+func (r *rule) appliesToModuleType(moduleType string) bool {
+	return (len(r.moduleTypes) == 0 || InList(moduleType, r.moduleTypes)) && !InList(moduleType, r.unlessModuleTypes)
+}
+
 func (r *rule) appliesToProperties(properties []interface{}) bool {
 	includeProps := hasAllProperties(properties, r.props)
 	excludeProps := hasAnyProperty(properties, r.unlessProps)
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 8d53087..d55ca57 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -148,6 +148,17 @@
 		},
 		expectedError: "Only core libraries projects can depend on core-libart",
 	},
+	{
+		name: "java_device_for_host",
+		fs: map[string][]byte{
+			"Blueprints": []byte(`
+				java_device_for_host {
+					name: "device_for_host",
+					libs: ["core-libart"],
+				}`),
+		},
+		expectedError: "java_device_for_host can only be used in whitelisted projects",
+	},
 }
 
 func TestNeverallow(t *testing.T) {
@@ -176,6 +187,7 @@
 	ctx := NewTestContext()
 	ctx.RegisterModuleType("cc_library", ModuleFactoryAdaptor(newMockCcLibraryModule))
 	ctx.RegisterModuleType("java_library", ModuleFactoryAdaptor(newMockJavaLibraryModule))
+	ctx.RegisterModuleType("java_device_for_host", ModuleFactoryAdaptor(newMockJavaLibraryModule))
 	ctx.PostDepsMutators(registerNeverallowMutator)
 	ctx.Register()