Make javac rules output a jar with soong_zip

Make javac rules output a jar file instead of a classes.list.
Combine the output jar, static jar dependencies, and resources
into the final jar using a separate rule.  For now, use a shell
command with unzip and soong_zip to create the final jar,
eventually it will be done with a zip2zip-style jar combiner.

Bug: 64691570
Test: java_test.go
Change-Id: Id8e6313e0097b78947d88e86e47b56ad08caca1a
diff --git a/java/java.go b/java/java.go
index 7b213b2..b76c2a4 100644
--- a/java/java.go
+++ b/java/java.go
@@ -134,12 +134,6 @@
 	// output file suitable for installing or running
 	outputFile android.Path
 
-	// jarSpecs suitable for inserting classes from a static library into another jar
-	classJarSpecs []jarSpec
-
-	// jarSpecs suitable for inserting resources from a static library into another jar
-	resourceJarSpecs []jarSpec
-
 	exportAidlIncludeDirs android.Paths
 
 	logtagsSrcs android.Paths
@@ -154,8 +148,6 @@
 
 type Dependency interface {
 	ClasspathFiles() android.Paths
-	ClassJarSpecs() []jarSpec
-	ResourceJarSpecs() []jarSpec
 	AidlIncludeDirs() android.Paths
 }
 
@@ -229,9 +221,8 @@
 	return flags
 }
 
