Add support for Metalava implicit dependencies for remote execution.

Test: built aosp crosshatch userdebug with RBE_METALAVA=1
Change-Id: Ic64d98785e34717ef9bdad62b4885085f84f132a
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 821bb6d..b16c9cd 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -376,6 +376,7 @@
 	srcFiles    android.Paths
 	sourcepaths android.Paths
 	argFiles    android.Paths
+	implicits   android.Paths
 
 	args string
 
@@ -575,6 +576,7 @@
 	// do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
 	// may contain filegroup or genrule.
 	srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
+	j.implicits = append(j.implicits, srcFiles...)
 
 	filterByPackage := func(srcs []android.Path, filterPackages []string) []android.Path {
 		if filterPackages == nil {
@@ -600,6 +602,24 @@
 	}
 	srcFiles = filterByPackage(srcFiles, j.properties.Filter_packages)
 
+	// While metalava needs package html files, it does not need them to be explicit on the command
+	// line. More importantly, the metalava rsp file is also used by the subsequent jdiff action if
+	// jdiff_enabled=true. javadoc complains if it receives html files on the command line. The filter
+	// below excludes html files from the rsp file for both metalava and jdiff. Note that the html
+	// files are still included as implicit inputs for successful remote execution and correct
+	// incremental builds.
+	filterHtml := func(srcs []android.Path) []android.Path {
+		filtered := []android.Path{}
+		for _, src := range srcs {
+			if src.Ext() == ".html" {
+				continue
+			}
+			filtered = append(filtered, src)
+		}
+		return filtered
+	}
+	srcFiles = filterHtml(srcFiles)
+
 	flags := j.collectAidlFlags(ctx, deps)
 	srcFiles = j.genSources(ctx, srcFiles, flags)
 
@@ -1402,10 +1422,26 @@
 }
 
 func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
-	srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths) *android.RuleBuilderCommand {
+	srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths, implicits android.Paths) *android.RuleBuilderCommand {
 	// Metalava uses lots of memory, restrict the number of metalava jobs that can run in parallel.
 	rule.HighMem()
 	cmd := rule.Command()
+
+	rspFile := ""
+	if len(implicits) > 0 {
+		implicitsRsp := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"implicits.rsp")
+		rspFile = implicitsRsp.String()
+		impRule := android.NewRuleBuilder()
+		impCmd := impRule.Command()
+		// A dummy action that copies the ninja generated rsp file to a new location. This allows us to
+		// add a large number of inputs to a file without exceeding bash command length limits (which
+		// would happen if we use the WriteFile rule). The cp is needed because RuleBuilder sets the
+		// rsp file to be ${output}.rsp.
+		impCmd.Text("cp").FlagWithRspFileInputList("", implicits).Output(implicitsRsp)
+		impRule.Build(pctx, ctx, "implicitsGen", "implicits generation")
+		cmd.Implicits(implicits)
+		cmd.Implicit(implicitsRsp)
+	}
 	if ctx.Config().IsEnvTrue("RBE_METALAVA") {
 		rule.Remoteable(android.RemoteRuleSupports{RBE: true})
 		execStrategy := remoteexec.LocalExecStrategy
@@ -1417,7 +1453,6 @@
 			pool = v
 		}
 		inputs := []string{android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "metalava.jar").String()}
-		inputs = append(inputs, sourcepaths.Strings()...)
 		if v := ctx.Config().Getenv("RBE_METALAVA_INPUTS"); v != "" {
 			inputs = append(inputs, strings.Split(v, ",")...)
 		}
@@ -1425,6 +1460,7 @@
 			Labels:          map[string]string{"type": "compile", "lang": "java", "compiler": "metalava"},
 			ExecStrategy:    execStrategy,
 			Inputs:          inputs,
+			RSPFile:         rspFile,
 			ToolchainInputs: []string{config.JavaCmd(ctx).String()},
 			Platform:        map[string]string{remoteexec.PoolKey: pool},
 		}).NoVarTemplate(ctx.Config()))
@@ -1482,7 +1518,7 @@
 	srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
 
 	cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList,
-		deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths)
+		deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths, d.Javadoc.implicits)
 
 	d.stubsFlags(ctx, cmd, stubsDir)
 
diff --git a/java/java_test.go b/java/java_test.go
index e03e57b..9266d29 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1038,7 +1038,7 @@
 	for _, i := range metalavaRule.Implicits {
 		systemJars = append(systemJars, i.Base())
 	}
-	if len(systemJars) != 1 || systemJars[0] != systemJar {
+	if len(systemJars) < 1 || systemJars[0] != systemJar {
 		t.Errorf("inputs of %q must be []string{%q}, but was %#v.", moduleName, systemJar, systemJars)
 	}
 }