Fetch generated srcs from java libs for droiddoc.

api-stubs, system-api-stubs and etc need generated sources and srcjars from "framework",
so add a property that tell module to fetch srcs and srcjars from its
dependency libraries. The libraries in that property has to be in the
module's classpath.

Also add doc_defaults targets.

Bug: b/70351683
Test: m -j
Change-Id: I05831fbcad488037710950e4f05dc8fb2a12f403
diff --git a/android/neverallow.go b/android/neverallow.go
index 261f2ee..3c6c004 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -50,7 +50,7 @@
 		because("the VNDK can never contain a library that is device dependent."),
 	neverallow().with("vndk.enabled", "true").without("owner", "").
 		because("a VNDK module can never have an owner."),
-	neverallow().notIn("libcore").with("no_standard_libs", "true"),
+	neverallow().notIn("libcore", "development").with("no_standard_libs", "true"),
 
 	// TODO(b/67974785): always enforce the manifest
 	neverallow().
diff --git a/java/droiddoc.go b/java/droiddoc.go
index eaa6c5f..8c60535 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -18,6 +18,7 @@
 	"android/soong/android"
 	"android/soong/java/config"
 	"fmt"
+	"path/filepath"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -49,6 +50,8 @@
 )
 
 func init() {
+	android.RegisterModuleType("doc_defaults", DocDefaultsFactory)
+
 	android.RegisterModuleType("droiddoc", DroiddocFactory)
 	android.RegisterModuleType("droiddoc_host", DroiddocHostFactory)
 	android.RegisterModuleType("droiddoc_template", DroiddocTemplateFactory)
@@ -63,22 +66,31 @@
 
 	// list of directories rooted at the Android.bp file that will
 	// be added to the search paths for finding source files when passing package names.
-	Local_sourcepaths []string `android:"arch_variant"`
+	Local_sourcepaths []string
 
 	// list of source files that should not be used to build the Java module.
 	// This is most useful in the arch/multilib variants to remove non-common files
 	// filegroup or genrule can be included within this property.
 	Exclude_srcs []string `android:"arch_variant"`
 
-	// list of of java libraries that will be in the classpath.
+	// list of java libraries that will be in the classpath.
 	Libs []string `android:"arch_variant"`
 
 	// don't build against the framework libraries (legacy-test, core-junit,
 	// ext, and framework for device targets)
 	No_framework_libs *bool
 
+	// the java library (in classpath) for documentation that provides java srcs and srcjars.
+	Srcs_lib *string
+
+	// the base dirs under srcs_lib will be scanned for java srcs.
+	Srcs_lib_whitelist_dirs []string
+
+	// the sub dirs under srcs_lib_whitelist_dirs will be scanned for java srcs.
+	Srcs_lib_whitelist_pkgs []string
+
 	// If set to false, don't allow this module(-docs.zip) to be exported. Defaults to true.
-	Installable *bool `android:"arch_variant"`
+	Installable *bool
 
 	// if not blank, set to the version of the sdk to compile against
 	Sdk_version *string `android:"arch_variant"`
@@ -86,37 +98,43 @@
 
 type DroiddocProperties struct {
 	// directory relative to top of the source tree that contains doc templates files.
-	Custom_template *string `android:"arch_variant"`
+	Custom_template *string
 
 	// directories relative to top of the source tree which contains html/jd files.
-	Html_dirs []string `android:"arch_variant"`
+	Html_dirs []string
 
 	// set a value in the Clearsilver hdf namespace.
-	Hdf []string `android:"arch_variant"`
+	Hdf []string
 
 	// proofread file contains all of the text content of the javadocs concatenated into one file,
 	// suitable for spell-checking and other goodness.
-	Proofread_file *string `android:"arch_variant"`
+	Proofread_file *string
 
 	// a todo file lists the program elements that are missing documentation.
 	// At some point, this might be improved to show more warnings.
-	Todo_file *string `android:"arch_variant"`
+	Todo_file *string
+
+	// directory under current module source that provide additional resources (images).
+	Resourcesdir *string
+
+	// resources output directory under out/soong/.intermediates.
+	Resourcesoutdir *string
 
 	// local files that are used within user customized droiddoc options.
-	Arg_files []string `android:"arch_variant"`
+	Arg_files []string
 
 	// user customized droiddoc args.
 	// Available variables for substitution:
 	//
 	//  $(location <label>): the path to the arg_files with name <label>
-	Args *string `android:"arch_variant"`
+	Args *string
 
 	// names of the output files used in args that will be generated
-	Out []string `android:"arch_variant"`
+	Out []string
 
 	// a list of files under current module source dir which contains known tags in Java sources.
 	// filegroup or genrule can be included within this property.
-	Knowntags []string `android:"arch_variant"`
+	Knowntags []string
 }
 
 type Javadoc struct {
@@ -133,6 +151,12 @@
 	stubsSrcJar android.WritablePath
 }
 
+func (j *Javadoc) Srcs() android.Paths {
+	return android.Paths{j.stubsSrcJar}
+}
+
+var _ android.SourceFileProducer = (*Javadoc)(nil)
+
 type Droiddoc struct {
 	Javadoc
 
@@ -203,6 +227,17 @@
 	android.ExtractSourcesDeps(ctx, j.properties.Exclude_srcs)
 }
 
+func (j *Javadoc) genWhitelistPathPrefixes(whitelistPathPrefixes map[string]bool) {
+	for _, dir := range j.properties.Srcs_lib_whitelist_dirs {
+		for _, pkg := range j.properties.Srcs_lib_whitelist_pkgs {
+			prefix := filepath.Join(dir, pkg)
+			if _, found := whitelistPathPrefixes[prefix]; !found {
+				whitelistPathPrefixes[prefix] = true
+			}
+		}
+	}
+}
+
 func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
 	var deps deps
 
@@ -224,6 +259,24 @@
 				deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars()...)
 			case libTag:
 				deps.classpath = append(deps.classpath, dep.ImplementationJars()...)
