Merge "Set default pool when RBE or goma is enabled"
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a09c56d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/.idea
diff --git a/Android.bp b/Android.bp
index 8d0c1ea..c73c3da 100644
--- a/Android.bp
+++ b/Android.bp
@@ -206,6 +206,7 @@
     ],
     testSrcs: [
         "cc/cc_test.go",
+        "cc/compiler_test.go",
         "cc/gen_test.go",
         "cc/genrule_test.go",
         "cc/library_test.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index b66fd18..4893bf4 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -230,9 +230,6 @@
 		}
 		a.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(amod.commonProperties.Device_specific))
 		a.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(amod.commonProperties.Product_specific))
-		// TODO(b/135957588) product_services_specific is matched to LOCAL_PRODUCT_MODULE
-		// as a workaround. Remove this after clearing all Android.bp
-		a.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(amod.commonProperties.Product_services_specific))
 		a.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(amod.commonProperties.System_ext_specific))
 		if amod.commonProperties.Owner != nil {
 			a.SetString("LOCAL_MODULE_OWNER", *amod.commonProperties.Owner)
diff --git a/android/module.go b/android/module.go
index a6b8d53..e8d7360 100644
--- a/android/module.go
+++ b/android/module.go
@@ -365,11 +365,6 @@
 	// /system/product if product partition does not exist).
 	Product_specific *bool
 
-	// TODO(b/135957588) Product_services_specific will be removed once we clear all Android.bp
-	// files that have 'product_services_specific: true'. This will be converted to
-	// Product_speicific as a workaround.
-	Product_services_specific *bool
-
 	// whether this module extends system. When set to true, it is installed into /system_ext
 	// (or /system/system_ext if system_ext partition does not exist).
 	System_ext_specific *bool
diff --git a/android/sdk.go b/android/sdk.go
index 8e1e106..d66816d 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -31,6 +31,9 @@
 	MemberName() string
 	BuildWithSdks(sdks SdkRefs)
 	RequiredSdks() SdkRefs
+
+	// Build a snapshot of the module.
+	BuildSnapshot(sdkModuleContext ModuleContext, builder SnapshotBuilder)
 }
 
 // SdkRef refers to a version of an SDK
@@ -103,6 +106,7 @@
 // interface. InitSdkAwareModule should be called to initialize this struct.
 type SdkBase struct {
 	properties sdkProperties
+	module     SdkAware
 }
 
 func (s *SdkBase) sdkBase() *SdkBase {
@@ -142,9 +146,34 @@
 	return s.properties.RequiredSdks
 }
 
+func (s *SdkBase) BuildSnapshot(sdkModuleContext ModuleContext, builder SnapshotBuilder) {
+	sdkModuleContext.ModuleErrorf("module type " + sdkModuleContext.OtherModuleType(s.module) + " cannot be used in an sdk")
+}
+
 // InitSdkAwareModule initializes the SdkBase struct. This must be called by all modules including
 // SdkBase.
 func InitSdkAwareModule(m SdkAware) {
 	base := m.sdkBase()
+	base.module = m
 	m.AddProperties(&base.properties)
 }
+
+// Provide support for generating the build rules which will build the snapshot.
+type SnapshotBuilder interface {
+	// Copy src to the dest (which is a snapshot relative path) and add the dest
+	// to the zip
+	CopyToSnapshot(src Path, dest string)
+
+	// Get the AndroidBpFile for the snapshot.
+	AndroidBpFile() GeneratedSnapshotFile
+
+	// Get a versioned name appropriate for the SDK snapshot version being taken.
+	VersionedSdkMemberName(unversionedName string) interface{}
+}
+
+// Provides support for generating a file, e.g. the Android.bp file.
+type GeneratedSnapshotFile interface {
+	Printfln(format string, args ...interface{})
+	Indent()
+	Dedent()
+}
diff --git a/apex/apex.go b/apex/apex.go
index f03a8f9..fe085b9 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -219,7 +219,7 @@
 }
 
 func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
-	ctx.TopDown("apex_deps", apexDepsMutator)
+	ctx.BottomUp("apex_deps", apexDepsMutator)
 	ctx.BottomUp("apex", apexMutator).Parallel()
 	ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
 	ctx.BottomUp("apex_uses", apexUsesMutator).Parallel()
@@ -272,7 +272,7 @@
 
 // Mark the direct and transitive dependencies of apex bundles so that they
 // can be built for the apex bundles.
-func apexDepsMutator(mctx android.TopDownMutatorContext) {
+func apexDepsMutator(mctx android.BottomUpMutatorContext) {
 	if a, ok := mctx.Module().(*apexBundle); ok {
 		apexBundleName := mctx.ModuleName()
 		mctx.WalkDeps(func(child, parent android.Module) bool {
@@ -1217,7 +1217,7 @@
 			if am, ok := child.(android.ApexModule); ok {
 				// We cannot use a switch statement on `depTag` here as the checked
 				// tags used below are private (e.g. `cc.sharedDepTag`).
-				if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) || java.IsJniDepTag(depTag) {
+				if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) {
 					if cc, ok := child.(*cc.Module); ok {
 						if android.InList(cc.Name(), providedNativeSharedLibs) {
 							// If we're using a shared library which is provided from other APEX,
@@ -1254,6 +1254,8 @@
 						filesInfo = append(filesInfo, apexFile{fileToCopy, moduleName, dirInApex, nativeTest, cc, nil})
 						return true
 					}
+				} else if java.IsJniDepTag(depTag) {
+					// Do nothing for JNI dep. JNI libraries are always embedded in APK-in-APEX.
 				} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
 					ctx.ModuleErrorf("unexpected tag %q for indirect dependency %q", depTag, depName)
 				}
@@ -1362,7 +1364,7 @@
 	})
 
 	// b/143654022 Q apexd can't understand newly added keys in apex_manifest.json
-	// prepare stripp-downed version so that APEX modules built from R+ can be installed to Q
+	// prepare stripped-down version so that APEX modules built from R+ can be installed to Q
 	a.manifestJsonOut = android.PathForModuleOut(ctx, "apex_manifest.json")
 	ctx.Build(pctx, android.BuildParams{
 		Rule:   stripApexManifestRule,
@@ -2118,7 +2120,7 @@
 				entries.SetString("LOCAL_MODULE_PATH", p.installDir.ToMakePath().String())
 				entries.SetString("LOCAL_MODULE_STEM", p.installFilename)
 				entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable())
-				entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", p.properties.Overrides...)
+				entries.AddStrings("LOCAL_OVERRIDES_MODULES", p.properties.Overrides...)
 			},
 		},
 	}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 614164d..1aac852 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -115,6 +115,9 @@
 	ctx.RegisterModuleType("cc_prebuilt_library_static", android.ModuleFactoryAdaptor(cc.PrebuiltStaticLibraryFactory))
 	ctx.RegisterModuleType("cc_binary", android.ModuleFactoryAdaptor(cc.BinaryFactory))
 	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
+	ctx.RegisterModuleType("cc_defaults", android.ModuleFactoryAdaptor(func() android.Module {
+		return cc.DefaultsFactory()
+	}))
 	ctx.RegisterModuleType("cc_test", android.ModuleFactoryAdaptor(cc.TestFactory))
 	ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory))
 	ctx.RegisterModuleType("vndk_prebuilt_shared", android.ModuleFactoryAdaptor(cc.VndkPrebuiltSharedFactory))
@@ -2251,9 +2254,9 @@
 	p := ctx.ModuleForTests("myapex.prebuilt", "android_common").Module().(*Prebuilt)
 
 	expected := []string{"myapex"}
-	actual := android.AndroidMkEntriesForTest(t, config, "", p).EntryMap["LOCAL_OVERRIDES_PACKAGES"]
+	actual := android.AndroidMkEntriesForTest(t, config, "", p).EntryMap["LOCAL_OVERRIDES_MODULES"]
 	if !reflect.DeepEqual(actual, expected) {
-		t.Errorf("Incorrect LOCAL_OVERRIDES_PACKAGES value '%s', expected '%s'", actual, expected)
+		t.Errorf("Incorrect LOCAL_OVERRIDES_MODULES value '%s', expected '%s'", actual, expected)
 	}
 }
 
@@ -2538,7 +2541,17 @@
 
 	ensureContains(t, copyCmds, "image.apex/app/AppFoo/AppFoo.apk")
 	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv/AppFooPriv.apk")
-	ensureContains(t, copyCmds, "image.apex/lib64/libjni.so")
+
+	// JNI libraries are embedded inside APK
+	appZipRule := ctx.ModuleForTests("AppFoo", "android_common_myapex").Rule("zip")
+	libjniOutput := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_core_shared_myapex").Module().(*cc.Module).OutputFile()
+	ensureListContains(t, appZipRule.Implicits.Strings(), libjniOutput.String())
+	// ... uncompressed
+	if args := appZipRule.Args["jarArgs"]; !strings.Contains(args, "-L 0") {
+		t.Errorf("jni lib is not uncompressed for AppFoo")
+	}
+	// ... and not directly inside the APEX
+	ensureNotContains(t, copyCmds, "image.apex/lib64/libjni.so")
 }
 
 func TestApexWithAppImports(t *testing.T) {
@@ -2586,6 +2599,40 @@
 	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPrivPrebuilt/AppFooPrivPrebuilt.apk")
 }
 
