Merge "Make override modules compatible with prebuilts."
diff --git a/OWNERS b/OWNERS
index adf2b4c..dbb491d 100644
--- a/OWNERS
+++ b/OWNERS
@@ -11,3 +11,4 @@
 per-file tidy.go = srhines@google.com, chh@google.com
 per-file lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
 per-file docs/map_files.md = danalbert@google.com, enh@google.com, jiyong@google.com
+per-file *ndk_api_coverage_parser.py = sophiez@google.com
\ No newline at end of file
diff --git a/android/Android.bp b/android/Android.bp
index 47dbc5d..487372b 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -36,6 +36,7 @@
         "package_ctx.go",
         "path_properties.go",
         "paths.go",
+        "phony.go",
         "prebuilt.go",
         "proto.go",
         "register.go",
diff --git a/android/config.go b/android/config.go
index 675660e..de76803 100644
--- a/android/config.go
+++ b/android/config.go
@@ -111,6 +111,10 @@
 	fs         pathtools.FileSystem
 	mockBpList string
 
+	// If testAllowNonExistentPaths is true then PathForSource and PathForModuleSrc won't error
+	// in tests when a path doesn't exist.
+	testAllowNonExistentPaths bool
+
 	OncePer
 }
 
@@ -230,6 +234,10 @@
 		buildDir:     buildDir,
 		captureBuild: true,
 		env:          envCopy,
+
+		// Set testAllowNonExistentPaths so that test contexts don't need to specify every path
+		// passed to PathForSource or PathForModuleSrc.
+		testAllowNonExistentPaths: true,
 	}
 	config.deviceConfig = &deviceConfig{
 		config: config,
diff --git a/android/makevars.go b/android/makevars.go
index aba4cce..ff7c8e4 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -17,12 +17,11 @@
 import (
 	"bytes"
 	"fmt"
-	"io/ioutil"
-	"os"
 	"strconv"
 	"strings"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/pathtools"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -84,6 +83,29 @@
 	// builder whenever a file matching the pattern as added or removed, without rerunning if a
 	// file that does not match the pattern is added to a searched directory.
 	GlobWithDeps(pattern string, excludes []string) ([]string, error)
+
+	// Phony creates a phony rule in Make, which will allow additional DistForGoal
+	// dependencies to be added to it.  Phony can be called on the same name multiple
+	// times to add additional dependencies.
+	Phony(names string, deps ...Path)
+
+	// DistForGoal creates a rule to copy one or more Paths to the artifacts
+	// directory on the build server when the specified goal is built.
+	DistForGoal(goal string, paths ...Path)
+
+	// DistForGoalWithFilename creates a rule to copy a Path to the artifacts
+	// directory on the build server with the given filename when the specified
+	// goal is built.
+	DistForGoalWithFilename(goal string, path Path, filename string)
+
+	// DistForGoals creates a rule to copy one or more Paths to the artifacts
+	// directory on the build server when any of the specified goals are built.
+	DistForGoals(goals []string, paths ...Path)
+
+	// DistForGoalsWithFilename creates a rule to copy a Path to the artifacts
+	// directory on the build server with the given filename when any of the
+	// specified goals are built.
+	DistForGoalsWithFilename(goals []string, path Path, filename string)
 }
 
 var _ PathContext = MakeVarsContext(nil)
@@ -130,9 +152,11 @@
 
 type makeVarsContext struct {
 	SingletonContext
-	config Config
-	pctx   PackageContext
-	vars   []makeVarsVariable
+	config  Config
+	pctx    PackageContext
+	vars    []makeVarsVariable
+	phonies []phony
+	dists   []dist
 }
 
 var _ MakeVarsContext = &makeVarsContext{}
@@ -144,6 +168,16 @@
 	strict bool
 }
 
+type phony struct {
+	name string
+	deps []string
+}
+
+type dist struct {
+	goals []string
+	paths []string
+}
+
 func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
 	if !ctx.Config().EmbeddedInMake() {
 		return
@@ -152,11 +186,16 @@
 	outFile := absolutePath(PathForOutput(ctx,
 		"make_vars"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
 
+	lateOutFile := absolutePath(PathForOutput(ctx,
+		"late"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
+
 	if ctx.Failed() {
 		return
 	}
 
-	vars := []makeVarsVariable{}
+	var vars []makeVarsVariable
+	var dists []dist
+	var phonies []phony
 	for _, provider := range makeVarsProviders {
 		mctx := &makeVarsContext{
 			SingletonContext: ctx,
@@ -166,6 +205,8 @@
 		provider.call(mctx)
 
 		vars = append(vars, mctx.vars...)
+		phonies = append(phonies, mctx.phonies...)
+		dists = append(dists, mctx.dists...)
 	}
 
 	if ctx.Failed() {
@@ -174,17 +215,16 @@
 
 	outBytes := s.writeVars(vars)
 
-	if _, err := os.Stat(absolutePath(outFile)); err == nil {
-		if data, err := ioutil.ReadFile(absolutePath(outFile)); err == nil {
-			if bytes.Equal(data, outBytes) {
-				return
-			}
-		}
-	}
-
-	if err := ioutil.WriteFile(absolutePath(outFile), outBytes, 0666); err != nil {
+	if err := pathtools.WriteFileIfChanged(outFile, outBytes, 0666); err != nil {
 		ctx.Errorf(err.Error())
 	}
+
+	lateOutBytes := s.writeLate(phonies, dists)
+
+	if err := pathtools.WriteFileIfChanged(lateOutFile, lateOutBytes, 0666); err != nil {
+		ctx.Errorf(err.Error())
+	}
+
 }
 
 func (s *makeVarsSingleton) writeVars(vars []makeVarsVariable) []byte {
@@ -263,6 +303,33 @@
 
 	fmt.Fprintln(buf, "\nsoong-compare-var :=")
 
+	fmt.Fprintln(buf)
+
+	return buf.Bytes()
+}
+
+func (s *makeVarsSingleton) writeLate(phonies []phony, dists []dist) []byte {
+	buf := &bytes.Buffer{}
+
+	fmt.Fprint(buf, `# Autogenerated file
+
+# Values written by Soong read after parsing all Android.mk files.
+
+
+`)
+
+	for _, phony := range phonies {
+		fmt.Fprintf(buf, ".PHONY: %s\n", phony.name)
+		fmt.Fprintf(buf, "%s: %s\n", phony.name, strings.Join(phony.deps, "\\\n  "))
+	}
+
+	fmt.Fprintln(buf)
+
+	for _, dist := range dists {
+		fmt.Fprintf(buf, "$(call dist-for-goals,%s,%s)\n",
+			strings.Join(dist.goals, " "), strings.Join(dist.paths, " "))
+	}
+
 	return buf.Bytes()
 }
 
@@ -299,6 +366,17 @@
 	c.addVariableRaw(name, value, strict, sort)
 }
 
+func (c *makeVarsContext) addPhony(name string, deps []string) {
+	c.phonies = append(c.phonies, phony{name, deps})
+}
+
+func (c *makeVarsContext) addDist(goals []string, paths []string) {
+	c.dists = append(c.dists, dist{
+		goals: goals,
+		paths: paths,
+	})
+}
+
 func (c *makeVarsContext) Strict(name, ninjaStr string) {
 	c.addVariable(name, ninjaStr, true, false)
 }
@@ -318,3 +396,23 @@
 func (c *makeVarsContext) CheckRaw(name, value string) {
 	c.addVariableRaw(name, value, false, false)
 }
+
+func (c *makeVarsContext) Phony(name string, deps ...Path) {
+	c.addPhony(name, Paths(deps).Strings())
+}
+
+func (c *makeVarsContext) DistForGoal(goal string, paths ...Path) {
+	c.DistForGoals([]string{goal}, paths...)
+}
+
+func (c *makeVarsContext) DistForGoalWithFilename(goal string, path Path, filename string) {
+	c.DistForGoalsWithFilename([]string{goal}, path, filename)
+}
+
+func (c *makeVarsContext) DistForGoals(goals []string, paths ...Path) {
+	c.addDist(goals, Paths(paths).Strings())
+}
+
+func (c *makeVarsContext) DistForGoalsWithFilename(goals []string, path Path, filename string) {
+	c.addDist(goals, []string{path.String() + ":" + filename})
+}
diff --git a/android/module.go b/android/module.go
index 82321f4..a488c0d 100644
--- a/android/module.go
+++ b/android/module.go
@@ -207,6 +207,10 @@
 	// Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
 	// and performs more verification.
 	Build(pctx PackageContext, params BuildParams)
+	// Phony creates a Make-style phony rule, a rule with no commands that can depend on other
+	// phony rules or real files.  Phony can be called on the same name multiple times to add
+	// additional dependencies.
+	Phony(phony string, deps ...Path)
 
 	PrimaryModule() Module
 	FinalModule() Module
@@ -722,6 +726,7 @@
 	installFiles       InstallPaths
 	checkbuildFiles    Paths
 	noticeFiles        Paths
+	phonies            map[string]Paths
 
 	// Used by buildTargetSingleton to create checkbuild and per-directory build targets
 	// Only set on the final variant of each module
@@ -1093,26 +1098,17 @@
 	}
 
 	if len(allInstalledFiles) > 0 {
-		name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-install")
-		ctx.Build(pctx, BuildParams{
-			Rule:      blueprint.Phony,
-			Output:    name,
-			Implicits: allInstalledFiles.Paths(),
-			Default:   !ctx.Config().EmbeddedInMake(),
-		})
-		deps = append(deps, name)
-		m.installTarget = name
+		name := namespacePrefix + ctx.ModuleName() + "-install"
+		ctx.Phony(name, allInstalledFiles.Paths()...)
+		m.installTarget = PathForPhony(ctx, name)
+		deps = append(deps, m.installTarget)
 	}
 
 	if len(allCheckbuildFiles) > 0 {
-		name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-checkbuild")
-		ctx.Build(pctx, BuildParams{
-			Rule:      blueprint.Phony,
-			Output:    name,
-			Implicits: allCheckbuildFiles,
-		})
-		deps = append(deps, name)
-		m.checkbuildTarget = name
+		name := namespacePrefix + ctx.ModuleName() + "-checkbuild"
+		ctx.Phony(name, allCheckbuildFiles...)
+		m.checkbuildTarget = PathForPhony(ctx, name)
+		deps = append(deps, m.checkbuildTarget)
 	}
 
 	if len(deps) > 0 {
@@ -1121,12 +1117,7 @@
 			suffix = "-soong"
 		}
 
-		name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+suffix)
-		ctx.Build(pctx, BuildParams{
-			Rule:      blueprint.Phony,
-			Outputs:   []WritablePath{name},
-			Implicits: deps,
-		})
+		ctx.Phony(namespacePrefix+ctx.ModuleName()+suffix, deps...)
 
 		m.blueprintDir = ctx.ModuleDir()
 	}
@@ -1313,6 +1304,9 @@
 		m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
 		m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
 		m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
+		for k, v := range ctx.phonies {
+			m.phonies[k] = append(m.phonies[k], v...)
+		}
 	} else if ctx.Config().AllowMissingDependencies() {
 		// If the module is not enabled it will not create any build rules, nothing will call
 		// ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled
@@ -1460,6 +1454,7 @@
 	installFiles    InstallPaths
 	checkbuildFiles Paths
 	module          Module
+	phonies         map[string]Paths
 
 	// For tests
 	buildParams []BuildParams
@@ -1574,6 +1569,11 @@
 
 	m.bp.Build(pctx.PackageContext, convertBuildParams(params))
 }
+
+func (m *moduleContext) Phony(name string, deps ...Path) {
+	addPhony(m.config, name, deps...)
+}
+
 func (m *moduleContext) GetMissingDependencies() []string {
 	var missingDeps []string
 	missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...)
@@ -2233,9 +2233,8 @@
 func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
 	var checkbuildDeps Paths
 
-	mmTarget := func(dir string) WritablePath {
-		return PathForPhony(ctx,
-			"MODULES-IN-"+strings.Replace(filepath.Clean(dir), "/", "-", -1))
+	mmTarget := func(dir string) string {
+		return "MODULES-IN-" + strings.Replace(filepath.Clean(dir), "/", "-", -1)
 	}
 
 	modulesInDir := make(map[string]Paths)
@@ -2261,11 +2260,7 @@
 	}
 
 	// Create a top-level checkbuild target that depends on all modules
-	ctx.Build(pctx, BuildParams{
-		Rule:      blueprint.Phony,
-		Output:    PathForPhony(ctx, "checkbuild"+suffix),
-		Implicits: checkbuildDeps,
-	})
+	ctx.Phony("checkbuild"+suffix, checkbuildDeps...)
 
 	// Make will generate the MODULES-IN-* targets
 	if ctx.Config().EmbeddedInMake() {
@@ -2289,7 +2284,7 @@
 	for _, dir := range dirs {
 		p := parentDir(dir)
 		if p != "." && p != "/" {
-			modulesInDir[p] = append(modulesInDir[p], mmTarget(dir))
+			modulesInDir[p] = append(modulesInDir[p], PathForPhony(ctx, mmTarget(dir)))
 		}
 	}
 
@@ -2297,14 +2292,7 @@
 	// depends on the MODULES-IN-* targets of all of its subdirectories that contain Android.bp
 	// files.
 	for _, dir := range dirs {
-		ctx.Build(pctx, BuildParams{
-			Rule:      blueprint.Phony,
-			Output:    mmTarget(dir),
-			Implicits: modulesInDir[dir],
-			// HACK: checkbuild should be an optional build, but force it
-			// enabled for now in standalone builds
-			Default: !ctx.Config().EmbeddedInMake(),
-		})
+		ctx.Phony(mmTarget(dir), modulesInDir[dir]...)
 	}
 
 	// Create (host|host-cross|target)-<OS> phony rules to build a reduced checkbuild.
@@ -2331,23 +2319,15 @@
 			continue
 		}
 
-		name := PathForPhony(ctx, className+"-"+os.Name)
-		osClass[className] = append(osClass[className], name)
+		name := className + "-" + os.Name
+		osClass[className] = append(osClass[className], PathForPhony(ctx, name))
 
-		ctx.Build(pctx, BuildParams{
-			Rule:      blueprint.Phony,
-			Output:    name,
-			Implicits: deps,
-		})
+		ctx.Phony(name, deps...)
 	}
 
 	// Wrap those into host|host-cross|target phony rules
 	for _, class := range SortedStringKeys(osClass) {
-		ctx.Build(pctx, BuildParams{
-			Rule:      blueprint.Phony,
-			Output:    PathForPhony(ctx, class),
-			Implicits: osClass[class],
-		})
+		ctx.Phony(class, osClass[class]...)
 	}
 }
 
diff --git a/android/paths.go b/android/paths.go
index 3ad27ac..bed6f3f 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -405,7 +405,7 @@
 		p := pathForModuleSrc(ctx, s)
 		if exists, _, err := ctx.Config().fs.Exists(p.String()); err != nil {
 			reportPathErrorf(ctx, "%s: %s", p, err.Error())
-		} else if !exists {
+		} else if !exists && !ctx.Config().testAllowNonExistentPaths {
 			reportPathErrorf(ctx, "module source path %q does not exist", p)
 		}
 
@@ -798,7 +798,7 @@
 		}
 	} else if exists, _, err := ctx.Config().fs.Exists(path.String()); err != nil {
 		reportPathErrorf(ctx, "%s: %s", path, err.Error())
-	} else if !exists {
+	} else if !exists && !ctx.Config().testAllowNonExistentPaths {
 		reportPathErrorf(ctx, "source path %q does not exist", path)
 	}
 	return path
diff --git a/android/phony.go b/android/phony.go
new file mode 100644
index 0000000..f8e5a44
--- /dev/null
+++ b/android/phony.go
@@ -0,0 +1,75 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+	"sync"
+
+	"github.com/google/blueprint"
+)
+
+var phonyMapOnceKey = NewOnceKey("phony")
+
+type phonyMap map[string]Paths
+
+var phonyMapLock sync.Mutex
+
+func getPhonyMap(config Config) phonyMap {
+	return config.Once(phonyMapOnceKey, func() interface{} {
+		return make(phonyMap)
+	}).(phonyMap)
+}
+
+func addPhony(config Config, name string, deps ...Path) {
+	phonyMap := getPhonyMap(config)
+	phonyMapLock.Lock()
+	defer phonyMapLock.Unlock()
+	phonyMap[name] = append(phonyMap[name], deps...)
+}
+
+type phonySingleton struct {
+	phonyMap  phonyMap
+	phonyList []string
+}
+
+var _ SingletonMakeVarsProvider = (*phonySingleton)(nil)
+
+func (p *phonySingleton) GenerateBuildActions(ctx SingletonContext) {
+	p.phonyMap = getPhonyMap(ctx.Config())
+	p.phonyList = SortedStringKeys(p.phonyMap)
+	for _, phony := range p.phonyList {
+		p.phonyMap[phony] = SortedUniquePaths(p.phonyMap[phony])
+	}
+
+	if !ctx.Config().EmbeddedInMake() {
+		for _, phony := range p.phonyList {
+			ctx.Build(pctx, BuildParams{
+				Rule:      blueprint.Phony,
+				Outputs:   []WritablePath{PathForPhony(ctx, phony)},
+				Implicits: p.phonyMap[phony],
+			})
+		}
+	}
+}
+
+func (p phonySingleton) MakeVars(ctx MakeVarsContext) {
+	for _, phony := range p.phonyList {
+		ctx.Phony(phony, p.phonyMap[phony]...)
+	}
+}
+
+func phonySingletonFactory() Singleton {
+	return &phonySingleton{}
+}
diff --git a/android/register.go b/android/register.go
index ccfe01e..036a811 100644
--- a/android/register.go
+++ b/android/register.go
@@ -104,6 +104,9 @@
 
 	registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
 
