Merge "Revert "Some clarifications in preparation to automatically order linker dependencies""
diff --git a/Android.bp b/Android.bp
index b8a4f82..ae31a60 100644
--- a/Android.bp
+++ b/Android.bp
@@ -209,6 +209,7 @@
         "java/builder.go",
         "java/gen.go",
         "java/java.go",
+        "java/proto.go",
         "java/resources.go",
     ],
     testSrcs: [
@@ -339,7 +340,7 @@
         linux_bionic: {
             enabled: true,
         },
-        linux: {
+        linux_glibc: {
             enabled: false,
         },
         darwin: {
@@ -360,7 +361,7 @@
         linux_bionic: {
             enabled: true,
         },
-        linux: {
+        linux_glibc: {
             enabled: false,
         },
         darwin: {
diff --git a/android/arch.go b/android/arch.go
index 3fe0345..db017fd 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -87,7 +87,7 @@
         host: {
             // Host variants
         },
-        linux: {
+        linux_glibc: {
             // Linux host variants
         },
         darwin: {
@@ -468,7 +468,7 @@
 		"Android64",
 		"Android32",
 		"Bionic",
-		"Linux",
+		// TODO(dwillemsen): "Linux",
 		"Not_windows",
 		"Arm_on_x86",
 		"Arm_on_x86_64",
@@ -479,7 +479,7 @@
 		for _, archType := range osArchTypeMap[os] {
 			targets = append(targets, os.Field+"_"+archType.Name)
 
-			if os == Linux { // TODO(dwillemsen): os.Linux()
+			if false { // TODO(dwillemsen): os.Linux()
 				target := "Linux_" + archType.Name
 				if !inList(target, targets) {
 					targets = append(targets, target)
@@ -597,10 +597,6 @@
 	arch := a.Arch()
 	os := a.Os()
 
-	if arch.ArchType == Common {
-		return
-	}
-
 	for i := range a.generalProperties {
 		genProps := a.generalProperties[i]
 		if a.archProperties[i] == nil {
@@ -612,6 +608,9 @@
 		multilibProp := archProps.FieldByName("Multilib")
 		targetProp := archProps.FieldByName("Target")
 
+		var field string
+		var prefix string
+
 		// Handle arch-specific properties in the form:
 		// arch: {
 		//     arm64: {
@@ -620,59 +619,61 @@
 		// },
 		t := arch.ArchType
 
-		field := proptools.FieldNameForProperty(t.Name)
-		prefix := "arch." + t.Name
-		archStruct := a.appendProperties(ctx, genProps, archProp, field, prefix)
+		if arch.ArchType != Common {
+			field := proptools.FieldNameForProperty(t.Name)
+			prefix := "arch." + t.Name
+			archStruct := a.appendProperties(ctx, genProps, archProp, field, prefix)
 
-		// Handle arch-variant-specific properties in the form:
-		// arch: {
-		//     variant: {
-		//         key: value,
-		//     },
-		// },
-		v := variantReplacer.Replace(arch.ArchVariant)
-		if v != "" {
-			field := proptools.FieldNameForProperty(v)
-			prefix := "arch." + t.Name + "." + v
-			a.appendProperties(ctx, genProps, archStruct, field, prefix)
-		}
-
-		// Handle cpu-variant-specific properties in the form:
-		// arch: {
-		//     variant: {
-		//         key: value,
-		//     },
-		// },
-		if arch.CpuVariant != arch.ArchVariant {
-			c := variantReplacer.Replace(arch.CpuVariant)
-			if c != "" {
-				field := proptools.FieldNameForProperty(c)
-				prefix := "arch." + t.Name + "." + c
+			// Handle arch-variant-specific properties in the form:
+			// arch: {
+			//     variant: {
+			//         key: value,
+			//     },
+			// },
+			v := variantReplacer.Replace(arch.ArchVariant)
+			if v != "" {
+				field := proptools.FieldNameForProperty(v)
+				prefix := "arch." + t.Name + "." + v
 				a.appendProperties(ctx, genProps, archStruct, field, prefix)
 			}
-		}
 
-		// Handle arch-feature-specific properties in the form:
-		// arch: {
-		//     feature: {
-		//         key: value,
-		//     },
-		// },
-		for _, feature := range arch.ArchFeatures {
-			field := proptools.FieldNameForProperty(feature)
-			prefix := "arch." + t.Name + "." + feature
-			a.appendProperties(ctx, genProps, archStruct, field, prefix)
-		}
+			// Handle cpu-variant-specific properties in the form:
+			// arch: {
+			//     variant: {
+			//         key: value,
+			//     },
+			// },
+			if arch.CpuVariant != arch.ArchVariant {
+				c := variantReplacer.Replace(arch.CpuVariant)
+				if c != "" {
+					field := proptools.FieldNameForProperty(c)
+					prefix := "arch." + t.Name + "." + c
+					a.appendProperties(ctx, genProps, archStruct, field, prefix)
+				}
+			}
 
-		// Handle multilib-specific properties in the form:
-		// multilib: {
-		//     lib32: {
-		//         key: value,
-		//     },
-		// },
-		field = proptools.FieldNameForProperty(t.Multilib)
-		prefix = "multilib." + t.Multilib
-		a.appendProperties(ctx, genProps, multilibProp, field, prefix)
+			// Handle arch-feature-specific properties in the form:
+			// arch: {
+			//     feature: {
+			//         key: value,
+			//     },
+			// },
+			for _, feature := range arch.ArchFeatures {
+				field := proptools.FieldNameForProperty(feature)
+				prefix := "arch." + t.Name + "." + feature
+				a.appendProperties(ctx, genProps, archStruct, field, prefix)
+			}
+
+			// Handle multilib-specific properties in the form:
+			// multilib: {
+			//     lib32: {
+			//         key: value,
+			//     },
+			// },
+			field = proptools.FieldNameForProperty(t.Multilib)
+			prefix = "multilib." + t.Multilib
+			a.appendProperties(ctx, genProps, multilibProp, field, prefix)
+		}
 
 		// Handle host-specific properties in the form:
 		// target: {
@@ -695,14 +696,16 @@
 		//         key: value,
 		//     },
 		// }
-		if os == Linux { // TODO(dwillemsen): os.Linux()
+		if false { // TODO(dwillemsen): os.Linux()
 			field = "Linux"
 			prefix = "target.linux"
 			a.appendProperties(ctx, genProps, targetProp, field, prefix)
 
-			field = "Linux_" + t.Name
-			prefix = "target.linux_" + t.Name
-			a.appendProperties(ctx, genProps, targetProp, field, prefix)
+			if arch.ArchType != Common {
+				field = "Linux_" + arch.ArchType.Name
+				prefix = "target.linux_" + arch.ArchType.Name
+				a.appendProperties(ctx, genProps, targetProp, field, prefix)
+			}
 		}
 
 		if os.Bionic() {
@@ -710,9 +713,11 @@
 			prefix = "target.bionic"
 			a.appendProperties(ctx, genProps, targetProp, field, prefix)
 
-			field = "Bionic_" + t.Name
-			prefix = "target.bionic_" + t.Name
-			a.appendProperties(ctx, genProps, targetProp, field, prefix)
+			if arch.ArchType != Common {
+				field = "Bionic_" + t.Name
+				prefix = "target.bionic_" + t.Name
+				a.appendProperties(ctx, genProps, targetProp, field, prefix)
+			}
 		}
 
 		// Handle target OS properties in the form:
@@ -743,9 +748,11 @@
 		prefix = "target." + os.Name
 		a.appendProperties(ctx, genProps, targetProp, field, prefix)
 
-		field = os.Field + "_" + t.Name
-		prefix = "target." + os.Name + "_" + t.Name
-		a.appendProperties(ctx, genProps, targetProp, field, prefix)
+		if arch.ArchType != Common {
+			field = os.Field + "_" + t.Name
+			prefix = "target." + os.Name + "_" + t.Name
+			a.appendProperties(ctx, genProps, targetProp, field, prefix)
+		}
 
 		if (os.Class == Host || os.Class == HostCross) && os != Windows {
 			field := "Not_windows"
diff --git a/android/paths.go b/android/paths.go
index 4a49d55..69a7b0d 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -247,6 +247,9 @@
 // each string.
 func pathsForModuleSrcFromFullPath(ctx ModuleContext, paths []string) Paths {
 	prefix := filepath.Join(ctx.AConfig().srcDir, ctx.ModuleDir()) + "/"
+	if prefix == "./" {
+		prefix = ""
+	}
 	ret := make(Paths, 0, len(paths))
 	for _, p := range paths {
 		path := filepath.Clean(p)
diff --git a/android/proto.go b/android/proto.go
index 9bb9cfb..1c70656 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -14,22 +14,6 @@
 
 package android
 
-import (
-	"github.com/google/blueprint"
-)
-
-func init() {
-	pctx.HostBinToolVariable("protocCmd", "aprotoc")
-}
-
-var (
-	proto = pctx.AndroidStaticRule("protoc",
-		blueprint.RuleParams{
-			Command:     "$protocCmd $protoOut=$protoOutFlags:$outDir $protoFlags $in",
-			CommandDeps: []string{"$protocCmd"},
-		}, "protoFlags", "protoOut", "protoOutFlags", "outDir")
-)
-
 // TODO(ccross): protos are often used to communicate between multiple modules.  If the only
 // way to convert a proto to source is to reference it as a source file, and external modules cannot
 // reference source files in other modules, then every module that owns a proto file will need to
@@ -38,30 +22,6 @@
 // and then external modules could depend on the proto module but use their own settings to
 // generate the source.
 
-func GenProto(ctx ModuleContext, protoFile Path,
-	protoFlags string, protoOut, protoOutFlags string, extensions []string) WritablePaths {
-
-	var outFiles WritablePaths
-	for _, ext := range extensions {
-		outFiles = append(outFiles, GenPathWithExt(ctx, "proto", protoFile, ext))
-	}
-
-	ctx.ModuleBuild(pctx, ModuleBuildParams{
-		Rule:        proto,
-		Description: "protoc " + protoFile.Rel(),
-		Outputs:     outFiles,
-		Input:       protoFile,
-		Args: map[string]string{
-			"outDir":        ProtoDir(ctx).String(),
-			"protoOut":      protoOut,
-			"protoOutFlags": protoOutFlags,
-			"protoFlags":    protoFlags,
-		},
-	})
-
-	return outFiles
-}
-
 func ProtoFlags(ctx ModuleContext, p *ProtoProperties) []string {
 	var protoFlags []string
 	if len(p.Proto.Local_include_dirs) > 0 {
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index 469e960..f5858a7 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -107,7 +107,7 @@
 			"LOCAL_RENDERSCRIPT_INCLUDES": "renderscript.include_dirs",
 			"LOCAL_RENDERSCRIPT_FLAGS":    "renderscript.flags",
 
-			"LOCAL_JAVA_RESOURCE_DIRS":    "resource_dirs",
+			"LOCAL_JAVA_RESOURCE_DIRS":    "java_resource_dirs",
 			"LOCAL_JAVACFLAGS":            "javacflags",
 			"LOCAL_DX_FLAGS":              "dxflags",
 			"LOCAL_JAVA_LIBRARIES":        "libs",
@@ -357,7 +357,7 @@
 	}
 
 	if !inList("linux") && err == nil {
-		err = setVariable(ctx.file, ctx.append, "target.linux", "enabled", falseValue, true)
+		err = setVariable(ctx.file, ctx.append, "target.linux_glibc", "enabled", falseValue, true)
 	}
 
 	if !inList("darwin") && err == nil {
@@ -609,7 +609,7 @@
 	// 64 must be after x86_64
 	{"64", "multilib.lib64"},
 	{"darwin", "target.darwin"},
-	{"linux", "target.linux"},
+	{"linux", "target.linux_glibc"},
 	{"windows", "target.windows"},
 }
 
@@ -627,11 +627,11 @@
 		true:  "target.windows",
 		false: "target.not_windows"},
 	"($(HOST_OS),linux)": {
-		true:  "target.linux",
-		false: "target.not_linux"},
+		true:  "target.linux_glibc",
+		false: "target.not_linux_glibc"},
 	"($(HOST_OS), linux)": {
-		true:  "target.linux",
-		false: "target.not_linux"},
+		true:  "target.linux_glibc",
+		false: "target.not_linux_glibc"},
 	"($(BUILD_OS),darwin)": {
 		true:  "target.darwin",
 		false: "target.not_darwin"},
@@ -639,11 +639,11 @@
 		true:  "target.darwin",
 		false: "target.not_darwin"},
 	"($(BUILD_OS),linux)": {
-		true:  "target.linux",
-		false: "target.not_linux"},
+		true:  "target.linux_glibc",
+		false: "target.not_linux_glibc"},
 	"($(BUILD_OS), linux)": {
-		true:  "target.linux",
-		false: "target.not_linux"},
+		true:  "target.linux_glibc",
+		false: "target.not_linux_glibc"},
 	"(,$(TARGET_BUILD_APPS))": {
 		false: "product_variables.unbundled_build"},
 	"($(TARGET_BUILD_PDK),true)": {
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index 664d12c..4681a7d 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -256,7 +256,7 @@
         darwin: {
             srcs: ["darwin.c"],
         },
-        linux: {
+        linux_glibc: {
             srcs: ["linux.c"],
         },
         windows: {
diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go
index 103f91f..3f079a4 100644
--- a/cc/config/x86_darwin_host.go
+++ b/cc/config/x86_darwin_host.go
@@ -100,7 +100,6 @@
 			"ncurses",
 			"objc",
 			"pthread",
-			"z",
 		}, "-l"),
 		"-framework AppKit",
 		"-framework CoreFoundation",
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 80e9289..75416bd 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -123,7 +123,6 @@
 		"resolv",
 		"rt",
 		"util",
-		"z",
 	}, "-l")
 )
 
diff --git a/cc/gen.go b/cc/gen.go
index 9fc14c5..2280e0f 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -153,10 +153,9 @@
 			srcFiles[i] = cppFile
 			genLex(ctx, srcFile, cppFile)
 		case ".proto":
-			protoFiles := android.GenProto(ctx, srcFile, buildFlags.protoFlags,
-				"--cpp_out", "", []string{"pb.cc", "pb.h"})
-			srcFiles[i] = protoFiles[0]
-			deps = append(deps, protoFiles[1])
+			ccFile, headerFile := genProto(ctx, srcFile, buildFlags.protoFlags)
+			srcFiles[i] = ccFile
+			deps = append(deps, headerFile)
 		case ".aidl":
 			cppFile := android.GenPathWithExt(ctx, "aidl", srcFile, "cpp")
 			srcFiles[i] = cppFile
diff --git a/cc/pgo.go b/cc/pgo.go
index ccddece..f9c8bbf 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -24,7 +24,7 @@
 var (
 	// Add flags to ignore warnings that profiles are old or missing for
 	// some functions
-	profileUseOtherFlags = []string{}
+	profileUseOtherFlags = []string{"-Wno-backend-plugin"}
 )
 
 const pgoProfileProject = "toolchain/pgo-profiles"
diff --git a/cc/proto.go b/cc/proto.go
index 6049d44..a01951f 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -15,11 +15,46 @@
 package cc
 
 import (
+	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
 )
 
+func init() {
+	pctx.HostBinToolVariable("protocCmd", "aprotoc")
+}
+
+var (
+	proto = pctx.AndroidStaticRule("protoc",
+		blueprint.RuleParams{
+			Command:     "$protocCmd --cpp_out=$outDir $protoFlags $in",
+			CommandDeps: []string{"$protocCmd"},
+		}, "protoFlags", "outDir")
+)
+
+// genProto creates a rule to convert a .proto file to generated .pb.cc and .pb.h files and returns
+// the paths to the generated files.
+func genProto(ctx android.ModuleContext, protoFile android.Path,
+	protoFlags string) (ccFile, headerFile android.WritablePath) {
+
+	ccFile = android.GenPathWithExt(ctx, "proto", protoFile, "pb.cc")
+	headerFile = android.GenPathWithExt(ctx, "proto", protoFile, "pb.h")
+
+	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+		Rule:        proto,
+		Description: "protoc " + protoFile.Rel(),
+		Outputs:     android.WritablePaths{ccFile, headerFile},
+		Input:       protoFile,
+		Args: map[string]string{
+			"outDir":     android.ProtoDir(ctx).String(),
+			"protoFlags": protoFlags,
+		},
+	})
+
+	return ccFile, headerFile
+}
+
 func protoDeps(ctx BaseModuleContext, deps Deps, p *android.ProtoProperties, static bool) Deps {
 	var lib string
 
diff --git a/jar/jar.go b/jar/jar.go
index f17bc98..08fa1ab 100644
--- a/jar/jar.go
+++ b/jar/jar.go
@@ -94,6 +94,8 @@
 		Method:             zip.Store,
 		UncompressedSize64: uint64(len(b)),
 	}
+	fh.SetMode(0700)
+	fh.SetModTime(DefaultTime)
 
 	return fh, b, nil
 }
diff --git a/java/app.go b/java/app.go
index 80d62fd..e40478a 100644
--- a/java/app.go
+++ b/java/app.go
@@ -53,8 +53,8 @@
 	Asset_dirs []string
 
 	// list of directories relative to the Blueprints file containing
-	// Java resources
-	Android_resource_dirs []string
+	// Android resources
+	Resource_dirs []string
 }
 
 type AndroidApp struct {
@@ -183,7 +183,7 @@
 	}
 
 	assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Asset_dirs, "assets")
-	resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Android_resource_dirs, "res")
+	resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Resource_dirs, "res")
 
 	var overlayResourceDirs android.Paths
 	// For every resource directory, check if there is an overlay directory with the same path.
diff --git a/java/builder.go b/java/builder.go
index b8332ad..b924d65 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -127,14 +127,9 @@
 	desugarFlags  string
 	aidlFlags     string
 	javaVersion   string
-}
 
-type jarSpec struct {
-	fileList, dir android.Path
-}
-
-func (j jarSpec) soongJarArgs() string {
-	return "-C " + j.dir.String() + " -l " + j.fileList.String()
+	protoFlags   string
+	protoOutFlag string
 }
 
 func TransformJavaToClasses(ctx android.ModuleContext, srcFiles, srcFileLists android.Paths,
@@ -144,7 +139,10 @@
 	annoDir := android.PathForModuleOut(ctx, "anno")
 	classJar := android.PathForModuleOut(ctx, "classes-compiled.jar")
 
-	javacFlags := flags.javacFlags + android.JoinWithPrefix(srcFileLists.Strings(), "@")
+	javacFlags := flags.javacFlags
+	if len(srcFileLists) > 0 {
+		javacFlags += " " + android.JoinWithPrefix(srcFileLists.Strings(), "@")
+	}
 
 	deps = append(deps, srcFileLists...)
 	deps = append(deps, flags.bootClasspath...)
@@ -169,8 +167,8 @@
 	return classJar
 }
 
-func RunErrorProne(ctx android.ModuleContext, srcFiles android.Paths, srcFileLists android.Paths,
-	flags javaBuilderFlags, deps android.Paths) android.Path {
+func RunErrorProne(ctx android.ModuleContext, srcFiles, srcFileLists android.Paths,
+	flags javaBuilderFlags) android.Path {
 
 	if config.ErrorProneJar == "" {
 		ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
@@ -181,7 +179,12 @@
 	annoDir := android.PathForModuleOut(ctx, "anno-errorprone")
 	classFileList := android.PathForModuleOut(ctx, "classes-errorprone.list")
 
-	javacFlags := flags.javacFlags + android.JoinWithPrefix(srcFileLists.Strings(), "@")
+	javacFlags := flags.javacFlags
+	if len(srcFileLists) > 0 {
+		javacFlags += " " + android.JoinWithPrefix(srcFileLists.Strings(), "@")
+	}
+
+	var deps android.Paths
 
 	deps = append(deps, srcFileLists...)
 	deps = append(deps, flags.bootClasspath...)
@@ -206,18 +209,11 @@
 	return classFileList
 }
 
-func TransformResourcesToJar(ctx android.ModuleContext, resources []jarSpec,
+func TransformResourcesToJar(ctx android.ModuleContext, jarArgs []string,
 	deps android.Paths) android.Path {
 
 	outputFile := android.PathForModuleOut(ctx, "res.jar")
 
-	jarArgs := []string{}
-
-	for _, j := range resources {
-		deps = append(deps, j.fileList)
-		jarArgs = append(jarArgs, j.soongJarArgs())
-	}
-
 	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
 		Rule:        jar,
 		Description: "jar",
diff --git a/java/gen.go b/java/gen.go
index e473859..e55be91 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -85,21 +85,37 @@
 }
 
 func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths,
-	flags javaBuilderFlags) android.Paths {
+	flags javaBuilderFlags) (android.Paths, android.Paths) {
 
-	for i, srcFile := range srcFiles {
+	var protoFiles android.Paths
+	outSrcFiles := make(android.Paths, 0, len(srcFiles))
+
+	for _, srcFile := range srcFiles {
 		switch srcFile.Ext() {
 		case ".aidl":
 			javaFile := genAidl(ctx, srcFile, flags.aidlFlags)
-			srcFiles[i] = javaFile
+			outSrcFiles = append(outSrcFiles, javaFile)
 		case ".logtags":
 			j.logtagsSrcs = append(j.logtagsSrcs, srcFile)
 			javaFile := genLogtags(ctx, srcFile)
-			srcFiles[i] = javaFile
+			outSrcFiles = append(outSrcFiles, javaFile)
+		case ".proto":
+			protoFiles = append(protoFiles, srcFile)
+		default:
+			outSrcFiles = append(outSrcFiles, srcFile)
 		}
 	}
 
-	return srcFiles
+	var outSrcFileLists android.Paths
+
+	if len(protoFiles) > 0 {
+		protoFileList := genProto(ctx, protoFiles,
+			flags.protoFlags, flags.protoOutFlag, "")
+
+		outSrcFileLists = append(outSrcFileLists, protoFileList)
+	}
+
+	return outSrcFiles, outSrcFileLists
 }
 
 func LogtagsSingleton() blueprint.Singleton {
diff --git a/java/java.go b/java/java.go
index 5e063a5..9cde824 100644
--- a/java/java.go
+++ b/java/java.go
@@ -35,8 +35,8 @@
 func init() {
 	android.RegisterModuleType("java_defaults", defaultsFactory)
 
-	android.RegisterModuleType("java_library", LibraryFactory)
-	android.RegisterModuleType("java_library_static", LibraryFactory)
+	android.RegisterModuleType("java_library", LibraryFactory(true))
+	android.RegisterModuleType("java_library_static", LibraryFactory(false))
 	android.RegisterModuleType("java_library_host", LibraryHostFactory)
 	android.RegisterModuleType("java_binary", BinaryFactory)
 	android.RegisterModuleType("java_binary_host", BinaryHostFactory)
@@ -49,7 +49,6 @@
 
 // TODO:
 // Autogenerated files:
-//  Proto
 //  Renderscript
 // Post-jar passes:
 //  Proguard
@@ -70,15 +69,25 @@
 	Exclude_srcs []string `android:"arch_variant"`
 
 	// list of directories containing Java resources
-	Resource_dirs []string `android:"arch_variant"`
+	Java_resource_dirs []string `android:"arch_variant"`
 
-	// list of directories that should be excluded from resource_dirs
-	Exclude_resource_dirs []string `android:"arch_variant"`
+	// list of directories that should be excluded from java_resource_dirs
+	Exclude_java_resource_dirs []string `android:"arch_variant"`
 
-	// don't build against the default libraries (legacy-test, core-junit,
+	// list of files to use as Java resources
+	Java_resources []string `android:"arch_variant"`
+
+	// list of files that should be excluded from java_resources
+	Exclude_java_resources []string `android:"arch_variant"`
+
+	// don't build against the default libraries (bootclasspath, legacy-test, core-junit,
 	// ext, and framework for device targets)
 	No_standard_libs *bool
 
+	// don't build against the framework libraries (legacy-test, core-junit,
+	// ext, and framework for device targets)
+	No_framework_libs *bool
+
 	// list of module-specific flags that will be used for javac compiles
 	Javacflags []string `android:"arch_variant"`
 
@@ -100,6 +109,9 @@
 	// If set to false, don't allow this module to be installed.  Defaults to true.
 	Installable *bool
 
+	// If set to true, include sources used to compile the module in to the final jar
+	Include_srcs *bool
+
 	// List of modules to use as annotation processors
 	Annotation_processors []string
 
@@ -132,6 +144,7 @@
 	android.DefaultableModuleBase
 
 	properties       CompilerProperties
+	protoProperties  android.ProtoProperties
 	deviceProperties CompilerDeviceProperties
 
 	// output file suitable for inserting into the classpath of another compile
@@ -182,10 +195,11 @@
 )
 
 type sdkDep struct {
-	useModule, useFiles, useDefaultLibs bool
-	module                              string
-	jar                                 android.Path
-	aidl                                android.Path
+	useModule, useFiles, useDefaultLibs, invalidVersion bool
+
+	module string
+	jar    android.Path
+	aidl   android.Path
 }
 
 func decodeSdkDep(ctx android.BaseContext, v string) sdkDep {
@@ -205,14 +219,24 @@
 		aidl := filepath.Join(dir, "framework.aidl")
 		jarPath := android.ExistentPathForSource(ctx, "sdkdir", jar)
 		aidlPath := android.ExistentPathForSource(ctx, "sdkdir", aidl)
+
+		if (!jarPath.Valid() || !aidlPath.Valid()) && ctx.AConfig().AllowMissingDependencies() {
+			return sdkDep{
+				invalidVersion: true,
+				module:         "sdk_v" + v,
+			}
+		}
+
 		if !jarPath.Valid() {
 			ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, jar)
 			return sdkDep{}
 		}
+
 		if !aidlPath.Valid() {
 			ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, aidl)
 			return sdkDep{}
 		}
+
 		return sdkDep{
 			useFiles: true,
 			jar:      jarPath.Path(),
@@ -227,13 +251,7 @@
 		}
 	}
 
-	if ctx.AConfig().UnbundledBuild() {
-		if v == "" {
-			if ctx, ok := ctx.(android.ModuleContext); ok {
-				ctx.AddMissingDependencies([]string{"sdk_version_must_be_set_for_modules_used_in_unbundled_builds"})
-			}
-			return sdkDep{}
-		}
+	if ctx.AConfig().UnbundledBuild() && v != "" {
 		return toFile(v)
 	}
 
@@ -259,15 +277,15 @@
 			sdkDep := decodeSdkDep(ctx, j.deviceProperties.Sdk_version)
 			if sdkDep.useDefaultLibs {
 				ctx.AddDependency(ctx.Module(), bootClasspathTag, config.DefaultBootclasspathLibraries...)
-				ctx.AddDependency(ctx.Module(), libTag, config.DefaultLibraries...)
+				if !proptools.Bool(j.properties.No_framework_libs) {
+					ctx.AddDependency(ctx.Module(), libTag, config.DefaultLibraries...)
+				}
 			}
 			if sdkDep.useModule {
 				ctx.AddDependency(ctx.Module(), bootClasspathTag, sdkDep.module)
 			}
 		} else {
-			if j.deviceProperties.Dex {
-				ctx.AddDependency(ctx.Module(), bootClasspathTag, config.DefaultBootclasspathLibraries...)
-			}
+			// TODO(ccross): add hostdex support
 		}
 	}
 	ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
@@ -275,6 +293,25 @@
 	ctx.AddDependency(ctx.Module(), libTag, j.properties.Annotation_processors...)
 
 	android.ExtractSourcesDeps(ctx, j.properties.Srcs)
+	android.ExtractSourcesDeps(ctx, j.properties.Java_resources)
+
+	if j.hasSrcExt(".proto") {
+		protoDeps(ctx, &j.protoProperties)
+	}
+}
+
+func hasSrcExt(srcs []string, ext string) bool {
+	for _, src := range srcs {
+		if filepath.Ext(src) == ext {
+			return true
+		}
+	}
+
+	return false
+}
+
+func (j *Module) hasSrcExt(ext string) bool {
+	return hasSrcExt(j.properties.Srcs, ext)
 }
 
 func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath,
@@ -313,7 +350,9 @@
 	var deps deps
 
 	sdkDep := decodeSdkDep(ctx, j.deviceProperties.Sdk_version)
-	if sdkDep.useFiles {
+	if sdkDep.invalidVersion {
+		ctx.AddMissingDependencies([]string{sdkDep.module})
+	} else if sdkDep.useFiles {
 		deps.classpath = append(deps.classpath, sdkDep.jar)
 		deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, sdkDep.aidl)
 	}
@@ -377,8 +416,6 @@
 		flags.javaVersion = "${config.DefaultJavaVersion}"
 	}
 
-	var extraDeps android.Paths
-
 	flags.bootClasspath.AddPaths(deps.bootClasspath)
 	flags.classpath.AddPaths(deps.classpath)
 
@@ -395,7 +432,15 @@
 
 	srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs)
 
-	srcFiles = j.genSources(ctx, srcFiles, flags)
+	if hasSrcExt(srcFiles.Strings(), ".proto") {
+		flags = protoFlags(ctx, &j.protoProperties, flags)
+	}
+
+	var srcFileLists android.Paths
+
+	srcFiles, srcFileLists = j.genSources(ctx, srcFiles, flags)
+
+	srcFileLists = append(srcFileLists, deps.srcFileLists...)
 
 	ctx.VisitDirectDeps(func(module blueprint.Module) {
 		if gen, ok := module.(genrule.SourceFileGenerator); ok {
@@ -403,37 +448,52 @@
 		}
 	})
 
-	deps.srcFileLists = append(deps.srcFileLists, j.ExtraSrcLists...)
-
-	var extraJarDeps android.Paths
+	srcFileLists = append(srcFileLists, j.ExtraSrcLists...)
 
 	var jars android.Paths
 
 	if len(srcFiles) > 0 {
-		// Compile java sources into .class files
-		classes := TransformJavaToClasses(ctx, srcFiles, deps.srcFileLists, flags, extraDeps)
-		if ctx.Failed() {
-			return
-		}
-
+		var extraJarDeps android.Paths
 		if ctx.AConfig().IsEnvTrue("RUN_ERROR_PRONE") {
 			// If error-prone is enabled, add an additional rule to compile the java files into
 			// a separate set of classes (so that they don't overwrite the normal ones and require
-			// a rebuild when error-prone is turned off).  Add the classes as a dependency to
-			// the jar command so the two compiles can run in parallel.
+			// a rebuild when error-prone is turned off).
 			// TODO(ccross): Once we always compile with javac9 we may be able to conditionally
 			//    enable error-prone without affecting the output class files.
-			errorprone := RunErrorProne(ctx, srcFiles, deps.srcFileLists, flags, extraDeps)
+			errorprone := RunErrorProne(ctx, srcFiles, srcFileLists, flags)
 			extraJarDeps = append(extraJarDeps, errorprone)
 		}
 
+		// Compile java sources into .class files
+		classes := TransformJavaToClasses(ctx, srcFiles, srcFileLists, flags, extraJarDeps)
+		if ctx.Failed() {
+			return
+		}
+
 		jars = append(jars, classes)
 	}
 
-	resourceJarSpecs := ResourceDirsToJarSpecs(ctx, j.properties.Resource_dirs, j.properties.Exclude_resource_dirs)
-	if len(resourceJarSpecs) > 0 {
+	dirArgs, dirDeps := ResourceDirsToJarArgs(ctx, j.properties.Java_resource_dirs, j.properties.Exclude_java_resource_dirs)
+	fileArgs, fileDeps := ResourceFilesToJarArgs(ctx, j.properties.Java_resources, j.properties.Exclude_java_resources)
+
+	var resArgs []string
+	var resDeps android.Paths
+
+	resArgs = append(resArgs, dirArgs...)
+	resDeps = append(resDeps, dirDeps...)
+
+	resArgs = append(resArgs, fileArgs...)
+	resDeps = append(resDeps, fileDeps...)
+
+	if proptools.Bool(j.properties.Include_srcs) {
+		srcArgs, srcDeps := ResourceFilesToJarArgs(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
+		resArgs = append(resArgs, srcArgs...)
+		resDeps = append(resDeps, srcDeps...)
+	}
+
+	if len(resArgs) > 0 {
 		// Combine classes + resources into classes-full-debug.jar
-		resourceJar := TransformResourcesToJar(ctx, resourceJarSpecs, extraJarDeps)
+		resourceJar := TransformResourcesToJar(ctx, resArgs, resDeps)
 		if ctx.Failed() {
 			return
 		}
@@ -452,12 +512,12 @@
 	manifest := android.OptionalPathForModuleSrc(ctx, j.properties.Manifest)
 
 	// 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.
+	// classes.jar.  If there is only one input jar this step will be skipped.
 	outputFile := TransformJarsToJar(ctx, "classes.jar", jars, manifest, false)
 
 	if j.properties.Jarjar_rules != nil {
 		jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
-		// Transform classes-combined.jar into classes-jarjar.jar
+		// Transform classes.jar into classes-jarjar.jar
 		outputFile = TransformJarJar(ctx, outputFile, jarjar_rules)
 		if ctx.Failed() {
 			return
@@ -467,7 +527,7 @@
 	j.classpathFile = outputFile
 
 	// TODO(ccross): handle hostdex
-	if ctx.Device() && len(srcFiles) > 0 {
+	if ctx.Device() && j.installable() {
 		dxFlags := j.deviceProperties.Dxflags
 		if false /* emma enabled */ {
 			// If you instrument class files that have local variable debug information in
@@ -520,10 +580,6 @@
 			return
 		}
 
-		// TODO(ccross): For now, use the desugared jar as the classpath file.  Eventually this
-		// might cause problems because desugar wants non-desugared jars in its class path.
-		j.classpathFile = desugarJar
-
 		// Compile classes.jar into classes.dex
 		dexJarFile := TransformClassesJarToDexJar(ctx, desugarJar, flags)
 		if ctx.Failed() {
@@ -541,6 +597,10 @@
 	j.outputFile = outputFile
 }
 
+func (j *Module) installable() bool {
+	return j.properties.Installable == nil || *j.properties.Installable
+}
+
 var _ Dependency = (*Library)(nil)
 
 func (j *Module) ClasspathFiles() android.Paths {
@@ -572,7 +632,7 @@
 func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	j.compile(ctx)
 
-	if j.properties.Installable == nil || *j.properties.Installable == true {
+	if j.installable() {
 		j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
 			ctx.ModuleName()+".jar", j.outputFile)
 	}
@@ -582,23 +642,31 @@
 	j.deps(ctx)
 }
 
-func LibraryFactory() android.Module {
-	module := &Library{}
+func LibraryFactory(installable bool) func() android.Module {
+	return func() android.Module {
+		module := &Library{}
 
-	module.deviceProperties.Dex = true
+		if !installable {
+			module.properties.Installable = proptools.BoolPtr(false)
+		}
+		module.deviceProperties.Dex = true
 
-	module.AddProperties(
-		&module.Module.properties,
-		&module.Module.deviceProperties)
+		module.AddProperties(
+			&module.Module.properties,
+			&module.Module.deviceProperties,
+			&module.Module.protoProperties)
 
-	InitJavaModule(module, android.HostAndDeviceSupported)
-	return module
+		InitJavaModule(module, android.HostAndDeviceSupported)
+		return module
+	}
 }
 
 func LibraryHostFactory() android.Module {
 	module := &Library{}
 
-	module.AddProperties(&module.Module.properties)
+	module.AddProperties(
+		&module.Module.properties,
+		&module.Module.protoProperties)
 
 	InitJavaModule(module, android.HostSupported)
 	return module
@@ -644,6 +712,7 @@
 	module.AddProperties(
 		&module.Module.properties,
 		&module.Module.deviceProperties,
+		&module.Module.protoProperties,
 		&module.binaryProperties)
 
 	InitJavaModule(module, android.HostAndDeviceSupported)
@@ -656,6 +725,7 @@
 	module.AddProperties(
 		&module.Module.properties,
 		&module.Module.deviceProperties,
+		&module.Module.protoProperties,
 		&module.binaryProperties)
 
 	InitJavaModule(module, android.HostSupported)
diff --git a/java/java_test.go b/java/java_test.go
index 7159e3f..a4a3f52 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/genrule"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -55,10 +56,11 @@
 
 	ctx := android.NewTestArchContext()
 	ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(AndroidAppFactory))
-	ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(LibraryFactory))
+	ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(LibraryFactory(true)))
 	ctx.RegisterModuleType("java_library_host", android.ModuleFactoryAdaptor(LibraryHostFactory))
 	ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(ImportFactory))
 	ctx.RegisterModuleType("java_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
+	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(genrule.FileGroupFactory))
 	ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
 	ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
@@ -92,6 +94,10 @@
 		"c.java":     nil,
 		"a.jar":      nil,
 		"b.jar":      nil,
+		"res/a":      nil,
+		"res/b":      nil,
+		"res2/a":     nil,
+
 		"prebuilts/sdk/14/android.jar":    nil,
 		"prebuilts/sdk/14/framework.aidl": nil,
 	})
@@ -111,7 +117,7 @@
 	case strings.HasSuffix(name, ".jar"):
 		return name
 	default:
-		return filepath.Join(buildDir, ".intermediates", name, "android_common", "classes-desugar.jar")
+		return filepath.Join(buildDir, ".intermediates", name, "android_common", "classes-compiled.jar")
 	}
 }
 
@@ -133,7 +139,7 @@
 			name: "baz",
 			srcs: ["c.java"],
 		}
-		`)
+	`)
 
 	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
 	combineJar := ctx.ModuleForTests("foo", "android_common").Rule("combineJar")