+func TestApexPropertiesShouldBeDefaultable(t *testing.T) {
+	// libfoo's apex_available comes from cc_defaults
+	testApexError(t, `"myapex" .*: requires "libfoo" that is not available for the APEX`, `
+	apex {
+		name: "myapex",
+		key: "myapex.key",
+		native_shared_libs: ["libfoo"],
+	}
+
+	apex_key {
+		name: "myapex.key",
+		public_key: "testkey.avbpubkey",
+		private_key: "testkey.pem",
+	}
+
+	apex {
+		name: "otherapex",
+		key: "myapex.key",
+		native_shared_libs: ["libfoo"],
+	}
+
+	cc_defaults {
+		name: "libfoo-defaults",
+		apex_available: ["otherapex"],
+	}
+
+	cc_library {
+		name: "libfoo",
+		defaults: ["libfoo-defaults"],
+		stl: "none",
+		system_shared_libs: [],
+	}`)
+}
+
 func TestApexAvailable(t *testing.T) {
 	// libfoo is not available to myapex, but only to otherapex
 	testApexError(t, "requires \"libfoo\" that is not available for the APEX", `
diff --git a/bpfix/Android.bp b/bpfix/Android.bp
index aec9ff9..e291578 100644
--- a/bpfix/Android.bp
+++ b/bpfix/Android.bp
@@ -28,9 +28,9 @@
 
 bootstrap_go_package {
     name: "bpfix-cmd",
-    pkgPath: "android/soong/bpfix/bpfix/cmd",
+    pkgPath: "android/soong/bpfix/cmd_lib",
     srcs: [
-        "cmd-lib/bpfix.go",
+        "cmd_lib/bpfix.go",
     ],
     deps: [
         "bpfix-lib",
diff --git a/bpfix/cmd/main.go b/bpfix/cmd/main.go
index 8ca16b4..ad68144 100644
--- a/bpfix/cmd/main.go
+++ b/bpfix/cmd/main.go
@@ -16,10 +16,8 @@
 
 package main
 
-import (
-	"android/soong/bpfix/bpfix/cmd"
-)
+import "android/soong/bpfix/cmd_lib"
 
 func main() {
-	cmd.Run()
+	cmd_lib.Run()
 }
diff --git a/bpfix/cmd-lib/bpfix.go b/bpfix/cmd_lib/bpfix.go
similarity index 99%
rename from bpfix/cmd-lib/bpfix.go
rename to bpfix/cmd_lib/bpfix.go
index 98122f2..f90f65b 100644
--- a/bpfix/cmd-lib/bpfix.go
+++ b/bpfix/cmd_lib/bpfix.go
@@ -16,7 +16,7 @@
 
 // TODO(jeffrygaston) should this file be consolidated with bpfmt.go?
 
-package cmd
+package cmd_lib
 
 import (
 	"bytes"
diff --git a/cc/cc.go b/cc/cc.go
index 840fe24..06617ad 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -509,7 +509,7 @@
 	return String(c.Properties.Sdk_version)
 }
 
-func (c *Module) IncludeDirs(ctx android.BaseModuleContext) android.Paths {
+func (c *Module) IncludeDirs() android.Paths {
 	if c.linker != nil {
 		if library, ok := c.linker.(exportedFlagsProducer); ok {
 			return library.exportedDirs()
@@ -719,11 +719,9 @@
 		}
 	})
 	android.InitAndroidArchModule(c, c.hod, c.multilib)
-
-	android.InitDefaultableModule(c)
-
 	android.InitApexModule(c)
 	android.InitSdkAwareModule(c)
+	android.InitDefaultableModule(c)
 
 	return c
 }
@@ -2042,10 +2040,11 @@
 				}
 			}
 
+			depPaths.IncludeDirs = append(depPaths.IncludeDirs, ccDep.IncludeDirs()...)
+
 			// Exporting flags only makes sense for cc.Modules
 			if _, ok := ccDep.(*Module); ok {
 				if i, ok := ccDep.(*Module).linker.(exportedFlagsProducer); ok {
-					depPaths.IncludeDirs = append(depPaths.IncludeDirs, i.exportedDirs()...)
 					depPaths.SystemIncludeDirs = append(depPaths.SystemIncludeDirs, i.exportedSystemDirs()...)
 					depPaths.GeneratedHeaders = append(depPaths.GeneratedHeaders, i.exportedDeps()...)
 					depPaths.Flags = append(depPaths.Flags, i.exportedFlags()...)
@@ -2469,10 +2468,10 @@
 		&PgoProperties{},
 		&XomProperties{},
 		&android.ProtoProperties{},
+		&android.ApexProperties{},
 	)
 
 	android.InitDefaultsModule(module)
-	android.InitApexModule(module)
 
 	return module
 }
diff --git a/cc/check.go b/cc/check.go
index 4e9e160..46328e9 100644
--- a/cc/check.go
+++ b/cc/check.go
@@ -38,6 +38,11 @@
 			ctx.PropertyErrorf(prop, "Illegal flag `%s`", flag)
 		} else if flag == "--coverage" {
 			ctx.PropertyErrorf(prop, "Bad flag: `%s`, use native_coverage instead", flag)
+		} else if flag == "-Weverything" {
+			if !ctx.Config().IsEnvTrue("ANDROID_TEMPORARILY_ALLOW_WEVERYTHING") {
+				ctx.PropertyErrorf(prop, "-Weverything is not allowed in Android.bp files.  "+
+					"Build with `m ANDROID_TEMPORARILY_ALLOW_WEVERYTHING=true` to experiment locally with -Weverything.")
+			}
 		} else if strings.Contains(flag, " ") {
 			args := strings.Split(flag, " ")
 			if args[0] == "-include" {
diff --git a/cc/compiler.go b/cc/compiler.go
index bb40a5b..671861b 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -17,6 +17,7 @@
 import (
 	"fmt"
 	"path/filepath"
+	"regexp"
 	"strconv"
 	"strings"
 
@@ -252,6 +253,7 @@
 // per-target values, module type values, and per-module Blueprints properties
 func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags {
 	tc := ctx.toolchain()
+	modulePath := android.PathForModuleSrc(ctx).String()
 
 	compiler.srcsBeforeGen = android.PathsForModuleSrcExcludes(ctx, compiler.Properties.Srcs, compiler.Properties.Exclude_srcs)
 	compiler.srcsBeforeGen = append(compiler.srcsBeforeGen, deps.GeneratedSources...)
@@ -289,8 +291,8 @@
 
 	if compiler.Properties.Include_build_directory == nil ||
 		*compiler.Properties.Include_build_directory {
-		flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-I"+android.PathForModuleSrc(ctx).String())
-		flags.Local.YasmFlags = append(flags.Local.YasmFlags, "-I"+android.PathForModuleSrc(ctx).String())
+		flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-I"+modulePath)
+		flags.Local.YasmFlags = append(flags.Local.YasmFlags, "-I"+modulePath)
 	}
 
 	if !(ctx.useSdk() || ctx.useVndk()) || ctx.Host() {
@@ -381,7 +383,7 @@
 		"${config.CommonClangGlobalCflags}",
 		fmt.Sprintf("${config.%sClangGlobalCflags}", hod))
 
-	if strings.HasPrefix(android.PathForModuleSrc(ctx).String(), "external/") {
+	if isThirdParty(modulePath) {
 		flags.Global.CommonFlags = append([]string{"${config.ClangExternalCflags}"}, flags.Global.CommonFlags...)
 	}
 
@@ -438,7 +440,7 @@
 	// vendor/device specific things), we could extend this to be a ternary
 	// value.
 	strict := true
-	if strings.HasPrefix(android.PathForModuleSrc(ctx).String(), "external/") {
+	if strings.HasPrefix(modulePath, "external/") {
 		strict = false
 	}
 
@@ -580,3 +582,28 @@
 
 	return TransformSourceToObj(ctx, subdir, srcFiles, flags, pathDeps, cFlagsDeps)
 }
+
+var thirdPartyDirPrefixExceptions = []*regexp.Regexp{
+	regexp.MustCompile("^vendor/[^/]*google[^/]*/"),
+	regexp.MustCompile("^hardware/google/"),
+	regexp.MustCompile("^hardware/interfaces/"),
+	regexp.MustCompile("^hardware/libhardware[^/]*/"),
+	regexp.MustCompile("^hardware/ril/"),
+}
+
+func isThirdParty(path string) bool {
+	thirdPartyDirPrefixes := []string{"external/", "vendor/", "hardware/"}
+
+	for _, prefix := range thirdPartyDirPrefixes {
+		if strings.HasPrefix(path, prefix) {
+			for _, prefix := range thirdPartyDirPrefixExceptions {
+				if prefix.MatchString(path) {
+					return false
+				}
+			}
+			break
+		}
+	}
+
+	return true
+}
diff --git a/cc/compiler_test.go b/cc/compiler_test.go
new file mode 100644
index 0000000..c301388
--- /dev/null
+++ b/cc/compiler_test.go
@@ -0,0 +1,43 @@
+// Copyright 2019 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 cc
+
+import (
+	"testing"
+)
+
+func TestIsThirdParty(t *testing.T) {
+	shouldFail := []string{
+		"external/foo/",
+		"vendor/bar/",
+		"hardware/underwater_jaguar/",
+	}
+	shouldPass := []string{
+		"vendor/google/cts/",
+		"hardware/google/pixel",
+		"hardware/interfaces/camera",
+		"hardware/ril/supa_ril",
+	}
+	for _, path := range shouldFail {
+		if !isThirdParty(path) {
+			t.Errorf("Expected %s to be considered third party", path)
+		}
+	}
+	for _, path := range shouldPass {
+		if isThirdParty(path) {
+			t.Errorf("Expected %s to *not* be considered third party", path)
+		}
+	}
+}
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 030a076..eddc341 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -163,8 +163,8 @@
 		"-Wno-tautological-type-limit-compare",
 	}, " "))
 
-	// Extra cflags for projects under external/ directory to disable warnings that are infeasible
-	// to fix in all the external projects and their upstream repos.
+	// Extra cflags for external third-party projects to disable warnings that
+	// are infeasible to fix in all the external projects and their upstream repos.
 	pctx.StaticVariable("ClangExtraExternalCflags", strings.Join([]string{
 		"-Wno-enum-compare",
 		"-Wno-enum-compare-switch",
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 1f06fb0..476d805 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -103,8 +103,11 @@
 
 func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
 	flags = fuzz.binaryDecorator.linkerFlags(ctx, flags)
-	// RunPaths on devices isn't instantiated by the base linker.
+	// RunPaths on devices isn't instantiated by the base linker. `../lib` for
+	// installed fuzz targets (both host and device), and `./lib` for fuzz
+	// target packages.
 	flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
+	flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
 	return flags
 }
 
@@ -123,19 +126,23 @@
 	// Enumerate the first level of dependencies, as we discard all non-library
 	// modules in the BFS loop below.
 	ctx.VisitDirectDeps(module, func(dep android.Module) {
-		fringe = append(fringe, dep)
+		if isValidSharedDependency(dep, sharedDeps) {
+			fringe = append(fringe, dep)
+		}
 	})
 
 	for i := 0; i < len(fringe); i++ {
 		module := fringe[i]
-		if !isValidSharedDependency(module, sharedDeps) {
+		if _, exists := sharedDeps[module.Name()]; exists {
 			continue
 		}
 
 		ccModule := module.(*Module)
 		sharedDeps[ccModule.Name()] = ccModule.UnstrippedOutputFile()
 		ctx.VisitDirectDeps(module, func(dep android.Module) {
-			fringe = append(fringe, dep)
+			if isValidSharedDependency(dep, sharedDeps) {
+				fringe = append(fringe, dep)
+			}
 		})
 	}
 }
@@ -155,10 +162,21 @@
 	if linkable, ok := dependency.(LinkableInterface); !ok || // Discard non-linkables.
 		!linkable.CcLibraryInterface() || !linkable.Shared() || // Discard static libs.
 		linkable.UseVndk() || // Discard vendor linked libraries.
-		!linkable.CcLibrary() || linkable.BuildStubs() { // Discard stubs libs (only CCLibrary variants).
+		// Discard stubs libs (only CCLibrary variants). Prebuilt libraries should not
+		// be excluded on the basis of they're not CCLibrary()'s.
+		(linkable.CcLibrary() && linkable.BuildStubs()) {
 		return false
 	}
 
+	// We discarded module stubs libraries above, but the LLNDK prebuilts stubs
+	// libraries must be handled differently - by looking for the stubDecorator.
+	// Discard LLNDK prebuilts stubs as well.
+	if ccLibrary, isCcLibrary := dependency.(*Module); isCcLibrary {
+		if _, isLLndkStubLibrary := ccLibrary.linker.(*stubDecorator); isLLndkStubLibrary {
+			return false
+		}
+	}
+
 	// If this library has already been traversed, we don't need to do any more work.
 	if _, exists := sharedDeps[dependency.Name()]; exists {
 		return false
@@ -232,6 +250,8 @@
 			sharedLibraryInstallLocation(
 				lib, ctx.Host(), ctx.Arch().ArchType.String()))
 	}
+
+	sort.Strings(fuzz.installedSharedDeps)
 }
 
 func NewFuzz(hod android.HostOrDeviceSupported) *Module {
@@ -315,9 +335,10 @@
 			return
 		}
 
-		// Discard vendor-NDK-linked modules, they're duplicates of fuzz targets
-		// we're going to package anyway.
-		if ccModule.UseVndk() || !ccModule.Enabled() {
+		// Discard vendor-NDK-linked + recovery modules, they're duplicates of
+		// fuzz targets we're going to package anyway.
+		if !ccModule.Enabled() || ccModule.Properties.PreventInstall ||
+			ccModule.UseVndk() || ccModule.InRecovery() {
 			return
 		}
 
@@ -335,7 +356,24 @@
 		sharedLibraries := make(map[string]android.Path)
 		collectAllSharedDependencies(module, sharedLibraries, ctx)
 
+		var files []fileToZip
+		builder := android.NewRuleBuilder()
+
+		// Package the corpora into a zipfile.
+		if fuzzModule.corpus != nil {
+			corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip")
+			command := builder.Command().BuiltTool(ctx, "soong_zip").
+				Flag("-j").
+				FlagWithOutput("-o ", corpusZip)
+			command.FlagWithRspFileInputList("-l ", fuzzModule.corpus)
+			files = append(files, fileToZip{corpusZip, ""})
+		}
+
+		// Find and mark all the transiently-dependent shared libraries for
+		// packaging.
 		for _, library := range sharedLibraries {
+			files = append(files, fileToZip{library, "lib"})
+
 			if _, exists := archSharedLibraryDeps[archAndLibraryKey{archDir, library}]; exists {
 				continue
 			}
@@ -355,33 +393,36 @@
 		}
 
 		// The executable.
-		archDirs[archDir] = append(archDirs[archDir],
-			fileToZip{ccModule.UnstrippedOutputFile(), ccModule.Name()})
-
-		// The corpora.
-		for _, corpusEntry := range fuzzModule.corpus {
-			archDirs[archDir] = append(archDirs[archDir],
-				fileToZip{corpusEntry, ccModule.Name() + "/corpus"})
-		}
+		files = append(files, fileToZip{ccModule.UnstrippedOutputFile(), ""})
 
 		// The dictionary.
 		if fuzzModule.dictionary != nil {
-			archDirs[archDir] = append(archDirs[archDir],
-				fileToZip{fuzzModule.dictionary, ccModule.Name()})
+			files = append(files, fileToZip{fuzzModule.dictionary, ""})
 		}
 
 		// Additional fuzz config.
 		if fuzzModule.config != nil {
-			archDirs[archDir] = append(archDirs[archDir],
-				fileToZip{fuzzModule.config, ccModule.Name()})
+			files = append(files, fileToZip{fuzzModule.config, ""})
 		}
-	})
 
-	// Add the shared library deps for packaging.
-	for key, _ := range archSharedLibraryDeps {
-		archDirs[key.ArchDir] = append(archDirs[key.ArchDir],
-			fileToZip{key.Library, "lib"})
-	}
+		fuzzZip := archDir.Join(ctx, module.Name()+".zip")
+		command := builder.Command().BuiltTool(ctx, "soong_zip").
+			Flag("-j").
+			FlagWithOutput("-o ", fuzzZip)
+		for _, file := range files {
+			if file.DestinationPathPrefix != "" {
+				command.FlagWithArg("-P ", file.DestinationPathPrefix)
+			} else {
+				command.Flag("-P ''")
+			}
+			command.FlagWithInput("-f ", file.SourceFilePath)
+		}
+
+		builder.Build(pctx, ctx, "create-"+fuzzZip.String(),
+			"Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
+
+		archDirs[archDir] = append(archDirs[archDir], fileToZip{fuzzZip, ""})
+	})
 
 	for archDir, filesToZip := range archDirs {
 		arch := archDir.Base()
@@ -392,11 +433,16 @@
 
 		command := builder.Command().BuiltTool(ctx, "soong_zip").
 			Flag("-j").
-			FlagWithOutput("-o ", outputFile)
+			FlagWithOutput("-o ", outputFile).
+			Flag("-L 0") // No need to try and re-compress the zipfiles.
 
 		for _, fileToZip := range filesToZip {
-			command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix).
-				FlagWithInput("-f ", fileToZip.SourceFilePath)
+			if fileToZip.DestinationPathPrefix != "" {
+				command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
+			} else {
+				command.Flag("-P ''")
+			}
+			command.FlagWithInput("-f ", fileToZip.SourceFilePath)
 		}
 
 		builder.Build(pctx, ctx, "create-fuzz-package-"+arch+"-"+hostOrTarget,
diff --git a/cc/gen_stub_libs.py b/cc/gen_stub_libs.py
index 81bc398..0de703c 100755
--- a/cc/gen_stub_libs.py
+++ b/cc/gen_stub_libs.py
@@ -108,7 +108,7 @@
     return version.endswith('_PRIVATE') or version.endswith('_PLATFORM')
 
 
-def should_omit_version(version, arch, api, vndk, apex):
+def should_omit_version(version, arch, api, llndk, apex):
     """Returns True if the version section should be ommitted.
 
     We want to omit any sections that do not have any symbols we'll have in the
@@ -120,9 +120,9 @@
     if 'platform-only' in version.tags:
         return True
 
-    no_vndk_no_apex = 'vndk' not in version.tags and 'apex' not in version.tags
-    keep = no_vndk_no_apex or \
-           ('vndk' in version.tags and vndk) or \
+    no_llndk_no_apex = 'llndk' not in version.tags and 'apex' not in version.tags
+    keep = no_llndk_no_apex or \
+           ('llndk' in version.tags and llndk) or \
            ('apex' in version.tags and apex)
     if not keep:
         return True
@@ -133,11 +133,11 @@
     return False
 
 
-def should_omit_symbol(symbol, arch, api, vndk, apex):
+def should_omit_symbol(symbol, arch, api, llndk, apex):
     """Returns True if the symbol should be omitted."""
-    no_vndk_no_apex = 'vndk' not in symbol.tags and 'apex' not in symbol.tags
-    keep = no_vndk_no_apex or \
-           ('vndk' in symbol.tags and vndk) or \
+    no_llndk_no_apex = 'llndk' not in symbol.tags and 'apex' not in symbol.tags
+    keep = no_llndk_no_apex or \
+           ('llndk' in symbol.tags and llndk) or \
            ('apex' in symbol.tags and apex)
     if not keep:
         return True
@@ -250,12 +250,12 @@
 
 class SymbolFileParser(object):
     """Parses NDK symbol files."""
-    def __init__(self, input_file, api_map, arch, api, vndk, apex):
+    def __init__(self, input_file, api_map, arch, api, llndk, apex):
         self.input_file = input_file
         self.api_map = api_map
         self.arch = arch
         self.api = api
-        self.vndk = vndk
+        self.llndk = llndk
         self.apex = apex
         self.current_line = None
 
@@ -284,11 +284,11 @@
         symbol_names = set()
         multiply_defined_symbols = set()
         for version in versions:
-            if should_omit_version(version, self.arch, self.api, self.vndk, self.apex):
+            if should_omit_version(version, self.arch, self.api, self.llndk, self.apex):
                 continue
 
             for symbol in version.symbols:
-                if should_omit_symbol(symbol, self.arch, self.api, self.vndk, self.apex):
+                if should_omit_symbol(symbol, self.arch, self.api, self.llndk, self.apex):
                     continue
 
                 if symbol.name in symbol_names:
@@ -372,12 +372,12 @@
 
 class Generator(object):
     """Output generator that writes stub source files and version scripts."""
-    def __init__(self, src_file, version_script, arch, api, vndk, apex):
+    def __init__(self, src_file, version_script, arch, api, llndk, apex):
         self.src_file = src_file
         self.version_script = version_script
         self.arch = arch
         self.api = api
-        self.vndk = vndk
+        self.llndk = llndk
         self.apex = apex
 
     def write(self, versions):
@@ -387,14 +387,14 @@
 
     def write_version(self, version):
         """Writes a single version block's data to the output files."""
-        if should_omit_version(version, self.arch, self.api, self.vndk, self.apex):
+        if should_omit_version(version, self.arch, self.api, self.llndk, self.apex):
             return
 
         section_versioned = symbol_versioned_in_api(version.tags, self.api)
         version_empty = True
         pruned_symbols = []
         for symbol in version.symbols:
-            if should_omit_symbol(symbol, self.arch, self.api, self.vndk, self.apex):
+            if should_omit_symbol(symbol, self.arch, self.api, self.llndk, self.apex):
                 continue
 
             if symbol_versioned_in_api(symbol.tags, self.api):
@@ -456,7 +456,7 @@
         '--arch', choices=ALL_ARCHITECTURES, required=True,
         help='Architecture being targeted.')
     parser.add_argument(
-        '--vndk', action='store_true', help='Use the VNDK variant.')
+        '--llndk', action='store_true', help='Use the LLNDK variant.')
     parser.add_argument(
         '--apex', action='store_true', help='Use the APEX variant.')
 
@@ -493,14 +493,14 @@
     with open(args.symbol_file) as symbol_file:
         try:
             versions = SymbolFileParser(symbol_file, api_map, args.arch, api,
-                                        args.vndk, args.apex).parse()
+                                        args.llndk, args.apex).parse()
         except MultiplyDefinedSymbolError as ex:
             sys.exit('{}: error: {}'.format(args.symbol_file, ex))
 
     with open(args.stub_src, 'w') as src_file:
         with open(args.version_script, 'w') as version_file:
             generator = Generator(src_file, version_file, args.arch, api,
-                                  args.vndk, args.apex)
+                                  args.llndk, args.apex)
             generator.write(versions)
 
 
diff --git a/cc/linkable.go b/cc/linkable.go
index cfbaffe..2efefea 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -13,7 +13,7 @@
 
 	OutputFile() android.OptionalPath
 
-	IncludeDirs(ctx android.BaseModuleContext) android.Paths
+	IncludeDirs() android.Paths
 	SetDepsInLinkOrder([]android.Path)
 	GetDepsInLinkOrder() []android.Path
 
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 3a5b3a6..f3ee5c1 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -86,7 +86,7 @@
 		// For non-enforcing devices, use "current"
 		vndk_ver = "current"
 	}
-	objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), vndk_ver, "--vndk")
+	objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), vndk_ver, "--llndk")
 	stub.versionScriptPath = versionScript
 	return objs
 }
diff --git a/cc/test_gen_stub_libs.py b/cc/test_gen_stub_libs.py
index 2ee9886..0b45e71 100755
--- a/cc/test_gen_stub_libs.py
+++ b/cc/test_gen_stub_libs.py
@@ -179,17 +179,17 @@
                 gsl.Version('foo', None, ['platform-only'], []), 'arm', 9,
                 False, False))
 
-    def test_omit_vndk(self):
+    def test_omit_llndk(self):
         self.assertTrue(
             gsl.should_omit_version(
-                gsl.Version('foo', None, ['vndk'], []), 'arm', 9, False, False))
+                gsl.Version('foo', None, ['llndk'], []), 'arm', 9, False, False))
 
         self.assertFalse(
             gsl.should_omit_version(
                 gsl.Version('foo', None, [], []), 'arm', 9, True, False))
         self.assertFalse(
             gsl.should_omit_version(
-                gsl.Version('foo', None, ['vndk'], []), 'arm', 9, True, False))
+                gsl.Version('foo', None, ['llndk'], []), 'arm', 9, True, False))
 
     def test_omit_apex(self):
         self.assertTrue(
@@ -231,16 +231,16 @@
 
 
 class OmitSymbolTest(unittest.TestCase):
-    def test_omit_vndk(self):
+    def test_omit_llndk(self):
         self.assertTrue(
             gsl.should_omit_symbol(
-                gsl.Symbol('foo', ['vndk']), 'arm', 9, False, False))
+                gsl.Symbol('foo', ['llndk']), 'arm', 9, False, False))
 
         self.assertFalse(
             gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, True, False))
         self.assertFalse(
             gsl.should_omit_symbol(
-                gsl.Symbol('foo', ['vndk']), 'arm', 9, True, False))
+                gsl.Symbol('foo', ['llndk']), 'arm', 9, True, False))
 
     def test_omit_apex(self):
         self.assertTrue(
@@ -441,12 +441,12 @@
 
         self.assertEqual(expected, versions)
 
-    def test_parse_vndk_apex_symbol(self):
+    def test_parse_llndk_apex_symbol(self):
         input_file = io.StringIO(textwrap.dedent("""\
             VERSION_1 {
                 foo;
-                bar; # vndk
-                baz; # vndk apex
+                bar; # llndk
+                baz; # llndk apex
                 qux; # apex
             };
         """))
@@ -459,8 +459,8 @@
 
         expected_symbols = [
             gsl.Symbol('foo', []),
-            gsl.Symbol('bar', ['vndk']),
-            gsl.Symbol('baz', ['vndk', 'apex']),
+            gsl.Symbol('bar', ['llndk']),
+            gsl.Symbol('baz', ['llndk', 'apex']),
             gsl.Symbol('qux', ['apex']),
         ]
         self.assertEqual(expected_symbols, version.symbols)
@@ -517,7 +517,7 @@
         self.assertEqual('', version_file.getvalue())
 
         version = gsl.Version('VERSION_1', None, [], [
-            gsl.Symbol('foo', ['vndk']),
+            gsl.Symbol('foo', ['llndk']),
         ])
         generator.write_version(version)
         self.assertEqual('', src_file.getvalue())
@@ -607,7 +607,7 @@
 
             VERSION_4 { # versioned=9
                 wibble;
-                wizzes; # vndk
+                wizzes; # llndk
                 waggle; # apex
             } VERSION_2;
 
@@ -749,10 +749,10 @@
 
             VERSION_4 { # versioned=9
                 wibble;
-                wizzes; # vndk
+                wizzes; # llndk
                 waggle; # apex
-                bubble; # apex vndk
-                duddle; # vndk apex
+                bubble; # apex llndk
+                duddle; # llndk apex
             } VERSION_2;
 
             VERSION_5 { # versioned=14
diff --git a/cmd/javac_wrapper/javac_wrapper.go b/cmd/javac_wrapper/javac_wrapper.go
index 7a448ba..4679906 100644
--- a/cmd/javac_wrapper/javac_wrapper.go
+++ b/cmd/javac_wrapper/javac_wrapper.go
@@ -31,6 +31,7 @@
 	"os"
 	"os/exec"
 	"regexp"
+	"strconv"
 	"syscall"
 )
 
@@ -80,10 +81,11 @@
 
 	pw.Close()
 
+	proc := processor{}
 	// Process subprocess stdout asynchronously
 	errCh := make(chan error)
 	go func() {
-		errCh <- process(pr, out)
+		errCh <- proc.process(pr, out)
 	}()
 
 	// Wait for subprocess to finish
@@ -117,14 +119,18 @@
 	return 0, nil
 }
 
-func process(r io.Reader, w io.Writer) error {
+type processor struct {
+	silencedWarnings int
+}
+
+func (proc *processor) process(r io.Reader, w io.Writer) error {
 	scanner := bufio.NewScanner(r)
 	// Some javac wrappers output the entire list of java files being
 	// compiled on a single line, which can be very large, set the maximum
 	// buffer size to 2MB.
 	scanner.Buffer(nil, 2*1024*1024)
 	for scanner.Scan() {
-		processLine(w, scanner.Text())
+		proc.processLine(w, scanner.Text())
 	}
 	err := scanner.Err()
 	if err != nil {
@@ -133,12 +139,32 @@
 	return nil
 }
 
-func processLine(w io.Writer, line string) {
+func (proc *processor) processLine(w io.Writer, line string) {
+	for _, f := range warningFilters {
+		if f.MatchString(line) {
+			proc.silencedWarnings++
+			return
+		}
+	}
 	for _, f := range filters {
 		if f.MatchString(line) {
 			return
 		}
 	}
+	if match := warningCount.FindStringSubmatch(line); match != nil {
+		c, err := strconv.Atoi(match[1])
+		if err == nil {
+			c -= proc.silencedWarnings
+			if c == 0 {
+				return
+			} else {
+				line = fmt.Sprintf("%d warning", c)
+				if c > 1 {
+					line += "s"
+				}
+			}
+		}
+	}
 	for _, p := range colorPatterns {
 		var matched bool
 		if line, matched = applyColor(line, p.color, p.re); matched {
@@ -170,12 +196,17 @@
 	{markerRe, green},
 }
 
+var warningCount = regexp.MustCompile(`^([0-9]+) warning(s)?$`)
+
+var warningFilters = []*regexp.Regexp{
+	regexp.MustCompile(`bootstrap class path not set in conjunction with -source`),
+}
+
 var filters = []*regexp.Regexp{
 	regexp.MustCompile(`Note: (Some input files|.*\.java) uses? or overrides? a deprecated API.`),
 	regexp.MustCompile(`Note: Recompile with -Xlint:deprecation for details.`),
 	regexp.MustCompile(`Note: (Some input files|.*\.java) uses? unchecked or unsafe operations.`),
 	regexp.MustCompile(`Note: Recompile with -Xlint:unchecked for details.`),
-	regexp.MustCompile(`bootstrap class path not set in conjunction with -source`),
 
 	regexp.MustCompile(`javadoc: warning - The old Doclet and Taglet APIs in the packages`),
 	regexp.MustCompile(`com.sun.javadoc, com.sun.tools.doclets and their implementations`),
diff --git a/cmd/javac_wrapper/javac_wrapper_test.go b/cmd/javac_wrapper/javac_wrapper_test.go
index ad657e7..ad23001 100644
--- a/cmd/javac_wrapper/javac_wrapper_test.go
+++ b/cmd/javac_wrapper/javac_wrapper_test.go
@@ -75,13 +75,29 @@
 `,
 		out: "\n",
 	},
+	{
+		in: `
+warning: [options] bootstrap class path not set in conjunction with -source 1.9\n
+1 warning
+`,
+		out: "\n",
+	},
+	{
+		in: `
+warning: foo
+warning: [options] bootstrap class path not set in conjunction with -source 1.9\n
+2 warnings
+`,
+		out: "\n\x1b[1m\x1b[35mwarning:\x1b[0m\x1b[1m foo\x1b[0m\n1 warning\n",
+	},
 }
 
 func TestJavacColorize(t *testing.T) {
 	for i, test := range testCases {
 		t.Run(strconv.Itoa(i), func(t *testing.T) {
 			buf := new(bytes.Buffer)
-			err := process(bytes.NewReader([]byte(test.in)), buf)
+			proc := processor{}
+			err := proc.process(bytes.NewReader([]byte(test.in)), buf)
 			if err != nil {
 				t.Errorf("error: %q", err)
 			}
diff --git a/java/androidmk.go b/java/androidmk.go
index 0510680..c973739 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -262,6 +262,11 @@
 }
 
 func (app *AndroidApp) AndroidMkEntries() android.AndroidMkEntries {
+	if !app.IsForPlatform() {
+		return android.AndroidMkEntries{
+			Disabled: true,
+		}
+	}
 	return android.AndroidMkEntries{
 		Class:      "APPS",
 		OutputFile: android.OptionalPathForPath(app.outputFile),
diff --git a/java/app.go b/java/app.go
index d53d626..30cd6cb 100644
--- a/java/app.go
+++ b/java/app.go
@@ -78,8 +78,9 @@
 
 	// Store native libraries uncompressed in the APK and set the android:extractNativeLibs="false" manifest
 	// flag so that they are used from inside the APK at runtime.  Defaults to true for android_test modules unless
-	// sdk_version or min_sdk_version is set to a version that doesn't support it (<23), defaults to false for other
-	// module types where the native libraries are generally preinstalled outside the APK.
+	// sdk_version or min_sdk_version is set to a version that doesn't support it (<23), defaults to true for
+	// android_app modules that are embedded to APEXes, defaults to false for other module types where the native
+	// libraries are generally preinstalled outside the APK.
 	Use_embedded_native_libs *bool
 
 	// Store dex files uncompressed in the APK and set the android:useEmbeddedDex="true" manifest attribute so that
@@ -217,7 +218,8 @@
 		ctx.PropertyErrorf("min_sdk_version", "invalid value %q: %s", a.minSdkVersion(), err)
 	}
 
-	return minSdkVersion >= 23 && Bool(a.appProperties.Use_embedded_native_libs)
+	return (minSdkVersion >= 23 && Bool(a.appProperties.Use_embedded_native_libs)) ||
+		!a.IsForPlatform()
 }
 
 // Returns whether this module should have the dex file stored uncompressed in the APK.
@@ -241,7 +243,7 @@
 
 func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool {
 	return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
-		a.appProperties.AlwaysPackageNativeLibs
+		!a.IsForPlatform() || a.appProperties.AlwaysPackageNativeLibs
 }
 
 func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
@@ -496,9 +498,11 @@
 	a.bundleFile = bundleFile
 
 	// Install the app package.
-	ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile)
-	for _, extra := range a.extraOutputFiles {
-		ctx.InstallFile(a.installDir, extra.Base(), extra)
+	if (Bool(a.Module.properties.Installable) || ctx.Host()) && a.IsForPlatform() {
+		ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile)
+		for _, extra := range a.extraOutputFiles {
+			ctx.InstallFile(a.installDir, extra.Base(), extra)
+		}
 	}
 }
 
@@ -585,6 +589,7 @@
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
 	android.InitOverridableModule(module, &module.appProperties.Overrides)
+	android.InitApexModule(module)
 
 	return module
 }