+	// Register phony just before makevars so it can write out its phony rules as Make rules
+	ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(phonySingletonFactory))
+
 	// Register makevars after other singletons so they can export values through makevars
 	ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(makeVarsSingletonFunc))
 
diff --git a/android/singleton.go b/android/singleton.go
index 568398c..2c51c6c 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -36,6 +36,12 @@
 	Variable(pctx PackageContext, name, value string)
 	Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
 	Build(pctx PackageContext, params BuildParams)
+
+	// Phony creates a Make-style phony rule, a rule with no commands that can depend on other
+	// phony rules or real files.  Phony can be called on the same name multiple times to add
+	// additional dependencies.
+	Phony(name string, deps ...Path)
+
 	RequireNinjaVersion(major, minor, micro int)
 
 	// SetNinjaBuildDir sets the value of the top-level "builddir" Ninja variable
@@ -156,6 +162,10 @@
 
 }
 
+func (s *singletonContextAdaptor) Phony(name string, deps ...Path) {
+	addPhony(s.Config(), name, deps...)
+}
+
 func (s *singletonContextAdaptor) SetNinjaBuildDir(pctx PackageContext, value string) {
 	s.SingletonContext.SetNinjaBuildDir(pctx.PackageContext, value)
 }
diff --git a/android/writedocs.go b/android/writedocs.go
index 7262ad8..9e43e80 100644
--- a/android/writedocs.go
+++ b/android/writedocs.go
@@ -69,9 +69,5 @@
 	})
 
 	// Add a phony target for building the documentation
-	ctx.Build(pctx, BuildParams{
-		Rule:   blueprint.Phony,
-		Output: PathForPhony(ctx, "soong_docs"),
-		Input:  docsFile,
-	})
+	ctx.Phony("soong_docs", docsFile)
 }
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 52480ea..b3ad610 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -457,6 +457,9 @@
 		entries.SetString("LOCAL_MODULE_PATH", path)
 		entries.SetString("LOCAL_MODULE_STEM", stem)
 		entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
+		if c.parsedCoverageXmlPath.String() != "" {
+			entries.SetString("SOONG_NDK_API_XML", "$(SOONG_NDK_API_XML) "+c.parsedCoverageXmlPath.String())
+		}
 	})
 }
 
diff --git a/cc/cc.go b/cc/cc.go
index 770391a..f80c229 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -3223,12 +3223,7 @@
 	})
 	// TODO(asmundak): Perhaps emit a rule to output a warning if there were no xrefTargets
 	if len(xrefTargets) > 0 {
-		ctx.Build(pctx, android.BuildParams{
-			Rule:   blueprint.Phony,
-			Output: android.PathForPhony(ctx, "xref_cxx"),
-			Inputs: xrefTargets,
-			//Default: true,
-		})
+		ctx.Phony("xref_cxx", xrefTargets...)
 	}
 }
 
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 1597b88..d79badb 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -25,8 +25,12 @@
 	"android/soong/android"
 )
 
+func init() {
+	pctx.HostBinToolVariable("ndk_api_coverage_parser", "ndk_api_coverage_parser")
+}
+
 var (
-	toolPath = pctx.SourcePathVariable("toolPath", "build/soong/cc/gen_stub_libs.py")
+	toolPath = pctx.SourcePathVariable("toolPath", "build/soong/cc/scriptlib/gen_stub_libs.py")
 
 	genStubSrc = pctx.AndroidStaticRule("genStubSrc",
 		blueprint.RuleParams{
@@ -35,6 +39,12 @@
 			CommandDeps: []string{"$toolPath"},
 		}, "arch", "apiLevel", "apiMap", "flags")
 
+	parseNdkApiRule = pctx.AndroidStaticRule("parseNdkApiRule",
+		blueprint.RuleParams{
+			Command:     "$ndk_api_coverage_parser $in $out --api-map $apiMap",
+			CommandDeps: []string{"$ndk_api_coverage_parser"},
+		}, "apiMap")
+
 	ndkLibrarySuffix = ".ndk"
 
 	ndkPrebuiltSharedLibs = []string{
@@ -111,8 +121,9 @@
 
 	properties libraryProperties
 
-	versionScriptPath android.ModuleGenPath
-	installPath       android.Path
+	versionScriptPath     android.ModuleGenPath
+	parsedCoverageXmlPath android.ModuleOutPath
+	installPath           android.Path
 }
 
 // OMG GO
@@ -308,14 +319,35 @@
 	return compileObjs(ctx, flagsToBuilderFlags(flags), subdir, srcs, nil, nil), versionScriptPath
 }
 
