Merge "Revert^5 "Move -Wno-enum-compare{,-switch} to external cflags""
diff --git a/android/config.go b/android/config.go
index f5a5e8e..8330b3d 100644
--- a/android/config.go
+++ b/android/config.go
@@ -108,8 +108,7 @@
 	captureBuild      bool // true for tests, saves build parameters for each module
 	ignoreEnvironment bool // true for tests, returns empty from all Getenv calls
 
-	useOpenJDK9    bool // Use OpenJDK9, but possibly target 1.8
-	targetOpenJDK9 bool // Use OpenJDK9 and target 1.9
+	targetOpenJDK9 bool // Target 1.9
 
 	stopBefore bootstrap.StopBefore
 
@@ -321,22 +320,13 @@
 
 func (c *config) fromEnv() error {
 	switch c.Getenv("EXPERIMENTAL_USE_OPENJDK9") {
-	case "":
-		if c.Getenv("RUN_ERROR_PRONE") != "true" {
-			// Use OpenJDK9, but target 1.8
-			c.useOpenJDK9 = true
-		}
-	case "false":
-		// Use OpenJDK8
-	case "1.8":
-		// Use OpenJDK9, but target 1.8
-		c.useOpenJDK9 = true
+	case "", "1.8":
+		// Nothing, we always use OpenJDK9
 	case "true":
 		// Use OpenJDK9 and target 1.9
-		c.useOpenJDK9 = true
 		c.targetOpenJDK9 = true
 	default:
-		return fmt.Errorf(`Invalid value for EXPERIMENTAL_USE_OPENJDK9, should be "", "false", "1.8", or "true"`)
+		return fmt.Errorf(`Invalid value for EXPERIMENTAL_USE_OPENJDK9, should be "", "1.8", or "true"`)
 	}
 
 	return nil
@@ -631,9 +621,8 @@
 	return Bool(c.productVariables.UseGoma)
 }
 
