Merge "Extract default image specific logic from buildBootImage"
diff --git a/android/neverallow.go b/android/neverallow.go
index a385bbc..d4a1ff1 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -63,8 +63,7 @@
 }
 
 func createIncludeDirsRules() []Rule {
-	// The list of paths that cannot be referenced using include_dirs
-	paths := []string{
+	notInIncludeDir := []string{
 		"art",
 		"art/libnativebridge",
 		"art/libnativeloader",
@@ -80,12 +79,13 @@
 		"external/vixl",
 		"external/wycheproof",
 	}
+	noUseIncludeDir := []string{
+		"system/libfmq",
+	}
 
-	// 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 {
+	rules := make([]Rule, 0, len(notInIncludeDir)+len(noUseIncludeDir))
+
+	for _, path := range notInIncludeDir {
 		rule :=
 			NeverAllow().
 				WithMatcher("include_dirs", StartsWith(path+"/")).
@@ -95,6 +95,13 @@
 		rules = append(rules, rule)
 	}
 
+	for _, path := range noUseIncludeDir {
+		rule := NeverAllow().In(path+"/").WithMatcher("include_dirs", isSetMatcherInstance).
+			Because("include_dirs is deprecated, all usages of them in '" + path + "' have been migrated" +
+				" to use alternate mechanisms and so can no longer be used.")
+		rules = append(rules, rule)
+	}
+
 	return rules
 }
 
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 268346a..35aadd8 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -76,7 +76,20 @@
 		},
 	},
 	{
-		name: "include_dir can reference another location",
+		name: "include_dir not allowed to reference art",
+		fs: map[string][]byte{
+			"system/libfmq/Android.bp": []byte(`
+				cc_library {
+					name: "libother",
+					include_dirs: ["any/random/file"],
+				}`),
+		},
+		expectedErrors: []string{
+			"all usages of them in 'system/libfmq' have been migrated",
+		},
+	},
+	{
+		name: "include_dir can work",
 		fs: map[string][]byte{
 			"other/Android.bp": []byte(`
 				cc_library {
diff --git a/cc/cc.go b/cc/cc.go
index 260fcf1..4d8f4e1 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1135,9 +1135,9 @@
 	return false
 }
 
-func (m *Module) HasLlndkStubs() bool {
+func (m *Module) NeedsLlndkVariants() bool {
 	lib := moduleLibraryInterface(m)
-	return lib != nil && lib.hasLLNDKStubs()
+	return lib != nil && (lib.hasLLNDKStubs() || lib.hasLLNDKHeaders())
 }
 
 // isImplementationForLLNDKPublic returns true for any variant of a cc_library that has LLNDK stubs
diff --git a/cc/image.go b/cc/image.go
index c1e5dfe..6265b13 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -437,13 +437,13 @@
 		productVndkVersion = platformVndkVersion
 	}
 
-	if m.IsLlndkLibrary() || m.IsLlndkHeaders() || m.HasLlndkStubs() {
+	if m.IsLlndkLibrary() || m.IsLlndkHeaders() || m.NeedsLlndkVariants() {
 		// This is an LLNDK library.  The implementation of the library will be on /system,
 		// and vendor and product variants will be created with LLNDK stubs.
 		// The LLNDK libraries need vendor variants even if there is no VNDK.
 		// The obsolete llndk_library and llndk_headers modules also need the vendor variants
 		// so the cc_library LLNDK stubs can depend on them.
-		if m.HasLlndkStubs() {
+		if m.NeedsLlndkVariants() {
 			coreVariantNeeded = true
 		}
 		if platformVndkVersion != "" {
diff --git a/cc/library.go b/cc/library.go
index f49698e..3ac7e11 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -868,6 +868,7 @@
 
 	implementationModuleName(name string) string
 	hasLLNDKStubs() bool
+	hasLLNDKHeaders() bool
 }
 
 var _ libraryInterface = (*libraryDecorator)(nil)
@@ -1682,6 +1683,12 @@
 	return String(library.Properties.Llndk_stubs) != ""
 }
 
+// hasLLNDKHeaders returns true if this cc_library module has a variant that provides headers
+// to a module that sets llndk.symbol_file.
+func (library *libraryDecorator) hasLLNDKHeaders() bool {
+	return Bool(library.Properties.Llndk.Llndk_headers)
+}
+
 func (library *libraryDecorator) implementationModuleName(name string) string {
 	return name
 }
diff --git a/cc/linkable.go b/cc/linkable.go
index 2fa12f6..8fe0b4a 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -112,8 +112,8 @@
 	// IsLlndkLibrary returns true if this module is an LLNDK library module.
 	IsLlndkLibrary() bool
 
-	// HasLlndkStubs returns true if this module has LLNDK stubs.
-	HasLlndkStubs() bool
+	// NeedsLlndkVariants returns true if this module has LLNDK stubs or provides LLNDK headers.
+	NeedsLlndkVariants() bool
 
 	UseVndk() bool
 	MustUseVendorVariant() bool
diff --git a/cc/linker.go b/cc/linker.go
index ae33356..73fc4f0 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -322,7 +322,7 @@
 
 	if ctx.toolchain().Bionic() {
 		// libclang_rt.builtins has to be last on the command line
-		if !Bool(linker.Properties.No_libcrt) {
+		if !Bool(linker.Properties.No_libcrt) && !ctx.header() {
 			deps.LateStaticLibs = append(deps.LateStaticLibs, config.BuiltinsRuntimeLibrary(ctx.toolchain()))
 		}
 
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index d05dbce..ad19e47 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -69,6 +69,10 @@
 	// vendor nor product libraries. This effectively hides this module from
 	// non-system modules. Default value is false.
 	Private *bool
+
+	// if true, make this module available to provide headers to other modules that set
+	// llndk.symbol_file.
+	Llndk_headers *bool
 }
 
 type llndkStubDecorator struct {
diff --git a/cc/stl.go b/cc/stl.go
index 4f8865f..75921c6 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -62,6 +62,8 @@
 		s := ""
 		if stl.Properties.Stl != nil {
 			s = *stl.Properties.Stl
+		} else if ctx.header() {
+			s = "none"
 		}
 		if ctx.useSdk() && ctx.Device() {
 			switch s {
diff --git a/rust/rust.go b/rust/rust.go
index 78a793d..e1a69c0 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -274,7 +274,7 @@
 	return false
 }
 
-func (m *Module) HasLlndkStubs() bool {
+func (m *Module) NeedsLlndkVariants() bool {
 	return false
 }