-func (j *Module) collectDeps(ctx android.ModuleContext) (classpath android.Paths,
-	bootClasspath android.Paths, classJarSpecs, resourceJarSpecs []jarSpec, aidlPreprocess android.OptionalPath,
-	aidlIncludeDirs android.Paths, srcFileLists android.Paths) {
+func (j *Module) collectDeps(ctx android.ModuleContext) (classpath, bootClasspath, staticJars,
+	aidlIncludeDirs, srcFileLists android.Paths, aidlPreprocess android.OptionalPath) {
 
 	ctx.VisitDirectDeps(func(module blueprint.Module) {
 		otherName := ctx.OtherModuleName(module)
@@ -254,8 +245,7 @@
 			classpath = append(classpath, dep.ClasspathFiles()...)
 		case staticLibTag:
 			classpath = append(classpath, dep.ClasspathFiles()...)
-			classJarSpecs = append(classJarSpecs, dep.ClassJarSpecs()...)
-			resourceJarSpecs = append(resourceJarSpecs, dep.ResourceJarSpecs()...)
+			staticJars = append(staticJars, dep.ClasspathFiles()...)
 		case frameworkResTag:
 			if ctx.ModuleName() == "framework" {
 				// framework.jar has a one-off dependency on the R.java and Manifest.java files
@@ -280,16 +270,15 @@
 		aidlIncludeDirs = append(aidlIncludeDirs, dep.AidlIncludeDirs()...)
 	})
 
-	return classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess,
-		aidlIncludeDirs, srcFileLists
+	return
 }
 
 func (j *Module) compile(ctx android.ModuleContext) {
 
 	j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Export_aidl_include_dirs)
 
-	classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess,
-		aidlIncludeDirs, srcFileLists := j.collectDeps(ctx)
+	classpath, bootClasspath, staticJars, aidlIncludeDirs, srcFileLists,
+		aidlPreprocess := j.collectDeps(ctx)
 
 	var flags javaBuilderFlags
 
@@ -341,6 +330,8 @@
 
 	var extraJarDeps android.Paths
 
+	var jars android.Paths
+
 	if len(srcFiles) > 0 {
 		// Compile java sources into .class files
 		classes := TransformJavaToClasses(ctx, srcFiles, srcFileLists, flags, deps)
@@ -359,37 +350,37 @@
 			extraJarDeps = append(extraJarDeps, errorprone)
 		}
 
-		classJarSpecs = append([]jarSpec{classes}, classJarSpecs...)
+		jars = append(jars, classes)
 	}
 
-	resourceJarSpecs = append(ResourceDirsToJarSpecs(ctx, j.properties.Resource_dirs, j.properties.Exclude_resource_dirs),
-		resourceJarSpecs...)
-
+	resourceJarSpecs := ResourceDirsToJarSpecs(ctx, j.properties.Resource_dirs, j.properties.Exclude_resource_dirs)
 	manifest := android.OptionalPathForModuleSrc(ctx, j.properties.Manifest)
 
-	allJarSpecs := append([]jarSpec(nil), classJarSpecs...)
-	allJarSpecs = append(allJarSpecs, resourceJarSpecs...)
-
-	// Combine classes + resources into classes-full-debug.jar
-	outputFile := TransformClassesToJar(ctx, allJarSpecs, manifest, extraJarDeps)
-	if ctx.Failed() {
-		return
-	}
-
-	if j.properties.Jarjar_rules != nil {
-		jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
-		// Transform classes-full-debug.jar into classes-jarjar.jar
-		outputFile = TransformJarJar(ctx, outputFile, jarjar_rules)
+	if len(resourceJarSpecs) > 0 || manifest.Valid() {
+		// Combine classes + resources into classes-full-debug.jar
+		resourceJar := TransformResourcesToJar(ctx, resourceJarSpecs, manifest, extraJarDeps)
 		if ctx.Failed() {
 			return
 		}
 
-		classes, _ := TransformPrebuiltJarToClasses(ctx, "jarjar_extracted", outputFile)
-		classJarSpecs = []jarSpec{classes}
+		jars = append(jars, resourceJar)
 	}
 
-	j.resourceJarSpecs = resourceJarSpecs
-	j.classJarSpecs = classJarSpecs
+	jars = append(jars, staticJars...)
+
+	// Combine the classes built from sources, any manifests, and any static libraries into
+	// classes-combined.jar.  If there is only one input jar this step will be skipped.
+	outputFile := TransformJarsToJar(ctx, "classes-combined.jar", jars)
+
+	if j.properties.Jarjar_rules != nil {
+		jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
+		// Transform classes-combined.jar into classes-jarjar.jar
+		outputFile = TransformJarJar(ctx, outputFile, jarjar_rules)
+		if ctx.Failed() {
+			return
+		}
+	}
+
 	j.classpathFile = outputFile
 
 	if j.deviceProperties.Dex && len(srcFiles) > 0 {
@@ -447,14 +438,6 @@
 	return android.Paths{j.classpathFile}
 }
 
-func (j *Module) ClassJarSpecs() []jarSpec {
-	return j.classJarSpecs
-}
-
-func (j *Module) ResourceJarSpecs() []jarSpec {
-	return j.resourceJarSpecs
-}
-
 func (j *Module) AidlIncludeDirs() android.Paths {
 	return j.exportAidlIncludeDirs
 }
@@ -580,9 +563,8 @@
 
 	properties ImportProperties
 
-	classpathFiles                  android.Paths
-	combinedClasspathFile           android.Path
-	classJarSpecs, resourceJarSpecs []jarSpec
+	classpathFiles        android.Paths
+	combinedClasspathFile android.Path
 }
 
 func (j *Import) Prebuilt() *android.Prebuilt {
@@ -603,14 +585,7 @@
 func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	j.classpathFiles = android.PathsForModuleSrc(ctx, j.properties.Jars)
 
-	for i, prebuilt := range j.classpathFiles {
-		subdir := "extracted" + strconv.Itoa(i)
-		classJarSpec, resourceJarSpec := TransformPrebuiltJarToClasses(ctx, subdir, prebuilt)
-		j.classJarSpecs = append(j.classJarSpecs, classJarSpec)
-		j.resourceJarSpecs = append(j.resourceJarSpecs, resourceJarSpec)
-	}
-
-	j.combinedClasspathFile = TransformClassesToJar(ctx, j.classJarSpecs, android.OptionalPath{}, nil)
+	j.combinedClasspathFile = TransformJarsToJar(ctx, "classes.jar", j.classpathFiles)
 }
 
 var _ Dependency = (*Import)(nil)
@@ -619,14 +594,6 @@
 	return j.classpathFiles
 }
 
-func (j *Import) ClassJarSpecs() []jarSpec {
-	return j.classJarSpecs
-}
-
-func (j *Import) ResourceJarSpecs() []jarSpec {
-	return j.resourceJarSpecs
-}
-
 func (j *Import) AidlIncludeDirs() android.Paths {
 	return nil
 }