Add java_genrules to use jars as inputs and outputs

Add a java_genrule that has the right multilib flags to be a
dependency of a java rule.  Make java libraries implement
SourceFileProducer so that their classes jar can be used as an
input to a java_genrule.  Allow libs and static_libs dependencies
to be a java_genrule.

Test: TestJarGenrules
Change-Id: Ib1b31ef9c0b7e72eeed2c9ecc4ce8a1088e0b1c9
diff --git a/java/java.go b/java/java.go
index 4355200..0a47db0 100644
--- a/java/java.go
+++ b/java/java.go
@@ -211,6 +211,12 @@
 	compiledSrcJars  android.Paths
 }
 
+func (j *Module) Srcs() android.Paths {
+	return android.Paths{j.implementationJarFile}
+}
+
+var _ android.SourceFileProducer = (*Module)(nil)
+
 type Dependency interface {
 	HeaderJars() android.Paths
 	ImplementationJars() android.Paths
@@ -446,6 +452,15 @@
 	kotlinStdlib       android.Paths
 }
 
+func checkProducesJars(ctx android.ModuleContext, dep android.SourceFileProducer) {
+	for _, f := range dep.Srcs() {
+		if f.Ext() != ".jar" {
+			ctx.ModuleErrorf("genrule %q must generate files ending with .jar to be used as a libs or static_libs dependency",
+				ctx.OtherModuleName(dep.(blueprint.Module)))
+		}
+	}
+}
+
 func (j *Module) collectDeps(ctx android.ModuleContext) deps {
 	var deps deps
 
@@ -462,8 +477,46 @@
 		otherName := ctx.OtherModuleName(module)
 		tag := ctx.OtherModuleDependencyTag(module)
 
-		dep, _ := module.(Dependency)
-		if dep == nil {
+		switch dep := module.(type) {
+		case Dependency:
+			switch tag {
+			case bootClasspathTag:
+				deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...)
+			case libTag:
+				deps.classpath = append(deps.classpath, dep.HeaderJars()...)
+			case staticLibTag:
+				deps.classpath = append(deps.classpath, dep.HeaderJars()...)
+				deps.staticJars = append(deps.staticJars, dep.ImplementationJars()...)
+				deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...)
+			case frameworkResTag:
+				if ctx.ModuleName() == "framework" {
+					// framework.jar has a one-off dependency on the R.java and Manifest.java files
+					// generated by framework-res.apk
+					deps.srcJars = append(deps.srcJars, dep.(*AndroidApp).aaptSrcJar)
+				}
+			case kotlinStdlibTag:
+				deps.kotlinStdlib = dep.HeaderJars()
+			default:
+				panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
+			}
+
+			deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
+		case android.SourceFileProducer:
+			switch tag {
+			case libTag:
+				checkProducesJars(ctx, dep)
+				deps.classpath = append(deps.classpath, dep.Srcs()...)
+			case staticLibTag:
+				checkProducesJars(ctx, dep)
+				deps.classpath = append(deps.classpath, dep.Srcs()...)
+				deps.staticJars = append(deps.staticJars, dep.Srcs()...)
+				deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs()...)
+			case android.DefaultsDepTag, android.SourceDepTag:
+				// Nothing to do
+			default:
+				ctx.ModuleErrorf("dependency on genrule %q may only be in srcs, libs, or static_libs", otherName)
+			}
+		default:
 			switch tag {
 			case android.DefaultsDepTag, android.SourceDepTag:
 				// Nothing to do
@@ -479,31 +532,7 @@
 			default:
 				ctx.ModuleErrorf("depends on non-java module %q", otherName)
 			}
-			return
 		}
-
-		switch tag {
-		case bootClasspathTag:
-			deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...)
-		case libTag:
-			deps.classpath = append(deps.classpath, dep.HeaderJars()...)
-		case staticLibTag:
-			deps.classpath = append(deps.classpath, dep.HeaderJars()...)
-			deps.staticJars = append(deps.staticJars, dep.ImplementationJars()...)
-			deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...)
-		case frameworkResTag:
-			if ctx.ModuleName() == "framework" {
-				// framework.jar has a one-off dependency on the R.java and Manifest.java files
-				// generated by framework-res.apk
-				deps.srcJars = append(deps.srcJars, dep.(*AndroidApp).aaptSrcJar)
-			}
-		case kotlinStdlibTag:
-			deps.kotlinStdlib = dep.HeaderJars()
-		default:
-			panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
-		}
-
-		deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
 	})
 
 	return deps