diff --git a/java/java.go b/java/java.go
index 9bbdff7..d4f65ba 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1664,6 +1664,57 @@
 	j.deps(ctx)
 }
 
+const (
+	aidlIncludeDir     = "aidl"
+	javaStubDir        = "java"
+	javaStubFileSuffix = ".jar"
+)
+
+// path to the stub file of a java library. Relative to <sdk_root>/<api_dir>
+func (j *Library) javaStubFilePathFor() string {
+	return filepath.Join(javaStubDir, j.Name()+javaStubFileSuffix)
+}
+
+func (j *Library) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder) {
+	headerJars := j.HeaderJars()
+	if len(headerJars) != 1 {
+		panic(fmt.Errorf("there must be only one header jar from %q", j.Name()))
+	}
+	snapshotRelativeJavaLibPath := j.javaStubFilePathFor()
+	builder.CopyToSnapshot(headerJars[0], snapshotRelativeJavaLibPath)
+
+	for _, dir := range j.AidlIncludeDirs() {
+		// TODO(jiyong): copy parcelable declarations only
+		aidlFiles, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.aidl", nil)
+		for _, file := range aidlFiles {
+			builder.CopyToSnapshot(android.PathForSource(sdkModuleContext, file), filepath.Join(aidlIncludeDir, file))
+		}
+	}
+
+	name := j.Name()
+	bp := builder.AndroidBpFile()
+	bp.Printfln("java_import {")
+	bp.Indent()
+	bp.Printfln("name: %q,", builder.VersionedSdkMemberName(name))
+	bp.Printfln("sdk_member_name: %q,", name)
+	bp.Printfln("jars: [%q],", snapshotRelativeJavaLibPath)
+	bp.Dedent()
+	bp.Printfln("}")
+	bp.Printfln("")
+
+	// This module is for the case when the source tree for the unversioned module
+	// doesn't exist (i.e. building in an unbundled tree). "prefer:" is set to false
+	// so that this module does not eclipse the unversioned module if it exists.
+	bp.Printfln("java_import {")
+	bp.Indent()
+	bp.Printfln("name: %q,", name)
+	bp.Printfln("jars: [%q],", snapshotRelativeJavaLibPath)
+	bp.Printfln("prefer: false,")
+	bp.Dedent()
+	bp.Printfln("}")
+	bp.Printfln("")
+}
+
 // java_library builds and links sources into a `.jar` file for the device, and possibly for the host as well.
 //
 // By default, a java_library has a single variant that produces a `.jar` file containing `.class` files that were
@@ -1684,9 +1735,9 @@
 		&module.Module.dexpreoptProperties,
 		&module.Module.protoProperties)
 
-	InitJavaModule(module, android.HostAndDeviceSupported)
 	android.InitApexModule(module)
 	android.InitSdkAwareModule(module)
+	InitJavaModule(module, android.HostAndDeviceSupported)
 	return module
 }
 
@@ -1708,8 +1759,8 @@
 
 	module.Module.properties.Installable = proptools.BoolPtr(true)
 
-	InitJavaModule(module, android.HostSupported)
 	android.InitApexModule(module)
+	InitJavaModule(module, android.HostSupported)
 	return module
 }
 
@@ -2135,9 +2186,9 @@
 	module.AddProperties(&module.properties)
 
 	android.InitPrebuiltModule(module, &module.properties.Jars)
-	InitJavaModule(module, android.HostAndDeviceSupported)
 	android.InitApexModule(module)
 	android.InitSdkAwareModule(module)
+	InitJavaModule(module, android.HostAndDeviceSupported)
 	return module
 }
 
@@ -2152,8 +2203,8 @@
 	module.AddProperties(&module.properties)
 
 	android.InitPrebuiltModule(module, &module.properties.Jars)
-	InitJavaModule(module, android.HostSupported)
 	android.InitApexModule(module)
+	InitJavaModule(module, android.HostSupported)
 	return module
 }
 
@@ -2264,8 +2315,8 @@
 	module.AddProperties(&module.properties)
 
 	android.InitPrebuiltModule(module, &module.properties.Jars)
-	InitJavaModule(module, android.DeviceSupported)
 	android.InitApexModule(module)
+	InitJavaModule(module, android.DeviceSupported)
 	return module
 }
 
@@ -2331,10 +2382,10 @@
 		&AARImportProperties{},
 		&sdkLibraryProperties{},
 		&DexImportProperties{},
+		&android.ApexProperties{},
 	)
 
 	android.InitDefaultsModule(module)
-	android.InitApexModule(module)
 	return module
 }
 
diff --git a/androidmk/partner_androidmk/Android.bp b/partner/Android.bp
similarity index 71%
rename from androidmk/partner_androidmk/Android.bp
rename to partner/Android.bp
index 532116a..f2ced8d 100644
--- a/androidmk/partner_androidmk/Android.bp
+++ b/partner/Android.bp
@@ -1,4 +1,4 @@
-// Copyright 2015 Google Inc. All rights reserved.
+// Copyright 2019 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.
@@ -19,31 +19,31 @@
 blueprint_go_binary {
     name: "partner_androidmk",
     srcs: [
-        "partner_androidmk/androidmk.go",
+        "androidmk/androidmk.go",
     ],
     testSrcs: [
-        "partner_androidmk/androidmk_test.go",
+        "androidmk/androidmk_test.go",
     ],
     deps: [
         "androidmk-lib",
-        "partner_bpfix_extensions",
+        "partner-bpfix-extensions",
     ],
 }
 
 blueprint_go_binary {
     name: "partner_bpfix",
     srcs: [
-        "partner_bpfix/bpfix.go",
+        "bpfix/bpfix.go",
     ],
     deps: [
         "bpfix-cmd",
-        "partner_bpfix_extensions",
+        "partner-bpfix-extensions",
     ],
 }
 
 bootstrap_go_package {
-    name: "partner_bpfix_extensions",
-    pkgPath: "partner/android/bpfix/extensions",
-    srcs: ["fixes/headers.go"],
+    name: "partner-bpfix-extensions",
+    pkgPath: "android/soong/partner/bpfix/extensions",
+    srcs: ["bpfix/extensions/headers.go"],
     deps: ["bpfix-lib"],
 }
diff --git a/androidmk/partner_androidmk/partner_androidmk/androidmk.go b/partner/androidmk/androidmk.go
similarity index 96%
rename from androidmk/partner_androidmk/partner_androidmk/androidmk.go
rename to partner/androidmk/androidmk.go
index af8cdf3..f49981b 100644
--- a/androidmk/partner_androidmk/partner_androidmk/androidmk.go
+++ b/partner/androidmk/androidmk.go
@@ -23,7 +23,7 @@
 
 	"android/soong/androidmk/androidmk"
 
-	_ "partner/android/bpfix/extensions"
+	_ "android/soong/partner/bpfix/extensions"
 )
 
 var usage = func() {
diff --git a/androidmk/partner_androidmk/partner_androidmk/androidmk_test.go b/partner/androidmk/androidmk_test.go
similarity index 97%
rename from androidmk/partner_androidmk/partner_androidmk/androidmk_test.go
rename to partner/androidmk/androidmk_test.go
index ff04e88..6bae836 100644
--- a/androidmk/partner_androidmk/partner_androidmk/androidmk_test.go
+++ b/partner/androidmk/androidmk_test.go
@@ -23,7 +23,7 @@
 	"android/soong/androidmk/androidmk"
 	"android/soong/bpfix/bpfix"
 
-	_ "partner/android/bpfix/extensions"
+	_ "android/soong/partner/bpfix/extensions"
 )
 
 var testCases = []struct {
diff --git a/androidmk/partner_androidmk/partner_bpfix/bpfix.go b/partner/bpfix/bpfix.go
similarity index 88%
rename from androidmk/partner_androidmk/partner_bpfix/bpfix.go
rename to partner/bpfix/bpfix.go
index 2c8e0a8..687fe1c 100644
--- a/androidmk/partner_androidmk/partner_bpfix/bpfix.go
+++ b/partner/bpfix/bpfix.go
@@ -17,11 +17,11 @@
 package main
 
 import (
-	"android/soong/bpfix/bpfix/cmd"
+	"android/soong/bpfix/cmd_lib"
 
-	_ "partner/android/bpfix/extensions"
+	_ "android/soong/partner/bpfix/extensions"
 )
 
 func main() {
-	cmd.Run()
+	cmd_lib.Run()
 }
diff --git a/androidmk/partner_androidmk/fixes/headers.go b/partner/bpfix/extensions/headers.go
similarity index 100%
rename from androidmk/partner_androidmk/fixes/headers.go
rename to partner/bpfix/extensions/headers.go
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 49115f2..2a9a6c0 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -87,9 +87,23 @@
 	})
 }
 
-func (test *testBinaryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+func (test *testDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
 	test.binaryDecorator.AndroidMk(ctx, ret)
-	ret.SubName = "_" + String(test.baseCompiler.Properties.Stem)
+	stem := String(test.baseCompiler.Properties.Stem)
+	if stem != "" && !strings.HasSuffix(ctx.Name(), "_"+stem) {
+		// Avoid repeated suffix in the module name.
+		ret.SubName = "_" + stem
+	}
+	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+		if len(test.Properties.Test_suites) > 0 {
+			fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
+				strings.Join(test.Properties.Test_suites, " "))
+		}
+		if test.testConfig != nil {
+			fmt.Fprintln(w, "LOCAL_FULL_TEST_CONFIG :=", test.testConfig.String())
+		}
+	})
+	// TODO(chh): add test data with androidMkWriteTestData(test.data, ctx, ret)
 }
 
 func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
diff --git a/rust/binary.go b/rust/binary.go
index 52f840e..d4b6614 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -16,7 +16,6 @@
 
 import (
 	"android/soong/android"
-	"android/soong/rust/config"
 )
 
 func init() {
@@ -28,7 +27,8 @@
 	// path to the main source file that contains the program entry point (e.g. src/main.rs)
 	Srcs []string `android:"path,arch_variant"`
 
-	// passes -C prefer-dynamic to rustc, which tells it to dynamically link the stdlib (assuming it has no dylib dependencies already)
+	// passes -C prefer-dynamic to rustc, which tells it to dynamically link the stdlib
+	// (assuming it has no dylib dependencies already)
 	Prefer_dynamic *bool
 }
 
@@ -73,7 +73,8 @@
 	flags = binary.baseCompiler.compilerFlags(ctx, flags)
 
 	if ctx.toolchain().Bionic() {
-		// no-undefined-version breaks dylib compilation since __rust_*alloc* functions aren't defined, but we can apply this to binaries.
+		// no-undefined-version breaks dylib compilation since __rust_*alloc* functions aren't defined,
+		// but we can apply this to binaries.
 		flags.LinkFlags = append(flags.LinkFlags,
 			"-Wl,--gc-sections",
 			"-Wl,-z,nocopyreloc",
@@ -89,12 +90,6 @@
 func (binary *binaryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
 	deps = binary.baseCompiler.compilerDeps(ctx, deps)
 
-	if binary.preferDynamic() || len(deps.Dylibs) > 0 {
-		for _, stdlib := range config.Stdlibs {
-			deps.Dylibs = append(deps.Dylibs, stdlib+"_"+ctx.toolchain().RustTriple())
-		}
-	}
-
 	if ctx.toolchain().Bionic() {
 		deps = binary.baseCompiler.bionicDeps(ctx, deps)
 		deps.CrtBegin = "crtbegin_dynamic"
diff --git a/rust/builder.go b/rust/builder.go
index d9e36db..9109651 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -31,8 +31,9 @@
 				"-C link-args=\"${crtBegin} ${config.RustLinkerArgs} ${linkFlags} ${crtEnd}\" " +
 				"--emit link -o $out --emit dep-info=$out.d $in ${libFlags} $rustcFlags",
 			CommandDeps: []string{"$rustcCmd"},
-			Depfile:     "$out.d",
-			Deps:        blueprint.DepsGCC, // Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
+			// Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
+			Deps:    blueprint.DepsGCC,
+			Depfile: "$out.d",
 		},
 		"rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd")
 )
@@ -41,28 +42,34 @@
 
 }
 
-func TransformSrcToBinary(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "bin", includeDirs)
+func TransformSrcToBinary(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
+	outputFile android.WritablePath, includeDirs []string) {
+	transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "bin", includeDirs)
 }
 
-func TransformSrctoRlib(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "rlib", includeDirs)
+func TransformSrctoRlib(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
+	outputFile android.WritablePath, includeDirs []string) {
+	transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "rlib", includeDirs)
 }
 
-func TransformSrctoDylib(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "dylib", includeDirs)
+func TransformSrctoDylib(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
+	outputFile android.WritablePath, includeDirs []string) {
+	transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "dylib", includeDirs)
 }
 
-func TransformSrctoStatic(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "staticlib", includeDirs)
+func TransformSrctoStatic(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
+	outputFile android.WritablePath, includeDirs []string) {
+	transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "staticlib", includeDirs)
 }
 
-func TransformSrctoShared(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "cdylib", includeDirs)
+func TransformSrctoShared(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
+	outputFile android.WritablePath, includeDirs []string) {
+	transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "cdylib", includeDirs)
 }
 
-func TransformSrctoProcMacro(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "proc-macro", includeDirs)
+func TransformSrctoProcMacro(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps,
+	flags Flags, outputFile android.WritablePath, includeDirs []string) {
+	transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "proc-macro", includeDirs)
 }
 
 func rustLibsToPaths(libs RustLibraries) android.Paths {
@@ -73,11 +80,11 @@
 	return paths
 }
 
-func transformSrctoCrate(ctx android.ModuleContext, main android.Path,
-	rlibs, dylibs, proc_macros RustLibraries, static_libs, shared_libs android.Paths, crtBegin, crtEnd android.OptionalPath, flags Flags, outputFile android.WritablePath, crate_type string, includeDirs []string) {
+func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps PathDeps, flags Flags,
+	outputFile android.WritablePath, crate_type string, includeDirs []string) {
 
 	var inputs android.Paths
-	var deps android.Paths
+	var implicits android.Paths
 	var libFlags, rustcFlags, linkFlags []string
 	crate_name := ctx.(ModuleContext).CrateName()
 	targetTriple := ctx.(ModuleContext).toolchain().RustTriple()
@@ -95,18 +102,24 @@
 		rustcFlags = append(rustcFlags, "--target="+targetTriple)
 		linkFlags = append(linkFlags, "-target "+targetTriple)
 	}
+	// TODO once we have static libraries in the host prebuilt .bp, this
+	// should be unconditionally added.
+	if !ctx.Host() {
+		// If we're on a device build, do not use an implicit sysroot
+		rustcFlags = append(rustcFlags, "--sysroot=/dev/null")
+	}
 	// Collect linker flags
 	linkFlags = append(linkFlags, flags.GlobalLinkFlags...)
 	linkFlags = append(linkFlags, flags.LinkFlags...)
 
 	// Collect library/crate flags