+func parseSymbolFileForCoverage(ctx ModuleContext, symbolFile string) android.ModuleOutPath {
+	apiLevelsJson := android.GetApiLevelsJson(ctx)
+	symbolFilePath := android.PathForModuleSrc(ctx, symbolFile)
+	outputFileName := strings.Split(symbolFilePath.Base(), ".")[0]
+	parsedApiCoveragePath := android.PathForModuleOut(ctx, outputFileName+".xml")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        parseNdkApiRule,
+		Description: "parse ndk api symbol file for api coverage: " + symbolFilePath.Rel(),
+		Outputs:     []android.WritablePath{parsedApiCoveragePath},
+		Input:       symbolFilePath,
+		Args: map[string]string{
+			"apiMap": apiLevelsJson.String(),
+		},
+	})
+	return parsedApiCoveragePath
+}
+
 func (c *stubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
 	if !strings.HasSuffix(String(c.properties.Symbol_file), ".map.txt") {
 		ctx.PropertyErrorf("symbol_file", "must end with .map.txt")
 	}
 
-	objs, versionScript := compileStubLibrary(ctx, flags, String(c.properties.Symbol_file),
+	symbolFile := String(c.properties.Symbol_file)
+	objs, versionScript := compileStubLibrary(ctx, flags, symbolFile,
 		c.properties.ApiLevel, "")
 	c.versionScriptPath = versionScript
+	if c.properties.ApiLevel == "current" && ctx.PrimaryArch() {
+		c.parsedCoverageXmlPath = parseSymbolFileForCoverage(ctx, symbolFile)
+	}
 	return objs
 }
 
diff --git a/cc/scriptlib/Android.bp b/cc/scriptlib/Android.bp
new file mode 100644
index 0000000..ff9a2f0
--- /dev/null
+++ b/cc/scriptlib/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+python_test_host {
+    name: "test_ndk_api_coverage_parser",
+    main: "test_ndk_api_coverage_parser.py",
+    srcs: [
+        "test_ndk_api_coverage_parser.py",
+    ],
+}
+
+python_binary_host {
+    name: "ndk_api_coverage_parser",
+    main: "ndk_api_coverage_parser.py",
+    srcs: [
+        "gen_stub_libs.py",
+        "ndk_api_coverage_parser.py",
+    ],
+}
diff --git a/cc/scriptlib/__init__.py b/cc/scriptlib/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cc/scriptlib/__init__.py
diff --git a/cc/gen_stub_libs.py b/cc/scriptlib/gen_stub_libs.py
similarity index 99%
rename from cc/gen_stub_libs.py
rename to cc/scriptlib/gen_stub_libs.py
index 7deb804..d61dfbb 100755
--- a/cc/gen_stub_libs.py
+++ b/cc/scriptlib/gen_stub_libs.py
@@ -246,6 +246,7 @@
     def __eq__(self, other):
         return self.name == other.name and set(self.tags) == set(other.tags)
 
+
 class SymbolFileParser(object):
     """Parses NDK symbol files."""
     def __init__(self, input_file, api_map, arch, api, llndk, apex):
diff --git a/cc/scriptlib/ndk_api_coverage_parser.py b/cc/scriptlib/ndk_api_coverage_parser.py
new file mode 100755
index 0000000..d74035b
--- /dev/null
+++ b/cc/scriptlib/ndk_api_coverage_parser.py
@@ -0,0 +1,134 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Generates xml of NDK libraries used for API coverage analysis."""
+import argparse
+import json
+import os
+import sys
+
+from xml.etree.ElementTree import Element, SubElement, tostring
+from gen_stub_libs import ALL_ARCHITECTURES, FUTURE_API_LEVEL, MultiplyDefinedSymbolError, SymbolFileParser
+
+
+ROOT_ELEMENT_TAG = 'ndk-library'
+SYMBOL_ELEMENT_TAG = 'symbol'
+ARCHITECTURE_ATTRIBUTE_KEY = 'arch'
+DEPRECATED_ATTRIBUTE_KEY = 'is_deprecated'
+PLATFORM_ATTRIBUTE_KEY = 'is_platform'
+NAME_ATTRIBUTE_KEY = 'name'
+VARIABLE_TAG = 'var'
+EXPOSED_TARGET_TAGS = (
+    'vndk',
+    'apex',
+    'llndk',
+)
+API_LEVEL_TAG_PREFIXES = (
+    'introduced=',
+    'introduced-',
+)
+
+
+def parse_tags(tags):
+    """Parses tags and save needed tags in the created attributes.
+
+    Return attributes dictionary.
+    """
+    attributes = {}
+    arch = []
+    for tag in tags:
+        if tag.startswith(tuple(API_LEVEL_TAG_PREFIXES)):
+            key, _, value = tag.partition('=')
+            attributes.update({key: value})
+        elif tag in ALL_ARCHITECTURES:
+            arch.append(tag)
+        elif tag in EXPOSED_TARGET_TAGS:
+            attributes.update({tag: 'True'})
+    attributes.update({ARCHITECTURE_ATTRIBUTE_KEY: ','.join(arch)})
+    return attributes
+
+
+class XmlGenerator(object):
+    """Output generator that writes parsed symbol file to a xml file."""
+    def __init__(self, output_file):
+        self.output_file = output_file
+
+    def convertToXml(self, versions):
+        """Writes all symbol data to the output file."""
+        root = Element(ROOT_ELEMENT_TAG)
+        for version in versions:
+            if VARIABLE_TAG in version.tags:
+                continue
+            version_attributes = parse_tags(version.tags)
+            _, _, postfix = version.name.partition('_')
+            is_platform = postfix == 'PRIVATE' or postfix == 'PLATFORM'
+            is_deprecated = postfix == 'DEPRECATED'
+            version_attributes.update({PLATFORM_ATTRIBUTE_KEY: str(is_platform)})
+            version_attributes.update({DEPRECATED_ATTRIBUTE_KEY: str(is_deprecated)})
+            for symbol in version.symbols:
+                if VARIABLE_TAG in symbol.tags:
+                    continue
+                attributes = {NAME_ATTRIBUTE_KEY: symbol.name}
+                attributes.update(version_attributes)
+                # If same version tags already exist, it will be overwrite here.
+                attributes.update(parse_tags(symbol.tags))
+                SubElement(root, SYMBOL_ELEMENT_TAG, attributes)
+        return root
+
+    def write_xml_to_file(self, root):
+        """Write xml element root to output_file."""
+        parsed_data = tostring(root)
+        output_file = open(self.output_file, "wb")
+        output_file.write(parsed_data)
+
+    def write(self, versions):
+        root = self.convertToXml(versions)
+        self.write_xml_to_file(root)
+
+
+def parse_args():
+    """Parses and returns command line arguments."""
+    parser = argparse.ArgumentParser()
+
+    parser.add_argument('symbol_file', type=os.path.realpath, help='Path to symbol file.')
+    parser.add_argument(
+        'output_file', type=os.path.realpath,
+        help='The output parsed api coverage file.')
+    parser.add_argument(
+        '--api-map', type=os.path.realpath, required=True,
+        help='Path to the API level map JSON file.')
+    return parser.parse_args()
+
+
+def main():
+    """Program entry point."""
+    args = parse_args()
+
+    with open(args.api_map) as map_file:
+        api_map = json.load(map_file)
+
+    with open(args.symbol_file) as symbol_file:
+        try:
+            versions = SymbolFileParser(symbol_file, api_map, "", FUTURE_API_LEVEL,
+                                        True, True).parse()
+        except MultiplyDefinedSymbolError as ex:
+            sys.exit('{}: error: {}'.format(args.symbol_file, ex))
+
+    generator = XmlGenerator(args.output_file)
+    generator.write(versions)
+
+if __name__ == '__main__':
+    main()
diff --git a/cc/test_gen_stub_libs.py b/cc/scriptlib/test_gen_stub_libs.py
similarity index 100%
rename from cc/test_gen_stub_libs.py
rename to cc/scriptlib/test_gen_stub_libs.py
diff --git a/cc/scriptlib/test_ndk_api_coverage_parser.py b/cc/scriptlib/test_ndk_api_coverage_parser.py
new file mode 100644
index 0000000..a3c9b70
--- /dev/null
+++ b/cc/scriptlib/test_ndk_api_coverage_parser.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Tests for ndk_api_coverage_parser.py."""
+import io
+import textwrap
+import unittest
+
+from xml.etree.ElementTree import tostring
+from gen_stub_libs import FUTURE_API_LEVEL, SymbolFileParser
+import ndk_api_coverage_parser as nparser
+
+
+# pylint: disable=missing-docstring
+
+
+class ApiCoverageSymbolFileParserTest(unittest.TestCase):
+    def test_parse(self):
+        input_file = io.StringIO(textwrap.dedent(u"""\
+            LIBLOG { # introduced-arm64=24 introduced-x86=24 introduced-x86_64=24
+              global:
+                android_name_to_log_id; # apex llndk introduced=23
+                android_log_id_to_name; # llndk arm
+                __android_log_assert; # introduced-x86=23
+                __android_log_buf_print; # var
+                __android_log_buf_write;
+              local:
+                *;
+            };
+            
+            LIBLOG_PLATFORM {
+                android_fdtrack; # llndk
+                android_net; # introduced=23
+            };
+            
+            LIBLOG_FOO { # var
+                android_var;
+            };
+        """))
+        parser = SymbolFileParser(input_file, {}, "", FUTURE_API_LEVEL, True, True)
+        generator = nparser.XmlGenerator(io.StringIO())
+        result = tostring(generator.convertToXml(parser.parse())).decode()
+        expected = '<ndk-library><symbol apex="True" arch="" introduced="23" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_name_to_log_id" /><symbol arch="arm" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_log_id_to_name" /><symbol arch="" introduced-arm64="24" introduced-x86="23" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_assert" /><symbol arch="" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_buf_write" /><symbol arch="" is_deprecated="False" is_platform="True" llndk="True" name="android_fdtrack" /><symbol arch="" introduced="23" is_deprecated="False" is_platform="True" name="android_net" /></ndk-library>'
+        self.assertEqual(expected, result)
+
+
+def main():
+    suite = unittest.TestLoader().loadTestsFromName(__name__)
+    unittest.TextTestRunner(verbosity=3).run(suite)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/cc/testing.go b/cc/testing.go
index edbb24d..479b424 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -467,15 +467,6 @@
 }
 
 func GatherRequiredFilesForTest(fs map[string][]byte) {
-	fs["prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-arm/usr/lib/crtbegin_so.o"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-arm/usr/lib/crtend_so.o"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-arm64/usr/lib/crtbegin_so.o"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-arm64/usr/lib/crtend_so.o"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-x86/usr/lib/crtbegin_so.o"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-x86/usr/lib/crtend_so.o"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-x86_64/usr/lib64/crtbegin_so.o"] = nil
-	fs["prebuilts/ndk/current/platforms/android-27/arch-x86_64/usr/lib64/crtend_so.o"] = nil
 }
 
 func TestConfig(buildDir string, os android.OsType, env map[string]string,
@@ -484,20 +475,7 @@
 	// add some modules that are required by the compiler and/or linker
 	bp = bp + GatherRequiredDepsForTest(os)
 
-	mockFS := map[string][]byte{
-		"foo.c":       nil,
-		"foo.lds":     nil,
-		"bar.c":       nil,
-		"baz.c":       nil,
-		"baz.o":       nil,
-		"a.proto":     nil,
-		"b.aidl":      nil,
-		"sub/c.aidl":  nil,
-		"my_include":  nil,
-		"foo.map.txt": nil,
-		"liba.so":     nil,
-		"libb.a":      nil,
-	}
+	mockFS := map[string][]byte{}
 
 	GatherRequiredFilesForTest(mockFS)
 
diff --git a/java/app_test.go b/java/app_test.go
index eeba161..e45ba70 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2657,7 +2657,7 @@
 }
 
 func TestEmbedNotice(t *testing.T) {
-	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
+	ctx, _ := testJavaWithFS(t, cc.GatherRequiredDepsForTest(android.Android)+`
 		android_app {
 			name: "foo",
 			srcs: ["a.java"],
@@ -2713,7 +2713,12 @@
 			srcs: ["b.java"],
 			notice: "TOOL_NOTICE",
 		}
-	`)
+	`, map[string][]byte{
+		"APP_NOTICE":     nil,
+		"GENRULE_NOTICE": nil,
+		"LIB_NOTICE":     nil,
+		"TOOL_NOTICE":    nil,
+	})
 
 	// foo has NOTICE files to process, and embed_notices is true.
 	foo := ctx.ModuleForTests("foo", "android_common")
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 4c3e112..68cfe9f 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1470,7 +1470,7 @@
 		FlagWithInput("@", srcJarList).
 		FlagWithOutput("--strict-input-files:warn ", android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"violations.txt"))
 
-	if implicitsRsp.String() != "" {
+	if implicitsRsp != nil {
 		cmd.FlagWithArg("--strict-input-files-exempt ", "@"+implicitsRsp.String())
 	}
 
diff --git a/java/java.go b/java/java.go
index 5f8ad03..1cdfbf1 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2874,11 +2874,7 @@
 	})
 	// TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets
 	if len(xrefTargets) > 0 {
-		ctx.Build(pctx, android.BuildParams{
-			Rule:   blueprint.Phony,
-			Output: android.PathForPhony(ctx, "xref_java"),
-			Inputs: xrefTargets,
-		})
+		ctx.Phony("xref_java", xrefTargets...)
 	}
 }
 
diff --git a/java/java_test.go b/java/java_test.go
index 8ea34d9..215070e 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -142,9 +142,14 @@
 	return ctx, config
 }
 
+func testJavaWithFS(t *testing.T, bp string, fs map[string][]byte) (*android.TestContext, android.Config) {
+	t.Helper()
+	return testJavaWithConfig(t, testConfig(nil, bp, fs))
+}
+
 func testJava(t *testing.T, bp string) (*android.TestContext, android.Config) {
 	t.Helper()
-	return testJavaWithConfig(t, testConfig(nil, bp, nil))
+	return testJavaWithFS(t, bp, nil)
 }
 
 func testJavaWithConfig(t *testing.T, config android.Config) (*android.TestContext, android.Config) {
@@ -740,7 +745,7 @@
 
 	for _, test := range table {
 		t.Run(test.name, func(t *testing.T) {
-			ctx, _ := testJava(t, `
+			ctx, _ := testJavaWithFS(t, `
 				java_library {
 					name: "foo",
 					srcs: [
@@ -750,7 +755,13 @@
 					],
 					`+test.prop+`,
 				}
-			`+test.extra)
+			`+test.extra,
+				map[string][]byte{
+					"java-res/a/a": nil,
+					"java-res/b/b": nil,
+					"java-res2/a":  nil,
+				},
+			)
 
 			foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar")
 			fooRes := ctx.ModuleForTests("foo", "android_common").Output("res/foo.jar")
@@ -769,7 +780,7 @@
 }
 
 func TestIncludeSrcs(t *testing.T) {
-	ctx, _ := testJava(t, `
+	ctx, _ := testJavaWithFS(t, `
 		java_library {
 			name: "foo",
 			srcs: [
@@ -790,7 +801,11 @@
 			java_resource_dirs: ["java-res"],
 			include_srcs: true,
 		}
-	`)
+	`, map[string][]byte{
+		"java-res/a/a": nil,
+		"java-res/b/b": nil,
+		"java-res2/a":  nil,
+	})
 
 	// Test a library with include_srcs: true
 	foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar")
@@ -832,7 +847,7 @@
 }
 
 func TestGeneratedSources(t *testing.T) {
-	ctx, _ := testJava(t, `
+	ctx, _ := testJavaWithFS(t, `
 		java_library {
 			name: "foo",
 			srcs: [
@@ -847,7 +862,10 @@
 			tool_files: ["java-res/a"],
 			out: ["gen.java"],
 		}
-	`)
+	`, map[string][]byte{
+		"a.java": nil,
+		"b.java": nil,
+	})
 
 	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
 	genrule := ctx.ModuleForTests("gen", "").Rule("generator")
@@ -932,7 +950,7 @@
 }
 
 func TestDroiddoc(t *testing.T) {
-	ctx, _ := testJava(t, `
+	ctx, _ := testJavaWithFS(t, `
 		droiddoc_exported_dir {
 		    name: "droiddoc-templates-sdk",
 		    path: ".",
@@ -945,7 +963,7 @@
 		droiddoc {
 		    name: "bar-doc",
 		    srcs: [
-		        "bar-doc/*.java",
+		        "bar-doc/a.java",
 		        "bar-doc/IFoo.aidl",
 		        ":bar-doc-aidl-srcs",
 		    ],
@@ -963,7 +981,11 @@
 		    todo_file: "libcore-docs-todo.html",
 		    args: "-offlinemode -title \"libcore\"",
 		}
-		`)
+		`,
+		map[string][]byte{
+			"bar-doc/a.java": nil,
+			"bar-doc/b.java": nil,
+		})
 
 	barDoc := ctx.ModuleForTests("bar-doc", "android_common").Rule("javadoc")
 	var javaSrcs []string
@@ -989,7 +1011,7 @@
 		droidstubs {
 		    name: "stubs-source-system-modules",
 		    srcs: [
-		        "bar-doc/*.java",
+		        "bar-doc/a.java",
 		    ],
 				sdk_version: "none",
 				system_modules: "source-system-modules",
@@ -1010,7 +1032,7 @@
 		droidstubs {
 		    name: "stubs-prebuilt-system-modules",
 		    srcs: [
-		        "bar-doc/*.java",
+		        "bar-doc/a.java",
 		    ],
 				sdk_version: "none",
 				system_modules: "prebuilt-system-modules",
diff --git a/java/testing.go b/java/testing.go
index f993f56..f34c64a 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -25,35 +25,12 @@
 	bp += GatherRequiredDepsForTest()
 
 	mockFS := map[string][]byte{
-		"a.java":                 nil,
-		"b.java":                 nil,
-		"c.java":                 nil,
-		"b.kt":                   nil,
-		"a.jar":                  nil,
-		"b.jar":                  nil,
-		"c.jar":                  nil,
-		"APP_NOTICE":             nil,
-		"GENRULE_NOTICE":         nil,
-		"LIB_NOTICE":             nil,
-		"TOOL_NOTICE":            nil,
-		"AndroidTest.xml":        nil,
-		"java-res/a/a":           nil,
-		"java-res/b/b":           nil,
-		"java-res2/a":            nil,
-		"java-fg/a.java":         nil,
-		"java-fg/b.java":         nil,
-		"java-fg/c.java":         nil,
 		"api/current.txt":        nil,
 		"api/removed.txt":        nil,
 		"api/system-current.txt": nil,
 		"api/system-removed.txt": nil,
 		"api/test-current.txt":   nil,
 		"api/test-removed.txt":   nil,
-		"framework/aidl/a.aidl":  nil,
-		"aidl/foo/IFoo.aidl":     nil,
-		"aidl/bar/IBar.aidl":     nil,
-		"assets_a/a":             nil,
-		"assets_b/b":             nil,
 
 		"prebuilts/sdk/14/public/android.jar":                      nil,
 		"prebuilts/sdk/14/public/framework.aidl":                   nil,
@@ -103,45 +80,6 @@
 		"prebuilts/sdk/30/test/api/bar-removed.txt":                nil,
 		"prebuilts/sdk/tools/core-lambda-stubs.jar":                nil,
 		"prebuilts/sdk/Android.bp":                                 []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"],}`),
