Merge changes I6f7d40b7,I25654032

* changes:
  add a library to report build numbers without causing rebuilds
  Rewrite symbol_inject to be testable
diff --git a/android/module.go b/android/module.go
index 07c4e8f..4a8e8ac 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1220,7 +1220,7 @@
 				ctx.ModuleErrorf("srcs dependency %q is not a source file producing module", m)
 			}
 		} else if pathtools.IsGlob(s) {
-			globbedSrcFiles := ctx.Glob(filepath.Join(prefix, s), expandedExcludes)
+			globbedSrcFiles := ctx.GlobFiles(filepath.Join(prefix, s), expandedExcludes)
 			for i, s := range globbedSrcFiles {
 				globbedSrcFiles[i] = s.(ModuleSrcPath).WithSubDir(ctx, subDir)
 			}
@@ -1246,25 +1246,15 @@
 	if err != nil {
 		ctx.ModuleErrorf("glob: %s", err.Error())
 	}
-	return pathsForModuleSrcFromFullPath(ctx, ret)
+	return pathsForModuleSrcFromFullPath(ctx, ret, true)
 }
 
-// glob only "files" under the directory relative to top of the source tree.
 func (ctx *androidModuleContext) GlobFiles(globPattern string, excludes []string) Paths {
-	paths, err := ctx.GlobWithDeps(globPattern, excludes)
+	ret, err := ctx.GlobWithDeps(globPattern, excludes)
 	if err != nil {
 		ctx.ModuleErrorf("glob: %s", err.Error())
 	}
-	var ret []Path
-	for _, p := range paths {
-		if isDir, err := ctx.Fs().IsDir(p); err != nil {
-			ctx.ModuleErrorf("error in IsDir(%s): %s", p, err.Error())
-			return nil
-		} else if !isDir {
-			ret = append(ret, PathForSource(ctx, p))
-		}
-	}
-	return ret
+	return pathsForModuleSrcFromFullPath(ctx, ret, false)
 }
 
 func init() {
diff --git a/android/paths.go b/android/paths.go
index 3b1cea6..cf5544d 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -228,14 +228,17 @@
 
 // pathsForModuleSrcFromFullPath returns Paths rooted from the module's local
 // source directory, but strip the local source directory from the beginning of
-// each string.
-func pathsForModuleSrcFromFullPath(ctx ModuleContext, paths []string) Paths {
+// each string. If incDirs is false, strip paths with a trailing '/' from the list.
+func pathsForModuleSrcFromFullPath(ctx ModuleContext, paths []string, incDirs bool) Paths {
 	prefix := filepath.Join(ctx.Config().srcDir, ctx.ModuleDir()) + "/"
 	if prefix == "./" {
 		prefix = ""
 	}
 	ret := make(Paths, 0, len(paths))
 	for _, p := range paths {
+		if !incDirs && strings.HasSuffix(p, "/") {
+			continue
+		}
 		path := filepath.Clean(p)
 		if !strings.HasPrefix(path, prefix) {
 			reportPathErrorf(ctx, "Path '%s' is not in module source directory '%s'", p, prefix)
@@ -773,7 +776,12 @@
 // PathForVndkRefDump returns an OptionalPath representing the path of the reference
 // abi dump for the given module. This is not guaranteed to be valid.
 func PathForVndkRefAbiDump(ctx ModuleContext, version, fileName string, vndkOrNdk, isSourceDump bool) OptionalPath {
-	archName := ctx.Arch().ArchType.Name
+	arches := ctx.DeviceConfig().Arches()
+	currentArch := ctx.Arch()
+	archNameAndVariant := currentArch.ArchType.String()
+	if currentArch.ArchVariant != "" {
+		archNameAndVariant += "_" + currentArch.ArchVariant
+	}
 	var sourceOrBinaryDir string
 	var vndkOrNdkDir string
 	var ext string
@@ -789,8 +797,12 @@
 	} else {
 		vndkOrNdkDir = "ndk"
 	}
-	refDumpFileStr := "prebuilts/abi-dumps/" + vndkOrNdkDir + "/" + version + "/" +
-		archName + "/" + sourceOrBinaryDir + "/" + fileName + ext
+	if len(arches) == 0 {
+		panic("device build with no primary arch")
+	}
+	primary_arch := arches[0].ArchType.String()
+	refDumpFileStr := "prebuilts/abi-dumps/" + vndkOrNdkDir + "/" + version + "/" + primary_arch + "/" +
+		archNameAndVariant + "/" + sourceOrBinaryDir + "/" + fileName + ext
 	return ExistentPathForSource(ctx, refDumpFileStr)
 }
 
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index 2358f0c..8445490 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -130,6 +130,9 @@
 		case ".aar":
 			renameProperty(mod, "srcs", "aars")
 			mod.Type = "android_library_import"
+
+			// An android_library_import doesn't get installed, so setting "installable = false" isn't supported
+			removeProperty(mod, "installable")
 		}
 	}
 
@@ -195,3 +198,13 @@
 		}
 	}
 }
