Use RSP file for long classpaths

Setting use_resource_processor: true can increase the length of the
classpath enough to trigger "command line too long" errors.  There are
clockwork libraries with 546 transitive android_library dependencies.
Write classpaths longer than 64kB to a separate file and add them
to the javac and turbine command lines with the @file syntax.

Bug: 294256649
Test: m checkbuild
Change-Id: I2b6a57ae30de03347db3221e9c9a4b2efb490115
diff --git a/java/builder.go b/java/builder.go
index 085e7a1..944e26e 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -212,6 +212,14 @@
 			CommandDeps: []string{"${config.MergeZipsCmd}"},
 		},
 		"jarArgs")
+	combineJarRsp = pctx.AndroidStaticRule("combineJarRsp",
+		blueprint.RuleParams{
+			Command:        `${config.MergeZipsCmd} --ignore-duplicates -j $jarArgs $out @$out.rsp`,
+			CommandDeps:    []string{"${config.MergeZipsCmd}"},
+			Rspfile:        "$out.rsp",
+			RspfileContent: "$in",
+		},
+		"jarArgs")
 
 	jarjar = pctx.AndroidStaticRule("jarjar",
 		blueprint.RuleParams{
@@ -418,7 +426,7 @@
 		})
 }
 
-func turbineFlags(ctx android.ModuleContext, flags javaBuilderFlags) (string, android.Paths) {
+func turbineFlags(ctx android.ModuleContext, flags javaBuilderFlags, dir string) (string, android.Paths) {
 	var deps android.Paths
 
 	classpath := flags.classpath
@@ -443,13 +451,21 @@
 	deps = append(deps, classpath...)
 	turbineFlags := bootClasspath + " " + classpath.FormTurbineClassPath("--classpath ")
 
+	const flagsLimit = 32 * 1024
+	if len(turbineFlags) > flagsLimit {
+		flagsRspFile := android.PathForModuleOut(ctx, dir, "turbine-flags.rsp")
+		android.WriteFileRule(ctx, flagsRspFile, turbineFlags)
+		turbineFlags = "@" + flagsRspFile.String()
+		deps = append(deps, flagsRspFile)
+	}
+
 	return turbineFlags, deps
 }
 
 func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath,
 	srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
 
-	turbineFlags, deps := turbineFlags(ctx, flags)
+	turbineFlags, deps := turbineFlags(ctx, flags, "turbine")
 
 	deps = append(deps, srcJars...)
 
@@ -481,7 +497,7 @@
 func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.WritablePath,
 	srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
 
-	turbineFlags, deps := turbineFlags(ctx, flags)
+	turbineFlags, deps := turbineFlags(ctx, flags, "kapt")
 
 	deps = append(deps, srcJars...)
 
@@ -534,14 +550,14 @@
 
 	deps = append(deps, srcJars...)
 
-	classpath := flags.classpath
+	javacClasspath := flags.classpath
 
 	var bootClasspath string
 	if flags.javaVersion.usesJavaModules() {
 		var systemModuleDeps android.Paths
 		bootClasspath, systemModuleDeps = flags.systemModules.FormJavaSystemModulesPath(ctx.Device())
 		deps = append(deps, systemModuleDeps...)
-		classpath = append(flags.java9Classpath, classpath...)
+		javacClasspath = append(flags.java9Classpath, javacClasspath...)
 	} else {
 		deps = append(deps, flags.bootClasspath...)
 		if len(flags.bootClasspath) == 0 && ctx.Device() {
@@ -553,7 +569,19 @@
 		}
 	}
 
-	deps = append(deps, classpath...)
+	classpathArg := javacClasspath.FormJavaClassPath("-classpath")
+
+	// Keep the command line under the MAX_ARG_STRLEN limit by putting the classpath argument into an rsp file
+	// if it is too long.
+	const classpathLimit = 64 * 1024
+	if len(classpathArg) > classpathLimit {
+		classpathRspFile := outputFile.ReplaceExtension(ctx, "classpath")
+		android.WriteFileRule(ctx, classpathRspFile, classpathArg)
+		deps = append(deps, classpathRspFile)
+		classpathArg = "@" + classpathRspFile.String()
+	}
+
+	deps = append(deps, javacClasspath...)
 	deps = append(deps, flags.processorPath...)
 
 	processor := "-proc:none"
@@ -584,7 +612,7 @@
 		Args: map[string]string{
 			"javacFlags":    flags.javacFlags,
 			"bootClasspath": bootClasspath,
-			"classpath":     classpath.FormJavaClassPath("-classpath"),
+			"classpath":     classpathArg,
 			"processorpath": flags.processorPath.FormJavaClassPath("-processorpath"),
 			"processor":     processor,
 			"srcJars":       strings.Join(srcJars.Strings(), " "),
@@ -643,8 +671,23 @@
 		jarArgs = append(jarArgs, "-D")
 	}
 
+	rule := combineJar
+	// Keep the command line under the MAX_ARG_STRLEN limit by putting the list of jars into an rsp file
+	// if it is too long.
+	const jarsLengthLimit = 64 * 1024
+	jarsLength := 0
+	for i, jar := range jars {
+		if i != 0 {
+			jarsLength += 1
+		}
+		jarsLength += len(jar.String())
+	}
+	if jarsLength > jarsLengthLimit {
+		rule = combineJarRsp
+	}
+
 	ctx.Build(pctx, android.BuildParams{
-		Rule:        combineJar,
+		Rule:        rule,
 		Description: desc,
 		Output:      outputFile,
 		Inputs:      jars,