-	for _, lib := range rlibs {
+	for _, lib := range deps.RLibs {
 		libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
 	}
-	for _, lib := range dylibs {
+	for _, lib := range deps.DyLibs {
 		libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
 	}
-	for _, proc_macro := range proc_macros {
+	for _, proc_macro := range deps.ProcMacros {
 		libFlags = append(libFlags, "--extern "+proc_macro.CrateName+"="+proc_macro.Path.String())
 	}
 
@@ -115,13 +128,13 @@
 	}
 
 	// Collect dependencies
-	deps = append(deps, rustLibsToPaths(rlibs)...)
-	deps = append(deps, rustLibsToPaths(dylibs)...)
-	deps = append(deps, rustLibsToPaths(proc_macros)...)
-	deps = append(deps, static_libs...)
-	deps = append(deps, shared_libs...)
-	if crtBegin.Valid() {
-		deps = append(deps, crtBegin.Path(), crtEnd.Path())
+	implicits = append(implicits, rustLibsToPaths(deps.RLibs)...)
+	implicits = append(implicits, rustLibsToPaths(deps.DyLibs)...)
+	implicits = append(implicits, rustLibsToPaths(deps.ProcMacros)...)
+	implicits = append(implicits, deps.StaticLibs...)
+	implicits = append(implicits, deps.SharedLibs...)
+	if deps.CrtBegin.Valid() {
+		implicits = append(implicits, deps.CrtBegin.Path(), deps.CrtEnd.Path())
 	}
 
 	ctx.Build(pctx, android.BuildParams{
@@ -129,13 +142,13 @@
 		Description: "rustc " + main.Rel(),
 		Output:      outputFile,
 		Inputs:      inputs,
-		Implicits:   deps,
+		Implicits:   implicits,
 		Args: map[string]string{
 			"rustcFlags": strings.Join(rustcFlags, " "),
 			"linkFlags":  strings.Join(linkFlags, " "),
 			"libFlags":   strings.Join(libFlags, " "),
-			"crtBegin":   crtBegin.String(),
-			"crtEnd":     crtEnd.String(),
+			"crtBegin":   deps.CrtBegin.String(),
+			"crtEnd":     deps.CrtEnd.String(),
 		},
 	})
 
diff --git a/rust/compiler.go b/rust/compiler.go
index 85e8ba6..88e3fb2 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -32,6 +32,10 @@
 	return BoolDefault(compiler.Properties.Deny_warnings, config.DefaultDenyWarnings)
 }
 
+func (compiler *baseCompiler) setNoStdlibs() {
+	compiler.Properties.No_stdlibs = proptools.BoolPtr(true)
+}
+
 func NewBaseCompiler(dir, dir64 string) *baseCompiler {
 	return &baseCompiler{
 		Properties: BaseCompilerProperties{},
@@ -82,6 +86,9 @@
 
 	// install to a subdirectory of the default install path for the module
 	Relative_install_path *string `android:"arch_variant"`
+
+	// whether to suppress inclusion of standard crates - defaults to false
+	No_stdlibs *bool
 }
 
 type baseCompiler struct {
@@ -161,6 +168,23 @@
 	deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...)
 	deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...)
 
+	if !Bool(compiler.Properties.No_stdlibs) {
+		for _, stdlib := range config.Stdlibs {
+			// If we're building for host, use the compiler's stdlibs
+			if ctx.Host() {
+				stdlib = stdlib + "_" + ctx.toolchain().RustTriple()
+			}
+
+			// This check is technically insufficient - on the host, where
+			// static linking is the default, if one of our static
+			// dependencies uses a dynamic library, we need to dynamically
+			// link the stdlib as well.
+			if (len(deps.Dylibs) > 0) || (!ctx.Host()) {
+				// Dynamically linked stdlib
+				deps.Dylibs = append(deps.Dylibs, stdlib)
+			}
+		}
+	}
 	return deps
 }
 
diff --git a/rust/config/whitelist.go b/rust/config/whitelist.go
index 8025bcf..7dfb002 100644
--- a/rust/config/whitelist.go
+++ b/rust/config/whitelist.go
@@ -5,6 +5,7 @@
 		"external/rust",
 		"external/crosvm",
 		"external/adhd",
+		"prebuilts/rust",
 	}
 
 	RustModuleTypes = []string{
@@ -13,9 +14,15 @@
 		"rust_library",
 		"rust_library_dylib",
 		"rust_library_rlib",
+		"rust_library_shared",
+		"rust_library_static",
 		"rust_library_host",
 		"rust_library_host_dylib",
 		"rust_library_host_rlib",
+		"rust_library_host_shared",
+		"rust_library_host_static",
 		"rust_proc_macro",
+		"rust_test",
+		"rust_test_host",
 	}
 )
diff --git a/rust/config/x86_64_device.go b/rust/config/x86_64_device.go
index 2aca56a..9a6c00b 100644
--- a/rust/config/x86_64_device.go
+++ b/rust/config/x86_64_device.go
@@ -41,8 +41,8 @@
 func init() {
 	registerToolchainFactory(android.Android, android.X86_64, x86_64ToolchainFactory)
 
-	pctx.StaticVariable("x86_64ToolchainRustFlags", strings.Join(x86_64RustFlags, " "))
-	pctx.StaticVariable("x86_64ToolchainLinkFlags", strings.Join(x86_64LinkFlags, " "))
+	pctx.StaticVariable("X86_64ToolchainRustFlags", strings.Join(x86_64RustFlags, " "))
+	pctx.StaticVariable("X86_64ToolchainLinkFlags", strings.Join(x86_64LinkFlags, " "))
 
 	for variant, rustFlags := range x86_64ArchVariantRustFlags {
 		pctx.StaticVariable("X86_64"+variant+"VariantRustFlags",
@@ -57,11 +57,11 @@
 }
 
 func (t *toolchainX86_64) RustTriple() string {
-	return "x86_64-unknown-linux-gnu"
+	return "x86_64-linux-android"
 }
 
 func (t *toolchainX86_64) ToolchainLinkFlags() string {
-	return "${config.x86_64ToolchainLinkFlags}"
+	return "${config.DeviceGlobalLinkFlags} ${config.X86_64ToolchainLinkFlags}"
 }
 
 func (t *toolchainX86_64) ToolchainRustFlags() string {
@@ -69,15 +69,21 @@
 }
 
 func (t *toolchainX86_64) RustFlags() string {
-	return "${config.x86_64ToolchainRustFlags}"
+	return "${config.X86_64ToolchainRustFlags}"
+}
+
+func (t *toolchainX86_64) Supported() bool {
+	return true
 }
 
 func x86_64ToolchainFactory(arch android.Arch) Toolchain {
 	toolchainRustFlags := []string{
-		"${config.x86_64ToolchainRustFlags}",
+		"${config.X86_64ToolchainRustFlags}",
 		"${config.X86_64" + arch.ArchVariant + "VariantRustFlags}",
 	}
 
+	toolchainRustFlags = append(toolchainRustFlags, deviceGlobalRustFlags...)
+
 	for _, feature := range arch.ArchFeatures {
 		toolchainRustFlags = append(toolchainRustFlags, x86_64ArchFeatureRustFlags[feature]...)
 	}
diff --git a/rust/library.go b/rust/library.go
index adf6e95..386ea47 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -78,6 +78,7 @@
 	MutatedProperties    LibraryMutatedProperties
 	distFile             android.OptionalPath
 	unstrippedOutputFile android.Path
+	includeDirs          android.Paths
 }
 
 type libraryInterface interface {
@@ -311,6 +312,13 @@
 
 	return deps
 }
+func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
+	flags = library.baseCompiler.compilerFlags(ctx, flags)
+	if library.shared() || library.static() {
+		library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...)
+	}
+	return flags
+}
 
 func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
 	var outputFile android.WritablePath
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index fa69fbb..45bef9e 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -42,6 +42,7 @@
 func NewPrebuiltDylib(hod android.HostOrDeviceSupported) (*Module, *prebuiltLibraryDecorator) {
 	module, library := NewRustLibrary(hod)
 	library.BuildOnlyDylib()
+	library.setNoStdlibs()
 	library.setDylib()
 	prebuilt := &prebuiltLibraryDecorator{
 		libraryDecorator: library,
diff --git a/rust/rust.go b/rust/rust.go
index 612e257..8782f8e 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -218,6 +218,7 @@
 		&LibraryCompilerProperties{},
 		&ProcMacroCompilerProperties{},
 		&PrebuiltProperties{},
+		&TestProperties{},
 	)
 
 	android.InitDefaultsModule(module)
@@ -246,10 +247,10 @@
 	return false
 }
 
-func (mod *Module) IncludeDirs(ctx android.BaseModuleContext) android.Paths {
+func (mod *Module) IncludeDirs() android.Paths {
 	if mod.compiler != nil {
 		if library, ok := mod.compiler.(*libraryDecorator); ok {
-			return android.PathsForSource(ctx, library.Properties.Include_dirs)
+			return library.includeDirs
 		}
 	}
 	panic(fmt.Errorf("IncludeDirs called on non-library module: %q", mod.BaseModuleName()))
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 599af09..91c2f09 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -199,6 +199,25 @@
 			srcs: ["foo.rs"],
 			crate_name: "bar",
 		}
+		// Make a dummy libstd to let resolution go through
+		rust_library_dylib {
+			name: "libstd",
+			crate_name: "std",
+			srcs: ["foo.rs"],
+			no_stdlibs: true,
+		}
+		rust_library_dylib {
+			name: "libterm",
+			crate_name: "term",
+			srcs: ["foo.rs"],
+			no_stdlibs: true,
+		}
+		rust_library_dylib {
+			name: "libtest",
+			crate_name: "test",
+			srcs: ["foo.rs"],
+			no_stdlibs: true,
+		}
 		rust_proc_macro {
 			name: "libpm",
 			rlibs: ["libbar"],
@@ -217,3 +236,18 @@
 		t.Errorf("Proc_macro is not using host variant of dependent modules.")
 	}
 }
+
+// Test that no_stdlibs suppresses dependencies on rust standard libraries
+func TestNoStdlibs(t *testing.T) {
+	ctx := testRust(t, `
+		rust_binary {
+			name: "fizz-buzz",
+			srcs: ["foo.rs"],
+                        no_stdlibs: true,
+		}`)
+	module := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a_core").Module().(*Module)
+
+	if android.InList("libstd", module.Properties.AndroidMkDylibs) {
+		t.Errorf("no_stdlibs did not suppress dependency on libstd")
+	}
+}
diff --git a/rust/test.go b/rust/test.go
index 816e3c7..cb64e8f 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -19,19 +19,41 @@
 	"strings"
 
 	"android/soong/android"
+	"android/soong/tradefed"
 )
 
+type TestProperties struct {
+	// the name of the test configuration (for example "AndroidTest.xml") that should be
+	// installed with the module.
+	Test_config *string `android:"arch_variant"`
+
+	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
+	// should be installed with the module.
+	Test_config_template *string `android:"arch_variant"`
+
+	// list of compatibility suites (for example "cts", "vts") that the module should be
+	// installed into.
+	Test_suites []string `android:"arch_variant"`
+
+	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
+	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
+	// explicitly.
+	Auto_gen_config *bool
+}
+
 // A test module is a binary module with extra --test compiler flag
 // and different default installation directory.
 // In golang, inheriance is written as a component.
-type testBinaryDecorator struct {
+type testDecorator struct {
 	*binaryDecorator
+	Properties TestProperties
+	testConfig android.Path
 }
 
-func NewRustTest(hod android.HostOrDeviceSupported) (*Module, *testBinaryDecorator) {
+func NewRustTest(hod android.HostOrDeviceSupported) (*Module, *testDecorator) {
 	module := newModule(hod, android.MultilibFirst)
 
-	test := &testBinaryDecorator{
+	test := &testDecorator{
 		binaryDecorator: &binaryDecorator{
 			// TODO(chh): set up dir64?
 			baseCompiler: NewBaseCompiler("testcases", ""),
@@ -43,7 +65,27 @@
 	return module, test
 }
 
-func (test *testBinaryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
+func (test *testDecorator) compilerProps() []interface{} {
+	return append(test.binaryDecorator.compilerProps(), &test.Properties)
+}
+
+func (test *testDecorator) install(ctx ModuleContext, file android.Path) {
+	name := ctx.ModuleName() // default executable name
+	if stem := String(test.baseCompiler.Properties.Stem); stem != "" {
+		name = stem
+	}
+	if path := test.baseCompiler.relativeInstallPath(); path != "" {
+		name = path + "/" + name
+	}
+	test.testConfig = tradefed.AutoGenRustHostTestConfig(ctx, name,
+		test.Properties.Test_config,
+		test.Properties.Test_config_template,
+		test.Properties.Test_suites,
+		test.Properties.Auto_gen_config)
+	test.binaryDecorator.install(ctx, file)
+}
+
+func (test *testDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
 	flags = test.binaryDecorator.compilerFlags(ctx, flags)
 	flags.RustFlags = append(flags.RustFlags, "--test")
 	return flags
@@ -65,21 +107,21 @@
 	return module.Init()
 }
 
-func (test *testBinaryDecorator) testPerSrc() bool {
+func (test *testDecorator) testPerSrc() bool {
 	return true
 }
 
-func (test *testBinaryDecorator) srcs() []string {
-	return test.Properties.Srcs
+func (test *testDecorator) srcs() []string {
+	return test.binaryDecorator.Properties.Srcs
 }
 
-func (test *testBinaryDecorator) setSrc(name, src string) {
-	test.Properties.Srcs = []string{src}
+func (test *testDecorator) setSrc(name, src string) {
+	test.binaryDecorator.Properties.Srcs = []string{src}
 	test.baseCompiler.Properties.Stem = StringPtr(name)
 }
 
-func (test *testBinaryDecorator) unsetSrc() {
-	test.Properties.Srcs = nil
+func (test *testDecorator) unsetSrc() {
+	test.binaryDecorator.Properties.Srcs = nil
 	test.baseCompiler.Properties.Stem = StringPtr("")
 }
 
@@ -90,7 +132,7 @@
 	unsetSrc()
 }
 
-var _ testPerSrc = (*testBinaryDecorator)(nil)
+var _ testPerSrc = (*testDecorator)(nil)
 
 func TestPerSrcMutator(mctx android.BottomUpMutatorContext) {
 	if m, ok := mctx.Module().(*Module); ok {
@@ -101,10 +143,21 @@
 					mctx.PropertyErrorf("srcs", "found a duplicate entry %q", duplicate)
 					return
 				}
+				// Rust compiler always compiles one source file at a time and
+				// uses the crate name as output file name.
+				// Cargo uses the test source file name as default crate name,
+				// but that can be redefined.
+				// So when there are multiple source files, the source file names will
+				// be the output file names, but when there is only one test file,
+				// use the crate name.
 				testNames := make([]string, numTests)
 				for i, src := range test.srcs() {
 					testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
 				}
+				crateName := m.compiler.crateName()
+				if numTests == 1 && crateName != "" {
+					testNames[0] = crateName
+				}
 				// TODO(chh): Add an "all tests" variation like cc/test.go?
 				tests := mctx.CreateLocalVariations(testNames...)
 				for i, src := range test.srcs() {
diff --git a/rust/test_test.go b/rust/test_test.go
index aa4c3c8..f131c6e 100644
--- a/rust/test_test.go
+++ b/rust/test_test.go
@@ -25,6 +25,7 @@
 		rust_test_host {
 			name: "my_test",
 			srcs: ["foo.rs", "src/bar.rs"],
+			crate_name: "new_test", // not used for multiple source files
 			relative_install_path: "rust/my-test",
 		}`)
 
@@ -41,3 +42,22 @@
 		}
 	}
 }
+
+// crate_name is output file name, when there is only one source file.
+func TestRustTestSingleFile(t *testing.T) {
+	ctx := testRust(t, `
+		rust_test_host {
+			name: "my-test",
+			srcs: ["foo.rs"],
+			crate_name: "new_test",
+			relative_install_path: "my-pkg",
+		}`)
+
+	name := "new_test"
+	testingModule := ctx.ModuleForTests("my-test", "linux_glibc_x86_64_"+name)
+	outPath := "/my-test/linux_glibc_x86_64_" + name + "/" + name
+	testingBuildParams := testingModule.Output(name)
+	if !strings.Contains(testingBuildParams.Output.String(), outPath) {
+		t.Errorf("wrong output: %v  expect: %v", testingBuildParams.Output, outPath)
+	}
+}
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index 947458a..b6ed659 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -25,7 +25,7 @@
 PLATFORM_SDK_VERSION=$(get_build_var PLATFORM_SDK_VERSION)
 PLATFORM_VERSION_ALL_CODENAMES=$(get_build_var PLATFORM_VERSION_ALL_CODENAMES)
 
-# PLATFORM_VERSION_ALL_CODESNAMES is a comma separated list like O,P. We need to
+# PLATFORM_VERSION_ALL_CODENAMES is a comma separated list like O,P. We need to
 # turn this into ["O","P"].
 PLATFORM_VERSION_ALL_CODENAMES=${PLATFORM_VERSION_ALL_CODENAMES/,/'","'}
 PLATFORM_VERSION_ALL_CODENAMES="[\"${PLATFORM_VERSION_ALL_CODENAMES}\"]"
diff --git a/sdk/update.go b/sdk/update.go
index 171bb3f..9fa9e04 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -43,17 +43,17 @@
 	}
 }
 
-func (gf *generatedFile) indent() {
+func (gf *generatedFile) Indent() {
 	gf.indentLevel++
 }
 
-func (gf *generatedFile) dedent() {
+func (gf *generatedFile) Dedent() {
 	gf.indentLevel--
 }
 
-func (gf *generatedFile) printfln(format string, args ...interface{}) {
+func (gf *generatedFile) Printfln(format string, args ...interface{}) {
 	// ninja consumes newline characters in rspfile_content. Prevent it by
-	// escaping the backslash in the newline character. The extra backshash
+	// escaping the backslash in the newline character. The extra backslash
 	// is removed when the rspfile is written to the actual script file
 	fmt.Fprintf(&(gf.content), strings.Repeat("    ", gf.indentLevel)+format+"\\n", args...)
 }
@@ -70,8 +70,8 @@
 	rb.Build(pctx, ctx, gf.path.Base(), "Build "+gf.path.Base())
 }
 
-func (s *sdk) javaLibs(ctx android.ModuleContext) []*java.Library {
-	result := []*java.Library{}
+func (s *sdk) javaLibs(ctx android.ModuleContext) []android.SdkAware {
+	result := []android.SdkAware{}
 	ctx.VisitDirectDeps(func(m android.Module) {
 		if j, ok := m.(*java.Library); ok {
 			result = append(result, j)
@@ -180,20 +180,12 @@
 //            libFoo.so   : a stub library
 
 const (
-	aidlIncludeDir            = "aidl"
-	javaStubDir               = "java"
-	javaStubFileSuffix        = ".jar"
 	nativeIncludeDir          = "include"
 	nativeGeneratedIncludeDir = "include_gen"
 	nativeStubDir             = "lib"
 	nativeStubFileSuffix      = ".so"
 )
 
-// path to the stub file of a java library. Relative to <sdk_root>/<api_dir>
-func javaStubFilePathFor(javaLib *java.Library) string {
-	return filepath.Join(javaStubDir, javaLib.Name()+javaStubFileSuffix)
-}
-
 // path to the stub file of a native shared library. Relative to <sdk_root>/<api_dir>
 func nativeStubFilePathFor(lib archSpecificNativeLibInfo) string {
 	return filepath.Join(lib.archType,
@@ -231,227 +223,205 @@
 	return ctx.ModuleName() + "_" + memberName + string(android.SdkVersionSeparator) + version
 }
 
-// buildAndroidBp creates the blueprint file that defines prebuilt modules for each of
-// the SDK members, and the entire sdk_snapshot module for the specified version
-// TODO(jiyong): create a meta info file (e.g. json, protobuf, etc.) instead, and convert it to
-// Android.bp in the (presumably old) branch where the snapshots will be used. This will give us
-// some flexibility to introduce backwards incompatible changes in soong.
-func (s *sdk) buildAndroidBp(ctx android.ModuleContext, version string) android.OutputPath {
-	bp := newGeneratedFile(ctx, "snapshot", "Android.bp")
-	bp.printfln("// This is auto-generated. DO NOT EDIT.")
-	bp.printfln("")
-
-	javaLibModules := s.javaLibs(ctx)
-	for _, m := range javaLibModules {
-		name := m.Name()
-		bp.printfln("java_import {")
-		bp.indent()
-		bp.printfln("name: %q,", versionedSdkMemberName(ctx, name, version))
-		bp.printfln("sdk_member_name: %q,", name)
-		bp.printfln("jars: [%q],", javaStubFilePathFor(m))
-		bp.dedent()
-		bp.printfln("}")
-		bp.printfln("")
-
-		// This module is for the case when the source tree for the unversioned module
-		// doesn't exist (i.e. building in an unbundled tree). "prefer:" is set to false
-		// so that this module does not eclipse the unversioned module if it exists.
-		bp.printfln("java_import {")
-		bp.indent()
-		bp.printfln("name: %q,", name)
-		bp.printfln("jars: [%q],", javaStubFilePathFor(m))
-		bp.printfln("prefer: false,")
-		bp.dedent()
-		bp.printfln("}")
-		bp.printfln("")
-	}
-
-	nativeLibInfos := s.nativeMemberInfos(ctx)
-	for _, info := range nativeLibInfos {
-		bp.printfln("cc_prebuilt_library_shared {")
-		bp.indent()
-		bp.printfln("name: %q,", versionedSdkMemberName(ctx, info.name, version))
-		bp.printfln("sdk_member_name: %q,", info.name)
-
-		// a function for emitting include dirs
-		printExportedDirsForNativeLibs := func(lib archSpecificNativeLibInfo, systemInclude bool) {
-			includeDirs := nativeIncludeDirPathsFor(ctx, lib, systemInclude, info.hasArchSpecificFlags)
-			if len(includeDirs) == 0 {
-				return
-			}
-			if !systemInclude {
-				bp.printfln("export_include_dirs: [")
-			} else {
-				bp.printfln("export_system_include_dirs: [")
-			}
-			bp.indent()
-			for _, dir := range includeDirs {
-				bp.printfln("%q,", dir)
-			}
-			bp.dedent()
-			bp.printfln("],")
-		}
-
-		if !info.hasArchSpecificFlags {
-			printExportedDirsForNativeLibs(info.archVariants[0], false /*systemInclude*/)
-			printExportedDirsForNativeLibs(info.archVariants[0], true /*systemInclude*/)
-		}
-
-		bp.printfln("arch: {")
-		bp.indent()
-		for _, av := range info.archVariants {
-			bp.printfln("%s: {", av.archType)
-			bp.indent()
-			bp.printfln("srcs: [%q],", nativeStubFilePathFor(av))
-			if info.hasArchSpecificFlags {
-				// export_* properties are added inside the arch: {<arch>: {...}} block
-				printExportedDirsForNativeLibs(av, false /*systemInclude*/)
-				printExportedDirsForNativeLibs(av, true /*systemInclude*/)
-			}
-			bp.dedent()
-			bp.printfln("},") // <arch>
-		}
-		bp.dedent()
-		bp.printfln("},") // arch
-		bp.printfln("stl: \"none\",")
-		bp.printfln("system_shared_libs: [],")
-		bp.dedent()
-		bp.printfln("}") // cc_prebuilt_library_shared
-		bp.printfln("")
-	}
-
-	bp.printfln("sdk_snapshot {")
-	bp.indent()
-	bp.printfln("name: %q,", ctx.ModuleName()+string(android.SdkVersionSeparator)+version)
-	if len(javaLibModules) > 0 {
-		bp.printfln("java_libs: [")
-		bp.indent()
-		for _, m := range javaLibModules {
-			bp.printfln("%q,", versionedSdkMemberName(ctx, m.Name(), version))
-		}
-		bp.dedent()
-		bp.printfln("],") // java_libs
-	}
-	if len(nativeLibInfos) > 0 {
-		bp.printfln("native_shared_libs: [")
-		bp.indent()
-		for _, info := range nativeLibInfos {
-			bp.printfln("%q,", versionedSdkMemberName(ctx, info.name, version))
-		}
-		bp.dedent()
-		bp.printfln("],") // native_shared_libs
-	}
-	bp.dedent()
-	bp.printfln("}") // sdk_snapshot
-	bp.printfln("")
-
-	bp.build(pctx, ctx, nil)
-	return bp.path
-}
-
 // buildSnapshot is the main function in this source file. It creates rules to copy
 // the contents (header files, stub libraries, etc) into the zip file.
 func (s *sdk) buildSnapshot(ctx android.ModuleContext) android.OutputPath {
-	snapshotPath := func(paths ...string) android.OutputPath {
-		return android.PathForModuleOut(ctx, "snapshot").Join(ctx, paths...)
-	}
+	snapshotDir := android.PathForModuleOut(ctx, "snapshot")
 
-	var filesToZip android.Paths
-	// copy src to dest and add the dest to the zip
-	copy := func(src android.Path, dest android.OutputPath) {
-		ctx.Build(pctx, android.BuildParams{
-			Rule:   android.Cp,
-			Input:  src,
-			Output: dest,
-		})
-		filesToZip = append(filesToZip, dest)
+	bp := newGeneratedFile(ctx, "snapshot", "Android.bp")
+	bp.Printfln("// This is auto-generated. DO NOT EDIT.")
+	bp.Printfln("")
+
+	builder := &snapshotBuilder{
+		ctx:           ctx,
+		version:       "current",
+		snapshotDir:   snapshotDir.OutputPath,
+		androidBpFile: bp,
+		filesToZip:    []android.Path{bp.path},
 	}
 
 	// copy exported AIDL files and stub jar files
-	for _, m := range s.javaLibs(ctx) {
-		headerJars := m.HeaderJars()
-		if len(headerJars) != 1 {
-			panic(fmt.Errorf("there must be only one header jar from %q", m.Name()))
-		}
-		copy(headerJars[0], snapshotPath(javaStubFilePathFor(m)))
-
-		for _, dir := range m.AidlIncludeDirs() {
-			// TODO(jiyong): copy parcelable declarations only
-			aidlFiles, _ := ctx.GlobWithDeps(dir.String()+"/**/*.aidl", nil)
-			for _, file := range aidlFiles {
-				copy(android.PathForSource(ctx, file), snapshotPath(aidlIncludeDir, file))
-			}
-		}
+	javaLibs := s.javaLibs(ctx)
+	for _, m := range javaLibs {
+		m.BuildSnapshot(ctx, builder)
 	}
 
 	// copy exported header files and stub *.so files
 	nativeLibInfos := s.nativeMemberInfos(ctx)
 	for _, info := range nativeLibInfos {
-
-		// a function for emitting include dirs
-		printExportedDirCopyCommandsForNativeLibs := func(lib archSpecificNativeLibInfo) {
-			includeDirs := lib.exportedIncludeDirs
-			includeDirs = append(includeDirs, lib.exportedSystemIncludeDirs...)
-			if len(includeDirs) == 0 {
-				return
-			}
-			for _, dir := range includeDirs {
-				if _, gen := dir.(android.WritablePath); gen {
-					// generated headers are copied via exportedDeps. See below.
-					continue
-				}
-				targetDir := nativeIncludeDir
-				if info.hasArchSpecificFlags {
-					targetDir = filepath.Join(lib.archType, targetDir)
-				}
-
-				// TODO(jiyong) copy headers having other suffixes
-				headers, _ := ctx.GlobWithDeps(dir.String()+"/**/*.h", nil)
-				for _, file := range headers {
-					src := android.PathForSource(ctx, file)
-					dest := snapshotPath(targetDir, file)
-					copy(src, dest)
-				}
-			}
-
-			genHeaders := lib.exportedDeps
-			for _, file := range genHeaders {
-				targetDir := nativeGeneratedIncludeDir
-				if info.hasArchSpecificFlags {
-					targetDir = filepath.Join(lib.archType, targetDir)
-				}
-				dest := snapshotPath(targetDir, lib.name, file.Rel())
-				copy(file, dest)
-			}
-		}
-
-		if !info.hasArchSpecificFlags {
-			printExportedDirCopyCommandsForNativeLibs(info.archVariants[0])
-		}
-
-		// for each architecture
-		for _, av := range info.archVariants {
-			copy(av.outputFile, snapshotPath(nativeStubFilePathFor(av)))
-
-			if info.hasArchSpecificFlags {
-				printExportedDirCopyCommandsForNativeLibs(av)
-			}
-		}
+		buildSharedNativeLibSnapshot(ctx, info, builder)
 	}
 
 	// generate Android.bp
-	bp := s.buildAndroidBp(ctx, "current")
-	filesToZip = append(filesToZip, bp)
+
+	bp.Printfln("sdk_snapshot {")
+	bp.Indent()
+	bp.Printfln("name: %q,", ctx.ModuleName()+string(android.SdkVersionSeparator)+builder.version)
+	if len(javaLibs) > 0 {
+		bp.Printfln("java_libs: [")
+		bp.Indent()
+		for _, m := range javaLibs {
+			bp.Printfln("%q,", builder.VersionedSdkMemberName(m.Name()))
+		}
+		bp.Dedent()
+		bp.Printfln("],") // java_libs
+	}
+	if len(nativeLibInfos) > 0 {
+		bp.Printfln("native_shared_libs: [")
+		bp.Indent()
+		for _, info := range nativeLibInfos {
+			bp.Printfln("%q,", builder.VersionedSdkMemberName(info.name))
+		}
+		bp.Dedent()
+		bp.Printfln("],") // native_shared_libs
+	}
+	bp.Dedent()
+	bp.Printfln("}") // sdk_snapshot
+	bp.Printfln("")
+
+	bp.build(pctx, ctx, nil)
+
+	filesToZip := builder.filesToZip
 
 	// zip them all
 	zipFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"-current.zip").OutputPath
 	rb := android.NewRuleBuilder()
 	rb.Command().
 		BuiltTool(ctx, "soong_zip").
-		FlagWithArg("-C ", snapshotPath().String()).
+		FlagWithArg("-C ", builder.snapshotDir.String()).
 		FlagWithRspFileInputList("-l ", filesToZip).
 		FlagWithOutput("-o ", zipFile)
 	rb.Build(pctx, ctx, "snapshot", "Building snapshot for "+ctx.ModuleName())
 
 	return zipFile
 }
+
+func buildSharedNativeLibSnapshot(ctx android.ModuleContext, info *nativeLibInfo, builder android.SnapshotBuilder) {
+	// a function for emitting include dirs
+	printExportedDirCopyCommandsForNativeLibs := func(lib archSpecificNativeLibInfo) {
+		includeDirs := lib.exportedIncludeDirs
+		includeDirs = append(includeDirs, lib.exportedSystemIncludeDirs...)
+		if len(includeDirs) == 0 {
+			return
+		}
+		for _, dir := range includeDirs {
+			if _, gen := dir.(android.WritablePath); gen {
+				// generated headers are copied via exportedDeps. See below.
+				continue
+			}
+			targetDir := nativeIncludeDir
+			if info.hasArchSpecificFlags {
+				targetDir = filepath.Join(lib.archType, targetDir)
+			}
+
+			// TODO(jiyong) copy headers having other suffixes
+			headers, _ := ctx.GlobWithDeps(dir.String()+"/**/*.h", nil)
+			for _, file := range headers {
+				src := android.PathForSource(ctx, file)
+				dest := filepath.Join(targetDir, file)
+				builder.CopyToSnapshot(src, dest)
+			}
+		}
+
+		genHeaders := lib.exportedDeps
+		for _, file := range genHeaders {
+			targetDir := nativeGeneratedIncludeDir
+			if info.hasArchSpecificFlags {
+				targetDir = filepath.Join(lib.archType, targetDir)
+			}
+			dest := filepath.Join(targetDir, lib.name, file.Rel())
+			builder.CopyToSnapshot(file, dest)
+		}
+	}
+
+	if !info.hasArchSpecificFlags {
+		printExportedDirCopyCommandsForNativeLibs(info.archVariants[0])
+	}
+
+	// for each architecture
+	for _, av := range info.archVariants {
+		builder.CopyToSnapshot(av.outputFile, nativeStubFilePathFor(av))
+
+		if info.hasArchSpecificFlags {
+			printExportedDirCopyCommandsForNativeLibs(av)
+		}
+	}
+
+	bp := builder.AndroidBpFile()
+	bp.Printfln("cc_prebuilt_library_shared {")
+	bp.Indent()
+	bp.Printfln("name: %q,", builder.VersionedSdkMemberName(info.name))
+	bp.Printfln("sdk_member_name: %q,", info.name)
+
+	// a function for emitting include dirs
+	printExportedDirsForNativeLibs := func(lib archSpecificNativeLibInfo, systemInclude bool) {
+		includeDirs := nativeIncludeDirPathsFor(ctx, lib, systemInclude, info.hasArchSpecificFlags)
+		if len(includeDirs) == 0 {
+			return
+		}
+		if !systemInclude {
+			bp.Printfln("export_include_dirs: [")
+		} else {
+			bp.Printfln("export_system_include_dirs: [")
+		}
+		bp.Indent()
+		for _, dir := range includeDirs {
+			bp.Printfln("%q,", dir)
+		}
+		bp.Dedent()
+		bp.Printfln("],")
+	}
+
+	if !info.hasArchSpecificFlags {
+		printExportedDirsForNativeLibs(info.archVariants[0], false /*systemInclude*/)
+		printExportedDirsForNativeLibs(info.archVariants[0], true /*systemInclude*/)
+	}
+
+	bp.Printfln("arch: {")
+	bp.Indent()
+	for _, av := range info.archVariants {
+		bp.Printfln("%s: {", av.archType)
+		bp.Indent()
+		bp.Printfln("srcs: [%q],", nativeStubFilePathFor(av))
+		if info.hasArchSpecificFlags {
+			// export_* properties are added inside the arch: {<arch>: {...}} block
+			printExportedDirsForNativeLibs(av, false /*systemInclude*/)
+			printExportedDirsForNativeLibs(av, true /*systemInclude*/)
+		}
+		bp.Dedent()
+		bp.Printfln("},") // <arch>
+	}
+	bp.Dedent()
+	bp.Printfln("},") // arch
+	bp.Printfln("stl: \"none\",")
+	bp.Printfln("system_shared_libs: [],")
+	bp.Dedent()
+	bp.Printfln("}") // cc_prebuilt_library_shared
+	bp.Printfln("")
+}
+
+type snapshotBuilder struct {
+	ctx           android.ModuleContext
+	version       string
+	snapshotDir   android.OutputPath
+	filesToZip    android.Paths
+	androidBpFile *generatedFile
+}
+
+func (s *snapshotBuilder) CopyToSnapshot(src android.Path, dest string) {
+	path := s.snapshotDir.Join(s.ctx, dest)
+	s.ctx.Build(pctx, android.BuildParams{
+		Rule:   android.Cp,
+		Input:  src,
+		Output: path,
+	})
+	s.filesToZip = append(s.filesToZip, path)
+}
+
+func (s *snapshotBuilder) AndroidBpFile() android.GeneratedSnapshotFile {
+	return s.androidBpFile
+}
+
+func (s *snapshotBuilder) VersionedSdkMemberName(unversionedName string) interface{} {
+	return versionedSdkMemberName(s.ctx, unversionedName, s.version)
+}
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index 3d30cfa..905acfa 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -105,6 +105,10 @@
 }
 
 func autogenTemplate(ctx android.ModuleContext, output android.WritablePath, template string, configs []Config) {
+	autogenTemplateWithName(ctx, ctx.ModuleName(), output, template, configs)
+}
+
+func autogenTemplateWithName(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config) {
 	var configStrings []string
 	for _, config := range configs {
 		configStrings = append(configStrings, config.Config())
@@ -117,7 +121,7 @@
 		Description: "test config",
 		Output:      output,
 		Args: map[string]string{
-			"name":         ctx.ModuleName(),
+			"name":         name,
 			"template":     template,
 			"extraConfigs": extraConfigs,
 		},
@@ -193,6 +197,21 @@
 	return path
 }
 
+func AutoGenRustHostTestConfig(ctx android.ModuleContext, name string, testConfigProp *string,
+	testConfigTemplateProp *string, testSuites []string, autoGenConfig *bool) android.Path {
+	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
+	if autogenPath != nil {
+		templatePathString := "${RustHostTestConfigTemplate}"
+		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
+		if templatePath.Valid() {
+			templatePathString = templatePath.String()
+		}
+		autogenTemplateWithName(ctx, name, autogenPath, templatePathString, nil)
+		return autogenPath
+	}
+	return path
+}
+
 var autogenInstrumentationTest = pctx.StaticRule("autogenInstrumentationTest", blueprint.RuleParams{
 	Command: "${AutoGenTestConfigScript} $out $in ${EmptyTestConfig} $template",
 	CommandDeps: []string{
diff --git a/tradefed/config.go b/tradefed/config.go
index 141e0c5..8249ffe 100644
--- a/tradefed/config.go
+++ b/tradefed/config.go
@@ -31,6 +31,7 @@
 	pctx.SourcePathVariable("NativeHostTestConfigTemplate", "build/make/core/native_host_test_config_template.xml")
 	pctx.SourcePathVariable("NativeTestConfigTemplate", "build/make/core/native_test_config_template.xml")
 	pctx.SourcePathVariable("PythonBinaryHostTestConfigTemplate", "build/make/core/python_binary_host_test_config_template.xml")
+	pctx.SourcePathVariable("RustHostTestConfigTemplate", "build/make/core/rust_host_test_config_template.xml")
 
 	pctx.SourcePathVariable("EmptyTestConfig", "build/make/core/empty_test_config.xml")
 }
diff --git a/tradefed/makevars.go b/tradefed/makevars.go
index aad7273..e6b88ea 100644
--- a/tradefed/makevars.go
+++ b/tradefed/makevars.go
@@ -31,6 +31,7 @@
 	ctx.Strict("NATIVE_HOST_TEST_CONFIG_TEMPLATE", "${NativeHostTestConfigTemplate}")
 	ctx.Strict("NATIVE_TEST_CONFIG_TEMPLATE", "${NativeTestConfigTemplate}")
 	ctx.Strict("PYTHON_BINARY_HOST_TEST_CONFIG_TEMPLATE", "${PythonBinaryHostTestConfigTemplate}")
+	ctx.Strict("RUST_HOST_TEST_CONFIG_TEMPLATE", "${RustHostTestConfigTemplate}")
 
 	ctx.Strict("EMPTY_TEST_CONFIG", "${EmptyTestConfig}")
 }