+
+func removeProperty(mod *parser.Module, propertyName string) {
+	newList := make([]*parser.Property, 0, len(mod.Properties))
+	for _, prop := range mod.Properties {
+		if prop.Name != propertyName {
+			newList = append(newList, prop)
+		}
+	}
+	mod.Properties = newList
+}
diff --git a/cc/builder.go b/cc/builder.go
index 1d12b5f..59a8cc8 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -687,6 +687,9 @@
 func TransformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path,
 	baseName, exportedHeaderFlags string) android.OptionalPath {
 	outputFile := android.PathForModuleOut(ctx, baseName+".lsdump")
+	sabiLock.Lock()
+	lsdumpPaths = append(lsdumpPaths, outputFile.String())
+	sabiLock.Unlock()
 	symbolFilterStr := "-so " + soFile.String()
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        sAbiLink,
diff --git a/cc/cc.go b/cc/cc.go
index 887f394..a58a84d 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -530,7 +530,12 @@
 
 // Create source abi dumps if the module belongs to the list of VndkLibraries.
 func (ctx *moduleContextImpl) createVndkSourceAbiDump() bool {
-	return ctx.ctx.Device() && ((ctx.useVndk() && ctx.isVndk()) || inList(ctx.baseModuleName(), llndkLibraries))
+	isUnsanitizedVariant := true
+	sanitize := ctx.mod.sanitize
+	if sanitize != nil {
+		isUnsanitizedVariant = sanitize.isUnsanitizedVariant()
+	}
+	return isUnsanitizedVariant && ctx.ctx.Device() && ((ctx.useVndk() && ctx.isVndk()) || inList(ctx.baseModuleName(), llndkLibraries))
 }
 
 func (ctx *moduleContextImpl) selectedStl() string {
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index e824d0f..b573c2e 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -100,7 +100,7 @@
 
 func (stub *llndkStubDecorator) processHeaders(ctx ModuleContext, srcHeaderDir string, outDir android.ModuleGenPath) android.Path {
 	srcDir := android.PathForModuleSrc(ctx, srcHeaderDir)
-	srcFiles := ctx.Glob(filepath.Join(srcDir.String(), "**/*.h"), nil)
+	srcFiles := ctx.GlobFiles(filepath.Join(srcDir.String(), "**/*.h"), nil)
 
 	var installPaths []android.WritablePath
 	for _, header := range srcFiles {
diff --git a/cc/makevars.go b/cc/makevars.go
index 779de8f..23910d3 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -100,6 +100,9 @@
 	ctx.Strict("LLNDK_LIBRARIES", strings.Join(llndkLibraries, " "))
 	ctx.Strict("VNDK_PRIVATE_LIBRARIES", strings.Join(vndkPrivateLibraries, " "))
 
+	sort.Strings(lsdumpPaths)
+	ctx.Strict("LSDUMP_PATHS", strings.Join(lsdumpPaths, " "))
+
 	ctx.Strict("ANDROID_WARNING_ALLOWED_PROJECTS", makeStringOfWarningAllowedProjects())
 	ctx.Strict("SOONG_MODULES_ADDED_WALL", makeStringOfKeys(ctx, modulesAddedWall))
 	ctx.Strict("SOONG_MODULES_USING_WNO_ERROR", makeStringOfKeys(ctx, modulesUsingWnoError))
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index d7c2a06..9fabc97 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -202,7 +202,7 @@
 
 	fromSrcPath := android.PathForModuleSrc(ctx, String(m.properties.From))
 	toOutputPath := getCurrentIncludePath(ctx).Join(ctx, String(m.properties.To))
-	srcFiles := ctx.Glob(filepath.Join(fromSrcPath.String(), "**/*.h"), nil)
+	srcFiles := ctx.GlobFiles(filepath.Join(fromSrcPath.String(), "**/*.h"), nil)
 	var installPaths []android.WritablePath
 	for _, header := range srcFiles {
 		installDir := getHeaderInstallDir(ctx, header, String(m.properties.From), String(m.properties.To))
diff --git a/cc/sabi.go b/cc/sabi.go
index ec1d246..f5a7c77 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -16,11 +16,17 @@
 
 import (
 	"strings"
+	"sync"
 
 	"android/soong/android"
 	"android/soong/cc/config"
 )
 
+var (
+	lsdumpPaths []string
+	sabiLock    sync.Mutex
+)
+
 type SAbiProperties struct {
 	CreateSAbiDumps        bool `blueprint:"mutated"`
 	ReexportedIncludeFlags []string
diff --git a/java/app.go b/java/app.go
index 34f05b7..ac88df7 100644
--- a/java/app.go
+++ b/java/app.go
@@ -342,17 +342,7 @@
 }
 
 func resourceGlob(ctx android.ModuleContext, dir android.Path) android.Paths {
-	var ret android.Paths
-	files := ctx.Glob(filepath.Join(dir.String(), "**/*"), aaptIgnoreFilenames)
-	for _, f := range files {
-		if isDir, err := ctx.Fs().IsDir(f.String()); err != nil {
-			ctx.ModuleErrorf("error in IsDir(%s): %s", f.String(), err.Error())
-			return nil
-		} else if !isDir {
-			ret = append(ret, f)
-		}
-	}
-	return ret
+	return ctx.GlobFiles(filepath.Join(dir.String(), "**/*"), aaptIgnoreFilenames)
 }
 
 type overlayGlobResult struct {
@@ -440,10 +430,7 @@
 		}
 		var paths android.Paths
 		for _, f := range files {
-			if isDir, err := ctx.Fs().IsDir(f); err != nil {
-				ctx.Errorf("error in IsDir(%s): %s", f, err.Error())
-				return
-			} else if !isDir {
+			if !strings.HasSuffix(f, "/") {
 				paths = append(paths, android.PathForSource(ctx, f))
 			}
 		}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index ac6bd33..9d6f58e 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -18,7 +18,6 @@
 	"android/soong/android"
 	"android/soong/java/config"
 	"fmt"
-	"path/filepath"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -52,6 +51,7 @@
 func init() {
 	android.RegisterModuleType("droiddoc", DroiddocFactory)
 	android.RegisterModuleType("droiddoc_host", DroiddocHostFactory)
+	android.RegisterModuleType("droiddoc_template", DroiddocTemplateFactory)
 	android.RegisterModuleType("javadoc", JavadocFactory)
 	android.RegisterModuleType("javadoc_host", JavadocHostFactory)
 }
@@ -82,7 +82,7 @@
 
 type DroiddocProperties struct {
 	// directory relative to top of the source tree that contains doc templates files.
-	Custom_template_dir *string `android:"arch_variant"`
+	Custom_template *string `android:"arch_variant"`
 
 	// directories relative to top of the source tree which contains html/jd files.
 	Html_dirs []string `android:"arch_variant"`
@@ -233,7 +233,7 @@
 			}
 		default:
 			switch tag {
-			case android.DefaultsDepTag, android.SourceDepTag:
+			case android.DefaultsDepTag, android.SourceDepTag, droiddocTemplateTag:
 				// Nothing to do
 			default:
 				ctx.ModuleErrorf("depends on non-java module %q", otherName)
@@ -249,7 +249,7 @@
 	j.srcFiles = srcFiles.FilterOutByExt(".srcjar")
 
 	j.docZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"docs.zip")
-	j.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.jar")
+	j.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
 
 	if j.properties.Local_sourcepaths == nil {
 		j.properties.Local_sourcepaths = append(j.properties.Local_sourcepaths, ".")
@@ -319,6 +319,13 @@
 func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) {
 	d.Javadoc.addDeps(ctx)
 
+	if String(d.properties.Custom_template) == "" {
+		// TODO: This is almost always droiddoc-templates-sdk
+		ctx.PropertyErrorf("custom_template", "must specify a template")
+	} else {
+		ctx.AddDependency(ctx.Module(), droiddocTemplateTag, String(d.properties.Custom_template))
+	}
+
 	// extra_arg_files may contains filegroup or genrule.
 	android.ExtractSourcesDeps(ctx, d.properties.Arg_files)
 
@@ -373,24 +380,32 @@
 		classpathArgs = "-classpath " + strings.Join(deps.classpath.Strings(), ":")
 	}
 
-	// templateDir (maybe missing) is relative to top of the source tree instead of current module.
-	templateDir := android.PathForSource(ctx, String(d.properties.Custom_template_dir)).String()
-	implicits = append(implicits, ctx.GlobFiles(filepath.Join(templateDir, "**/*"), nil)...)
+	var templateDir string
+	ctx.VisitDirectDepsWithTag(droiddocTemplateTag, func(m android.Module) {
+		if t, ok := m.(*DroiddocTemplate); ok {
+			implicits = append(implicits, t.deps...)
+			templateDir = t.dir.String()
+		} else {
+			ctx.PropertyErrorf("custom_template", "module %q is not a droiddoc_template", ctx.OtherModuleName(m))
+		}
+	})
 
 	var htmlDirArgs string
 	if len(d.properties.Html_dirs) > 0 {
-		// htmlDir is relative to top of the source tree instead of current module.
-		htmlDir := android.PathForSource(ctx, d.properties.Html_dirs[0]).String()
-		implicits = append(implicits, ctx.GlobFiles(filepath.Join(htmlDir, "**/*"), nil)...)
-		htmlDirArgs = "-htmldir " + htmlDir
+		htmlDir := android.PathForModuleSrc(ctx, d.properties.Html_dirs[0])
+		implicits = append(implicits, ctx.Glob(htmlDir.Join(ctx, "**/*").String(), nil)...)
+		htmlDirArgs = "-htmldir " + htmlDir.String()
 	}
 
 	var htmlDir2Args string
 	if len(d.properties.Html_dirs) > 1 {
-		// htmlDir2 is relative to top of the source tree instead of current module.
-		htmlDir2 := android.PathForSource(ctx, d.properties.Html_dirs[1]).String()
-		implicits = append(implicits, ctx.GlobFiles(filepath.Join(htmlDir2, "**/*"), nil)...)
-		htmlDirArgs = "-htmldir2 " + htmlDir2
+		htmlDir2 := android.PathForModuleSrc(ctx, d.properties.Html_dirs[1])
+		implicits = append(implicits, ctx.Glob(htmlDir2.Join(ctx, "**/*").String(), nil)...)
+		htmlDir2Args = "-htmldir2 " + htmlDir2.String()
+	}
+
+	if len(d.properties.Html_dirs) > 2 {
+		ctx.PropertyErrorf("html_dirs", "Droiddoc only supports up to 2 html dirs")
 	}
 
 	knownTags := ctx.ExpandSources(d.properties.Knowntags, nil)
@@ -451,3 +466,34 @@
 		},
 	})
 }
+
+var droiddocTemplateTag = dependencyTag{name: "droiddoc-template"}
+
+type DroiddocTemplateProperties struct {
+	// path to the directory containing the droiddoc templates.
+	Path *string
+}
+
+type DroiddocTemplate struct {
+	android.ModuleBase
+
+	properties DroiddocTemplateProperties
+
+	deps android.Paths
+	dir  android.Path
+}
+
+func DroiddocTemplateFactory() android.Module {
+	module := &DroiddocTemplate{}
+	module.AddProperties(&module.properties)
+	android.InitAndroidModule(module)
+	return module
+}
+
+func (d *DroiddocTemplate) DepsMutator(android.BottomUpMutatorContext) {}
+
+func (d *DroiddocTemplate) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	path := android.PathForModuleSrc(ctx, String(d.properties.Path))
+	d.dir = path
+	d.deps = ctx.Glob(path.Join(ctx, "**/*").String(), nil)
+}
diff --git a/java/java_test.go b/java/java_test.go
index eda229b..5d6a6e0 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -81,6 +81,7 @@
 	ctx.RegisterModuleType("genrule", android.ModuleFactoryAdaptor(genrule.GenRuleFactory))
 	ctx.RegisterModuleType("droiddoc", android.ModuleFactoryAdaptor(DroiddocFactory))
 	ctx.RegisterModuleType("droiddoc_host", android.ModuleFactoryAdaptor(DroiddocHostFactory))
+	ctx.RegisterModuleType("droiddoc_template", android.ModuleFactoryAdaptor(DroiddocTemplateFactory))
 	ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
 	ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
@@ -865,6 +866,10 @@
 
 func TestDroiddoc(t *testing.T) {
 	ctx := testJava(t, `
+		droiddoc_template {
+		    name: "droiddoc-templates-sdk",
+		    path: ".",
+		}
 		droiddoc {
 		    name: "bar-doc",
 		    srcs: [
@@ -873,7 +878,7 @@
 		    exclude_srcs: [
 		        "bar-doc/b.java"
 		    ],
-		    custom_template_dir: "external/doclava/templates-sdk",
+		    custom_template: "droiddoc-templates-sdk",
 		    hdf: [
 		        "android.whichdoc offline",
 		    ],
@@ -886,8 +891,8 @@
 		}
 		`)
 
-	stubsJar := filepath.Join(buildDir, ".intermediates", "bar-doc", "android_common", "bar-doc-stubs.jar")
-	barDoc := ctx.ModuleForTests("bar-doc", "android_common").Output("bar-doc-stubs.jar")
+	stubsJar := filepath.Join(buildDir, ".intermediates", "bar-doc", "android_common", "bar-doc-stubs.srcjar")
+	barDoc := ctx.ModuleForTests("bar-doc", "android_common").Output("bar-doc-stubs.srcjar")
 	if stubsJar != barDoc.Output.String() {
 		t.Errorf("expected stubs Jar [%q], got %q", stubsJar, barDoc.Output.String())
 	}