-// Returns true if OpenJDK9 prebuilts are being used
-func (c *config) UseOpenJDK9() bool {
-	return c.useOpenJDK9
+func (c *config) RunErrorProne() bool {
+	return c.IsEnvTrue("RUN_ERROR_PRONE")
 }
 
 // Returns true if -source 1.9 -target 1.9 is being passed to javac
diff --git a/android/defaults.go b/android/defaults.go
index c704529..d4fbf48 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -131,11 +131,16 @@
 func defaultsMutator(ctx TopDownMutatorContext) {
 	if defaultable, ok := ctx.Module().(Defaultable); ok && len(defaultable.defaults().Defaults) > 0 {
 		var defaultsList []Defaults
+		seen := make(map[Defaults]bool)
+
 		ctx.WalkDeps(func(module, parent Module) bool {
 			if ctx.OtherModuleDependencyTag(module) == DefaultsDepTag {
 				if defaults, ok := module.(Defaults); ok {
-					defaultsList = append(defaultsList, defaults)
-					return len(defaults.defaults().Defaults) > 0
+					if !seen[defaults] {
+						seen[defaults] = true
+						defaultsList = append(defaultsList, defaults)
+						return len(defaults.defaults().Defaults) > 0
+					}
 				} else {
 					ctx.PropertyErrorf("defaults", "module %s is not an defaults module",
 						ctx.OtherModuleName(module))
diff --git a/android/module.go b/android/module.go
index 3316a44..b6220dc 100644
--- a/android/module.go
+++ b/android/module.go
@@ -144,7 +144,9 @@
 	VisitDirectDeps(visit func(Module))
 	VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
 	VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
+	// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
 	VisitDepsDepthFirst(visit func(Module))
+	// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
 	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
 	WalkDeps(visit func(Module, Module) bool)
 
@@ -539,6 +541,7 @@
 	ctx blueprint.ModuleContext) Paths {
 
 	result := Paths{}
+	// TODO(ccross): we need to use WalkDeps and have some way to know which dependencies require installation
 	ctx.VisitDepsDepthFirstIf(isFileInstaller,
 		func(m blueprint.Module) {
 			fileInstaller := m.(fileInstaller)
diff --git a/android/paths.go b/android/paths.go
index 8cc3182..af2f956 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -950,7 +950,8 @@
 		if ctx.InstallInData() {
 			partition = "data"
 		} else if ctx.InstallInRecovery() {
-			partition = "recovery/root"
+			// the layout of recovery partion is the same as that of system partition
+			partition = "recovery/root/system"
 		} else if ctx.SocSpecific() {
 			partition = ctx.DeviceConfig().VendorPath()
 		} else if ctx.DeviceSpecific() {
diff --git a/android/singleton.go b/android/singleton.go
index f577b0a..fa1efdc 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -50,7 +50,9 @@
 
 	VisitAllModules(visit func(Module))
 	VisitAllModulesIf(pred func(Module) bool, visit func(Module))
+	// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
 	VisitDepsDepthFirst(module Module, visit func(Module))
+	// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
 	VisitDepsDepthFirstIf(module Module, pred func(Module) bool,
 		visit func(Module))
 
diff --git a/android/variable.go b/android/variable.go
index af414cb..4cd5313 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -62,6 +62,11 @@
 			Cflags []string
 		}
 
+		// Product_is_iot is true for Android Things devices.
+		Product_is_iot struct {
+			Cflags []string
+		}
+
 		// treble_linker_namespaces is true when the system/vendor linker namespace separation is
 		// enabled.
 		Treble_linker_namespaces struct {
@@ -201,6 +206,8 @@
 
 	Override_rs_driver *string `json:",omitempty"`
 
+	Product_is_iot *bool `json:",omitempty"`
+
 	DeviceKernelHeaders []string `json:",omitempty"`
 	DistDir             *string  `json:",omitempty"`
 
diff --git a/cc/binary.go b/cc/binary.go
index 04b912a..0303d9a 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -216,9 +216,6 @@
 	if ctx.Host() && !binary.static() {
 		if !ctx.Config().IsEnvTrue("DISABLE_HOST_PIE") {
 			flags.LdFlags = append(flags.LdFlags, "-pie")
-			if ctx.Windows() {
-				flags.LdFlags = append(flags.LdFlags, "-Wl,-e_mainCRTStartup")
-			}
 		}
 	}
 
@@ -357,11 +354,6 @@
 }
 
 func (binary *binaryDecorator) install(ctx ModuleContext, file android.Path) {
-	// <recovery>/bin is a symlink to /system/bin. Recovery binaries are all in /sbin.
-	if ctx.inRecovery() {
-		binary.baseInstaller.dir = "sbin"
-	}
-
 	binary.baseInstaller.install(ctx, file)
 	for _, symlink := range binary.Properties.Symlinks {
 		binary.symlinks = append(binary.symlinks,
diff --git a/cc/builder.go b/cc/builder.go
index bc3652e..51d3195 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -726,11 +726,14 @@
 	baseName, exportedHeaderFlags string, isVndkExt bool) android.OptionalPath {
 
 	outputFile := android.PathForModuleOut(ctx, baseName+".abidiff")
-
+	libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
 	localAbiCheckAllowFlags := append([]string(nil), abiCheckAllowFlags...)
 	if exportedHeaderFlags == "" {
 		localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-advice-only")
 	}
+	if inList(libName, llndkLibraries) {
+		localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-consider-opaque-types-different")
+	}
 	if isVndkExt {
 		localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-allow-extensions")
 	}
@@ -743,7 +746,7 @@
 		Implicit:    referenceDump,
 		Args: map[string]string{
 			"referenceDump": referenceDump.String(),
-			"libName":       baseName[0:(len(baseName) - len(filepath.Ext(baseName)))],
+			"libName":       libName,
 			"arch":          ctx.Arch().ArchType.Name,
 			"allowFlags":    strings.Join(localAbiCheckAllowFlags, " "),
 		},
diff --git a/cc/cc.go b/cc/cc.go
index 36b2f95..592f373 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -52,7 +52,7 @@
 		ctx.TopDown("tsan_deps", sanitizerDepsMutator(tsan))
 		ctx.BottomUp("tsan", sanitizerMutator(tsan)).Parallel()
 
-		ctx.TopDown("sanitize_runtime_deps", sanitizerRuntimeDepsMutator())
+		ctx.TopDown("sanitize_runtime_deps", sanitizerRuntimeDepsMutator)
 
 		ctx.BottomUp("coverage", coverageLinkingMutator).Parallel()
 		ctx.TopDown("vndk_deps", sabiDepsMutator)
@@ -571,7 +571,7 @@
 		isVariantOnProductionDevice = sanitize.isVariantOnProductionDevice()
 	}
 	vendorAvailable := Bool(ctx.mod.VendorProperties.Vendor_available)
-	return !skipAbiChecks && isVariantOnProductionDevice && ctx.ctx.Device() && ((ctx.useVndk() && ctx.isVndk() && vendorAvailable) || inList(ctx.baseModuleName(), llndkLibraries))
+	return !skipAbiChecks && isVariantOnProductionDevice && ctx.ctx.Device() && ((ctx.useVndk() && ctx.isVndk() && (vendorAvailable || ctx.isVndkExt())) || inList(ctx.baseModuleName(), llndkLibraries))
 }
 
 func (ctx *moduleContextImpl) selectedStl() string {
@@ -1569,6 +1569,19 @@
 				recoveryVariantNeeded = true
 			}
 
+			if recoveryVariantNeeded {
+				var recoveryMultilib string
+				if mctx.Config().DevicePrefer32BitExecutables() {
+					recoveryMultilib = "lib32"
+				} else {
+					recoveryMultilib = "lib64"
+				}
+				multilib := genrule.Target().Arch.ArchType.Multilib
+				if multilib != recoveryMultilib {
+					recoveryVariantNeeded = false
+				}
+			}
+
 			var variants []string
 			if coreVariantNeeded {
 				variants = append(variants, coreMode)
@@ -1676,6 +1689,19 @@
 		coreVariantNeeded = false
 	}
 
+	if recoveryVariantNeeded {
+		var recoveryMultilib string
+		if mctx.Config().DevicePrefer32BitExecutables() {
+			recoveryMultilib = "lib32"
+		} else {
+			recoveryMultilib = "lib64"
+		}
+		multilib := m.Target().Arch.ArchType.Multilib
+		if multilib != recoveryMultilib {
+			recoveryVariantNeeded = false
+		}
+	}
+
 	var variants []string
 	if coreVariantNeeded {
 		variants = append(variants, coreMode)
diff --git a/cc/cmakelists.go b/cc/cmakelists.go
index c25578e..a2f46cd 100644
--- a/cc/cmakelists.go
+++ b/cc/cmakelists.go
@@ -62,10 +62,14 @@
 
 	outputDebugInfo = (getEnvVariable(envVariableGenerateDebugInfo, ctx) == envVariableTrue)
 
+	// Track which projects have already had CMakeLists.txt generated to keep the first
+	// variant for each project.
+	seenProjects := map[string]bool{}
+
 	ctx.VisitAllModules(func(module android.Module) {
 		if ccModule, ok := module.(*Module); ok {
 			if compiledModule, ok := ccModule.compiler.(CompiledInterface); ok {
-				generateCLionProject(compiledModule, ctx, ccModule)
+				generateCLionProject(compiledModule, ctx, ccModule, seenProjects)
 			}
 		}
 	})
@@ -114,14 +118,22 @@
 	return nil
 }
 
-func generateCLionProject(compiledModule CompiledInterface, ctx android.SingletonContext, ccModule *Module) {
+func generateCLionProject(compiledModule CompiledInterface, ctx android.SingletonContext, ccModule *Module,
+	seenProjects map[string]bool) {
 	srcs := compiledModule.Srcs()
 	if len(srcs) == 0 {
 		return
 	}
 
-	// Ensure the directory hosting the cmakelists.txt exists
+	// Only write CMakeLists.txt for the first variant of each architecture of each module
 	clionproject_location := getCMakeListsForModule(ccModule, ctx)
+	if seenProjects[clionproject_location] {
+		return
+	}
+
+	seenProjects[clionproject_location] = true
+
+	// Ensure the directory hosting the cmakelists.txt exists
 	projectDir := path.Dir(clionproject_location)
 	os.MkdirAll(projectDir, os.ModePerm)
 
diff --git a/cc/compiler.go b/cc/compiler.go
index 10cec8c..8d034c9 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -332,6 +332,10 @@
 			"-D__ANDROID_API__="+version, "-D__ANDROID_VNDK__")
 	}
 
+	if ctx.inRecovery() {
+		flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_RECOVERY__")
+	}
+
 	instructionSet := String(compiler.Properties.Instruction_set)
 	if flags.RequiredInstructionSet != "" {
 		instructionSet = flags.RequiredInstructionSet
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 73cee5c..172784a 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -53,15 +53,12 @@
 			"-mcpu=cortex-a53",
 		},
 		"cortex-a55": []string{
-			// The cortex-a55 target is not yet supported,
-			// so use cortex-a53.
-			"-mcpu=cortex-a53",
+			"-mcpu=cortex-a55",
 		},
 		"cortex-a75": []string{
-			// Use the cortex-a53 since it is similar to the little
+			// Use the cortex-a55 since it is similar to the little
 			// core (cortex-a55) and is sensitive to ordering.
-			// The cortex-a55 target is not yet supported.
-			"-mcpu=cortex-a53",
+			"-mcpu=cortex-a55",
 		},
 		"kryo": []string{
 			// Use the cortex-a57 cpu since some compilers
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index 398df90..4719fb7 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -100,7 +100,7 @@
 			"-D__ARM_FEATURE_LPAE=1",
 		},
 		"cortex-a55": []string{
-			"-mcpu=cortex-a53",
+			"-mcpu=cortex-a55",
 			"-mfpu=neon-fp-armv8",
 			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
 			// don't advertise.
@@ -109,7 +109,7 @@
 			"-D__ARM_FEATURE_LPAE=1",
 		},
 		"cortex-a75": []string{
-			"-mcpu=cortex-a53",
+			"-mcpu=cortex-a55",
 			"-mfpu=neon-fp-armv8",
 			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
 			// don't advertise.
diff --git a/cc/config/global.go b/cc/config/global.go
index c734c2e..dee7640 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -89,6 +89,9 @@
 
 	deviceGlobalLldflags = append(ClangFilterUnknownLldflags(deviceGlobalLdflags),
 		[]string{
+			// TODO(b/109657296): needs --no-rosegment until Android
+			// stack unwinder can handle the read-only segment.
+			"-Wl,--no-rosegment",
 			"-Wl,--pack-dyn-relocs=android",
 			"-fuse-ld=lld",
 		}...)
diff --git a/cc/config/tidy.go b/cc/config/tidy.go
index a20d556..5d53a8c 100644
--- a/cc/config/tidy.go
+++ b/cc/config/tidy.go
@@ -19,6 +19,13 @@
 	"strings"
 )
 
+// clang-tidy doesn't recognize every flag that clang does. This is unlikely to
+// be a complete list, but we can populate this with the ones we know to avoid
+// issues with clang-diagnostic-unused-command-line-argument.
+var ClangTidyUnknownCflags = sorted([]string{
+	"-Wa,%",
+})
+
 func init() {
 	// Most Android source files are not clang-tidy clean yet.
 	// Global tidy checks include only google*, performance*,
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index ca863a7..ea8397d 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -243,6 +243,10 @@
 	return SanitizerRuntimeLibrary(t, "profile")
 }
 
+func ScudoRuntimeLibrary(t Toolchain) string {
+	return SanitizerRuntimeLibrary(t, "scudo")
+}
+
 func ToolPath(t Toolchain) string {
 	if p := t.ToolPath(); p != "" {
 		return p
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 6fbff9f..4cb8fa4 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -45,7 +45,6 @@
 
 	windowsIncludeFlags = []string{
 		"-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include",
-		"-isystem ${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3/include",
 	}
 
 	windowsClangCppflags = []string{
@@ -79,22 +78,34 @@
 		"-m32",
 		"-Wl,--large-address-aware",
 		"-L${WindowsGccRoot}/${WindowsGccTriple}/lib32",
+		"-static-libgcc",
 	}
 	windowsX86ClangLdflags = append(ClangFilterUnknownCflags(windowsX86Ldflags), []string{
+		"-B${WindowsGccRoot}/${WindowsGccTriple}/bin",
 		"-B${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3/32",
 		"-L${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3/32",
 		"-B${WindowsGccRoot}/${WindowsGccTriple}/lib32",
+		"-pthread",
+		// Bug: http://b/109759970 - WAR until issue with ld.bfd's
+		// inability to handle Clang-generated section names is fixed.
+		"-Wl,--allow-multiple-definition",
 	}...)
 	windowsX86ClangLldflags = ClangFilterUnknownLldflags(windowsX86ClangLdflags)
 
 	windowsX8664Ldflags = []string{
 		"-m64",
 		"-L${WindowsGccRoot}/${WindowsGccTriple}/lib64",
+		"-static-libgcc",
 	}
 	windowsX8664ClangLdflags = append(ClangFilterUnknownCflags(windowsX8664Ldflags), []string{
+		"-B${WindowsGccRoot}/${WindowsGccTriple}/bin",
 		"-B${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3",
 		"-L${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3",
 		"-B${WindowsGccRoot}/${WindowsGccTriple}/lib64",
+		"-pthread",
+		// Bug: http://b/109759970 - WAR until issue with ld.bfd's
+		// inability to handle Clang-generated section names is fixed.
+		"-Wl,--allow-multiple-definition",
 	}...)
 	windowsX8664ClangLldflags = ClangFilterUnknownLldflags(windowsX8664ClangLdflags)
 
@@ -220,7 +231,7 @@
 }
 
 func (t *toolchainWindows) ClangSupported() bool {
-	return false
+	return true
 }
 
 func (t *toolchainWindowsX86) ClangTriple() string {
diff --git a/cc/linker.go b/cc/linker.go
index f6223a7..6bbf015 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -246,6 +246,10 @@
 	if ctx.Darwin() {
 		return false
 	}
+	// http://b/110800681 - lld cannot link Android's Windows modules yet.
+	if ctx.Windows() {
+		return false
+	}
 	if linker.Properties.Use_clang_lld != nil {
 		return Bool(linker.Properties.Use_clang_lld)
 	}
diff --git a/cc/makevars.go b/cc/makevars.go
index 8b72dbb..88d4639 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -75,6 +75,7 @@
 	ctx.Strict("LLVM_OBJCOPY", "${config.ClangBin}/llvm-objcopy")
 	ctx.Strict("LLVM_STRIP", "${config.ClangBin}/llvm-strip")
 	ctx.Strict("PATH_TO_CLANG_TIDY", "${config.ClangBin}/clang-tidy")
+	ctx.Strict("CLANG_TIDY_UNKNOWN_CFLAGS", strings.Join(config.ClangTidyUnknownCflags, " "))
 	ctx.StrictSorted("CLANG_CONFIG_UNKNOWN_CFLAGS", strings.Join(config.ClangUnknownCflags, " "))
 
 	ctx.Strict("RS_LLVM_PREBUILTS_VERSION", "${config.RSClangVersion}")
@@ -302,6 +303,7 @@
 			ctx.Strict(secondPrefix+"UBSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain), ".so"))
 			ctx.Strict(secondPrefix+"UBSAN_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain), ".a"))
 			ctx.Strict(secondPrefix+"TSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.ThreadSanitizerRuntimeLibrary(toolchain), ".so"))
+			ctx.Strict(secondPrefix+"SCUDO_RUNTIME_LIBRARY", strings.TrimSuffix(config.ScudoRuntimeLibrary(toolchain), ".so"))
 		}
 
 		// This is used by external/gentoo/...
diff --git a/cc/sabi.go b/cc/sabi.go
index f5a7c77..42b2f35 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -74,8 +74,13 @@
 
 	// RSClang does not support recent mcpu option likes exynos-m2.
 	// So we need overriding mcpu option when we want to use it.
-	if ctx.Arch().CpuVariant == "exynos-m2" {
-		flags.ToolingCFlags = append(flags.ToolingCFlags, "-mcpu=cortex-a53")
+	mappedArch := map[string]string{
+		"exynos-m2":  "cortex-a53",
+		"cortex-a55": "cortex-a53",
+		"cortex-a75": "cortex-a57",
+	}
+	if arch, ok := mappedArch[ctx.Arch().CpuVariant]; ok {
+		flags.ToolingCFlags = append(flags.ToolingCFlags, "-mcpu="+arch)
 	}
 
 	return flags
diff --git a/cc/sanitize.go b/cc/sanitize.go
index e59edf5..4c8a611 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -21,6 +21,8 @@
 	"strings"
 	"sync"
 
+	"github.com/google/blueprint"
+
 	"android/soong/android"
 	"android/soong/cc/config"
 )
@@ -94,6 +96,7 @@
 		Safestack        *bool    `android:"arch_variant"`
 		Cfi              *bool    `android:"arch_variant"`
 		Integer_overflow *bool    `android:"arch_variant"`
+		Scudo            *bool    `android:"arch_variant"`
 
 		// Sanitizers to run in the diagnostic mode (as opposed to the release mode).
 		// Replaces abort() on error with a human-readable error message.
@@ -152,7 +155,9 @@
 
 	if ctx.clang() {
 		if ctx.Host() {
-			globalSanitizers = ctx.Config().SanitizeHost()
+			if !ctx.Windows() {
+				globalSanitizers = ctx.Config().SanitizeHost()
+			}
 		} else {
 			arches := ctx.Config().SanitizeDeviceArch()
 			if len(arches) == 0 || inList(ctx.Arch().ArchType.Name, arches) {
@@ -207,6 +212,10 @@
 			}
 		}
 
+		if found, globalSanitizers = removeFromList("scudo", globalSanitizers); found && s.Scudo == nil {
+			s.Scudo = boolPtr(true)
+		}
+
 		if len(globalSanitizers) > 0 {
 			ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0])
 		}
@@ -281,10 +290,16 @@
 	}
 
 	if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
-		Bool(s.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0) {
+		Bool(s.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
+		Bool(s.Scudo)) {
 		sanitize.Properties.SanitizerEnabled = true
 	}
 
+	// Disable Scudo if ASan or TSan is enabled.
+	if Bool(s.Address) || Bool(s.Thread) {
+		s.Scudo = nil
+	}
+
 	if Bool(s.Coverage) {
 		if !Bool(s.Address) {
 			ctx.ModuleErrorf(`Use of "coverage" also requires "address"`)
@@ -434,6 +449,10 @@
 		}
 	}
 
+	if Bool(sanitize.Properties.Sanitize.Scudo) {
+		sanitizers = append(sanitizers, "scudo")
+	}
+
 	if len(sanitizers) > 0 {
 		sanitizeArg := "-fsanitize=" + strings.Join(sanitizers, ",")
 
@@ -471,6 +490,8 @@
 		runtimeLibrary = config.AddressSanitizerRuntimeLibrary(ctx.toolchain())
 	} else if Bool(sanitize.Properties.Sanitize.Thread) {
 		runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(ctx.toolchain())
+	} else if Bool(sanitize.Properties.Sanitize.Scudo) {
+		runtimeLibrary = config.ScudoRuntimeLibrary(ctx.toolchain())
 	} else if len(diagSanitizers) > 0 || sanitize.Properties.UbsanRuntimeDep {
 		runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(ctx.toolchain())
 	}
@@ -593,43 +614,54 @@
 	return sanitizerVal != nil && *sanitizerVal == true
 }
 
+func isSanitizableDependencyTag(tag blueprint.DependencyTag) bool {
+	t, ok := tag.(dependencyTag)
+	return ok && t.library || t == reuseObjTag
+}
+
 // Propagate asan requirements down from binaries
 func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) {
 	return func(mctx android.TopDownMutatorContext) {
 		if c, ok := mctx.Module().(*Module); ok && c.sanitize.isSanitizerEnabled(t) {
-			mctx.VisitDepsDepthFirst(func(module android.Module) {
-				if d, ok := module.(*Module); ok && d.sanitize != nil &&
+			mctx.WalkDeps(func(child, parent android.Module) bool {
+				if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
+					return false
+				}
+				if d, ok := child.(*Module); ok && d.sanitize != nil &&
 					!Bool(d.sanitize.Properties.Sanitize.Never) &&
 					!d.sanitize.isSanitizerExplicitlyDisabled(t) {
 					if (t == cfi && d.static()) || t != cfi {
 						d.sanitize.Properties.SanitizeDep = true
 					}
 				}
+				return true
 			})
 		}
 	}
 }
 
 // Propagate the ubsan minimal runtime dependency when there are integer overflow sanitized static dependencies.
-func sanitizerRuntimeDepsMutator() func(android.TopDownMutatorContext) {
-	return func(mctx android.TopDownMutatorContext) {
-		if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
-			mctx.VisitDepsDepthFirst(func(module android.Module) {
-				if d, ok := module.(*Module); ok && d.static() && d.sanitize != nil {
+func sanitizerRuntimeDepsMutator(mctx android.TopDownMutatorContext) {
+	if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
+		mctx.WalkDeps(func(child, parent android.Module) bool {
+			if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
+				return false
+			}
+			if d, ok := child.(*Module); ok && d.static() && d.sanitize != nil {
 
-					if enableMinimalRuntime(d.sanitize) {
-						// If a static dependency is built with the minimal runtime,
-						// make sure we include the ubsan minimal runtime.
-						c.sanitize.Properties.MinimalRuntimeDep = true
-					} else if Bool(d.sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
-						len(d.sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0 {
-						// If a static dependency runs with full ubsan diagnostics,
-						// make sure we include the ubsan runtime.
-						c.sanitize.Properties.UbsanRuntimeDep = true
-					}
+				if enableMinimalRuntime(d.sanitize) {
+					// If a static dependency is built with the minimal runtime,
+					// make sure we include the ubsan minimal runtime.
+					c.sanitize.Properties.MinimalRuntimeDep = true
+				} else if Bool(d.sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
+					len(d.sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0 {
+					// If a static dependency runs with full ubsan diagnostics,
+					// make sure we include the ubsan runtime.
+					c.sanitize.Properties.UbsanRuntimeDep = true
 				}
-			})
-		}
+			}
+			return true
+		})
 	}
 }
 
@@ -705,6 +737,7 @@
 
 func enableMinimalRuntime(sanitize *sanitize) bool {
 	if !Bool(sanitize.Properties.Sanitize.Address) &&
+		!Bool(sanitize.Properties.Sanitize.Scudo) &&
 		(Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
 			len(sanitize.Properties.Sanitize.Misc_undefined) > 0) &&
 		!(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
diff --git a/java/aar.go b/java/aar.go
index 415170e..da353e0 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -475,6 +475,10 @@
 	return nil
 }
 
+func (a *AARImport) ExportedSdkLibs() []string {
+	return nil
+}
+
 var _ android.PrebuiltInterface = (*Import)(nil)
 
 func AARImportFactory() android.Module {
diff --git a/java/androidmk.go b/java/androidmk.go
index ab9ceeb..d6095ae 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -63,6 +63,10 @@
 					fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", library.jacocoReportClassesFile.String())
 				}
 
+				if len(library.exportedSdkLibs) != 0 {
+					fmt.Fprintln(w, "LOCAL_EXPORT_SDK_LIBRARIES :=", strings.Join(library.exportedSdkLibs, " "))
+				}
+
 				// Temporary hack: export sources used to compile framework.jar to Make
 				// to be used for droiddoc
 				// TODO(ccross): remove this once droiddoc is in soong
diff --git a/java/builder.go b/java/builder.go
index d338623..15e9631 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -26,7 +26,6 @@
 	"github.com/google/blueprint"
 
 	"android/soong/android"
-	"android/soong/java/config"
 )
 
 var (
@@ -42,10 +41,11 @@
 		blueprint.RuleParams{
 			Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
 				`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
+				`(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` +
 				`${config.SoongJavacWrapper} ${config.JavacWrapper}${config.JavacCmd} ${config.JavacHeapFlags} ${config.CommonJdkFlags} ` +
-				`$javacFlags $bootClasspath $classpath ` +
+				`$processorpath $javacFlags $bootClasspath $classpath ` +
 				`-source $javaVersion -target $javaVersion ` +
-				`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list && ` +
+				`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list ; fi ) && ` +
 				`${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
 			CommandDeps: []string{
 				"${config.JavacCmd}",
@@ -56,7 +56,7 @@
 			Rspfile:          "$out.rsp",
 			RspfileContent:   "$in",
 		},
-		"javacFlags", "bootClasspath", "classpath", "srcJars", "srcJarDir",
+		"javacFlags", "bootClasspath", "classpath", "processorpath", "srcJars", "srcJarDir",
 		"outDir", "annoDir", "javaVersion")
 
 	kotlinc = pctx.AndroidGomaStaticRule("kotlinc",
@@ -80,29 +80,6 @@
 		},
 		"kotlincFlags", "classpath", "srcJars", "srcJarDir", "outDir", "kotlinJvmTarget")
 
-	errorprone = pctx.AndroidStaticRule("errorprone",
-		blueprint.RuleParams{
-			Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
-				`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
-				`${config.SoongJavacWrapper} ${config.ErrorProneCmd} ` +
-				`$javacFlags $bootClasspath $classpath ` +
-				`-source $javaVersion -target $javaVersion ` +
-				`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list && ` +
-				`${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
-			CommandDeps: []string{
-				"${config.JavaCmd}",
-				"${config.ErrorProneJavacJar}",
-				"${config.ErrorProneJar}",
-				"${config.SoongZipCmd}",
-				"${config.ZipSyncCmd}",
-			},
-			CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
-			Rspfile:          "$out.rsp",
-			RspfileContent:   "$in",
-		},
-		"javacFlags", "bootClasspath", "classpath", "srcJars", "srcJarDir",
-		"outDir", "annoDir", "javaVersion")
-
 	turbine = pctx.AndroidStaticRule("turbine",
 		blueprint.RuleParams{
 			Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
@@ -155,11 +132,13 @@
 	javacFlags    string
 	bootClasspath classpath
 	classpath     classpath
+	processorPath classpath
 	systemModules classpath
 	aidlFlags     string
 	javaVersion   string
 
 	errorProneExtraJavacFlags string
+	errorProneProcessorPath   classpath
 
 	kotlincFlags     string
 	kotlincClasspath classpath
@@ -207,26 +186,24 @@
 		desc += strconv.Itoa(shardIdx)
 	}
 
-	transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, flags, deps, "javac", desc, javac)
+	transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, flags, deps, "javac", desc)
 }
 
 func RunErrorProne(ctx android.ModuleContext, outputFile android.WritablePath,
 	srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
 
-	if config.ErrorProneJar == "" {
-		ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
-	}
+	flags.processorPath = append(flags.errorProneProcessorPath, flags.processorPath...)
 
 	if len(flags.errorProneExtraJavacFlags) > 0 {
 		if len(flags.javacFlags) > 0 {
-			flags.javacFlags = flags.errorProneExtraJavacFlags + " " + flags.javacFlags
+			flags.javacFlags += " " + flags.errorProneExtraJavacFlags
 		} else {
 			flags.javacFlags = flags.errorProneExtraJavacFlags
 		}
 	}
 
 	transformJavaToClasses(ctx, outputFile, -1, srcFiles, srcJars, flags, nil,
-		"errorprone", "errorprone", errorprone)
+		"errorprone", "errorprone")
 }
 
 func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath,
@@ -275,7 +252,7 @@
 func transformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
 	shardIdx int, srcFiles, srcJars android.Paths,
 	flags javaBuilderFlags, deps android.Paths,
-	intermediatesDir, desc string, rule blueprint.Rule) {
+	intermediatesDir, desc string) {
 
 	deps = append(deps, srcJars...)
 
@@ -295,6 +272,7 @@
 	}
 
 	deps = append(deps, flags.classpath...)
+	deps = append(deps, flags.processorPath...)
 
 	srcJarDir := "srcjars"
 	outDir := "classes"
@@ -306,7 +284,7 @@
 		annoDir = filepath.Join(shardDir, annoDir)
 	}
 	ctx.Build(pctx, android.BuildParams{
-		Rule:        rule,
+		Rule:        javac,
 		Description: desc,
 		Output:      outputFile,
 		Inputs:      srcFiles,
@@ -315,6 +293,7 @@
 			"javacFlags":    flags.javacFlags,
 			"bootClasspath": bootClasspath,
 			"classpath":     flags.classpath.FormJavaClassPath("-classpath"),
+			"processorpath": flags.processorPath.FormJavaClassPath("-processorpath"),
 			"srcJars":       strings.Join(srcJars.Strings(), " "),
 			"srcJarDir":     android.PathForModuleOut(ctx, intermediatesDir, srcJarDir).String(),
 			"outDir":        android.PathForModuleOut(ctx, intermediatesDir, outDir).String(),
diff --git a/java/config/config.go b/java/config/config.go
index c6555f1..2fa48cb 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -132,4 +132,6 @@
 	}
 
 	hostBinToolVariableWithPrebuilt("Aapt2Cmd", "prebuilts/sdk/tools", "aapt2")
+
+	pctx.SourcePathVariable("ManifestFixerCmd", "build/soong/scripts/manifest_fixer.py")
 }
diff --git a/java/config/error_prone.go b/java/config/error_prone.go
index 2c1c002..48681b5 100644
--- a/java/config/error_prone.go
+++ b/java/config/error_prone.go
@@ -14,39 +14,40 @@
 
 package config
 
-import "android/soong/android"
+import (
+	"strings"
+
+	"android/soong/android"
+)
 
 var (
 	// These will be filled out by external/error_prone/soong/error_prone.go if it is available
-	ErrorProneJavacJar              string
-	ErrorProneJar                   string
-	ErrorProneClasspath             string
-	ErrorProneChecksError           string
-	ErrorProneChecksWarning         string
-	ErrorProneChecksDefaultDisabled string
-	ErrorProneFlags                 string
+	ErrorProneClasspath             []string
+	ErrorProneChecksError           []string
+	ErrorProneChecksWarning         []string
+	ErrorProneChecksDefaultDisabled []string
+	ErrorProneChecksOff             []string
+	ErrorProneFlags                 []string
 )
 
 // Wrapper that grabs value of val late so it can be initialized by a later module's init function
-func errorProneVar(name string, val *string) {
+func errorProneVar(name string, val *[]string, sep string) {
 	pctx.VariableFunc(name, func(android.PackageVarContext) string {
-		return *val
+		return strings.Join(*val, sep)
 	})
 }
 
 func init() {
-	errorProneVar("ErrorProneJar", &ErrorProneJar)
-	errorProneVar("ErrorProneJavacJar", &ErrorProneJavacJar)
-	errorProneVar("ErrorProneClasspath", &ErrorProneClasspath)
-	errorProneVar("ErrorProneChecksError", &ErrorProneChecksError)
-	errorProneVar("ErrorProneChecksWarning", &ErrorProneChecksWarning)
-	errorProneVar("ErrorProneChecksDefaultDisabled", &ErrorProneChecksDefaultDisabled)
-	errorProneVar("ErrorProneFlags", &ErrorProneFlags)
-
-	pctx.StaticVariable("ErrorProneCmd",
-		"${JavaCmd} -Xmx${JavacHeapSize} -Xbootclasspath/p:${ErrorProneJavacJar} "+
-			"-cp ${ErrorProneJar}:${ErrorProneClasspath} "+
-			"${ErrorProneFlags} ${CommonJdkFlags} "+
-			"${ErrorProneChecksError} ${ErrorProneChecksWarning} ${ErrorProneChecksDefaultDisabled}")
-
+	errorProneVar("ErrorProneClasspath", &ErrorProneClasspath, ":")
+	errorProneVar("ErrorProneChecksError", &ErrorProneChecksError, " ")
+	errorProneVar("ErrorProneChecksWarning", &ErrorProneChecksWarning, " ")
+	errorProneVar("ErrorProneChecksDefaultDisabled", &ErrorProneChecksDefaultDisabled, " ")
+	errorProneVar("ErrorProneChecksOff", &ErrorProneChecksOff, " ")
+	errorProneVar("ErrorProneFlags", &ErrorProneFlags, " ")
+	pctx.StaticVariable("ErrorProneChecks", strings.Join([]string{
+		"${ErrorProneChecksOff}",
+		"${ErrorProneChecksError}",
+		"${ErrorProneChecksWarning}",
+		"${ErrorProneChecksDefaultDisabled}",
+	}, " "))
 }
diff --git a/java/config/makevars.go b/java/config/makevars.go
index 4dffa02..d378877 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -52,18 +52,17 @@
 
 	ctx.Strict("TURBINE", "${TurbineJar}")
 
-	if ctx.Config().IsEnvTrue("RUN_ERROR_PRONE") {
-		ctx.Strict("TARGET_JAVAC", "${ErrorProneCmd}")
-		ctx.Strict("HOST_JAVAC", "${ErrorProneCmd}")
-	} else {
-		ctx.Strict("TARGET_JAVAC", "${JavacCmd} ${CommonJdkFlags}")
-		ctx.Strict("HOST_JAVAC", "${JavacCmd} ${CommonJdkFlags}")
+	if ctx.Config().RunErrorProne() {
+		ctx.Strict("ERROR_PRONE_JARS", strings.Join(ErrorProneClasspath, " "))
+		ctx.Strict("ERROR_PRONE_FLAGS", "${ErrorProneFlags}")
+		ctx.Strict("ERROR_PRONE_CHECKS", "${ErrorProneChecks}")
 	}
 
-	if ctx.Config().UseOpenJDK9() {
-		ctx.Strict("JLINK", "${JlinkCmd}")
-		ctx.Strict("JMOD", "${JmodCmd}")
-	}
+	ctx.Strict("TARGET_JAVAC", "${JavacCmd} ${CommonJdkFlags}")
+	ctx.Strict("HOST_JAVAC", "${JavacCmd} ${CommonJdkFlags}")
+
+	ctx.Strict("JLINK", "${JlinkCmd}")
+	ctx.Strict("JMOD", "${JmodCmd}")
 
 	ctx.Strict("SOONG_JAVAC_WRAPPER", "${SoongJavacWrapper}")
 	ctx.Strict("ZIPSYNC", "${ZipSyncCmd}")
@@ -72,4 +71,6 @@
 	ctx.Strict("DEFAULT_JACOCO_EXCLUDE_FILTER", strings.Join(DefaultJacocoExcludeFilter, ","))
 
 	ctx.Strict("EXTRACT_JAR_PACKAGES", "${ExtractJarPackagesCmd}")
+
+	ctx.Strict("MANIFEST_FIXER", "${ManifestFixerCmd}")
 }
diff --git a/java/droiddoc.go b/java/droiddoc.go
index ca99e76..1eb935f 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -69,9 +69,9 @@
 		blueprint.RuleParams{
 			Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` +
 				`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
-				`${config.JavaCmd} -jar ${config.MetalavaJar} -encoding UTF-8 -source 1.8 @$out.rsp @$srcJarDir/list ` +
-				`$bootclasspathArgs $classpathArgs -sourcepath $sourcepath --no-banner --color ` +
-				`--stubs $stubsDir --quiet --write-stubs-source-list $outDir/stubs_src_list $opts && ` +
+				`${config.JavaCmd} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` +
+				`$bootclasspathArgs $classpathArgs -sourcepath $sourcepath --no-banner --color --quiet ` +
+				`--stubs $stubsDir $opts && ` +
 				`${config.SoongZipCmd} -write_if_changed -d -o $docZip -C $outDir -D $outDir && ` +
 				`${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir`,
 			CommandDeps: []string{
@@ -85,7 +85,8 @@
 			RspfileContent: "$in",
 			Restat:         true,
 		},
-		"outDir", "srcJarDir", "stubsDir", "srcJars", "bootclasspathArgs", "classpathArgs", "sourcepath", "opts", "docZip")
+		"outDir", "srcJarDir", "stubsDir", "srcJars", "javaVersion", "bootclasspathArgs",
+		"classpathArgs", "sourcepath", "opts", "docZip")
 )
 
 func init() {
@@ -98,6 +99,10 @@
 	android.RegisterModuleType("javadoc_host", JavadocHostFactory)
 }
 
+var (
+	srcsLibTag = dependencyTag{name: "sources from javalib"}
+)
+
 type JavadocProperties struct {
 	// list of source files used to compile the Java module.  May be .java, .logtags, .proto,
 	// or .aidl files.
@@ -141,6 +146,9 @@
 		// Directories rooted at the Android.bp file to pass to aidl tool
 		Local_include_dirs []string
 	}
+
+	// If not blank, set the java version passed to javadoc as -source
+	Java_version *string
 }
 
 type ApiToCheck struct {
@@ -240,7 +248,7 @@
 	// is set to true, Metalava will allow framework SDK to contain annotations.
 	Metalava_annotations_enabled *bool
 
-	// a XML files set to merge annotations.
+	// a top level directory contains XML files set to merge annotations.
 	Metalava_merge_annotations_dir *string
 }
 
@@ -329,15 +337,24 @@
 		sdkDep := decodeSdkDep(ctx, String(j.properties.Sdk_version))
 		if sdkDep.useDefaultLibs {
 			ctx.AddDependency(ctx.Module(), bootClasspathTag, config.DefaultBootclasspathLibraries...)
+			if ctx.Config().TargetOpenJDK9() {
+				ctx.AddDependency(ctx.Module(), systemModulesTag, config.DefaultSystemModules)
+			}
 			if !Bool(j.properties.No_framework_libs) {
 				ctx.AddDependency(ctx.Module(), libTag, []string{"ext", "framework"}...)
 			}
 		} else if sdkDep.useModule {
+			if ctx.Config().TargetOpenJDK9() {
+				ctx.AddDependency(ctx.Module(), systemModulesTag, sdkDep.systemModules)
+			}
 			ctx.AddDependency(ctx.Module(), bootClasspathTag, sdkDep.modules...)
 		}
 	}
 
 	ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
+	if j.properties.Srcs_lib != nil {
+		ctx.AddDependency(ctx.Module(), srcsLibTag, *j.properties.Srcs_lib)
+	}
 
 	android.ExtractSourcesDeps(ctx, j.properties.Srcs)
 
@@ -437,24 +454,6 @@
 			switch dep := module.(type) {
 			case Dependency:
 				deps.classpath = append(deps.classpath, dep.ImplementationJars()...)
-				if otherName == String(j.properties.Srcs_lib) {
-					srcs := dep.(SrcDependency).CompiledSrcs()
-					whitelistPathPrefixes := make(map[string]bool)
-					j.genWhitelistPathPrefixes(whitelistPathPrefixes)
-					for _, src := range srcs {
-						if _, ok := src.(android.WritablePath); ok { // generated sources
-							deps.srcs = append(deps.srcs, src)
-						} else { // select source path for documentation based on whitelist path prefixs.
-							for k, _ := range whitelistPathPrefixes {
-								if strings.HasPrefix(src.Rel(), k) {
-									deps.srcs = append(deps.srcs, src)
-									break
-								}
-							}
-						}
-					}
-					deps.srcJars = append(deps.srcJars, dep.(SrcDependency).CompiledSrcJars()...)
-				}
 			case SdkLibraryDependency:
 				sdkVersion := String(j.properties.Sdk_version)
 				linkType := javaSdk
@@ -470,6 +469,37 @@
 			default:
 				ctx.ModuleErrorf("depends on non-java module %q", otherName)
 			}
+		case srcsLibTag:
+			switch dep := module.(type) {
+			case Dependency:
+				srcs := dep.(SrcDependency).CompiledSrcs()
+				whitelistPathPrefixes := make(map[string]bool)
+				j.genWhitelistPathPrefixes(whitelistPathPrefixes)
+				for _, src := range srcs {
+					if _, ok := src.(android.WritablePath); ok { // generated sources
+						deps.srcs = append(deps.srcs, src)
+					} else { // select source path for documentation based on whitelist path prefixs.
+						for k, _ := range whitelistPathPrefixes {
+							if strings.HasPrefix(src.Rel(), k) {
+								deps.srcs = append(deps.srcs, src)
+								break
+							}
+						}
+					}
+				}
+				deps.srcJars = append(deps.srcJars, dep.(SrcDependency).CompiledSrcJars()...)
+			default:
+				ctx.ModuleErrorf("depends on non-java module %q", otherName)
+			}
+		case systemModulesTag:
+			if deps.systemModules != nil {
+				panic("Found two system module dependencies")
+			}
+			sm := module.(*SystemModules)
+			if sm.outputFile == nil {
+				panic("Missing directory for system module dependency")
+			}
+			deps.systemModules = sm.outputFile
 		}
 	})
 	// do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
@@ -508,19 +538,15 @@
 	implicits = append(implicits, deps.classpath...)
 
 	var bootClasspathArgs, classpathArgs string
-	if ctx.Config().UseOpenJDK9() {
-		if len(deps.bootClasspath) > 0 {
-			// For OpenJDK 9 we use --patch-module to define the core libraries code.
-			// TODO(tobiast): Reorganize this when adding proper support for OpenJDK 9
-			// modules. Here we treat all code in core libraries as being in java.base
-			// to work around the OpenJDK 9 module system. http://b/62049770
-			bootClasspathArgs = "--patch-module=java.base=" + strings.Join(deps.bootClasspath.Strings(), ":")
+
+	javaVersion := getJavaVersion(ctx, String(j.properties.Java_version), String(j.properties.Sdk_version))
+	if len(deps.bootClasspath) > 0 {
+		var systemModules classpath
+		if deps.systemModules != nil {
+			systemModules = append(systemModules, deps.systemModules)
 		}
-	} else {
-		if len(deps.bootClasspath.Strings()) > 0 {
-			// For OpenJDK 8 we can use -bootclasspath to define the core libraries code.
-			bootClasspathArgs = deps.bootClasspath.FormJavaClassPath("-bootclasspath")
-		}
+		bootClasspathArgs = systemModules.FormJavaSystemModulesPath("--system ", ctx.Device())
+		bootClasspathArgs = bootClasspathArgs + " --patch-module java.base=."
 	}
 	if len(deps.classpath.Strings()) > 0 {
 		classpathArgs = "-classpath " + strings.Join(deps.classpath.Strings(), ":")
@@ -528,7 +554,7 @@
 
 	implicits = append(implicits, j.srcJars...)
 
-	opts := "-J-Xmx1024m -XDignore.symbol.file -Xdoclint:none"
+	opts := "-source " + javaVersion + " -J-Xmx1024m -XDignore.symbol.file -Xdoclint:none"
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:           javadoc,
@@ -612,7 +638,20 @@
 	implicits = append(implicits, deps.bootClasspath...)
 	implicits = append(implicits, deps.classpath...)
 
-	bootClasspathArgs := deps.bootClasspath.FormJavaClassPath("-bootclasspath")
+	var bootClasspathArgs string
+	javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), String(d.Javadoc.properties.Sdk_version))
+	// Doclava has problem with "-source 1.9", so override javaVersion when Doclava
+	// is running with EXPERIMENTAL_USE_OPENJDK9=true. And eventually Doclava will be
+	// replaced by Metalava.
+	if !Bool(d.properties.Metalava_enabled) {
+		javaVersion = "1.8"
+	}
+	// continue to use -bootclasspath even if Metalava under -source 1.9 is enabled
+	// since it doesn't support system modules yet.
+	if len(deps.bootClasspath.Strings()) > 0 {
+		// For OpenJDK 8 we can use -bootclasspath to define the core libraries code.
+		bootClasspathArgs = deps.bootClasspath.FormJavaClassPath("-bootclasspath")
+	}
 	classpathArgs := deps.classpath.FormJavaClassPath("-classpath")
 
 	argFiles := ctx.ExpandSources(d.properties.Arg_files, nil)
@@ -801,7 +840,7 @@
 		date = `date -d`
 	}
 
-	doclavaOpts := "-source 1.8 -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " +
+	doclavaOpts := "-source " + javaVersion + " -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " +
 		"-doclet com.google.doclava.Doclava -docletpath " + jsilver.String() + ":" + doclava.String() + " " +
 		"-templatedir " + templateDir + " " + htmlDirArgs + " " + htmlDir2Args + " " +
 		"-hdf page.build " + ctx.Config().BuildId() + "-" + ctx.Config().BuildNumberFromFile() + " " +
@@ -844,6 +883,7 @@
 			"srcJarDir":         android.PathForModuleOut(ctx, "docs", "srcjars").String(),
 			"stubsDir":          android.PathForModuleOut(ctx, "docs", "stubsDir").String(),
 			"srcJars":           strings.Join(d.Javadoc.srcJars.Strings(), " "),
+			"javaVersion":       javaVersion,
 			"bootclasspathArgs": bootClasspathArgs,
 			"classpathArgs":     classpathArgs,
 			"sourcepath":        strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
@@ -854,7 +894,7 @@
 		if String(d.properties.Metalava_previous_api) != "" {
 			previousApi = ctx.ExpandSource(String(d.properties.Metalava_previous_api),
 				"metalava_previous_api")
-			opts += " --check-compatibility  --previous-api " + previousApi.String()
+			opts += " --previous-api " + previousApi.String()
 			implicits = append(implicits, previousApi)
 		}
 
@@ -873,19 +913,19 @@
 					"has to be non-empty if annotations was enabled!")
 			}
 
-			mergeAnnotationsDir := android.PathForModuleSrc(ctx,
-				String(d.properties.Metalava_merge_annotations_dir))
-			implicits = append(implicits, ctx.Glob(mergeAnnotationsDir.Join(ctx, "**/*").String(), nil)...)
+			mergeAnnotationsDir := android.PathForSource(ctx, String(d.properties.Metalava_merge_annotations_dir))
 
 			opts += " --extract-annotations " + annotationsZip.String() + " --merge-annotations " + mergeAnnotationsDir.String()
 			// TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
-			opts += "--hide HiddenTypedefConstant --hide SuperfluousPrefix --hide AnnotationExtraction"
+			opts += " --hide HiddenTypedefConstant --hide SuperfluousPrefix --hide AnnotationExtraction"
 		}
 
 		if genDocsForMetalava {
-			opts += " --generate-documentation ${config.JavadocCmd} -encoding UTF-8 STUBS_SOURCE_LIST " +
+			opts += " --doc-stubs " + android.PathForModuleOut(ctx, "docs", "docStubsDir").String() +
+				" --write-doc-stubs-source-list $outDir/doc_stubs_src_list " +
+				" --generate-documentation ${config.JavadocCmd} -encoding UTF-8 DOC_STUBS_SOURCE_LIST " +
 				doclavaOpts + docArgsForMetalava + bootClasspathArgs + " " + classpathArgs + " " + " -sourcepath " +
-				strings.Join(d.Javadoc.sourcepaths.Strings(), ":") + " -quiet -d $outDir "
+				android.PathForModuleOut(ctx, "docs", "docStubsDir").String() + " -quiet -d $outDir "
 			implicits = append(implicits, jsilver)
 			implicits = append(implicits, doclava)
 		}
diff --git a/java/java.go b/java/java.go
index 1fefcab..5458ea1 100644
--- a/java/java.go
+++ b/java/java.go
@@ -281,6 +281,9 @@
 
 	// list of extra progurad flag files
 	extraProguardFlagFiles android.Paths
+
+	// list of SDK lib names that this java moudule is exporting
+	exportedSdkLibs []string
 }
 
 func (j *Module) Srcs() android.Paths {
@@ -293,6 +296,7 @@
 	HeaderJars() android.Paths
 	ImplementationJars() android.Paths
 	AidlIncludeDirs() android.Paths
+	ExportedSdkLibs() []string
 }
 
 type SdkLibraryDependency interface {
@@ -327,6 +331,7 @@
 var (
 	staticLibTag     = dependencyTag{name: "staticlib"}
 	libTag           = dependencyTag{name: "javalib"}
+	annoTag          = dependencyTag{name: "annotation processor"}
 	bootClasspathTag = dependencyTag{name: "bootclasspath"}
 	systemModulesTag = dependencyTag{name: "system modules"}
 	frameworkResTag  = dependencyTag{name: "framework-res"}
@@ -507,14 +512,17 @@
 		}
 		if ctx.ModuleName() == "android_stubs_current" ||
 			ctx.ModuleName() == "android_system_stubs_current" ||
-			ctx.ModuleName() == "android_test_stubs_current" {
+			ctx.ModuleName() == "android_test_stubs_current" ||
+			ctx.ModuleName() == "metalava_android_stubs_current" ||
+			ctx.ModuleName() == "metalava_android_system_stubs_current" ||
+			ctx.ModuleName() == "metalava_android_test_stubs_current" {
 			ctx.AddDependency(ctx.Module(), frameworkApkTag, "framework-res")
 		}
 	}
 
 	ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
 	ctx.AddDependency(ctx.Module(), staticLibTag, j.properties.Static_libs...)
-	ctx.AddDependency(ctx.Module(), libTag, j.properties.Annotation_processors...)
+	ctx.AddDependency(ctx.Module(), annoTag, j.properties.Annotation_processors...)
 
 	android.ExtractSourcesDeps(ctx, j.properties.Srcs)
 	android.ExtractSourcesDeps(ctx, j.properties.Exclude_srcs)
@@ -595,6 +603,7 @@
 type deps struct {
 	classpath          classpath
 	bootClasspath      classpath
+	processorPath      classpath
 	staticJars         android.Paths
 	staticHeaderJars   android.Paths
 	staticJarResources android.Paths
@@ -628,13 +637,13 @@
 	ver := String(m.deviceProperties.Sdk_version)
 	noStdLibs := Bool(m.properties.No_standard_libs)
 	switch {
-	case name == "core.current.stubs" || ver == "core_current" || noStdLibs:
+	case name == "core.current.stubs" || ver == "core_current" || noStdLibs || name == "stub-annotations":
 		return javaCore
-	case name == "android_system_stubs_current" || strings.HasPrefix(ver, "system_"):
+	case name == "android_system_stubs_current" || strings.HasPrefix(ver, "system_") || name == "metalava_android_system_stubs_current":
 		return javaSystem
-	case name == "android_test_stubs_current" || strings.HasPrefix(ver, "test_"):
+	case name == "android_test_stubs_current" || strings.HasPrefix(ver, "test_") || name == "metalava_android_test_stubs_current":
 		return javaPlatform
-	case name == "android_stubs_current" || ver == "current":
+	case name == "android_stubs_current" || ver == "current" || name == "metalava_android_stubs_current":
 		return javaSdk
 	case ver == "":
 		return javaPlatform
@@ -711,10 +720,16 @@
 				deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...)
 			case libTag:
 				deps.classpath = append(deps.classpath, dep.HeaderJars()...)
+				// sdk lib names from dependencies are re-exported
+				j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
 			case staticLibTag:
 				deps.classpath = append(deps.classpath, dep.HeaderJars()...)
 				deps.staticJars = append(deps.staticJars, dep.ImplementationJars()...)
 				deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...)
+				// sdk lib names from dependencies are re-exported
+				j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
+			case annoTag:
+				deps.processorPath = append(deps.processorPath, dep.ImplementationJars()...)
 			case frameworkResTag:
 				if ctx.ModuleName() == "framework" {
 					// framework.jar has a one-off dependency on the R.java and Manifest.java files
@@ -724,7 +739,10 @@
 			case frameworkApkTag:
 				if ctx.ModuleName() == "android_stubs_current" ||
 					ctx.ModuleName() == "android_system_stubs_current" ||
-					ctx.ModuleName() == "android_test_stubs_current" {
+					ctx.ModuleName() == "android_test_stubs_current" ||
+					ctx.ModuleName() == "metalava_android_stubs_current" ||
+					ctx.ModuleName() == "metalava_android_system_stubs_current" ||
+					ctx.ModuleName() == "metalava_android_test_stubs_current" {
 					// framework stubs.jar need to depend on framework-res.apk, in order to pull the
 					// resource files out of there for aapt.
 					//
@@ -742,6 +760,8 @@
 			switch tag {
 			case libTag:
 				deps.classpath = append(deps.classpath, dep.HeaderJars(getLinkType(j, ctx.ModuleName()))...)
+				// names of sdk libs that are directly depended are exported
+				j.exportedSdkLibs = append(j.exportedSdkLibs, otherName)
 			default:
 				ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
 			}
@@ -779,9 +799,30 @@
 		}
 	})
 
+	j.exportedSdkLibs = android.FirstUniqueStrings(j.exportedSdkLibs)
+
 	return deps
 }
 
+func getJavaVersion(ctx android.ModuleContext, javaVersion, sdkVersion string) string {
+	var ret string
+	sdk := sdkStringToNumber(ctx, sdkVersion)
+	if javaVersion != "" {
+		ret = javaVersion
+	} else if ctx.Device() && sdk <= 23 {
+		ret = "1.7"
+	} else if ctx.Device() && sdk <= 26 || !ctx.Config().TargetOpenJDK9() {
+		ret = "1.8"
+	} else if ctx.Device() && sdkVersion != "" && sdk == android.FutureApiLevel {
+		// TODO(ccross): once we generate stubs we should be able to use 1.9 for sdk_version: "current"
+		ret = "1.8"
+	} else {
+		ret = "1.9"
+	}
+
+	return ret
+}
+
 func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaBuilderFlags {
 
 	var flags javaBuilderFlags
@@ -802,28 +843,30 @@
 		flags.javacFlags = "$javacFlags"
 	}
 
-	if len(j.properties.Errorprone.Javacflags) > 0 {
-		flags.errorProneExtraJavacFlags = strings.Join(j.properties.Errorprone.Javacflags, " ")
+	if ctx.Config().RunErrorProne() {
+		if config.ErrorProneClasspath == nil {
+			ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
+		}
+
+		errorProneFlags := []string{
+			"-Xplugin:ErrorProne",
+			"${config.ErrorProneChecks}",
+		}
+		errorProneFlags = append(errorProneFlags, j.properties.Errorprone.Javacflags...)
+
+		flags.errorProneExtraJavacFlags = "${config.ErrorProneFlags} " +
+			"'" + strings.Join(errorProneFlags, " ") + "'"
+		flags.errorProneProcessorPath = classpath(android.PathsForSource(ctx, config.ErrorProneClasspath))
 	}
 
 	// javaVersion flag.
-	sdk := sdkStringToNumber(ctx, String(j.deviceProperties.Sdk_version))
-	if j.properties.Java_version != nil {
-		flags.javaVersion = *j.properties.Java_version
-	} else if ctx.Device() && sdk <= 23 {
-		flags.javaVersion = "1.7"
-	} else if ctx.Device() && sdk <= 26 || !ctx.Config().TargetOpenJDK9() {
-		flags.javaVersion = "1.8"
-	} else if ctx.Device() && String(j.deviceProperties.Sdk_version) != "" && sdk == android.FutureApiLevel {
-		// TODO(ccross): once we generate stubs we should be able to use 1.9 for sdk_version: "current"
-		flags.javaVersion = "1.8"
-	} else {
-		flags.javaVersion = "1.9"
-	}
+	flags.javaVersion = getJavaVersion(ctx,
+		String(j.properties.Java_version), String(j.deviceProperties.Sdk_version))
 
 	// classpath
 	flags.bootClasspath = append(flags.bootClasspath, deps.bootClasspath...)
 	flags.classpath = append(flags.classpath, deps.classpath...)
+	flags.processorPath = append(flags.processorPath, deps.processorPath...)
 
 	if len(flags.bootClasspath) == 0 && ctx.Host() && !ctx.Config().TargetOpenJDK9() &&
 		!Bool(j.properties.No_standard_libs) &&
@@ -963,7 +1006,7 @@
 	}
 	if len(uniqueSrcFiles) > 0 || len(srcJars) > 0 {
 		var extraJarDeps android.Paths
-		if ctx.Config().IsEnvTrue("RUN_ERROR_PRONE") {
+		if ctx.Config().RunErrorProne() {
 			// 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).
@@ -1183,6 +1226,10 @@
 	return j.exportAidlIncludeDirs
 }
 
+func (j *Module) ExportedSdkLibs() []string {
+	return j.exportedSdkLibs
+}
+
 var _ logtagsProducer = (*Module)(nil)
 
 func (j *Module) logtags() android.Paths {
@@ -1384,6 +1431,9 @@
 	Sdk_version *string
 
 	Installable *bool
+
+	// List of shared java libs that this module has dependencies to
+	Libs []string
 }
 
 type Import struct {
@@ -1394,6 +1444,7 @@
 
 	classpathFiles        android.Paths
 	combinedClasspathFile android.Path
+	exportedSdkLibs       []string
 }
 
 func (j *Import) Prebuilt() *android.Prebuilt {
@@ -1409,6 +1460,7 @@
 }
 
 func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
+	ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
 }
 
 func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1417,6 +1469,28 @@
 	outputFile := android.PathForModuleOut(ctx, "classes.jar")
 	TransformJarsToJar(ctx, outputFile, "for prebuilts", j.classpathFiles, android.OptionalPath{}, false, nil)
 	j.combinedClasspathFile = outputFile
+
+	ctx.VisitDirectDeps(func(module android.Module) {
+		otherName := ctx.OtherModuleName(module)
+		tag := ctx.OtherModuleDependencyTag(module)
+
+		switch dep := module.(type) {
+		case Dependency:
+			switch tag {
+			case libTag, staticLibTag:
+				// sdk lib names from dependencies are re-exported
+				j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
+			}
+		case SdkLibraryDependency:
+			switch tag {
+			case libTag:
+				// names of sdk libs that are directly depended are exported
+				j.exportedSdkLibs = append(j.exportedSdkLibs, otherName)
+			}
+		}
+	})
+
+	j.exportedSdkLibs = android.FirstUniqueStrings(j.exportedSdkLibs)
 }
 
 var _ Dependency = (*Import)(nil)
@@ -1433,6 +1507,10 @@
 	return nil
 }
 
+func (j *Import) ExportedSdkLibs() []string {
+	return j.exportedSdkLibs
+}
+
 var _ android.PrebuiltInterface = (*Import)(nil)
 
 func ImportFactory() android.Module {
diff --git a/java/java_test.go b/java/java_test.go
index 1678296..96bf224 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1095,6 +1095,12 @@
 			libs: ["foo", "bar"],
 			sdk_version: "system_current",
 		}
+		java_library {
+		    name: "qux",
+		    srcs: ["c.java"],
+		    libs: ["baz"],
+		    sdk_version: "system_current",
+		}
 		`)
 
 	// check the existence of the internal modules
@@ -1127,4 +1133,13 @@
 		t.Errorf("baz javac classpath %v should not contain %q", bazJavac.Args["classpath"],
 			"foo.stubs.jar")
 	}
+
+	// test if baz has exported SDK lib names foo and bar to qux
+	qux := ctx.ModuleForTests("qux", "android_common")
+	if quxLib, ok := qux.Module().(*Library); ok {
+		sdkLibs := quxLib.ExportedSdkLibs()
+		if len(sdkLibs) != 2 || !android.InList("foo", sdkLibs) || !android.InList("bar", sdkLibs) {
+			t.Errorf("qux should export \"foo\" and \"bar\" but exports %v", sdkLibs)
+		}
+	}
 }
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 50318bb..3f4b076 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -50,6 +50,20 @@
 	// no need to implement
 }
 
+func parseJarPath(ctx android.BaseModuleContext, path string) (module string, apiver string, scope string) {
+	elements := strings.Split(path, "/")
+
+	apiver = elements[0]
+	scope = elements[1]
+	if scope != "public" && scope != "system" && scope != "test" && scope != "core" {
+		// scope must be public, system or test
+		return
+	}
+
+	module = strings.TrimSuffix(elements[2], ".jar")
+	return
+}
+
 func parseApiFilePath(ctx android.BaseModuleContext, path string) (module string, apiver int, scope string) {
 	elements := strings.Split(path, "/")
 	ver, err := strconv.Atoi(elements[0])
@@ -70,6 +84,22 @@
 	return
 }
 
+func createImport(mctx android.TopDownMutatorContext, module string, scope string, apiver string, path string) {
+	props := struct {
+		Name        *string
+		Jars        []string
+		Sdk_version *string
+		Installable *bool
+	}{}
+	props.Name = proptools.StringPtr("sdk_" + scope + "_" + apiver + "_" + module)
+	props.Jars = append(props.Jars, path)
+	// TODO(hansson): change to scope after migration is done.
+	props.Sdk_version = proptools.StringPtr("current")
+	props.Installable = proptools.BoolPtr(false)
+
+	mctx.CreateModule(android.ModuleFactoryAdaptor(ImportFactory), &props)
+}
+
 func createFilegroup(mctx android.TopDownMutatorContext, module string, scope string, apiver string, path string) {
 	fgName := module + ".api." + scope + "." + apiver
 	filegroupProps := struct {
@@ -81,55 +111,82 @@
 	mctx.CreateModule(android.ModuleFactoryAdaptor(android.FileGroupFactory), &filegroupProps)
 }
 
+func prebuiltSdkStubs(mctx android.TopDownMutatorContext) {
+	mydir := mctx.ModuleDir() + "/"
+	// <apiver>/<scope>/<module>.jar
+	files, err := mctx.GlobWithDeps(mydir+"*/*/*.jar", nil)
+	if err != nil {
+		mctx.ModuleErrorf("failed to glob jar files under %q: %s", mydir, err)
+	}
+	if len(files) == 0 {
+		mctx.ModuleErrorf("no jar file found under %q", mydir)
+	}
+
+	for _, f := range files {
+		// create a Import module for each jar file
+		localPath := strings.TrimPrefix(f, mydir)
+		module, apiver, scope := parseJarPath(mctx, localPath)
+
+		if len(module) != 0 {
+			createImport(mctx, module, scope, apiver, localPath)
+		}
+	}
+}
+
+func prebuiltApiFiles(mctx android.TopDownMutatorContext) {
+	mydir := mctx.ModuleDir() + "/"
+	// <apiver>/<scope>/api/<module>.txt
+	files, err := mctx.GlobWithDeps(mydir+"*/*/api/*.txt", nil)
+	if err != nil {
+		mctx.ModuleErrorf("failed to glob api txt files under %q: %s", mydir, err)
+	}
+	if len(files) == 0 {
+		mctx.ModuleErrorf("no api file found under %q", mydir)
+	}
+
+	// construct a map to find out the latest api file path
+	// for each (<module>, <scope>) pair.
+	type latestApiInfo struct {
+		module string
+		scope  string
+		apiver int
+		path   string
+	}
+	m := make(map[string]latestApiInfo)
+
+	for _, f := range files {
+		// create a filegroup for each api txt file
+		localPath := strings.TrimPrefix(f, mydir)
+		module, apiver, scope := parseApiFilePath(mctx, localPath)
+		createFilegroup(mctx, module, scope, strconv.Itoa(apiver), localPath)
+
+		// find the latest apiver
+		key := module + "." + scope
+		info, ok := m[key]
+		if !ok {
+			m[key] = latestApiInfo{module, scope, apiver, localPath}
+		} else if apiver > info.apiver {
+			info.apiver = apiver
+			info.path = localPath
+		}
+	}
+	// create filegroups for the latest version of (<module>, <scope>) pairs
+	// sort the keys in order to make build.ninja stable
+	keys := make([]string, 0, len(m))
+	for k := range m {
+		keys = append(keys, k)
+	}
+	sort.Strings(keys)
+	for _, k := range keys {
+		info := m[k]
+		createFilegroup(mctx, info.module, info.scope, "latest", info.path)
+	}
+}
+
 func prebuiltApisMutator(mctx android.TopDownMutatorContext) {
 	if _, ok := mctx.Module().(*prebuiltApis); ok {
-		mydir := mctx.ModuleDir() + "/"
-		// <apiver>/<scope>/api/<module>.txt
-		files, err := mctx.GlobWithDeps(mydir+"*/*/api/*.txt", nil)
-		if err != nil {
-			mctx.ModuleErrorf("failed to glob api txt files under %q: %s", mydir, err)
-		}
-		if len(files) == 0 {
-			mctx.ModuleErrorf("no api file found under %q", mydir)
-		}
-
-		// construct a map to find out the latest api file path
-		// for each (<module>, <scope>) pair.
-		type latestApiInfo struct {
-			module string
-			scope  string
-			apiver int
-			path   string
-		}
-		m := make(map[string]latestApiInfo)
-
-		for _, f := range files {
-			// create a filegroup for each api txt file
-			localPath := strings.TrimPrefix(f, mydir)
-			module, apiver, scope := parseApiFilePath(mctx, localPath)
-			createFilegroup(mctx, module, scope, strconv.Itoa(apiver), localPath)
-
-			// find the latest apiver
-			key := module + "." + scope
-			info, ok := m[key]
-			if !ok {
-				m[key] = latestApiInfo{module, scope, apiver, localPath}
-			} else if apiver > info.apiver {
-				info.apiver = apiver
-				info.path = localPath
-			}
-		}
-		// create filegroups for the latest version of (<module>, <scope>) pairs
-		// sort the keys in order to make build.ninja stable
-		keys := make([]string, 0, len(m))
-		for k := range m {
-			keys = append(keys, k)
-		}
-		sort.Strings(keys)
-		for _, k := range keys {
-			info := m[k]
-			createFilegroup(mctx, info.module, info.scope, "latest", info.path)
-		}
+		prebuiltApiFiles(mctx)
+		prebuiltSdkStubs(mctx)
 	}
 }
 
diff --git a/java/sdk_library.go b/java/sdk_library.go
index abd2dc2..5dfc32f 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -67,9 +67,8 @@
 // classpath at runtime if requested via <uses-library>.
 //
 // TODO: these are big features that are currently missing
-// 1) ensuring that apps have appropriate <uses-library> tag
-// 2) disallowing linking to the runtime shared lib
-// 3) HTML generation
+// 1) disallowing linking to the runtime shared lib
+// 2) HTML generation
 
 func init() {
 	android.RegisterModuleType("java_sdk_library", sdkLibraryFactory)
@@ -100,12 +99,20 @@
 	// These libraries are not compiled into the stubs jar.
 	Static_libs []string `android:"arch_variant"`
 
+	// List of Java libraries that will be in the classpath when building stubs
+	Stub_only_libs []string `android:"arch_variant"`
+
 	// list of package names that will be documented and publicized as API
 	Api_packages []string
 
 	// list of package names that must be hidden from the API
 	Hidden_api_packages []string
 
+	Errorprone struct {
+		// List of javac flags that should only be used when running errorprone.
+		Javacflags []string
+	}
+
 	// TODO: determines whether to create HTML doc or not
 	//Html_doc *bool
 }
@@ -293,6 +300,7 @@
 		Name              *string
 		Srcs              []string
 		Sdk_version       *string
+		Libs              []string
 		Soc_specific      *bool
 		Device_specific   *bool
 		Product_specific  *bool
@@ -310,6 +318,7 @@
 	// sources are generated from the droiddoc
 	props.Srcs = []string{":" + module.docsName(apiScope)}
 	props.Sdk_version = proptools.StringPtr(module.sdkVersion(apiScope))
+	props.Libs = module.properties.Stub_only_libs
 	// Unbundled apps will use the prebult one from /prebuilts/sdk
 	props.Product_variables.Unbundled_build.Enabled = proptools.BoolPtr(false)
 	props.Product_variables.Pdk.Enabled = proptools.BoolPtr(false)
@@ -445,6 +454,9 @@
 		Device_specific  *bool
 		Product_specific *bool
 		Required         []string
+		Errorprone       struct {
+			Javacflags []string
+		}
 	}{}
 
 	props.Name = proptools.StringPtr(module.implName())
@@ -453,6 +465,7 @@
 	props.Static_libs = module.properties.Static_libs
 	// XML file is installed along with the impl lib
 	props.Required = []string{module.xmlFileName()}
+	props.Errorprone.Javacflags = module.properties.Errorprone.Javacflags
 
 	if module.SocSpecific() {
 		props.Soc_specific = proptools.BoolPtr(true)
diff --git a/python/python.go b/python/python.go
index 4b9111f..feb17da 100644
--- a/python/python.go
+++ b/python/python.go
@@ -574,32 +574,39 @@
 		destToPyData[path.dest] = path.src.String()
 	}
 
+	seen := make(map[android.Module]bool)
+
 	// visit all its dependencies in depth first.
-	ctx.VisitDepsDepthFirst(func(module android.Module) {
-		if ctx.OtherModuleDependencyTag(module) != pythonLibTag {
-			return
+	ctx.WalkDeps(func(child, parent android.Module) bool {
+		if ctx.OtherModuleDependencyTag(child) != pythonLibTag {
+			return false
 		}
+		if seen[child] {
+			return false
+		}
+		seen[child] = true
 		// Python modules only can depend on Python libraries.
-		if !isPythonLibModule(module) {
+		if !isPythonLibModule(child) {
 			panic(fmt.Errorf(
 				"the dependency %q of module %q is not Python library!",
-				ctx.ModuleName(), ctx.OtherModuleName(module)))
+				ctx.ModuleName(), ctx.OtherModuleName(child)))
 		}
-		if dep, ok := module.(PythonDependency); ok {
+		if dep, ok := child.(PythonDependency); ok {
 			srcs := dep.GetSrcsPathMappings()
 			for _, path := range srcs {
 				if !fillInMap(ctx, destToPySrcs,
-					path.dest, path.src.String(), ctx.ModuleName(), ctx.OtherModuleName(module)) {
+					path.dest, path.src.String(), ctx.ModuleName(), ctx.OtherModuleName(child)) {
 					continue
 				}
 			}
 			data := dep.GetDataPathMappings()
 			for _, path := range data {
 				fillInMap(ctx, destToPyData,
-					path.dest, path.src.String(), ctx.ModuleName(), ctx.OtherModuleName(module))
+					path.dest, path.src.String(), ctx.ModuleName(), ctx.OtherModuleName(child))
 			}
 			p.depsSrcsZips = append(p.depsSrcsZips, dep.GetSrcsZip())
 		}
+		return true
 	})
 }
 
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
new file mode 100755
index 0000000..6af0ca9
--- /dev/null
+++ b/scripts/manifest_fixer.py
@@ -0,0 +1,247 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# 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.
+#
+"""A tool for inserting values from the build system into a manifest."""
+
+from __future__ import print_function
+import argparse
+import sys
+from xml.dom import minidom
+
+
+android_ns = 'http://schemas.android.com/apk/res/android'
+
+
+def get_children_with_tag(parent, tag_name):
+  children = []
+  for child in  parent.childNodes:
+    if child.nodeType == minidom.Node.ELEMENT_NODE and \
+       child.tagName == tag_name:
+      children.append(child)
+  return children
+
+
+def find_child_with_attribute(element, tag_name, namespace_uri,
+                              attr_name, value):
+  for child in get_children_with_tag(element, tag_name):
+    attr = child.getAttributeNodeNS(namespace_uri, attr_name)
+    if attr is not None and attr.value == value:
+      return child
+  return None
+
+
+def parse_args():
+  """Parse commandline arguments."""
+
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--minSdkVersion', default='', dest='min_sdk_version',
+                      help='specify minSdkVersion used by the build system')
+  parser.add_argument('--uses-library', dest='uses_libraries', action='append',
+                      help='specify additional <uses-library> tag to add')
+  parser.add_argument('input', help='input AndroidManifest.xml file')
+  parser.add_argument('output', help='output AndroidManifest.xml file')
+  return parser.parse_args()
+
+
+def parse_manifest(doc):
+  """Get the manifest element."""
+
+  manifest = doc.documentElement
+  if manifest.tagName != 'manifest':
+    raise RuntimeError('expected manifest tag at root')
+  return manifest
+
+
+def ensure_manifest_android_ns(doc):
+  """Make sure the manifest tag defines the android namespace."""
+
+  manifest = parse_manifest(doc)
+
+  ns = manifest.getAttributeNodeNS(minidom.XMLNS_NAMESPACE, 'android')
+  if ns is None:
+    attr = doc.createAttributeNS(minidom.XMLNS_NAMESPACE, 'xmlns:android')
+    attr.value = android_ns
+    manifest.setAttributeNode(attr)
+  elif ns.value != android_ns:
+    raise RuntimeError('manifest tag has incorrect android namespace ' +
+                       ns.value)
+
+
+def as_int(s):
+  try:
+    i = int(s)
+  except ValueError:
+    return s, False
+  return i, True
+
+
+def compare_version_gt(a, b):
+  """Compare two SDK versions.
+
+  Compares a and b, treating codenames like 'Q' as higher
+  than numerical versions like '28'.
+
+  Returns True if a > b
+
+  Args:
+    a: value to compare
+    b: value to compare
+  Returns:
+    True if a is a higher version than b
+  """
+
+  a, a_is_int = as_int(a.upper())
+  b, b_is_int = as_int(b.upper())
+
+  if a_is_int == b_is_int:
+    # Both are codenames or both are versions, compare directly
+    return a > b
+  else:
+    # One is a codename, the other is not.  Return true if
+    # b is an integer version
+    return b_is_int
+
+
+def get_indent(element, default_level):
+  indent = ''
+  if element is not None and element.nodeType == minidom.Node.TEXT_NODE:
+    text = element.nodeValue
+    indent = text[:len(text)-len(text.lstrip())]
+  if not indent or indent == '\n':
+    # 1 indent = 4 space
+    indent = '\n' + (' ' * default_level * 4)
+  return indent
+
+
+def raise_min_sdk_version(doc, requested):
+  """Ensure the manifest contains a <uses-sdk> tag with a minSdkVersion.
+
+  Args:
+    doc: The XML document.  May be modified by this function.
+    requested: The requested minSdkVersion attribute.
+  Raises:
+    RuntimeError: invalid manifest
+  """
+
+  manifest = parse_manifest(doc)
+
+  # Get or insert the uses-sdk element
+  uses_sdk = get_children_with_tag(manifest, 'uses-sdk')
+  if len(uses_sdk) > 1:
+    raise RuntimeError('found multiple uses-sdk elements')
+  elif len(uses_sdk) == 1:
+    element = uses_sdk[0]
+  else:
+    element = doc.createElement('uses-sdk')
+    indent = get_indent(manifest.firstChild, 1)
+    manifest.insertBefore(element, manifest.firstChild)
+
+    # Insert an indent before uses-sdk to line it up with the indentation of the
+    # other children of the <manifest> tag.
+    manifest.insertBefore(doc.createTextNode(indent), manifest.firstChild)
+
+  # Get or insert the minSdkVersion attribute
+  min_attr = element.getAttributeNodeNS(android_ns, 'minSdkVersion')
+  if min_attr is None:
+    min_attr = doc.createAttributeNS(android_ns, 'android:minSdkVersion')
+    min_attr.value = '1'
+    element.setAttributeNode(min_attr)
+
+  # Update the value of the minSdkVersion attribute if necessary
+  if compare_version_gt(requested, min_attr.value):
+    min_attr.value = requested
+
+
+def add_uses_libraries(doc, new_uses_libraries):
+  """Add additional <uses-library> tags with android:required=true.
+
+  Args:
+    doc: The XML document. May be modified by this function.
+    new_uses_libraries: The names of libraries to be added by this function.
+  Raises:
+    RuntimeError: Invalid manifest
+  """
+
+  manifest = parse_manifest(doc)
+  elems = get_children_with_tag(manifest, 'application')
+  application = elems[0] if len(elems) == 1 else None
+  if len(elems) > 1:
+    raise RuntimeError('found multiple <application> tags')
+  elif not elems:
+    application = doc.createElement('application')
+    indent = get_indent(manifest.firstChild, 1)
+    first = manifest.firstChild
+    manifest.insertBefore(doc.createTextNode(indent), first)
+    manifest.insertBefore(application, first)
+
+  indent = get_indent(application.firstChild, 2)
+
+  last = application.lastChild
+  if last is not None and last.nodeType != minidom.Node.TEXT_NODE:
+    last = None
+
+  for name in new_uses_libraries:
+    if find_child_with_attribute(application, 'uses-library', android_ns,
+                                 'name', name) is not None:
+      # If the uses-library tag of the same 'name' attribute value exists,
+      # respect it.
+      continue
+
+    ul = doc.createElement('uses-library')
+    ul.setAttributeNS(android_ns, 'android:name', name)
+    ul.setAttributeNS(android_ns, 'android:required', 'true')
+
+    application.insertBefore(doc.createTextNode(indent), last)
+    application.insertBefore(ul, last)
+
+  # align the closing tag with the opening tag if it's not
+  # indented
+  if application.lastChild.nodeType != minidom.Node.TEXT_NODE:
+    indent = get_indent(application.previousSibling, 1)
+    application.appendChild(doc.createTextNode(indent))
+
+
+def write_xml(f, doc):
+  f.write('<?xml version="1.0" encoding="utf-8"?>\n')
+  for node in doc.childNodes:
+    f.write(node.toxml(encoding='utf-8') + '\n')
+
+
+def main():
+  """Program entry point."""
+  try:
+    args = parse_args()
+
+    doc = minidom.parse(args.input)
+
+    ensure_manifest_android_ns(doc)
+
+    if args.min_sdk_version:
+      raise_min_sdk_version(doc, args.min_sdk_version)
+
+    if args.uses_libraries:
+      add_uses_libraries(doc, args.uses_libraries)
+
+    with open(args.output, 'wb') as f:
+      write_xml(f, doc)
+
+  # pylint: disable=broad-except
+  except Exception as err:
+    print('error: ' + str(err), file=sys.stderr)
+    sys.exit(-1)
+
+if __name__ == '__main__':
+  main()
diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py
new file mode 100755
index 0000000..54a3784
--- /dev/null
+++ b/scripts/manifest_fixer_test.py
@@ -0,0 +1,249 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# 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.
+#
+"""Unit tests for manifest_fixer_test.py."""
+
+import StringIO
+import sys
+import unittest
+from xml.dom import minidom
+
+import manifest_fixer
+
+sys.dont_write_bytecode = True
+
+
+class CompareVersionGtTest(unittest.TestCase):
+  """Unit tests for compare_version_gt function."""
+
+  def test_sdk(self):
+    """Test comparing sdk versions."""
+    self.assertTrue(manifest_fixer.compare_version_gt('28', '27'))
+    self.assertFalse(manifest_fixer.compare_version_gt('27', '28'))
+    self.assertFalse(manifest_fixer.compare_version_gt('28', '28'))
+
+  def test_codename(self):
+    """Test comparing codenames."""
+    self.assertTrue(manifest_fixer.compare_version_gt('Q', 'P'))
+    self.assertFalse(manifest_fixer.compare_version_gt('P', 'Q'))
+    self.assertFalse(manifest_fixer.compare_version_gt('Q', 'Q'))
+
+  def test_sdk_codename(self):
+    """Test comparing sdk versions with codenames."""
+    self.assertTrue(manifest_fixer.compare_version_gt('Q', '28'))
+    self.assertFalse(manifest_fixer.compare_version_gt('28', 'Q'))
+
+  def test_compare_numeric(self):
+    """Test that numbers are compared in numeric and not lexicographic order."""
+    self.assertTrue(manifest_fixer.compare_version_gt('18', '8'))
+
+
+class RaiseMinSdkVersionTest(unittest.TestCase):
+  """Unit tests for raise_min_sdk_version function."""
+
+  def raise_min_sdk_version_test(self, input_manifest, min_sdk_version):
+    doc = minidom.parseString(input_manifest)
+    manifest_fixer.raise_min_sdk_version(doc, min_sdk_version)
+    output = StringIO.StringIO()
+    manifest_fixer.write_xml(output, doc)
+    return output.getvalue()
+
+  manifest_tmpl = (
+      '<?xml version="1.0" encoding="utf-8"?>\n'
+      '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
+      '%s'
+      '</manifest>\n')
+
+  def uses_sdk(self, v, extra=''):
+    if extra:
+      extra = ' ' + extra
+    return '    <uses-sdk android:minSdkVersion="%s"%s/>\n' % (v, extra)
+
+  def test_no_uses_sdk(self):
+    """Tests inserting a uses-sdk element into a manifest."""
+
+    manifest_input = self.manifest_tmpl % ''
+    expected = self.manifest_tmpl % self.uses_sdk('28')
+    output = self.raise_min_sdk_version_test(manifest_input, '28')
+    self.assertEqual(output, expected)
+
+  def test_no_min(self):
+    """Tests inserting a minSdkVersion attribute into a uses-sdk element."""
+
+    manifest_input = self.manifest_tmpl % '    <uses-sdk extra="foo"/>\n'
+    expected = self.manifest_tmpl % self.uses_sdk('28', 'extra="foo"')
+    output = self.raise_min_sdk_version_test(manifest_input, '28')
+    self.assertEqual(output, expected)
+
+  def test_raise_min(self):
+    """Tests inserting a minSdkVersion attribute into a uses-sdk element."""
+
+    manifest_input = self.manifest_tmpl % self.uses_sdk('27')
+    expected = self.manifest_tmpl % self.uses_sdk('28')
+    output = self.raise_min_sdk_version_test(manifest_input, '28')
+    self.assertEqual(output, expected)
+
+  def test_raise(self):
+    """Tests raising a minSdkVersion attribute."""
+
+    manifest_input = self.manifest_tmpl % self.uses_sdk('27')
+    expected = self.manifest_tmpl % self.uses_sdk('28')
+    output = self.raise_min_sdk_version_test(manifest_input, '28')
+    self.assertEqual(output, expected)
+
+  def test_no_raise_min(self):
+    """Tests a minSdkVersion that doesn't need raising."""
+
+    manifest_input = self.manifest_tmpl % self.uses_sdk('28')
+    expected = manifest_input
+    output = self.raise_min_sdk_version_test(manifest_input, '27')
+    self.assertEqual(output, expected)
+
+  def test_raise_codename(self):
+    """Tests raising a minSdkVersion attribute to a codename."""
+
+    manifest_input = self.manifest_tmpl % self.uses_sdk('28')
+    expected = self.manifest_tmpl % self.uses_sdk('P')
+    output = self.raise_min_sdk_version_test(manifest_input, 'P')
+    self.assertEqual(output, expected)
+
+  def test_no_raise_codename(self):
+    """Tests a minSdkVersion codename that doesn't need raising."""
+
+    manifest_input = self.manifest_tmpl % self.uses_sdk('P')
+    expected = manifest_input
+    output = self.raise_min_sdk_version_test(manifest_input, '28')
+    self.assertEqual(output, expected)
+
+  def test_extra(self):
+    """Tests that extra attributes and elements are maintained."""
+
+    manifest_input = self.manifest_tmpl % (
+        '    <!-- comment -->\n'
+        '    <uses-sdk android:minSdkVersion="27" extra="foo"/>\n'
+        '    <application/>\n')
+
+    expected = self.manifest_tmpl % (
+        '    <!-- comment -->\n'
+        '    <uses-sdk android:minSdkVersion="28" extra="foo"/>\n'
+        '    <application/>\n')
+
+    output = self.raise_min_sdk_version_test(manifest_input, '28')
+
+    self.assertEqual(output, expected)
+
+  def test_indent(self):
+    """Tests that an inserted element copies the existing indentation."""
+
+    manifest_input = self.manifest_tmpl % '  <!-- comment -->\n'
+
+    expected = self.manifest_tmpl % (
+        '  <uses-sdk android:minSdkVersion="28"/>\n'
+        '  <!-- comment -->\n')
+
+    output = self.raise_min_sdk_version_test(manifest_input, '28')
+
+    self.assertEqual(output, expected)
+
+
+class AddUsesLibrariesTest(unittest.TestCase):
+  """Unit tests for add_uses_libraries function."""
+
+  def run_test(self, input_manifest, new_uses_libraries):
+    doc = minidom.parseString(input_manifest)
+    manifest_fixer.add_uses_libraries(doc, new_uses_libraries)
+    output = StringIO.StringIO()
+    manifest_fixer.write_xml(output, doc)
+    return output.getvalue()
+
+  manifest_tmpl = (
+      '<?xml version="1.0" encoding="utf-8"?>\n'
+      '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
+      '    <application>\n'
+      '%s'
+      '    </application>\n'
+      '</manifest>\n')
+
+  def uses_libraries(self, name_required_pairs):
+    ret = ''
+    for name, required in name_required_pairs:
+      ret += (
+          '        <uses-library android:name="%s" android:required="%s"/>\n'
+      ) % (name, required)
+
+    return ret
+
+  def test_empty(self):
+    """Empty new_uses_libraries must not touch the manifest."""
+    manifest_input = self.manifest_tmpl % self.uses_libraries([
+        ('foo', 'true'),
+        ('bar', 'false')])
+    expected = manifest_input
+    output = self.run_test(manifest_input, [])
+    self.assertEqual(output, expected)
+
+  def test_not_overwrite(self):
+    """new_uses_libraries must not overwrite existing tags."""
+    manifest_input = self.manifest_tmpl % self.uses_libraries([
+        ('foo', 'true'),
+        ('bar', 'false')])
+    expected = manifest_input
+    output = self.run_test(manifest_input, ['foo', 'bar'])
+    self.assertEqual(output, expected)
+
+  def test_add(self):
+    """New names are added with 'required:true'."""
+    manifest_input = self.manifest_tmpl % self.uses_libraries([
+        ('foo', 'true'),
+        ('bar', 'false')])
+    expected = self.manifest_tmpl % self.uses_libraries([
+        ('foo', 'true'),
+        ('bar', 'false'),
+        ('baz', 'true'),
+        ('qux', 'true')])
+    output = self.run_test(manifest_input, ['bar', 'baz', 'qux'])
+    self.assertEqual(output, expected)
+
+  def test_no_application(self):
+    """When there is no <application> tag, the tag is added."""
+    manifest_input = (
+        '<?xml version="1.0" encoding="utf-8"?>\n'
+        '<manifest xmlns:android='
+        '"http://schemas.android.com/apk/res/android">\n'
+        '</manifest>\n')
+    expected = self.manifest_tmpl % self.uses_libraries([
+        ('foo', 'true'),
+        ('bar', 'true')])
+    output = self.run_test(manifest_input, ['foo', 'bar'])
+    self.assertEqual(output, expected)
+
+  def test_empty_application(self):
+    """Even when here is an empty <application/> tag, the libs are added."""
+    manifest_input = (
+        '<?xml version="1.0" encoding="utf-8"?>\n'
+        '<manifest xmlns:android='
+        '"http://schemas.android.com/apk/res/android">\n'
+        '    <application/>\n'
+        '</manifest>\n')
+    expected = self.manifest_tmpl % self.uses_libraries([
+        ('foo', 'true'),
+        ('bar', 'true')])
+    output = self.run_test(manifest_input, ['foo', 'bar'])
+    self.assertEqual(output, expected)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/ui/build/config.go b/ui/build/config.go
index 6f2d24a..d0378ec 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -50,6 +50,7 @@
 	targetDevice    string
 	targetDeviceDir string
 
+	pdkBuild       bool
 	brokenDupRules bool
 
 	pathReplaced bool
@@ -163,19 +164,7 @@
 		if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
 			return override
 		}
-		v, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK9")
-		if !ok {
-			v2, ok2 := ret.environ.Get("RUN_ERROR_PRONE")
-			if ok2 && (v2 == "true") {
-				v = "false"
-			} else {
-				v = "1.8"
-			}
-		}
-		if v != "false" {
-			return java9Home
-		}
-		return java8Home
+		return java9Home
 	}()
 	absJavaHome := absPath(ctx, javaHome)
 
@@ -579,3 +568,11 @@
 func (c *configImpl) TargetDeviceDir() string {
 	return c.targetDeviceDir
 }
+
+func (c *configImpl) SetPdkBuild(pdk bool) {
+	c.pdkBuild = pdk
+}
+
+func (c *configImpl) IsPdkBuild() bool {
+	return c.pdkBuild
+}
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index cc9e742..8429a8a 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -162,6 +162,11 @@
 
 		// Whether --werror_overriding_commands will work
 		"BUILD_BROKEN_DUP_RULES",
+
+		// Not used, but useful to be in the soong.log
+		"BUILD_BROKEN_ANDROIDMK_EXPORTS",
+		"BUILD_BROKEN_DUP_COPY_HEADERS",
+		"BUILD_BROKEN_PHONY_TARGETS",
 	}, exportEnvVars...), BannerVars...)
 
 	make_vars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true)
@@ -187,5 +192,6 @@
 	config.SetTargetDevice(make_vars["TARGET_DEVICE"])
 	config.SetTargetDeviceDir(make_vars["TARGET_DEVICE_DIR"])
 
+	config.SetPdkBuild(make_vars["TARGET_BUILD_PDK"] == "true")
 	config.SetBuildBrokenDupRules(make_vars["BUILD_BROKEN_DUP_RULES"] != "false")
 }
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 81edd32..7635c10 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -77,10 +77,17 @@
 		"--color_warnings",
 		"--gen_all_targets",
 		"--werror_find_emulator",
+		"--no_builtin_rules",
+		"--werror_suffix_rules",
 		"--kati_stats",
 		"-f", "build/make/core/main.mk",
 	}
 
+	// PDK builds still uses a few implicit rules
+	if !config.IsPdkBuild() {
+		args = append(args, "--werror_implicit_rules")
+	}
+
 	if !config.BuildBrokenDupRules() {
 		args = append(args, "--werror_overriding_commands")
 	}
diff --git a/zip/zip.go b/zip/zip.go
index b7e3764..a89fa9f 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -788,13 +788,16 @@
 		Name: rel,
 	}
 	fileHeader.SetModTime(z.time)
-	fileHeader.SetMode(0700 | os.ModeSymlink)
+	fileHeader.SetMode(0777 | os.ModeSymlink)
 
 	dest, err := os.Readlink(file)
 	if err != nil {
 		return err
 	}
 
+	fileHeader.UncompressedSize64 = uint64(len(dest))
+	fileHeader.CRC32 = crc32.ChecksumIEEE([]byte(dest))
+
 	ze := make(chan *zipEntry, 1)
 	futureReaders := make(chan chan io.Reader, 1)
 	futureReader := make(chan io.Reader, 1)