+				if otherName == String(j.properties.Srcs_lib) {
+					srcs := dep.(SrcDependency).CompiledSrcs()
+					whitelistPathPrefixes := make(map[string]bool)
+					j.genWhitelistPathPrefixes(whitelistPathPrefixes)
+					for _, src := range srcs {
+						if _, ok := src.(android.WritablePath); ok { // generated sources
+							deps.srcs = append(deps.srcs, src)
+						} else { // select source path for documentation based on whitelist path prefixs.
+							for k, _ := range whitelistPathPrefixes {
+								if strings.HasPrefix(src.Rel(), k) {
+									deps.srcs = append(deps.srcs, src)
+									break
+								}
+							}
+						}
+					}
+					deps.srcJars = append(deps.srcJars, dep.(SrcDependency).CompiledSrcJars()...)
+				}
 			default:
 				panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
 			}
@@ -252,7 +305,10 @@
 
 	// srcs may depend on some genrule output.
 	j.srcJars = srcFiles.FilterByExt(".srcjar")
+	j.srcJars = append(j.srcJars, deps.srcJars...)
+
 	j.srcFiles = srcFiles.FilterOutByExt(".srcjar")
+	j.srcFiles = append(j.srcFiles, deps.srcs...)
 
 	j.docZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"docs.zip")
 	j.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
@@ -428,6 +484,7 @@
 		proofreadFile := android.PathForModuleOut(ctx, String(d.properties.Proofread_file))
 		args = args + " -proofread " + proofreadFile.String()
 	}
+
 	if String(d.properties.Todo_file) != "" {
 		// tricky part:
 		// we should not compute full path for todo_file through PathForModuleOut().
@@ -435,6 +492,18 @@
 		args = args + " -todo " + String(d.properties.Todo_file)
 	}
 
+	if String(d.properties.Resourcesdir) != "" {
+		// TODO: should we add files under resourcesDir to the implicits? It seems that
+		// resourcesDir is one sub dir of htmlDir
+		resourcesDir := android.PathForModuleSrc(ctx, String(d.properties.Resourcesdir))
+		args = args + " -resourcesdir " + resourcesDir.String()
+	}
+
+	if String(d.properties.Resourcesoutdir) != "" {
+		// TODO: it seems -resourceoutdir reference/android/images/ didn't get generated anywhere.
+		args = args + " -resourcesoutdir " + String(d.properties.Resourcesoutdir)
+	}
+
 	implicits = append(implicits, d.Javadoc.srcJars...)
 
 	opts := "-source 1.8 -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " +
@@ -503,3 +572,30 @@
 	d.dir = path
 	d.deps = ctx.Glob(path.Join(ctx, "**/*").String(), nil)
 }
+
+//
+// Defaults
+//
+type DocDefaults struct {
+	android.ModuleBase
+	android.DefaultsModuleBase
+}
+
+func (*DocDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+}
+
+func (d *DocDefaults) DepsMutator(ctx android.BottomUpMutatorContext) {
+}
+
+func DocDefaultsFactory() android.Module {
+	module := &DocDefaults{}
+
+	module.AddProperties(
+		&JavadocProperties{},
+		&DroiddocProperties{},
+	)
+
+	android.InitDefaultsModule(module)
+
+	return module
+}
diff --git a/java/java.go b/java/java.go
index 92170e6..5f5225c 100644
--- a/java/java.go
+++ b/java/java.go
@@ -283,6 +283,21 @@
 	AidlIncludeDirs() android.Paths
 }
 
+type SrcDependency interface {
+	CompiledSrcs() android.Paths
+	CompiledSrcJars() android.Paths
+}
+
+func (j *Module) CompiledSrcs() android.Paths {
+	return j.compiledJavaSrcs
+}
+
+func (j *Module) CompiledSrcJars() android.Paths {
+	return j.compiledSrcJars
+}
+
+var _ SrcDependency = (*Module)(nil)
+
 func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
 	android.InitAndroidArchModule(module, hod, android.MultilibCommon)
 	android.InitDefaultableModule(module)
@@ -299,6 +314,7 @@
 	bootClasspathTag = dependencyTag{name: "bootclasspath"}
 	systemModulesTag = dependencyTag{name: "system modules"}
 	frameworkResTag  = dependencyTag{name: "framework-res"}
+	frameworkApkTag  = dependencyTag{name: "framework-apk"}
 	kotlinStdlibTag  = dependencyTag{name: "kotlin-stdlib"}
 	proguardRaiseTag = dependencyTag{name: "proguard-raise"}
 )
@@ -459,6 +475,11 @@
 		if ctx.ModuleName() == "framework" {
 			ctx.AddDependency(ctx.Module(), frameworkResTag, "framework-res")
 		}
+		if ctx.ModuleName() == "android_stubs_current" ||
+			ctx.ModuleName() == "android_system_stubs_current" ||
+			ctx.ModuleName() == "android_test_stubs_current" {
+			ctx.AddDependency(ctx.Module(), frameworkApkTag, "framework-res")
+		}
 	}
 
 	ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
@@ -544,6 +565,7 @@
 	staticHeaderJars   android.Paths
 	staticJarResources android.Paths
 	aidlIncludeDirs    android.Paths
+	srcs               android.Paths
 	srcJars            android.Paths
 	systemModules      android.Path
 	aidlPreprocess     android.OptionalPath
@@ -606,6 +628,18 @@
 					// generated by framework-res.apk
 					deps.srcJars = append(deps.srcJars, dep.(*AndroidApp).aaptSrcJar)
 				}
+			case frameworkApkTag:
+				if ctx.ModuleName() == "android_stubs_current" ||
+					ctx.ModuleName() == "android_system_stubs_current" ||
+					ctx.ModuleName() == "android_test_stubs_current" {
+					// framework stubs.jar need to depend on framework-res.apk, in order to pull the
+					// resource files out of there for aapt.
+					//
+					// Normally the package rule runs aapt, which includes the resource,
+					// but we're not running that in our package rule so just copy in the
+					// resource files here.
+					deps.staticJarResources = append(deps.staticJarResources, dep.(*AndroidApp).exportPackage)
+				}
 			case kotlinStdlibTag:
 				deps.kotlinStdlib = dep.HeaderJars()
 			default:
@@ -895,6 +929,7 @@
 
 	// static classpath jars have the resources in them, so the resource jars aren't necessary here
 	jars = append(jars, deps.staticJars...)
+	jars = append(jars, deps.staticJarResources...)
 
 	var manifest android.OptionalPath
 	if j.properties.Manifest != nil {