-
-		"prebuilts/apk/app.apk":        nil,
-		"prebuilts/apk/app_arm.apk":    nil,
-		"prebuilts/apk/app_arm64.apk":  nil,
-		"prebuilts/apk/app_xhdpi.apk":  nil,
-		"prebuilts/apk/app_xxhdpi.apk": nil,
-
-		"prebuilts/apks/app.apks": nil,
-
-		// For framework-res, which is an implicit dependency for framework
-		"AndroidManifest.xml":                        nil,
-		"build/make/target/product/security/testkey": nil,
-
-		"build/soong/scripts/jar-wrapper.sh": nil,
-
-		"build/make/core/verify_uses_libraries.sh": nil,
-
-		"build/make/core/proguard.flags":             nil,
-		"build/make/core/proguard_basic_keeps.flags": nil,
-
-		"jdk8/jre/lib/jce.jar": nil,
-		"jdk8/jre/lib/rt.jar":  nil,
-		"jdk8/lib/tools.jar":   nil,
-
-		"bar-doc/a.java":                 nil,
-		"bar-doc/b.java":                 nil,
-		"bar-doc/IFoo.aidl":              nil,
-		"bar-doc/IBar.aidl":              nil,
-		"bar-doc/known_oj_tags.txt":      nil,
-		"external/doclava/templates-sdk": nil,
-
-		"cert/new_cert.x509.pem": nil,
-		"cert/new_cert.pk8":      nil,
-		"lineage.bin":            nil,
-
-		"testdata/data": nil,
-
-		"stubs-sources/foo/Foo.java": nil,
-		"stubs/sources/foo/Foo.java": nil,
 	}
 
 	cc.GatherRequiredFilesForTest(mockFS)
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index f836ea9..df763c8 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -20,6 +20,7 @@
   conscrypt-module-test-exports
   conscrypt-module-host-exports
   runtime-module-sdk
+  runtime-module-host-exports
 )
 
 # We want to create apex modules for all supported architectures.