@@ -142,8 +148,8 @@
 		t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
 	}
 
-	bar := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "classes-desugar.jar")
-	baz := filepath.Join(buildDir, ".intermediates", "baz", "android_common", "classes-desugar.jar")
+	bar := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "classes-compiled.jar")
+	baz := filepath.Join(buildDir, ".intermediates", "baz", "android_common", "classes-compiled.jar")
 
 	if !strings.Contains(javac.Args["classpath"], bar) {
 		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], bar)
@@ -158,8 +164,28 @@
 	}
 }
 
+func TestArchSpecific(t *testing.T) {
+	ctx := testJava(t, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+			target: {
+				android: {
+					srcs: ["b.java"],
+				},
+			},
+		}
+	`)
+
+	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
+	if len(javac.Inputs) != 2 || javac.Inputs[0].String() != "a.java" || javac.Inputs[1].String() != "b.java" {
+		t.Errorf(`foo inputs %v != ["a.java", "b.java"]`, javac.Inputs)
+	}
+}
+
 var classpathTestcases = []struct {
 	name          string
+	moduleType    string
 	host          android.OsClass
 	properties    string
 	bootclasspath []string
@@ -214,27 +240,41 @@
 	{
 
 		name:       "host default",
-		host:       android.Host,
+		moduleType: "java_library_host",
 		properties: ``,
+		host:       android.Host,
 		classpath:  []string{},
 	},
 	{
 		name:       "host nostdlib",
+		moduleType: "java_library_host",
 		host:       android.Host,
 		properties: `no_standard_libs: true`,
 		classpath:  []string{},
 	},
+	{
+
+		name:       "host supported default",
+		host:       android.Host,
+		properties: `host_supported: true,`,
+		classpath:  []string{},
+	},
+	{
+		name:       "host supported nostdlib",
+		host:       android.Host,
+		properties: `host_supported: true, no_standard_libs: true`,
+		classpath:  []string{},
+	},
 }
 
 func TestClasspath(t *testing.T) {
 	for _, testcase := range classpathTestcases {
 		t.Run(testcase.name, func(t *testing.T) {
-			hostExtra := ""
-			if testcase.host == android.Host {
-				hostExtra = "_host"
+			moduleType := "java_library"
+			if testcase.moduleType != "" {
+				moduleType = testcase.moduleType
 			}
-			ctx := testJava(t, `
-			java_library`+hostExtra+` {
+			ctx := testJava(t, moduleType+` {
 				name: "foo",
 				srcs: ["a.java"],
 				`+testcase.properties+`
@@ -349,17 +389,123 @@
 		t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
 	}
 
-	bar := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "classes-desugar.jar")
+	bar := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "classes-compiled.jar")
 	if !strings.Contains(javac.Args["classpath"], bar) {
 		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], bar)
 	}
 
-	baz := filepath.Join(buildDir, ".intermediates", "baz", "android_common", "classes-desugar.jar")
+	baz := filepath.Join(buildDir, ".intermediates", "baz", "android_common", "classes-compiled.jar")
 	if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
 		t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
 	}
 }
 
+func TestResources(t *testing.T) {
+	var table = []struct {
+		name  string
+		prop  string
+		extra string
+		args  string
+	}{
+		{
+			// Test that a module with java_resource_dirs includes a file list file
+			name: "resource dirs",
+			prop: `java_resource_dirs: ["res"]`,
+			args: "-C res -l ",
+		},
+		{
+			// Test that a module with java_resources includes the files
+			name: "resource files",
+			prop: `java_resources: ["res/a", "res/b"]`,
+			args: "-C . -f res/a -C . -f res/b",
+		},
+		{
+			// Test that a module with a filegroup in java_resources includes the files with the
+			// path prefix
+			name: "resource filegroup",
+			prop: `java_resources: [":foo-res"]`,
+			extra: `
+				filegroup {
+					name: "foo-res",
+					path: "res",
+					srcs: ["res/a", "res/b"],
+				}`,
+			args: "-C res -f res/a -C res -f res/b",
+		},
+		{
+			// Test that a module with "include_srcs: true" includes its source files in the resources jar
+			name: "include sources",
+			prop: `include_srcs: true`,
+			args: "-C . -f a.java -C . -f b.java -C . -f c.java",
+		},
+	}
+
+	for _, test := range table {
+		t.Run(test.name, func(t *testing.T) {
+			ctx := testJava(t, `
+				java_library {
+					name: "foo",
+					srcs: [
+						"a.java",
+						"b.java",
+						"c.java",
+					],
+					`+test.prop+`,
+				}
+			`+test.extra)
+
+			foo := ctx.ModuleForTests("foo", "android_common").Output("classes.jar")
+			fooRes := ctx.ModuleForTests("foo", "android_common").Output("res.jar")
+
+			if !inList(fooRes.Output.String(), foo.Inputs.Strings()) {
+				t.Errorf("foo combined jars %v does not contain %q",
+					foo.Inputs.Strings(), fooRes.Output.String())
+			}
+
+			if !strings.Contains(fooRes.Args["jarArgs"], test.args) {
+				t.Errorf("foo resource jar args %q does not contain %q",
+					fooRes.Args["jarArgs"], test.args)
+			}
+		})
+	}
+}
+
+func TestExcludeResources(t *testing.T) {
+	ctx := testJava(t, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+			java_resource_dirs: ["res", "res2"],
+			exclude_java_resource_dirs: ["res2"],
+		}
+
+		java_library {
+			name: "bar",
+			srcs: ["a.java"],
+			java_resources: ["res/*"],
+			exclude_java_resources: ["res/b"],
+		}
+	`)
+
+	fooRes := ctx.ModuleForTests("foo", "android_common").Output("res.jar")
+
+	expected := "-C res -l " + fooRes.Implicits[0].String()
+	if fooRes.Args["jarArgs"] != expected {
+		t.Errorf("foo resource jar args %q is not %q",
+			fooRes.Args["jarArgs"], expected)
+
+	}
+
+	barRes := ctx.ModuleForTests("bar", "android_common").Output("res.jar")
+
+	expected = "-C . -f res/a"
+	if barRes.Args["jarArgs"] != expected {
+		t.Errorf("bar resource jar args %q is not %q",
+			barRes.Args["jarArgs"], expected)
+
+	}
+}
+
 func fail(t *testing.T, errs []error) {
 	if len(errs) > 0 {
 		for _, err := range errs {
diff --git a/java/proto.go b/java/proto.go
new file mode 100644
index 0000000..324868a
--- /dev/null
+++ b/java/proto.go
@@ -0,0 +1,98 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
+
+	"android/soong/android"
+)
+
+func init() {
+	pctx.HostBinToolVariable("protocCmd", "aprotoc")
+}
+
+var (
+	proto = pctx.AndroidStaticRule("protoc",
+		blueprint.RuleParams{
+			Command: `rm -rf $outDir && mkdir -p $outDir && ` +
+				`$protocCmd $protoOut=$protoOutFlags:$outDir $protoFlags $in && ` +
+				`find $outDir -name "*.java" > $out`,
+			CommandDeps: []string{"$protocCmd"},
+		}, "protoFlags", "protoOut", "protoOutFlags", "outDir")
+)
+
+func genProto(ctx android.ModuleContext, protoFiles android.Paths,
+	protoFlags string, protoOut, protoOutFlags string) android.WritablePath {
+
+	protoFileList := android.PathForModuleGen(ctx, "proto.filelist")
+
+	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+		Rule:        proto,
+		Description: "protoc " + protoFiles[0].Rel(),
+		Output:      protoFileList,
+		Inputs:      protoFiles,
+		Args: map[string]string{
+			"outDir":        android.ProtoDir(ctx).String(),
+			"protoOut":      protoOut,
+			"protoOutFlags": protoOutFlags,
+			"protoFlags":    protoFlags,
+		},
+	})
+
+	return protoFileList
+}
+
+func protoDeps(ctx android.BottomUpMutatorContext, p *android.ProtoProperties) {
+	switch proptools.String(p.Proto.Type) {
+	case "micro":
+		ctx.AddDependency(ctx.Module(), staticLibTag, "libprotobuf-java-micro")
+	case "nano":
+		ctx.AddDependency(ctx.Module(), staticLibTag, "libprotobuf-java-nano")
+	case "stream":
+		// TODO(ccross): add dependency on protoc-gen-java-stream binary
+		ctx.PropertyErrorf("proto.type", `"stream" not supported yet`)
+		// No library for stream protobufs
+	case "lite", "":
+		ctx.AddDependency(ctx.Module(), staticLibTag, "libprotobuf-java-lite")
+	case "full":
+		if ctx.Host() {
+			ctx.AddDependency(ctx.Module(), staticLibTag, "libprotobuf-java-full")
+		} else {
+			ctx.PropertyErrorf("proto.type", "full java protos only supported on the host")
+		}
+	default:
+		ctx.PropertyErrorf("proto.type", "unknown proto type %q",
+			proptools.String(p.Proto.Type))
+	}
+}
+
+func protoFlags(ctx android.ModuleContext, p *android.ProtoProperties, flags javaBuilderFlags) javaBuilderFlags {
+	switch proptools.String(p.Proto.Type) {
+	case "micro":
+		flags.protoOutFlag = "--javamicro_out"
+	case "nano":
+		flags.protoOutFlag = "--javanano_out"
+	case "stream":
+		flags.protoOutFlag = "--javastream_out"
+	case "lite", "":
+		flags.protoOutFlag = "--java_out"
+	default:
+		ctx.PropertyErrorf("proto.type", "unknown proto type %q",
+			proptools.String(p.Proto.Type))
+	}
+	return flags
+}
diff --git a/java/resources.go b/java/resources.go
index 60dc934..85ebd52 100644
--- a/java/resources.go
+++ b/java/resources.go
@@ -15,7 +15,9 @@
 package java
 
 import (
+	"fmt"
 	"path/filepath"
+	"strings"
 
 	"github.com/google/blueprint/bootstrap"
 
@@ -40,17 +42,17 @@
 	return false
 }
 
-func ResourceDirsToJarSpecs(ctx android.ModuleContext, resourceDirs, excludeDirs []string) []jarSpec {
+func ResourceDirsToJarArgs(ctx android.ModuleContext,
+	resourceDirs, excludeDirs []string) (args []string, deps android.Paths) {
 	var excludes []string
 
 	for _, exclude := range excludeDirs {
-		excludes = append(excludes, android.PathForModuleSrc(ctx, exclude, "**/*").String())
+		excludes = append(excludes,
+			filepath.Join(android.PathForModuleSrc(ctx, exclude).String(), "**/*"))
 	}
 
 	excludes = append(excludes, resourceExcludes...)
 
-	var jarSpecs []jarSpec
-
 	for _, resourceDir := range resourceDirs {
 		if isStringInSlice(resourceDir, excludeDirs) {
 			continue
@@ -63,9 +65,29 @@
 
 			pattern := filepath.Join(dir.String(), "**/*")
 			bootstrap.GlobFile(ctx, pattern, excludes, fileListFile.String(), depFile)
-			jarSpecs = append(jarSpecs, jarSpec{fileListFile, dir})
+			args = append(args,
+				"-C", dir.String(),
+				"-l", fileListFile.String())
+			deps = append(deps, fileListFile)
 		}
 	}
 
-	return jarSpecs
+	return args, deps
+}
+
+func ResourceFilesToJarArgs(ctx android.ModuleContext,
+	res, exclude []string) (args []string, deps android.Paths) {
+	files := ctx.ExpandSources(res, exclude)
+
+	for _, f := range files {
+		rel := f.Rel()
+		path := f.String()
+		if !strings.HasSuffix(path, rel) {
+			panic(fmt.Errorf("path %q does not end with %q", path, rel))
+		}
+		path = filepath.Clean(strings.TrimSuffix(path, rel))
+		args = append(args, "-C", filepath.Clean(path), "-f", f.String())
+	}
+
+	return args, files
 }
diff --git a/python/binary.go b/python/binary.go
index 91b7a54..b7b5056 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -162,7 +162,7 @@
 	var interp string
 	switch actual_version {
 	case pyVersion2:
-		interp = "python2"
+		interp = "python2.7"
 	case pyVersion3:
 		interp = "python3"
 	default: