Support Javac sharding in Soong.

Test: m clean && m -j java and java_test.go

Change-Id: I110a0ff029448d3319aed2788d25d90a6c1a7fa0
diff --git a/java/java.go b/java/java.go
index f9a4c04..bb6e556 100644
--- a/java/java.go
+++ b/java/java.go
@@ -117,6 +117,9 @@
 	// List of classes to pass to javac to use as annotation processors
 	Annotation_processor_classes []string
 
+	// The number of Java source entries each Javac instance can process
+	Javac_shard_size *int64
+
 	Openjdk9 struct {
 		// List of source files that should only be used when passing -source 1.9
 		Srcs []string
@@ -355,6 +358,18 @@
 	return false
 }
 
+func shardPaths(paths android.Paths, shardSize int) []android.Paths {
+	ret := make([]android.Paths, 0, (len(paths)+shardSize-1)/shardSize)
+	for len(paths) > shardSize {
+		ret = append(ret, paths[0:shardSize])
+		paths = paths[shardSize:]
+	}
+	if len(paths) > 0 {
+		ret = append(ret, paths)
+	}
+	return ret
+}
+
 func (j *Module) hasSrcExt(ext string) bool {
 	return hasSrcExt(j.properties.Srcs, ext)
 }
@@ -571,7 +586,17 @@
 		}
 	}
 
+	enable_sharding := false
 	if ctx.Device() && !ctx.AConfig().IsEnvFalse("TURBINE_ENABLED") {
+		if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
+			enable_sharding = true
+			if len(j.properties.Annotation_processors) != 0 ||
+				len(j.properties.Annotation_processor_classes) != 0 {
+				ctx.PropertyErrorf("javac_shard_size",
+					"%q cannot be set when annotation processors are enabled.",
+					j.properties.Javac_shard_size)
+			}
+		}
 		// If sdk jar is java module, then directly return classesJar as header.jar
 		if j.Name() != "android_stubs_current" && j.Name() != "android_system_stubs_current" &&
 			j.Name() != "android_test_stubs_current" {
@@ -590,18 +615,35 @@
 			// TODO(ccross): Once we always compile with javac9 we may be able to conditionally
 			//    enable error-prone without affecting the output class files.
 			errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
-			RunErrorProne(ctx, errorprone, javaSrcFiles, srcJars, flags)
+			RunErrorProne(ctx, errorprone, uniqueSrcFiles, srcJars, flags)
 			extraJarDeps = append(extraJarDeps, errorprone)
 		}
 
-		// Compile java sources into .class files
-		classes := android.PathForModuleOut(ctx, "javac", jarName)
-		TransformJavaToClasses(ctx, classes, javaSrcFiles, srcJars, flags, extraJarDeps)
+		if enable_sharding {
+			flags.classpath.AddPaths([]android.Path{j.headerJarFile})
+			shardSize := int(*(j.properties.Javac_shard_size))
+			var shardSrcs []android.Paths
+			if len(uniqueSrcFiles) > 0 {
+				shardSrcs = shardPaths(uniqueSrcFiles, shardSize)
+				for idx, shardSrc := range shardSrcs {
+					classes := android.PathForModuleOut(ctx, "javac", jarName+strconv.Itoa(idx))
+					TransformJavaToClasses(ctx, classes, idx, shardSrc, nil, flags, extraJarDeps)
+					jars = append(jars, classes)
+				}
+			}
+			if len(srcJars) > 0 {
+				classes := android.PathForModuleOut(ctx, "javac", jarName+strconv.Itoa(len(shardSrcs)))
+				TransformJavaToClasses(ctx, classes, len(shardSrcs), nil, srcJars, flags, extraJarDeps)
+				jars = append(jars, classes)
+			}
+		} else {
+			classes := android.PathForModuleOut(ctx, "javac", jarName)
+			TransformJavaToClasses(ctx, classes, -1, uniqueSrcFiles, srcJars, flags, extraJarDeps)
+			jars = append(jars, classes)
+		}
 		if ctx.Failed() {
 			return
 		}
-
-		jars = append(jars, classes)
 	}
 
 	dirArgs, dirDeps := ResourceDirsToJarArgs(ctx, j.properties.Java_resource_dirs, j.properties.Exclude_java_resource_dirs)