Revert "Revert "Prevent runtime module paths being used in include_dirs""

This reverts commit ff3d72f0bf62ff4e8b7a947d38b386d93403bafa.

Repplies original change now that issue causing build breakage has been
resolved.

Adds a new StartsWith(string) ValueMatcher along with
With[Out]Matcher(...) methods to support new restrictions that prevent
any paths into runtime module repositories from being added to the
include_dirs.

Test: m nothing
Bug: 35624006
Change-Id: I4c802ef25ef56f0f9b0b5e9d75531ea6f7475714
diff --git a/android/neverallow.go b/android/neverallow.go
index ad1d5bd..8f1f1e0 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -48,6 +48,7 @@
 var neverallows = []Rule{}
 
 func init() {
+	AddNeverAllowRules(createIncludeDirsRules()...)
 	AddNeverAllowRules(createTrebleRules()...)
 	AddNeverAllowRules(createLibcoreRules()...)
 	AddNeverAllowRules(createMediaRules()...)
@@ -59,6 +60,42 @@
 	neverallows = append(neverallows, rules...)
 }
 
+func createIncludeDirsRules() []Rule {
+	// The list of paths that cannot be referenced using include_dirs
+	paths := []string{
+		"art",
+		"libcore",
+		"libnativehelper",
+		"external/apache-harmony",
+		"external/apache-xml",
+		"external/boringssl",
+		"external/bouncycastle",
+		"external/conscrypt",
+		"external/icu",
+		"external/okhttp",
+		"external/vixl",
+		"external/wycheproof",
+		"system/core/libnativebridge",
+		"system/core/libnativehelper",
+	}
+
+	// Create a composite matcher that will match if the value starts with any of the restricted
+	// paths. A / is appended to the prefix to ensure that restricting path X does not affect paths
+	// XY.
+	rules := make([]Rule, 0, len(paths))
+	for _, path := range paths {
+		rule :=
+			NeverAllow().
+				WithMatcher("include_dirs", StartsWith(path+"/")).
+				Because("include_dirs is deprecated, all usages of '" + path + "' have been migrated" +
+					" to use alternate mechanisms and so can no longer be used.")
+
+		rules = append(rules, rule)
+	}
+
+	return rules
+}
+
 func createTrebleRules() []Rule {
 	return []Rule{
 		NeverAllow().
@@ -195,6 +232,18 @@
 
 var anyMatcherInstance = &anyMatcher{}
 
+type startsWithMatcher struct {
+	prefix string
+}
+
+func (m *startsWithMatcher) test(value string) bool {
+	return strings.HasPrefix(value, m.prefix)
+}
+
+func (m *startsWithMatcher) String() string {
+	return ".starts-with(" + m.prefix + ")"
+}
+
 type ruleProperty struct {
 	fields  []string // e.x.: Vndk.Enabled
 	matcher ValueMatcher
@@ -212,8 +261,12 @@
 
 	With(properties, value string) Rule
 
+	WithMatcher(properties string, matcher ValueMatcher) Rule
+
 	Without(properties, value string) Rule
 
+	WithoutMatcher(properties string, matcher ValueMatcher) Rule
+
 	Because(reason string) Rule
 }
 
@@ -257,17 +310,25 @@
 }
 
 func (r *rule) With(properties, value string) Rule {
+	return r.WithMatcher(properties, selectMatcher(value))
+}
+
+func (r *rule) WithMatcher(properties string, matcher ValueMatcher) Rule {
 	r.props = append(r.props, ruleProperty{
 		fields:  fieldNamesForProperties(properties),
-		matcher: selectMatcher(value),
+		matcher: matcher,
 	})
 	return r
 }
 
 func (r *rule) Without(properties, value string) Rule {
+	return r.WithoutMatcher(properties, selectMatcher(value))
+}
+
+func (r *rule) WithoutMatcher(properties string, matcher ValueMatcher) Rule {
 	r.unlessProps = append(r.unlessProps, ruleProperty{
 		fields:  fieldNamesForProperties(properties),
-		matcher: selectMatcher(value),
+		matcher: matcher,
 	})
 	return r
 }
@@ -326,6 +387,10 @@
 	return includeProps && !excludeProps
 }
 
+func StartsWith(prefix string) ValueMatcher {
+	return &startsWithMatcher{prefix}
+}
+
 // assorted utils
 
 func cleanPaths(paths []string) []string {