Merge "androidmk conversion logic for android_app_import"
diff --git a/Android.bp b/Android.bp
index e2d606e..c9a48b4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -196,6 +196,7 @@
         "cc/gen_test.go",
         "cc/genrule_test.go",
         "cc/library_test.go",
+        "cc/prebuilt_test.go",
         "cc/proto_test.go",
         "cc/test_data_test.go",
         "cc/util_test.go",
diff --git a/android/arch.go b/android/arch.go
index c68fe46..68fc149 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1505,10 +1505,10 @@
 	return false
 }
 
-// hasArmArch returns true if targets has at least arm Android arch
+// hasArmArch returns true if targets has at least non-native_bridge arm Android arch
 func hasArmAndroidArch(targets []Target) bool {
 	for _, target := range targets {
-		if target.Os == Android && target.Arch.ArchType == Arm {
+		if target.Os == Android && target.Arch.ArchType == Arm && target.NativeBridge == NativeBridgeDisabled {
 			return true
 		}
 	}
diff --git a/android/config.go b/android/config.go
index 15e2ad4..1507c25 100644
--- a/android/config.go
+++ b/android/config.go
@@ -235,20 +235,14 @@
 }
 
 func TestArchConfigNativeBridge(buildDir string, env map[string]string) Config {
-	testConfig := TestConfig(buildDir, env)
+	testConfig := TestArchConfig(buildDir, env)
 	config := testConfig.config
 
-	config.Targets = map[OsType][]Target{
-		Android: []Target{
-			{Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled},
-			{Android, Arch{ArchType: X86, ArchVariant: "silvermont", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled},
-			{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled},
-			{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled},
-		},
-		BuildOs: []Target{
-			{BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled},
-			{BuildOs, Arch{ArchType: X86}, NativeBridgeDisabled},
-		},
+	config.Targets[Android] = []Target{
+		{Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled},
+		{Android, Arch{ArchType: X86, ArchVariant: "silvermont", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled},
+		{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled},
+		{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled},
 	}
 
 	return testConfig
@@ -286,8 +280,16 @@
 		},
 	}
 
+	if runtime.GOOS == "darwin" {
+		config.Targets[BuildOs] = config.Targets[BuildOs][:1]
+	}
+
 	config.BuildOsVariant = config.Targets[BuildOs][0].String()
 	config.BuildOsCommonVariant = getCommonTargets(config.Targets[BuildOs])[0].String()
+	config.TestProductVariables.DeviceArch = proptools.StringPtr("arm64")
+	config.TestProductVariables.DeviceArchVariant = proptools.StringPtr("armv8-a")
+	config.TestProductVariables.DeviceSecondaryArch = proptools.StringPtr("arm")
+	config.TestProductVariables.DeviceSecondaryArchVariant = proptools.StringPtr("armv7-a-neon")
 
 	return testConfig
 }
@@ -1100,3 +1102,23 @@
 func (c *config) ProductCompatibleProperty() bool {
 	return Bool(c.productVariables.ProductCompatibleProperty)
 }
+
+func (c *deviceConfig) BoardVndkRuntimeDisable() bool {
+	return Bool(c.config.productVariables.BoardVndkRuntimeDisable)
+}
+
+func (c *deviceConfig) DeviceArch() string {
+	return String(c.config.productVariables.DeviceArch)
+}
+
+func (c *deviceConfig) DeviceArchVariant() string {
+	return String(c.config.productVariables.DeviceArchVariant)
+}
+
+func (c *deviceConfig) DeviceSecondaryArch() string {
+	return String(c.config.productVariables.DeviceSecondaryArch)
+}
+
+func (c *deviceConfig) DeviceSecondaryArchVariant() string {
+	return String(c.config.productVariables.DeviceSecondaryArchVariant)
+}
diff --git a/android/mutator.go b/android/mutator.go
index 45954d3..085c055 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -77,7 +77,6 @@
 	RegisterNamespaceMutator,
 	RegisterPrebuiltsPreArchMutators,
 	RegisterDefaultsPreArchMutators,
-	RegisterOverridePreArchMutators,
 	registerVisibilityRuleGatherer,
 }
 
@@ -95,6 +94,7 @@
 	RegisterPrebuiltsPostDepsMutators,
 	registerVisibilityRuleEnforcer,
 	registerNeverallowMutator,
+	RegisterOverridePostDepsMutators,
 }
 
 func PreArchMutators(f RegisterMutatorFunc) {
diff --git a/android/onceper.go b/android/onceper.go
index 5ad17fa..ff865c2 100644
--- a/android/onceper.go
+++ b/android/onceper.go
@@ -40,7 +40,8 @@
 }
 
 // Once computes a value the first time it is called with a given key per OncePer, and returns the
-// value without recomputing when called with the same key.  key must be hashable.
+// value without recomputing when called with the same key.  key must be hashable.  If value panics
+// the panic will be propagated but the next call to Once with the same key will return nil.
 func (once *OncePer) Once(key OnceKey, value func() interface{}) interface{} {
 	// Fast path: check if the key is already in the map
 	if v, ok := once.values.Load(key); ok {
@@ -54,10 +55,15 @@
 		return once.maybeWaitFor(key, v)
 	}
 
-	// The waiter is inserted, call the value constructor, store it, and signal the waiter
-	v := value()
-	once.values.Store(key, v)
-	close(waiter)
+	// The waiter is inserted, call the value constructor, store it, and signal the waiter.  Use defer in case
+	// the function panics.
+	var v interface{}
+	defer func() {
+		once.values.Store(key, v)
+		close(waiter)
+	}()
+
+	v = value()
 
 	return v
 }
diff --git a/android/onceper_test.go b/android/onceper_test.go
index 95303ba..1a55ff4 100644
--- a/android/onceper_test.go
+++ b/android/onceper_test.go
@@ -175,3 +175,43 @@
 		t.Errorf(`reentrant Once should return "a": %q`, a)
 	}
 }
+
+// Test that a recovered panic in a Once function doesn't deadlock
+func TestOncePerPanic(t *testing.T) {
+	once := OncePer{}
+	key := NewOnceKey("key")
+
+	ch := make(chan interface{})
+
+	var a interface{}
+
+	go func() {
+		defer func() {
+			ch <- recover()
+		}()
+
+		a = once.Once(key, func() interface{} {
+			panic("foo")
+		})
+	}()
+
+	p := <-ch
+
+	if p.(string) != "foo" {
+		t.Errorf(`expected panic with "foo", got %#v`, p)
+	}
+
+	if a != nil {
+		t.Errorf(`expected a to be nil, got %#v`, a)
+	}
+
+	// If the call to Once that panicked leaves the key in a bad state this will deadlock
+	b := once.Once(key, func() interface{} {
+		return "bar"
+	})
+
+	// The second call to Once should return nil inserted by the first call that panicked.
+	if b != nil {
+		t.Errorf(`expected b to be nil, got %#v`, b)
+	}
+}
diff --git a/android/override_module.go b/android/override_module.go
index 119bca1..5a57c93 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -84,8 +84,13 @@
 	getOverrides() []OverrideModule
 
 	override(ctx BaseModuleContext, o OverrideModule)
+	getOverriddenBy() string
 
 	setOverridesProperty(overridesProperties *[]string)
+
+	// Due to complications with incoming dependencies, overrides are processed after DepsMutator.
+	// So, overridable properties need to be handled in a separate, dedicated deps mutator.
+	OverridablePropertiesDepsMutator(ctx BottomUpMutatorContext)
 }
 
 // Base module struct for overridable module types
@@ -106,6 +111,8 @@
 	// set this to a pointer to the property through the InitOverridableModule function, so that
 	// override information is propagated and aggregated correctly.
 	overridesProperty *[]string
+
+	overriddenBy string
 }
 
 func InitOverridableModule(m OverridableModule, overridesProperty *[]string) {
@@ -153,14 +160,23 @@
 			}
 		}
 	}
+	b.overriddenBy = o.Name()
+}
+
+func (b *OverridableModuleBase) getOverriddenBy() string {
+	return b.overriddenBy
+}
+
+func (b *OverridableModuleBase) OverridablePropertiesDepsMutator(ctx BottomUpMutatorContext) {
 }
 
 // Mutators for override/overridable modules. All the fun happens in these functions. It is critical
 // to keep them in this order and not put any order mutators between them.
-func RegisterOverridePreArchMutators(ctx RegisterMutatorsContext) {
+func RegisterOverridePostDepsMutators(ctx RegisterMutatorsContext) {
 	ctx.BottomUp("override_deps", overrideModuleDepsMutator).Parallel()
 	ctx.TopDown("register_override", registerOverrideMutator).Parallel()
 	ctx.BottomUp("perform_override", performOverrideMutator).Parallel()
+	ctx.BottomUp("overridable_deps", overridableModuleDepsMutator).Parallel()
 }
 
 type overrideBaseDependencyTag struct {
@@ -207,5 +223,22 @@
 		for i, o := range overrides {
 			mods[i+1].(OverridableModule).override(ctx, o)
 		}
+	} else if o, ok := ctx.Module().(OverrideModule); ok {
+		// Create a variant of the overriding module with its own name. This matches the above local
+		// variant name rule for overridden modules, and thus allows ReplaceDependencies to match the
+		// two.
+		ctx.CreateLocalVariations(o.Name())
+	}
+}
+
+func overridableModuleDepsMutator(ctx BottomUpMutatorContext) {
+	if b, ok := ctx.Module().(OverridableModule); ok {
+		if o := b.getOverriddenBy(); o != "" {
+			// Redirect dependencies on the overriding module to this overridden module. Overriding
+			// modules are basically pseudo modules, and all build actions are associated to overridden
+			// modules. Therefore, dependencies on overriding modules need to be forwarded there as well.
+			ctx.ReplaceDependencies(o)
+		}
+		b.OverridablePropertiesDepsMutator(ctx)
 	}
 }
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
index bec24c7..b13ce2a 100644
--- a/android/prebuilt_etc.go
+++ b/android/prebuilt_etc.go
@@ -23,6 +23,7 @@
 	RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory)
 	RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
 	RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory)
+	RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
 
 	PreDepsMutators(func(ctx RegisterMutatorsContext) {
 		ctx.BottomUp("prebuilt_etc", prebuiltEtcMutator).Parallel()
@@ -240,3 +241,12 @@
 		}
 	}
 }
+
+// prebuilt_font installs a font in <partition>/fonts directory.
+func PrebuiltFontFactory() Module {
+	module := &PrebuiltEtc{installDirBase: "fonts"}
+	InitPrebuiltEtcModule(module)
+	// This module is device-only
+	InitAndroidArchModule(module, DeviceSupported, MultilibFirst)
+	return module
+}
diff --git a/android/prebuilt_etc_test.go b/android/prebuilt_etc_test.go
index 08700ae..a5c4480 100644
--- a/android/prebuilt_etc_test.go
+++ b/android/prebuilt_etc_test.go
@@ -30,6 +30,7 @@
 	ctx.RegisterModuleType("prebuilt_etc_host", ModuleFactoryAdaptor(PrebuiltEtcHostFactory))
 	ctx.RegisterModuleType("prebuilt_usr_share", ModuleFactoryAdaptor(PrebuiltUserShareFactory))
 	ctx.RegisterModuleType("prebuilt_usr_share_host", ModuleFactoryAdaptor(PrebuiltUserShareHostFactory))
+	ctx.RegisterModuleType("prebuilt_font", ModuleFactoryAdaptor(PrebuiltFontFactory))
 	ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
 		ctx.BottomUp("prebuilt_etc", prebuiltEtcMutator).Parallel()
 	})
@@ -219,3 +220,18 @@
 		t.Errorf("expected %q, got %q", expected, p.installDirPath.RelPathString())
 	}
 }
+
+func TestPrebuiltFontInstallDirPath(t *testing.T) {
+	ctx, _ := testPrebuiltEtc(t, `
+		prebuilt_font {
+			name: "foo.conf",
+			src: "foo.conf",
+		}
+	`)
+
+	p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a_core").Module().(*PrebuiltEtc)
+	expected := "target/product/test_device/system/fonts"
+	if p.installDirPath.RelPathString() != expected {
+		t.Errorf("expected %q, got %q", expected, p.installDirPath.RelPathString())
+	}
+}
diff --git a/android/util.go b/android/util.go
index f9dce6f..f7a3437 100644
--- a/android/util.go
+++ b/android/util.go
@@ -52,6 +52,31 @@
 	return string(ret)
 }
 
+func JoinWithSuffix(strs []string, suffix string, separator string) string {
+	if len(strs) == 0 {
+		return ""
+	}
+
+	if len(strs) == 1 {
+		return strs[0] + suffix
+	}
+
+	n := len(" ") * (len(strs) - 1)
+	for _, s := range strs {
+		n += len(suffix) + len(s)
+	}
+
+	ret := make([]byte, 0, n)
+	for i, s := range strs {
+		if i != 0 {
+			ret = append(ret, separator...)
+		}
+		ret = append(ret, s...)
+		ret = append(ret, suffix...)
+	}
+	return string(ret)
+}
+
 func sortedKeys(m map[string][]string) []string {
 	s := make([]string, 0, len(m))
 	for k := range m {
diff --git a/android/variable.go b/android/variable.go
index c500671..ff3ebaf 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -279,6 +279,8 @@
 	BoardPlatPrivateSepolicyDirs []string `json:",omitempty"`
 	BoardSepolicyM4Defs          []string `json:",omitempty"`
 
+	BoardVndkRuntimeDisable *bool `json:",omitempty"`
+
 	VendorVars map[string]map[string]string `json:",omitempty"`
 
 	Ndk_abis               *bool `json:",omitempty"`
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 6809914..ea5316c 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -1,10 +1,11 @@
 package android
 
 import (
-	"github.com/google/blueprint"
 	"io/ioutil"
 	"os"
 	"testing"
+
+	"github.com/google/blueprint"
 )
 
 var visibilityTests = []struct {
@@ -198,10 +199,17 @@
 					name: "libnested",
 					deps: ["libexample"],
 				}`),
+			"other/Blueprints": []byte(`
+				mock_library {
+					name: "libother",
+					deps: ["libexample"],
+				}`),
 		},
 		expectedErrors: []string{
 			`module "libnested" variant "android_common": depends on //top:libexample which is not` +
 				` visible to this module; //top:libexample is only visible to \[//top:__pkg__\]`,
+			`module "libother" variant "android_common": depends on //top:libexample which is not` +
+				` visible to this module; //top:libexample is only visible to \[//top:__pkg__\]`,
 		},
 	},
 	{
@@ -223,10 +231,17 @@
 					name: "libnested",
 					deps: ["libexample"],
 				}`),
+			"other/Blueprints": []byte(`
+				mock_library {
+					name: "libother",
+					deps: ["libexample"],
+				}`),
 		},
 		expectedErrors: []string{
 			`module "libnested" variant "android_common": depends on //top:libexample which is not` +
 				` visible to this module; //top:libexample is only visible to \[//top:__pkg__\]`,
+			`module "libother" variant "android_common": depends on //top:libexample which is not` +
+				` visible to this module; //top:libexample is only visible to \[//top:__pkg__\]`,
 		},
 	},
 	{
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index 42bd44b..b3b1ce0 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -1119,6 +1119,45 @@
 `,
 	},
 	{
+		desc: "prebuilt_font",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := font.ttf
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts
+include $(BUILD_PREBUILT)
+`,
+		expected: `
+prebuilt_font {
+	name: "font.ttf",
+	src: "font.ttf",
+
+}
+`,
+	},
+	{
+		desc: "prebuilt_font",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := font.ttf
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/fonts
+include $(BUILD_PREBUILT)
+`,
+		expected: `
+prebuilt_font {
+	name: "font.ttf",
+	src: "font.ttf",
+	product_specific: true,
+
+}
+`,
+	},
+	{
 		desc: "prebuilt_usr_share_host subdir_bar",
 		in: `
 include $(CLEAR_VARS)
diff --git a/apex/apex.go b/apex/apex.go
index 68d0bc1..51d0718 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -521,6 +521,17 @@
 					a.properties.Multilib.Prefer32.Binaries, target.String(),
 					a.getImageVariation(config))
 			}
+
+			if strings.HasPrefix(ctx.ModuleName(), "com.android.runtime") && target.Os.Class == android.Device {
+				for _, sanitizer := range ctx.Config().SanitizeDevice() {
+					if sanitizer == "hwaddress" {
+						addDependenciesForNativeModules(ctx,
+							[]string{"libclang_rt.hwasan-aarch64-android"},
+							nil, target.String(), a.getImageVariation(config))
+						break
+					}
+				}
+			}
 		}
 
 	}
diff --git a/bpf/Android.bp b/bpf/Android.bp
index 7bd4d44..882cd8a 100644
--- a/bpf/Android.bp
+++ b/bpf/Android.bp
@@ -21,10 +21,14 @@
         "blueprint",
         "blueprint-proptools",
         "soong-android",
+        "soong-cc",
         "soong-cc-config",
     ],
     srcs: [
         "bpf.go",
     ],
+    testSrcs: [
+        "bpf_test.go",
+    ],
     pluginFor: ["soong_build"],
 }
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 13468c7..dcbf9ad 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -33,7 +33,7 @@
 var (
 	pctx = android.NewPackageContext("android/soong/bpf")
 
-	cc = pctx.AndroidGomaStaticRule("cc",
+	ccRule = pctx.AndroidGomaStaticRule("ccRule",
 		blueprint.RuleParams{
 			Depfile:     "${out}.d",
 			Deps:        blueprint.DepsGCC,
@@ -82,7 +82,7 @@
 		obj := android.ObjPathWithExt(ctx, "", src, "o")
 
 		ctx.Build(pctx, android.BuildParams{
-			Rule:   cc,
+			Rule:   ccRule,
 			Input:  src,
 			Output: obj,
 			Args: map[string]string{
diff --git a/bpf/bpf_test.go b/bpf/bpf_test.go
index 1d53e41..cbb251f 100644
--- a/bpf/bpf_test.go
+++ b/bpf/bpf_test.go
@@ -20,7 +20,7 @@
 	"testing"
 
 	"android/soong/android"
-	cc2 "android/soong/cc"
+	"android/soong/cc"
 )
 
 var buildDir string
@@ -49,115 +49,14 @@
 }
 
 func testContext(bp string) *android.TestContext {
-	ctx := android.NewTestArchContext()
-	ctx.RegisterModuleType("bpf", android.ModuleFactoryAdaptor(bpfFactory))
-	ctx.RegisterModuleType("cc_test", android.ModuleFactoryAdaptor(cc2.TestFactory))
-	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc2.LibraryFactory))
-	ctx.RegisterModuleType("cc_library_static", android.ModuleFactoryAdaptor(cc2.LibraryStaticFactory))
-	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc2.ObjectFactory))
-	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc2.ToolchainLibraryFactory))
-	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
-		ctx.BottomUp("link", cc2.LinkageMutator).Parallel()
-	})
-	ctx.Register()
-
-	// Add some modules that are required by the compiler and/or linker
-	bp = bp + `
-		toolchain_library {
-			name: "libatomic",
-			vendor_available: true,
-			recovery_available: true,
-			src: "",
-		}
-
-		toolchain_library {
-			name: "libclang_rt.builtins-arm-android",
-			vendor_available: true,
-			recovery_available: true,
-			src: "",
-		}
-
-		toolchain_library {
-			name: "libclang_rt.builtins-aarch64-android",
-			vendor_available: true,
-			recovery_available: true,
-			src: "",
-		}
-
-		toolchain_library {
-			name: "libgcc",
-			vendor_available: true,
-			recovery_available: true,
-			src: "",
-		}
-
-		cc_library {
-			name: "libc",
-			no_libgcc: true,
-			nocrt: true,
-			system_shared_libs: [],
-			recovery_available: true,
-		}
-
-		cc_library {
-			name: "libm",
-			no_libgcc: true,
-			nocrt: true,
-			system_shared_libs: [],
-			recovery_available: true,
-		}
-
-		cc_library {
-			name: "libdl",
-			no_libgcc: true,
-			nocrt: true,
-			system_shared_libs: [],
-			recovery_available: true,
-		}
-
-		cc_library {
-			name: "libgtest",
-			host_supported: true,
-			vendor_available: true,
-		}
-
-		cc_library {
-			name: "libgtest_main",
-			host_supported: true,
-			vendor_available: true,
-		}
-
-		cc_object {
-			name: "crtbegin_dynamic",
-			recovery_available: true,
-			vendor_available: true,
-		}
-
-		cc_object {
-			name: "crtend_android",
-			recovery_available: true,
-			vendor_available: true,
-		}
-
-		cc_object {
-			name: "crtbegin_so",
-			recovery_available: true,
-			vendor_available: true,
-		}
-
-		cc_object {
-			name: "crtend_so",
-			recovery_available: true,
-			vendor_available: true,
-		}
-	`
 	mockFS := map[string][]byte{
-		"Android.bp":  []byte(bp),
 		"bpf.c":       nil,
 		"BpfTest.cpp": nil,
 	}
 
-	ctx.MockFileSystem(mockFS)
+	ctx := cc.CreateTestContext(bp, mockFS, android.Android)
+	ctx.RegisterModuleType("bpf", android.ModuleFactoryAdaptor(bpfFactory))
+	ctx.Register()
 
 	return ctx
 }
@@ -174,6 +73,7 @@
 			name: "vts_test_binary_bpf_module",
 			srcs: ["BpfTest.cpp"],
 			data: [":bpf.o"],
+			gtest: false,
 		}
 	`
 
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index 1bc737a..17cff18 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -505,9 +505,9 @@
 var localModuleUpdate = map[string][]etcPrebuiltModuleUpdate{
 	"HOST_OUT":                        {{prefix: "/etc", modType: "prebuilt_etc_host"}, {prefix: "/usr/share", modType: "prebuilt_usr_share_host"}},
 	"PRODUCT_OUT":                     {{prefix: "/system/etc"}, {prefix: "/vendor/etc", flags: []string{"proprietary"}}},
-	"TARGET_OUT":                      {{prefix: "/etc"}, {prefix: "/usr/share", modType: "prebuilt_usr_share"}},
+	"TARGET_OUT":                      {{prefix: "/etc"}, {prefix: "/usr/share", modType: "prebuilt_usr_share"}, {prefix: "/fonts", modType: "prebuilt_font"}},
 	"TARGET_OUT_ETC":                  {{prefix: ""}},
-	"TARGET_OUT_PRODUCT":              {{prefix: "/etc", flags: []string{"product_specific"}}},
+	"TARGET_OUT_PRODUCT":              {{prefix: "/etc", flags: []string{"product_specific"}}, {prefix: "/fonts", modType: "prebuilt_font", flags: []string{"product_specific"}}},
 	"TARGET_OUT_PRODUCT_ETC":          {{prefix: "", flags: []string{"product_specific"}}},
 	"TARGET_OUT_ODM":                  {{prefix: "/etc", flags: []string{"device_specific"}}},
 	"TARGET_OUT_PRODUCT_SERVICES":     {{prefix: "/etc", flags: []string{"product_services_specific"}}},
diff --git a/cc/binary.go b/cc/binary.go
index 51e68fc..93d1de2 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -440,8 +440,8 @@
 	// Bionic binaries (e.g. linker) is installed to the bootstrap subdirectory.
 	// The original path becomes a symlink to the corresponding file in the
 	// runtime APEX.
-	if isBionic(ctx.baseModuleName()) && ctx.Arch().Native && ctx.apexName() == "" && !ctx.inRecovery() {
-		if ctx.Device() {
+	if installToBootstrap(ctx.baseModuleName(), ctx.Config()) && ctx.Arch().Native && ctx.apexName() == "" && !ctx.inRecovery() {
+		if ctx.Device() && isBionic(ctx.baseModuleName()) {
 			binary.installSymlinkToRuntimeApex(ctx, file)
 		}
 		binary.baseInstaller.subDir = "bootstrap"
diff --git a/cc/builder.go b/cc/builder.go
index c99e461..7cf5c29 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -123,12 +123,25 @@
 	_ = pctx.SourcePathVariable("stripPath", "build/soong/scripts/strip.sh")
 	_ = pctx.SourcePathVariable("xzCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/xz")
 
+	// b/132822437: objcopy uses a file descriptor per .o file when called on .a files, which runs the system out of
+	// file descriptors on darwin.  Limit concurrent calls to 5 on darwin.
+	darwinStripPool = func() blueprint.Pool {
+		if runtime.GOOS == "darwin" {
+			return pctx.StaticPool("darwinStripPool", blueprint.PoolParams{
+				Depth: 5,
+			})
+		} else {
+			return nil
+		}
+	}()
+
 	strip = pctx.AndroidStaticRule("strip",
 		blueprint.RuleParams{
 			Depfile:     "${out}.d",
 			Deps:        blueprint.DepsGCC,
 			Command:     "CROSS_COMPILE=$crossCompile XZ=$xzCmd CLANG_BIN=${config.ClangBin} $stripPath ${args} -i ${in} -o ${out} -d ${out}.d",
 			CommandDeps: []string{"$stripPath", "$xzCmd"},
+			Pool:        darwinStripPool,
 		},
 		"args", "crossCompile")
 
@@ -254,11 +267,12 @@
 
 	groupStaticLibs bool
 
-	stripKeepSymbols       bool
-	stripKeepSymbolsList   string
-	stripKeepMiniDebugInfo bool
-	stripAddGnuDebuglink   bool
-	stripUseGnuStrip       bool
+	stripKeepSymbols              bool
+	stripKeepSymbolsList          string
+	stripKeepSymbolsAndDebugFrame bool
+	stripKeepMiniDebugInfo        bool
+	stripAddGnuDebuglink          bool
+	stripUseGnuStrip              bool
 
 	proto            android.ProtoFlags
 	protoC           bool
@@ -839,6 +853,9 @@
 	if flags.stripKeepSymbolsList != "" {
 		args += " -k" + flags.stripKeepSymbolsList
 	}
+	if flags.stripKeepSymbolsAndDebugFrame {
+		args += " --keep-symbols-and-debug-frame"
+	}
 	if flags.stripUseGnuStrip {
 		args += " --use-gnu-strip"
 	}
diff --git a/cc/cc.go b/cc/cc.go
index eaf41d8..de108b4 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -600,6 +600,9 @@
 	if library, ok := c.linker.(*libraryDecorator); ok {
 		return len(library.Properties.Stubs.Versions) > 0
 	}
+	if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
+		return len(library.Properties.Stubs.Versions) > 0
+	}
 	return false
 }
 
@@ -619,6 +622,13 @@
 	return false
 }
 
+func installToBootstrap(name string, config android.Config) bool {
+	if name == "libclang_rt.hwasan-aarch64-android" {
+		return inList("hwaddress", config.SanitizeDevice())
+	}
+	return isBionic(name)
+}
+
 type baseModuleContext struct {
 	android.BaseContext
 	moduleContextImpl
@@ -909,7 +919,7 @@
 }
 
 func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
-	c.makeLinkType = c.getMakeLinkType(actx.Config())
+	c.makeLinkType = c.getMakeLinkType(actx)
 
 	ctx := &moduleContext{
 		ModuleContext: actx,
@@ -1011,7 +1021,7 @@
 		}
 	}
 
-	if c.installer != nil && !c.Properties.PreventInstall && c.IsForPlatform() && c.outputFile.Valid() {
+	if c.installable() {
 		c.installer.install(ctx, c.outputFile.Path())
 		if ctx.Failed() {
 			return
@@ -1930,19 +1940,22 @@
 	return false
 }
 
-func (c *Module) getMakeLinkType(config android.Config) string {
+func (c *Module) getMakeLinkType(actx android.ModuleContext) string {
+	name := actx.ModuleName()
 	if c.useVndk() {
-		if inList(c.Name(), *vndkCoreLibraries(config)) ||
-			inList(c.Name(), *vndkSpLibraries(config)) ||
-			inList(c.Name(), *llndkLibraries(config)) {
-			if inList(c.Name(), *vndkPrivateLibraries(config)) {
-				return "native:vndk_private"
-			} else {
+		if lib, ok := c.linker.(*llndkStubDecorator); ok {
+			if Bool(lib.Properties.Vendor_available) {
 				return "native:vndk"
 			}
-		} else {
-			return "native:vendor"
+			return "native:vndk_private"
 		}
+		if c.isVndk() && !c.isVndkExt() {
+			if Bool(c.VendorProperties.Vendor_available) {
+				return "native:vndk"
+			}
+			return "native:vndk_private"
+		}
+		return "native:vendor"
 	} else if c.inRecovery() {
 		return "native:recovery"
 	} else if c.Target().Os == android.Android && String(c.Properties.Sdk_version) != "" {
@@ -1950,7 +1963,7 @@
 		// TODO(b/114741097): use the correct ndk stl once build errors have been fixed
 		//family, link := getNdkStlFamilyAndLinkType(c)
 		//return fmt.Sprintf("native:ndk:%s:%s", family, link)
-	} else if inList(c.Name(), *vndkUsingCoreVariantLibraries(config)) {
+	} else if inList(name, *vndkUsingCoreVariantLibraries(actx.Config())) {
 		return "native:platform_vndk"
 	} else {
 		return "native:platform"
@@ -1968,6 +1981,10 @@
 	return false
 }
 
+func (c *Module) installable() bool {
+	return c.installer != nil && !c.Properties.PreventInstall && c.IsForPlatform() && c.outputFile.Valid()
+}
+
 func (c *Module) imageVariation() string {
 	variation := "core"
 	if c.useVndk() {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index f3d5e60..997e11e 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -20,6 +20,7 @@
 	"fmt"
 	"io/ioutil"
 	"os"
+	"path/filepath"
 	"reflect"
 	"sort"
 	"strings"
@@ -51,55 +52,14 @@
 	os.Exit(run())
 }
 
-func createTestContext(t *testing.T, config android.Config, bp string, os android.OsType) *android.TestContext {
-	ctx := android.NewTestArchContext()
-	ctx.RegisterModuleType("cc_binary", android.ModuleFactoryAdaptor(BinaryFactory))
-	ctx.RegisterModuleType("cc_binary_host", android.ModuleFactoryAdaptor(binaryHostFactory))
-	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(LibraryFactory))
-	ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(LibrarySharedFactory))
-	ctx.RegisterModuleType("cc_library_static", android.ModuleFactoryAdaptor(LibraryStaticFactory))
-	ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(LibraryHeaderFactory))
-	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(ToolchainLibraryFactory))
-	ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(LlndkLibraryFactory))
-	ctx.RegisterModuleType("llndk_headers", android.ModuleFactoryAdaptor(llndkHeadersFactory))
-	ctx.RegisterModuleType("vendor_public_library", android.ModuleFactoryAdaptor(vendorPublicLibraryFactory))
-	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(ObjectFactory))
-	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
-	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
-		ctx.BottomUp("image", ImageMutator).Parallel()
-		ctx.BottomUp("link", LinkageMutator).Parallel()
-		ctx.BottomUp("vndk", VndkMutator).Parallel()
-		ctx.BottomUp("version", VersionMutator).Parallel()
-		ctx.BottomUp("begin", BeginMutator).Parallel()
-	})
-	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
-		ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
-	})
-	ctx.Register()
-
-	// add some modules that are required by the compiler and/or linker
-	bp = bp + GatherRequiredDepsForTest(os)
-
-	ctx.MockFileSystem(map[string][]byte{
-		"Android.bp":  []byte(bp),
-		"foo.c":       nil,
-		"bar.c":       nil,
-		"a.proto":     nil,
-		"b.aidl":      nil,
-		"my_include":  nil,
-		"foo.map.txt": nil,
-	})
-
-	return ctx
-}
-
 func testCcWithConfig(t *testing.T, bp string, config android.Config) *android.TestContext {
 	return testCcWithConfigForOs(t, bp, config, android.Android)
 }
 
 func testCcWithConfigForOs(t *testing.T, bp string, config android.Config, os android.OsType) *android.TestContext {
 	t.Helper()
-	ctx := createTestContext(t, config, bp, os)
+	ctx := CreateTestContext(bp, nil, os)
+	ctx.Register()
 
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
 	android.FailIfErrored(t, errs)
@@ -132,7 +92,8 @@
 	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
 	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
 
-	ctx := createTestContext(t, config, bp, android.Android)
+	ctx := CreateTestContext(bp, nil, android.Android)
+	ctx.Register()
 
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
 	if len(errs) > 0 {
@@ -286,8 +247,28 @@
 	}
 }
 
+func checkVndkSnapshot(t *testing.T, ctx *android.TestContext, name, subDir, variant string) {
+	vndkSnapshot := ctx.SingletonForTests("vndk-snapshot")
+
+	snapshotPath := filepath.Join(subDir, name+".so")
+	mod := ctx.ModuleForTests(name, variant).Module().(*Module)
+	if !mod.outputFile.Valid() {
+		t.Errorf("%q must have output\n", name)
+		return
+	}
+
+	out := vndkSnapshot.Output(snapshotPath)
+	if out.Input != mod.outputFile.Path() {
+		t.Errorf("The input of VNDK snapshot must be %q, but %q", out.Input.String(), mod.outputFile.String())
+	}
+}
+
 func TestVndk(t *testing.T) {
-	ctx := testCc(t, `
+	config := android.TestArchConfig(buildDir, nil)
+	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+
+	ctx := testCcWithConfig(t, `
 		cc_library {
 			name: "libvndk",
 			vendor_available: true,
@@ -325,12 +306,35 @@
 			},
 			nocrt: true,
 		}
-	`)
+	`, config)
 
 	checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "")
 	checkVndkModule(t, ctx, "libvndk_private", "vndk-VER", false, "")
 	checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "")
 	checkVndkModule(t, ctx, "libvndk_sp_private", "vndk-sp-VER", true, "")
+
+	// Check VNDK snapshot output.
+
+	snapshotDir := "vndk-snapshot"
+	snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+
+	vndkLibPath := filepath.Join(snapshotVariantPath, fmt.Sprintf("arch-%s-%s",
+		"arm64", "armv8-a"))
+	vndkLib2ndPath := filepath.Join(snapshotVariantPath, fmt.Sprintf("arch-%s-%s",
+		"arm", "armv7-a-neon"))
+
+	vndkCoreLibPath := filepath.Join(vndkLibPath, "shared", "vndk-core")
+	vndkSpLibPath := filepath.Join(vndkLibPath, "shared", "vndk-sp")
+	vndkCoreLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-core")
+	vndkSpLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-sp")
+
+	variant := "android_arm64_armv8-a_vendor_shared"
+	variant2nd := "android_arm_armv7-a-neon_vendor_shared"
+
+	checkVndkSnapshot(t, ctx, "libvndk", vndkCoreLibPath, variant)
+	checkVndkSnapshot(t, ctx, "libvndk", vndkCoreLib2ndPath, variant2nd)
+	checkVndkSnapshot(t, ctx, "libvndk_sp", vndkSpLibPath, variant)
+	checkVndkSnapshot(t, ctx, "libvndk_sp", vndkSpLib2ndPath, variant2nd)
 }
 
 func TestVndkDepError(t *testing.T) {
@@ -1259,6 +1263,110 @@
 	`)
 }
 
+func TestMakeLinkType(t *testing.T) {
+	config := android.TestArchConfig(buildDir, nil)
+	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+	// native:vndk
+	ctx := testCcWithConfig(t, `
+	cc_library {
+		name: "libvndk",
+		vendor_available: true,
+		vndk: {
+			enabled: true,
+		},
+	}
+	cc_library {
+		name: "libvndksp",
+		vendor_available: true,
+		vndk: {
+			enabled: true,
+			support_system_process: true,
+		},
+	}
+	cc_library {
+		name: "libvndkprivate",
+		vendor_available: false,
+		vndk: {
+			enabled: true,
+		},
+	}
+	cc_library {
+		name: "libvendor",
+		vendor: true,
+	}
+	cc_library {
+		name: "libvndkext",
+		vendor: true,
+		vndk: {
+			enabled: true,
+			extends: "libvndk",
+		},
+	}
+	vndk_prebuilt_shared {
+		name: "prevndk",
+		version: "27",
+		target_arch: "arm",
+		binder32bit: true,
+		vendor_available: true,
+		vndk: {
+			enabled: true,
+		},
+		arch: {
+			arm: {
+				srcs: ["liba.so"],
+			},
+		},
+	}
+	cc_library {
+		name: "libllndk",
+	}
+	llndk_library {
+		name: "libllndk",
+		symbol_file: "",
+	}
+	cc_library {
+		name: "libllndkprivate",
+	}
+	llndk_library {
+		name: "libllndkprivate",
+		vendor_available: false,
+		symbol_file: "",
+	}`, config)
+
+	assertArrayString(t, *vndkCoreLibraries(config),
+		[]string{"libvndk", "libvndkprivate"})
+	assertArrayString(t, *vndkSpLibraries(config),
+		[]string{"libc++", "libvndksp"})
+	assertArrayString(t, *llndkLibraries(config),
+		[]string{"libc", "libdl", "libllndk", "libllndkprivate", "libm"})
+	assertArrayString(t, *vndkPrivateLibraries(config),
+		[]string{"libllndkprivate", "libvndkprivate"})
+
+	tests := []struct {
+		variant  string
+		name     string
+		expected string
+	}{
+		{vendorVariant, "libvndk", "native:vndk"},
+		{vendorVariant, "libvndksp", "native:vndk"},
+		{vendorVariant, "libvndkprivate", "native:vndk_private"},
+		{vendorVariant, "libvendor", "native:vendor"},
+		{vendorVariant, "libvndkext", "native:vendor"},
+		{vendorVariant, "prevndk.vndk.27.arm.binder32", "native:vndk"},
+		{vendorVariant, "libllndk.llndk", "native:vndk"},
+		{coreVariant, "libvndk", "native:platform"},
+		{coreVariant, "libvndkprivate", "native:platform"},
+		{coreVariant, "libllndk", "native:platform"},
+	}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			module := ctx.ModuleForTests(test.name, test.variant).Module().(*Module)
+			assertString(t, module.makeLinkType, test.expected)
+		})
+	}
+}
+
 var (
 	str11 = "01234567891"
 	str10 = str11[:10]
@@ -2155,3 +2263,25 @@
 		)
 	}
 }
+
+func assertString(t *testing.T, got, expected string) {
+	t.Helper()
+	if got != expected {
+		t.Errorf("expected %q got %q", expected, got)
+	}
+}
+
+func assertArrayString(t *testing.T, got, expected []string) {
+	t.Helper()
+	if len(got) != len(expected) {
+		t.Errorf("expected %d (%q) got (%d) %q", len(expected), expected, len(got), got)
+		return
+	}
+	for i := range got {
+		if got[i] != expected[i] {
+			t.Errorf("expected %d-th %q (%q) got %q (%q)",
+				i, expected[i], expected, got[i], got)
+			return
+		}
+	}
+}
diff --git a/cc/library.go b/cc/library.go
index c2ab098..3053831 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -23,7 +23,6 @@
 	"strings"
 	"sync"
 
-	"github.com/google/blueprint"
 	"github.com/google/blueprint/pathtools"
 
 	"android/soong/android"
@@ -962,8 +961,8 @@
 			// Bionic libraries (e.g. libc.so) is installed to the bootstrap subdirectory.
 			// The original path becomes a symlink to the corresponding file in the
 			// runtime APEX.
-			if isBionic(ctx.baseModuleName()) && !library.buildStubs() && ctx.Arch().Native && !ctx.inRecovery() {
-				if ctx.Device() {
+			if installToBootstrap(ctx.baseModuleName(), ctx.Config()) && !library.buildStubs() && ctx.Arch().Native && !ctx.inRecovery() {
+				if ctx.Device() && isBionic(ctx.baseModuleName()) {
 					library.installSymlinkToRuntimeApex(ctx, file)
 				}
 				library.baseInstaller.subDir = "bootstrap"
@@ -1106,10 +1105,28 @@
 
 func LinkageMutator(mctx android.BottomUpMutatorContext) {
 	if m, ok := mctx.Module().(*Module); ok && m.linker != nil {
-		if library, ok := m.linker.(libraryInterface); ok {
-			var modules []blueprint.Module
+		switch library := m.linker.(type) {
+		case prebuiltLibraryInterface:
+			// Always create both the static and shared variants for prebuilt libraries, and then disable the one
+			// that is not being used.  This allows them to share the name of a cc_library module, which requires that
+			// all the variants of the cc_library also exist on the prebuilt.
+			modules := mctx.CreateLocalVariations("static", "shared")
+			static := modules[0].(*Module)
+			shared := modules[1].(*Module)
+
+			static.linker.(prebuiltLibraryInterface).setStatic()
+			shared.linker.(prebuiltLibraryInterface).setShared()
+
+			if !library.buildStatic() {
+				static.linker.(prebuiltLibraryInterface).disablePrebuilt()
+			}
+			if !library.buildShared() {
+				shared.linker.(prebuiltLibraryInterface).disablePrebuilt()
+			}
+
+		case libraryInterface:
 			if library.buildStatic() && library.buildShared() {
-				modules = mctx.CreateLocalVariations("static", "shared")
+				modules := mctx.CreateLocalVariations("static", "shared")
 				static := modules[0].(*Module)
 				shared := modules[1].(*Module)
 
@@ -1119,10 +1136,10 @@
 				reuseStaticLibrary(mctx, static, shared)
 
 			} else if library.buildStatic() {
-				modules = mctx.CreateLocalVariations("static")
+				modules := mctx.CreateLocalVariations("static")
 				modules[0].(*Module).linker.(libraryInterface).setStatic()
 			} else if library.buildShared() {
-				modules = mctx.CreateLocalVariations("shared")
+				modules := mctx.CreateLocalVariations("shared")
 				modules[0].(*Module).linker.(libraryInterface).setShared()
 			}
 		}
diff --git a/cc/makevars.go b/cc/makevars.go
index 3c24f34..a71f479 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -96,7 +96,20 @@
 
 	ctx.Strict("VNDK_CORE_LIBRARIES", strings.Join(*vndkCoreLibraries(ctx.Config()), " "))
 	ctx.Strict("VNDK_SAMEPROCESS_LIBRARIES", strings.Join(*vndkSpLibraries(ctx.Config()), " "))
-	ctx.Strict("LLNDK_LIBRARIES", strings.Join(*llndkLibraries(ctx.Config()), " "))
+
+	// Make uses LLNDK_LIBRARIES to determine which libraries to install.
+	// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN.
+	// Therefore, by removing the library here, we cause it to only be installed if libc
+	// depends on it.
+	installedLlndkLibraries := []string{}
+	for _, lib := range *llndkLibraries(ctx.Config()) {
+		if strings.HasPrefix(lib, "libclang_rt.hwasan-") {
+			continue
+		}
+		installedLlndkLibraries = append(installedLlndkLibraries, lib)
+	}
+	ctx.Strict("LLNDK_LIBRARIES", strings.Join(installedLlndkLibraries, " "))
+
 	ctx.Strict("VNDK_PRIVATE_LIBRARIES", strings.Join(*vndkPrivateLibraries(ctx.Config()), " "))
 	ctx.Strict("VNDK_USING_CORE_VARIANT_LIBRARIES", strings.Join(*vndkUsingCoreVariantLibraries(ctx.Config()), " "))
 
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 5ffeb32..48e4667 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -53,12 +53,19 @@
 	return p.properties.Srcs
 }
 
+type prebuiltLibraryInterface interface {
+	libraryInterface
+	prebuiltLinkerInterface
+	disablePrebuilt()
+}
+
 type prebuiltLibraryLinker struct {
 	*libraryDecorator
 	prebuiltLinker
 }
 
 var _ prebuiltLinkerInterface = (*prebuiltLibraryLinker)(nil)
+var _ prebuiltLibraryInterface = (*prebuiltLibraryLinker)(nil)
 
 func (p *prebuiltLibraryLinker) linkerInit(ctx BaseModuleContext) {}
 
@@ -116,6 +123,10 @@
 	return false
 }
 
+func (p *prebuiltLibraryLinker) disablePrebuilt() {
+	p.properties.Srcs = nil
+}
+
 // cc_prebuilt_library_shared installs a precompiled shared library that are
 // listed in the srcs property in the device's directory.
 func prebuiltSharedLibraryFactory() android.Module {
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
new file mode 100644
index 0000000..98d78e8
--- /dev/null
+++ b/cc/prebuilt_test.go
@@ -0,0 +1,126 @@
+// 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"
+
+	"android/soong/android"
+
+	"github.com/google/blueprint"
+)
+
+func TestPrebuilt(t *testing.T) {
+	bp := `
+		cc_library {
+			name: "liba",
+		}
+
+		cc_prebuilt_library_shared {
+			name: "liba",
+			srcs: ["liba.so"],
+		}
+
+		cc_library {
+			name: "libb",
+		}
+
+		cc_prebuilt_library_static {
+			name: "libb",
+			srcs: ["libb.a"],
+		}
+
+		cc_library_shared {
+			name: "libd",
+		}
+
+		cc_prebuilt_library_shared {
+			name: "libd",
+			srcs: ["libd.so"],
+		}
+
+		cc_library_static {
+			name: "libe",
+		}
+
+		cc_prebuilt_library_static {
+			name: "libe",
+			srcs: ["libe.a"],
+		}
+	`
+
+	fs := map[string][]byte{
+		"liba.so": nil,
+		"libb.a":  nil,
+		"libd.so": nil,
+		"libe.a":  nil,
+	}
+
+	config := android.TestArchConfig(buildDir, nil)
+
+	ctx := CreateTestContext(bp, fs, android.Android)
+
+	ctx.RegisterModuleType("cc_prebuilt_library_shared", android.ModuleFactoryAdaptor(prebuiltSharedLibraryFactory))
+	ctx.RegisterModuleType("cc_prebuilt_library_static", android.ModuleFactoryAdaptor(prebuiltStaticLibraryFactory))
+	ctx.RegisterModuleType("cc_prebuilt_binary", android.ModuleFactoryAdaptor(prebuiltBinaryFactory))
+
+	ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
+	ctx.PostDepsMutators(android.RegisterPrebuiltsPostDepsMutators)
+
+	ctx.Register()
+
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	android.FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	android.FailIfErrored(t, errs)
+
+	// Verify that all the modules exist and that their dependencies were connected correctly
+	liba := ctx.ModuleForTests("liba", "android_arm64_armv8-a_core_shared").Module()
+	libb := ctx.ModuleForTests("libb", "android_arm64_armv8-a_core_static").Module()
+	libd := ctx.ModuleForTests("libd", "android_arm64_armv8-a_core_shared").Module()
+	libe := ctx.ModuleForTests("libe", "android_arm64_armv8-a_core_static").Module()
+
+	prebuiltLiba := ctx.ModuleForTests("prebuilt_liba", "android_arm64_armv8-a_core_shared").Module()
+	prebuiltLibb := ctx.ModuleForTests("prebuilt_libb", "android_arm64_armv8-a_core_static").Module()
+	prebuiltLibd := ctx.ModuleForTests("prebuilt_libd", "android_arm64_armv8-a_core_shared").Module()
+	prebuiltLibe := ctx.ModuleForTests("prebuilt_libe", "android_arm64_armv8-a_core_static").Module()
+
+	hasDep := func(m android.Module, wantDep android.Module) bool {
+		t.Helper()
+		var found bool
+		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
+			if dep == wantDep {
+				found = true
+			}
+		})
+		return found
+	}
+
+	if !hasDep(liba, prebuiltLiba) {
+		t.Errorf("liba missing dependency on prebuilt_liba")
+	}
+
+	if !hasDep(libb, prebuiltLibb) {
+		t.Errorf("libb missing dependency on prebuilt_libb")
+	}
+
+	if !hasDep(libd, prebuiltLibd) {
+		t.Errorf("libd missing dependency on prebuilt_libd")
+	}
+
+	if !hasDep(libe, prebuiltLibe) {
+		t.Errorf("libe missing dependency on prebuilt_libe")
+	}
+}
diff --git a/cc/strip.go b/cc/strip.go
index 7122585..4daa759 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -22,11 +22,12 @@
 
 type StripProperties struct {
 	Strip struct {
-		None              *bool    `android:"arch_variant"`
-		All               *bool    `android:"arch_variant"`
-		Keep_symbols      *bool    `android:"arch_variant"`
-		Keep_symbols_list []string `android:"arch_variant"`
-		Use_gnu_strip     *bool    `android:"arch_variant"`
+		None                         *bool    `android:"arch_variant"`
+		All                          *bool    `android:"arch_variant"`
+		Keep_symbols                 *bool    `android:"arch_variant"`
+		Keep_symbols_list            []string `android:"arch_variant"`
+		Keep_symbols_and_debug_frame *bool    `android:"arch_variant"`
+		Use_gnu_strip                *bool    `android:"arch_variant"`
 	} `android:"arch_variant"`
 }
 
@@ -46,6 +47,8 @@
 	} else {
 		if Bool(stripper.StripProperties.Strip.Keep_symbols) {
 			flags.stripKeepSymbols = true
+		} else if Bool(stripper.StripProperties.Strip.Keep_symbols_and_debug_frame) {
+			flags.stripKeepSymbolsAndDebugFrame = true
 		} else if len(stripper.StripProperties.Strip.Keep_symbols_list) > 0 {
 			flags.stripKeepSymbolsList = strings.Join(stripper.StripProperties.Strip.Keep_symbols_list, ",")
 		} else if !Bool(stripper.StripProperties.Strip.All) {
diff --git a/cc/testing.go b/cc/testing.go
index 8d76c2f..d9be900 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -148,6 +148,12 @@
 		}
 
 		cc_object {
+			name: "crtbegin_dynamic",
+			recovery_available: true,
+			vendor_available: true,
+		}
+
+		cc_object {
 			name: "crtbegin_static",
 			recovery_available: true,
 			vendor_available: true,
@@ -183,3 +189,56 @@
 	}
 	return ret
 }
+
+func CreateTestContext(bp string, fs map[string][]byte,
+	os android.OsType) *android.TestContext {
+
+	ctx := android.NewTestArchContext()
+	ctx.RegisterModuleType("cc_binary", android.ModuleFactoryAdaptor(BinaryFactory))
+	ctx.RegisterModuleType("cc_binary_host", android.ModuleFactoryAdaptor(binaryHostFactory))
+	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(LibraryFactory))
+	ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(LibrarySharedFactory))
+	ctx.RegisterModuleType("cc_library_static", android.ModuleFactoryAdaptor(LibraryStaticFactory))
+	ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(LibraryHeaderFactory))
+	ctx.RegisterModuleType("cc_test", android.ModuleFactoryAdaptor(TestFactory))
+	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(ToolchainLibraryFactory))
+	ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(LlndkLibraryFactory))
+	ctx.RegisterModuleType("llndk_headers", android.ModuleFactoryAdaptor(llndkHeadersFactory))
+	ctx.RegisterModuleType("vendor_public_library", android.ModuleFactoryAdaptor(vendorPublicLibraryFactory))
+	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(ObjectFactory))
+	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
+	ctx.RegisterModuleType("vndk_prebuilt_shared", android.ModuleFactoryAdaptor(vndkPrebuiltSharedFactory))
+	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.BottomUp("image", ImageMutator).Parallel()
+		ctx.BottomUp("link", LinkageMutator).Parallel()
+		ctx.BottomUp("vndk", VndkMutator).Parallel()
+		ctx.BottomUp("version", VersionMutator).Parallel()
+		ctx.BottomUp("begin", BeginMutator).Parallel()
+	})
+	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
+	})
+	ctx.RegisterSingletonType("vndk-snapshot", android.SingletonFactoryAdaptor(VndkSnapshotSingleton))
+
+	// add some modules that are required by the compiler and/or linker
+	bp = bp + GatherRequiredDepsForTest(os)
+
+	mockFS := map[string][]byte{
+		"Android.bp":  []byte(bp),
+		"foo.c":       nil,
+		"bar.c":       nil,
+		"a.proto":     nil,
+		"b.aidl":      nil,
+		"my_include":  nil,
+		"foo.map.txt": nil,
+		"liba.so":     nil,
+	}
+
+	for k, v := range fs {
+		mockFS[k] = v
+	}
+
+	ctx.MockFileSystem(mockFS)
+
+	return ctx
+}
diff --git a/cc/vndk.go b/cc/vndk.go
index 7859fa2..a1d67af 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -16,6 +16,8 @@
 
 import (
 	"errors"
+	"fmt"
+	"path/filepath"
 	"sort"
 	"strings"
 	"sync"
@@ -197,9 +199,20 @@
 	llndkLibrariesKey                = android.NewOnceKey("llndkLibrarires")
 	vndkPrivateLibrariesKey          = android.NewOnceKey("vndkPrivateLibrarires")
 	vndkUsingCoreVariantLibrariesKey = android.NewOnceKey("vndkUsingCoreVariantLibrarires")
+	modulePathsKey                   = android.NewOnceKey("modulePaths")
+	vndkSnapshotOutputsKey           = android.NewOnceKey("vndkSnapshotOutputs")
 	vndkLibrariesLock                sync.Mutex
 )
 
+type vndkSnapshotOutputPaths struct {
+	configs         android.Paths
+	notices         android.Paths
+	vndkCoreLibs    android.Paths
+	vndkCoreLibs2nd android.Paths
+	vndkSpLibs      android.Paths
+	vndkSpLibs2nd   android.Paths
+}
+
 func vndkCoreLibraries(config android.Config) *[]string {
 	return config.Once(vndkCoreLibrariesKey, func() interface{} {
 		return &[]string{}
@@ -230,66 +243,296 @@
 	}).(*[]string)
 }
 
-// gather list of vndk-core, vndk-sp, and ll-ndk libs
-func VndkMutator(mctx android.BottomUpMutatorContext) {
-	if m, ok := mctx.Module().(*Module); ok && m.Enabled() {
-		if lib, ok := m.linker.(*llndkStubDecorator); ok {
-			vndkLibrariesLock.Lock()
-			defer vndkLibrariesLock.Unlock()
+func modulePaths(config android.Config) map[string]string {
+	return config.Once(modulePathsKey, func() interface{} {
+		return make(map[string]string)
+	}).(map[string]string)
+}
 
-			llndkLibraries := llndkLibraries(mctx.Config())
-			vndkPrivateLibraries := vndkPrivateLibraries(mctx.Config())
+func vndkSnapshotOutputs(config android.Config) *vndkSnapshotOutputPaths {
+	return config.Once(vndkSnapshotOutputsKey, func() interface{} {
+		return &vndkSnapshotOutputPaths{}
+	}).(*vndkSnapshotOutputPaths)
+}
 
-			name := strings.TrimSuffix(m.Name(), llndkLibrarySuffix)
-			if !inList(name, *llndkLibraries) {
-				*llndkLibraries = append(*llndkLibraries, name)
-				sort.Strings(*llndkLibraries)
-			}
-			if !Bool(lib.Properties.Vendor_available) {
-				if !inList(name, *vndkPrivateLibraries) {
-					*vndkPrivateLibraries = append(*vndkPrivateLibraries, name)
-					sort.Strings(*vndkPrivateLibraries)
-				}
-			}
-		} else {
-			lib, is_lib := m.linker.(*libraryDecorator)
-			prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker)
-			if (is_lib && lib.shared()) || (is_prebuilt_lib && prebuilt_lib.shared()) {
-				name := strings.TrimPrefix(m.Name(), "prebuilt_")
-				if m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
-					vndkLibrariesLock.Lock()
-					defer vndkLibrariesLock.Unlock()
+func processLlndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
+	lib := m.linker.(*llndkStubDecorator)
+	name := strings.TrimSuffix(m.Name(), llndkLibrarySuffix)
 
-					vndkUsingCoreVariantLibraries := vndkUsingCoreVariantLibraries(mctx.Config())
-					vndkSpLibraries := vndkSpLibraries(mctx.Config())
-					vndkCoreLibraries := vndkCoreLibraries(mctx.Config())
-					vndkPrivateLibraries := vndkPrivateLibraries(mctx.Config())
+	vndkLibrariesLock.Lock()
+	defer vndkLibrariesLock.Unlock()
 
-					if mctx.DeviceConfig().VndkUseCoreVariant() && !inList(name, config.VndkMustUseVendorVariantList) {
-						if !inList(name, *vndkUsingCoreVariantLibraries) {
-							*vndkUsingCoreVariantLibraries = append(*vndkUsingCoreVariantLibraries, name)
-							sort.Strings(*vndkUsingCoreVariantLibraries)
-						}
-					}
-					if m.vndkdep.isVndkSp() {
-						if !inList(name, *vndkSpLibraries) {
-							*vndkSpLibraries = append(*vndkSpLibraries, name)
-							sort.Strings(*vndkSpLibraries)
-						}
-					} else {
-						if !inList(name, *vndkCoreLibraries) {
-							*vndkCoreLibraries = append(*vndkCoreLibraries, name)
-							sort.Strings(*vndkCoreLibraries)
-						}
-					}
-					if !Bool(m.VendorProperties.Vendor_available) {
-						if !inList(name, *vndkPrivateLibraries) {
-							*vndkPrivateLibraries = append(*vndkPrivateLibraries, name)
-							sort.Strings(*vndkPrivateLibraries)
-						}
-					}
-				}
-			}
+	llndkLibraries := llndkLibraries(mctx.Config())
+	if !inList(name, *llndkLibraries) {
+		*llndkLibraries = append(*llndkLibraries, name)
+		sort.Strings(*llndkLibraries)
+	}
+	if !Bool(lib.Properties.Vendor_available) {
+		vndkPrivateLibraries := vndkPrivateLibraries(mctx.Config())
+		if !inList(name, *vndkPrivateLibraries) {
+			*vndkPrivateLibraries = append(*vndkPrivateLibraries, name)
+			sort.Strings(*vndkPrivateLibraries)
 		}
 	}
 }
+
+func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
+	name := strings.TrimPrefix(m.Name(), "prebuilt_")
+
+	vndkLibrariesLock.Lock()
+	defer vndkLibrariesLock.Unlock()
+
+	modulePaths := modulePaths(mctx.Config())
+	if mctx.DeviceConfig().VndkUseCoreVariant() && !inList(name, config.VndkMustUseVendorVariantList) {
+		vndkUsingCoreVariantLibraries := vndkUsingCoreVariantLibraries(mctx.Config())
+		if !inList(name, *vndkUsingCoreVariantLibraries) {
+			*vndkUsingCoreVariantLibraries = append(*vndkUsingCoreVariantLibraries, name)
+			sort.Strings(*vndkUsingCoreVariantLibraries)
+		}
+	}
+	if m.vndkdep.isVndkSp() {
+		vndkSpLibraries := vndkSpLibraries(mctx.Config())
+		if !inList(name, *vndkSpLibraries) {
+			*vndkSpLibraries = append(*vndkSpLibraries, name)
+			sort.Strings(*vndkSpLibraries)
+			modulePaths[name] = mctx.ModuleDir()
+		}
+	} else {
+		vndkCoreLibraries := vndkCoreLibraries(mctx.Config())
+		if !inList(name, *vndkCoreLibraries) {
+			*vndkCoreLibraries = append(*vndkCoreLibraries, name)
+			sort.Strings(*vndkCoreLibraries)
+			modulePaths[name] = mctx.ModuleDir()
+		}
+	}
+	if !Bool(m.VendorProperties.Vendor_available) {
+		vndkPrivateLibraries := vndkPrivateLibraries(mctx.Config())
+		if !inList(name, *vndkPrivateLibraries) {
+			*vndkPrivateLibraries = append(*vndkPrivateLibraries, name)
+			sort.Strings(*vndkPrivateLibraries)
+		}
+	}
+}
+
+// gather list of vndk-core, vndk-sp, and ll-ndk libs
+func VndkMutator(mctx android.BottomUpMutatorContext) {
+	m, ok := mctx.Module().(*Module)
+	if !ok {
+		return
+	}
+
+	if !m.Enabled() {
+		return
+	}
+
+	if _, ok := m.linker.(*llndkStubDecorator); ok {
+		processLlndkLibrary(mctx, m)
+		return
+	}
+
+	lib, is_lib := m.linker.(*libraryDecorator)
+	prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker)
+
+	if (is_lib && lib.shared()) || (is_prebuilt_lib && prebuilt_lib.shared()) {
+		if m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
+			processVndkLibrary(mctx, m)
+			return
+		}
+	}
+}
+
+func init() {
+	android.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
+	android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
+		outputs := vndkSnapshotOutputs(ctx.Config())
+
+		ctx.Strict("SOONG_VNDK_SNAPSHOT_CONFIGS", strings.Join(outputs.configs.Strings(), " "))
+		ctx.Strict("SOONG_VNDK_SNAPSHOT_NOTICES", strings.Join(outputs.notices.Strings(), " "))
+		ctx.Strict("SOONG_VNDK_SNAPSHOT_CORE_LIBS", strings.Join(outputs.vndkCoreLibs.Strings(), " "))
+		ctx.Strict("SOONG_VNDK_SNAPSHOT_SP_LIBS", strings.Join(outputs.vndkSpLibs.Strings(), " "))
+		ctx.Strict("SOONG_VNDK_SNAPSHOT_CORE_LIBS_2ND", strings.Join(outputs.vndkCoreLibs2nd.Strings(), " "))
+		ctx.Strict("SOONG_VNDK_SNAPSHOT_SP_LIBS_2ND", strings.Join(outputs.vndkSpLibs2nd.Strings(), " "))
+	})
+}
+
+func VndkSnapshotSingleton() android.Singleton {
+	return &vndkSnapshotSingleton{}
+}
+
+type vndkSnapshotSingleton struct{}
+
+func installVndkSnapshotLib(ctx android.SingletonContext, name string, module *Module, dir string) android.Path {
+	if !module.outputFile.Valid() {
+		panic(fmt.Errorf("module %s has no outputFile\n", name))
+	}
+
+	out := android.PathForOutput(ctx, dir, name+".so")
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        android.Cp,
+		Input:       module.outputFile.Path(),
+		Output:      out,
+		Description: "vndk snapshot " + dir + "/" + name + ".so",
+		Args: map[string]string{
+			"cpFlags": "-f -L",
+		},
+	})
+
+	return out
+}
+
+func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+	// BOARD_VNDK_VERSION must be set to 'current' in order to generate a VNDK snapshot.
+	if ctx.DeviceConfig().VndkVersion() != "current" {
+		return
+	}
+
+	if ctx.DeviceConfig().PlatformVndkVersion() == "" {
+		return
+	}
+
+	if ctx.DeviceConfig().BoardVndkRuntimeDisable() {
+		return
+	}
+
+	outputs := vndkSnapshotOutputs(ctx.Config())
+
+	snapshotDir := "vndk-snapshot"
+
+	var vndkLibPath, vndkLib2ndPath string
+
+	snapshotVariantPath := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
+	if ctx.DeviceConfig().BinderBitness() == "32" {
+		vndkLibPath = filepath.Join(snapshotVariantPath, "binder32", fmt.Sprintf(
+			"arch-%s-%s", ctx.DeviceConfig().DeviceArch(), ctx.DeviceConfig().DeviceArchVariant()))
+		vndkLib2ndPath = filepath.Join(snapshotVariantPath, "binder32", fmt.Sprintf(
+			"arch-%s-%s", ctx.DeviceConfig().DeviceSecondaryArch(), ctx.DeviceConfig().DeviceSecondaryArchVariant()))
+	} else {
+		vndkLibPath = filepath.Join(snapshotVariantPath, fmt.Sprintf(
+			"arch-%s-%s", ctx.DeviceConfig().DeviceArch(), ctx.DeviceConfig().DeviceArchVariant()))
+		vndkLib2ndPath = filepath.Join(snapshotVariantPath, fmt.Sprintf(
+			"arch-%s-%s", ctx.DeviceConfig().DeviceSecondaryArch(), ctx.DeviceConfig().DeviceSecondaryArchVariant()))
+	}
+
+	vndkCoreLibPath := filepath.Join(vndkLibPath, "shared", "vndk-core")
+	vndkSpLibPath := filepath.Join(vndkLibPath, "shared", "vndk-sp")
+	vndkCoreLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-core")
+	vndkSpLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-sp")
+	noticePath := filepath.Join(snapshotVariantPath, "NOTICE_FILES")
+	noticeBuilt := make(map[string]bool)
+
+	tryBuildNotice := func(m *Module) {
+		name := ctx.ModuleName(m)
+
+		if _, ok := noticeBuilt[name]; ok {
+			return
+		}
+
+		noticeBuilt[name] = true
+
+		if m.NoticeFile().Valid() {
+			out := android.PathForOutput(ctx, noticePath, name+".so.txt")
+			ctx.Build(pctx, android.BuildParams{
+				Rule:        android.Cp,
+				Input:       m.NoticeFile().Path(),
+				Output:      out,
+				Description: "vndk snapshot notice " + name + ".so.txt",
+				Args: map[string]string{
+					"cpFlags": "-f -L",
+				},
+			})
+			outputs.notices = append(outputs.notices, out)
+		}
+	}
+
+	vndkCoreLibraries := vndkCoreLibraries(ctx.Config())
+	vndkSpLibraries := vndkSpLibraries(ctx.Config())
+	vndkPrivateLibraries := vndkPrivateLibraries(ctx.Config())
+
+	ctx.VisitAllModules(func(module android.Module) {
+		m, ok := module.(*Module)
+		if !ok || !m.Enabled() || !m.useVndk() || !m.installable() {
+			return
+		}
+
+		lib, is_lib := m.linker.(*libraryDecorator)
+		prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker)
+
+		if !(is_lib && lib.shared()) && !(is_prebuilt_lib && prebuilt_lib.shared()) {
+			return
+		}
+
+		is_2nd := m.Target().Arch.ArchType != ctx.Config().DevicePrimaryArchType()
+
+		name := ctx.ModuleName(module)
+
+		if inList(name, *vndkCoreLibraries) {
+			if is_2nd {
+				out := installVndkSnapshotLib(ctx, name, m, vndkCoreLib2ndPath)
+				outputs.vndkCoreLibs2nd = append(outputs.vndkCoreLibs2nd, out)
+			} else {
+				out := installVndkSnapshotLib(ctx, name, m, vndkCoreLibPath)
+				outputs.vndkCoreLibs = append(outputs.vndkCoreLibs, out)
+			}
+			tryBuildNotice(m)
+		} else if inList(name, *vndkSpLibraries) {
+			if is_2nd {
+				out := installVndkSnapshotLib(ctx, name, m, vndkSpLib2ndPath)
+				outputs.vndkSpLibs2nd = append(outputs.vndkSpLibs2nd, out)
+			} else {
+				out := installVndkSnapshotLib(ctx, name, m, vndkSpLibPath)
+				outputs.vndkSpLibs = append(outputs.vndkSpLibs, out)
+			}
+			tryBuildNotice(m)
+		}
+	})
+
+	configsPath := filepath.Join(snapshotVariantPath, "configs")
+	vndkCoreTxt := android.PathForOutput(ctx, configsPath, "vndkcore.libraries.txt")
+	vndkPrivateTxt := android.PathForOutput(ctx, configsPath, "vndkprivate.libraries.txt")
+	modulePathTxt := android.PathForOutput(ctx, configsPath, "module_paths.txt")
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        android.WriteFile,
+		Output:      vndkCoreTxt,
+		Description: "vndk snapshot vndkcore.libraries.txt",
+		Args: map[string]string{
+			"content": android.JoinWithSuffix(*vndkCoreLibraries, ".so", "\\n"),
+		},
+	})
+	outputs.configs = append(outputs.configs, vndkCoreTxt)
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        android.WriteFile,
+		Output:      vndkPrivateTxt,
+		Description: "vndk snapshot vndkprivate.libraries.txt",
+		Args: map[string]string{
+			"content": android.JoinWithSuffix(*vndkPrivateLibraries, ".so", "\\n"),
+		},
+	})
+	outputs.configs = append(outputs.configs, vndkPrivateTxt)
+
+	var modulePathTxtBuilder strings.Builder
+
+	first := true
+	for lib, dir := range modulePaths(ctx.Config()) {
+		if first {
+			first = false
+		} else {
+			modulePathTxtBuilder.WriteString("\\n")
+		}
+		modulePathTxtBuilder.WriteString(lib)
+		modulePathTxtBuilder.WriteString(".so ")
+		modulePathTxtBuilder.WriteString(dir)
+	}
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        android.WriteFile,
+		Output:      modulePathTxt,
+		Description: "vndk snapshot module_paths.txt",
+		Args: map[string]string{
+			"content": modulePathTxtBuilder.String(),
+		},
+	})
+	outputs.configs = append(outputs.configs, modulePathTxt)
+}
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 7b378cd..5d3cfa5 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -66,7 +66,7 @@
 	}
 
 	if useEmbeddedDex {
-		args = append(args, "--use-embedded-dex=true")
+		args = append(args, "--use-embedded-dex")
 	}
 
 	var deps android.Paths
diff --git a/java/app.go b/java/app.go
index db9c5dd..f7f08a8 100644
--- a/java/app.go
+++ b/java/app.go
@@ -85,6 +85,9 @@
 	// list of native libraries that will be provided in or alongside the resulting jar
 	Jni_libs []string `android:"arch_variant"`
 
+	// STL library to use for JNI libraries.
+	Stl *string `android:"arch_variant"`
+
 	// 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
@@ -149,10 +152,15 @@
 func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
 	a.Module.deps(ctx)
 
+	if String(a.appProperties.Stl) == "c++_shared" && a.sdkVersion() == "" {
+		ctx.PropertyErrorf("stl", "sdk_version must be set in order to use c++_shared")
+	}
+
 	if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
 		a.aapt.deps(ctx, sdkContext(a))
 	}
 
+	embedJni := a.shouldEmbedJnis(ctx)
 	for _, jniTarget := range ctx.MultiTargets() {
 		variation := []blueprint.Variation{
 			{Mutator: "arch", Variation: jniTarget.String()},
@@ -162,8 +170,15 @@
 			target: jniTarget,
 		}
 		ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
+		if String(a.appProperties.Stl) == "c++_shared" {
+			if embedJni {
+				ctx.AddFarVariationDependencies(variation, tag, "libc++")
+			}
+		}
 	}
+}
 
+func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
 	cert := android.SrcIsModule(a.getCertString(ctx))
 	if cert != "" {
 		ctx.AddDependency(ctx.Module(), certificateTag, cert)
@@ -215,6 +230,11 @@
 	return shouldUncompressDex(ctx, &a.dexpreopter)
 }
 
+func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool {
+	return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
+		a.appProperties.AlwaysPackageNativeLibs
+}
+
 func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
 	a.aapt.usesNonSdkApis = Bool(a.Module.deviceProperties.Platform_apis)
 
@@ -303,9 +323,7 @@
 func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext) android.WritablePath {
 	var jniJarFile android.WritablePath
 	if len(jniLibs) > 0 {
-		embedJni := ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
-			a.appProperties.AlwaysPackageNativeLibs
-		if embedJni {
+		if a.shouldEmbedJnis(ctx) {
 			jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip")
 			TransformJniLibsToJar(ctx, jniJarFile, jniLibs, a.useEmbeddedNativeLibs(ctx))
 		} else {
@@ -632,7 +650,7 @@
 	m := &OverrideAndroidApp{}
 	m.AddProperties(&overridableAppProperties{})
 
-	android.InitAndroidModule(m)
+	android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon)
 	android.InitOverrideModule(m)
 	return m
 }
diff --git a/java/app_test.go b/java/app_test.go
index bc35e21..40a64af 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -881,7 +881,7 @@
 			name: "foo",
 			srcs: ["a.java"],
 			certificate: "expiredkey",
-			overrides: ["baz"],
+			overrides: ["qux"],
 		}
 
 		override_android_app {
@@ -903,6 +903,7 @@
 		`)
 
 	expectedVariants := []struct {
+		moduleName  string
 		variantName string
 		apkName     string
 		apkPath     string
@@ -911,24 +912,27 @@
 		aaptFlag    string
 	}{
 		{
+			moduleName:  "foo",
 			variantName: "android_common",
 			apkPath:     "/target/product/test_device/system/app/foo/foo.apk",
 			signFlag:    "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
-			overrides:   []string{"baz"},
+			overrides:   []string{"qux"},
 			aaptFlag:    "",
 		},
 		{
-			variantName: "bar_android_common",
+			moduleName:  "bar",
+			variantName: "android_common_bar",
 			apkPath:     "/target/product/test_device/system/app/bar/bar.apk",
 			signFlag:    "cert/new_cert.x509.pem cert/new_cert.pk8",
-			overrides:   []string{"baz", "foo"},
+			overrides:   []string{"qux", "foo"},
 			aaptFlag:    "",
 		},
 		{
-			variantName: "baz_android_common",
+			moduleName:  "baz",
+			variantName: "android_common_baz",
 			apkPath:     "/target/product/test_device/system/app/baz/baz.apk",
 			signFlag:    "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
-			overrides:   []string{"baz", "foo"},
+			overrides:   []string{"qux", "foo"},
 			aaptFlag:    "--rename-manifest-package org.dandroid.bp",
 		},
 	}
@@ -972,6 +976,47 @@
 	}
 }
 
+func TestOverrideAndroidAppDependency(t *testing.T) {
+	ctx := testJava(t, `
+		android_app {
+			name: "foo",
+			srcs: ["a.java"],
+		}
+
+		override_android_app {
+			name: "bar",
+			base: "foo",
+			package_name: "org.dandroid.bp",
+		}
+
+		android_test {
+			name: "baz",
+			srcs: ["b.java"],
+			instrumentation_for: "foo",
+		}
+
+		android_test {
+			name: "qux",
+			srcs: ["b.java"],
+			instrumentation_for: "bar",
+		}
+		`)
+
+	// Verify baz, which depends on the overridden module foo, has the correct classpath javac arg.
+	javac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
+	fooTurbine := filepath.Join(buildDir, ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar")
+	if !strings.Contains(javac.Args["classpath"], fooTurbine) {
+		t.Errorf("baz classpath %v does not contain %q", javac.Args["classpath"], fooTurbine)
+	}
+
+	// Verify qux, which depends on the overriding module bar, has the correct classpath javac arg.
+	javac = ctx.ModuleForTests("qux", "android_common").Rule("javac")
+	barTurbine := filepath.Join(buildDir, ".intermediates", "foo", "android_common_bar", "turbine-combined", "foo.jar")
+	if !strings.Contains(javac.Args["classpath"], barTurbine) {
+		t.Errorf("qux classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
+	}
+}
+
 func TestAndroidAppImport(t *testing.T) {
 	ctx := testJava(t, `
 		android_app_import {
@@ -1133,3 +1178,64 @@
 		}
 	}
 }
+
+func TestStl(t *testing.T) {
+	ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
+		cc_library {
+			name: "libjni",
+		}
+
+		android_test {
+			name: "stl",
+			jni_libs: ["libjni"],
+			compile_multilib: "both",
+			sdk_version: "current",
+			stl: "c++_shared",
+		}
+
+		android_test {
+			name: "system",
+			jni_libs: ["libjni"],
+			compile_multilib: "both",
+			sdk_version: "current",
+		}
+		`)
+
+	testCases := []struct {
+		name string
+		jnis []string
+	}{
+		{"stl",
+			[]string{
+				"libjni.so",
+				"libc++.so",
+			},
+		},
+		{"system",
+			[]string{
+				"libjni.so",
+			},
+		},
+	}
+
+	for _, test := range testCases {
+		t.Run(test.name, func(t *testing.T) {
+			app := ctx.ModuleForTests(test.name, "android_common")
+			jniLibZip := app.Output("jnilibs.zip")
+			var jnis []string
+			args := strings.Fields(jniLibZip.Args["jarArgs"])
+			for i := 0; i < len(args); i++ {
+				if args[i] == "-f" {
+					jnis = append(jnis, args[i+1])
+					i += 1
+				}
+			}
+			jnisJoined := strings.Join(jnis, " ")
+			for _, jni := range test.jnis {
+				if !strings.Contains(jnisJoined, jni) {
+					t.Errorf("missing jni %q in %q", jni, jnis)
+				}
+			}
+		})
+	}
+}
diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go
index 4af2f5c..7d0109f 100644
--- a/java/dexpreopt_test.go
+++ b/java/dexpreopt_test.go
@@ -52,14 +52,26 @@
 				}`,
 			enabled: true,
 		},
-
 		{
 			name: "app without sources",
 			bp: `
 				android_app {
 					name: "foo",
 				}`,
-			// TODO(ccross): this should probably be false
+			enabled: false,
+		},
+		{
+			name: "app with libraries",
+			bp: `
+				android_app {
+					name: "foo",
+					static_libs: ["lib"],
+				}
+
+				java_library {
+					name: "lib",
+					srcs: ["a.java"],
+				}`,
 			enabled: true,
 		},
 		{
@@ -69,10 +81,8 @@
 					name: "foo",
 					installable: true,
 				}`,
-			// TODO(ccross): this should probably be false
-			enabled: true,
+			enabled: false,
 		},
-
 		{
 			name: "static java library",
 			bp: `
diff --git a/java/java.go b/java/java.go
index 866b33c..4483083 100644
--- a/java/java.go
+++ b/java/java.go
@@ -517,7 +517,8 @@
 	if j.hasSrcExt(".kt") {
 		// TODO(ccross): move this to a mutator pass that can tell if generated sources contain
 		// Kotlin files
-		ctx.AddVariationDependencies(nil, kotlinStdlibTag, "kotlin-stdlib")
+		ctx.AddVariationDependencies(nil, kotlinStdlibTag,
+			"kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8")
 		if len(j.properties.Plugins) > 0 {
 			ctx.AddVariationDependencies(nil, kotlinAnnotationsTag, "kotlin-annotations")
 		}
@@ -793,7 +794,7 @@
 					deps.staticResourceJars = append(deps.staticResourceJars, dep.(*AndroidApp).exportPackage)
 				}
 			case kotlinStdlibTag:
-				deps.kotlinStdlib = dep.HeaderJars()
+				deps.kotlinStdlib = append(deps.kotlinStdlib, dep.HeaderJars()...)
 			case kotlinAnnotationsTag:
 				deps.kotlinAnnotations = dep.HeaderJars()
 			}
@@ -854,7 +855,7 @@
 		ret = javaVersion
 	} else if ctx.Device() && sdk <= 23 {
 		ret = "1.7"
-	} else if ctx.Device() && sdk <= 28 || !ctx.Config().TargetOpenJDK9() {
+	} else if ctx.Device() && sdk <= 29 || !ctx.Config().TargetOpenJDK9() {
 		ret = "1.8"
 	} else if ctx.Device() && sdkContext.sdkVersion() != "" && sdk == android.FutureApiLevel {
 		// TODO(ccross): once we generate stubs we should be able to use 1.9 for sdk_version: "current"
@@ -962,7 +963,9 @@
 	return flags
 }
 
-func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path) {
+func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
+
+	hasSrcs := false
 
 	j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
 
@@ -978,10 +981,15 @@
 	}
 
 	srcFiles = j.genSources(ctx, srcFiles, flags)
+	if len(srcFiles) > 0 {
+		hasSrcs = true
+	}
 
 	srcJars := srcFiles.FilterByExt(".srcjar")
 	srcJars = append(srcJars, deps.srcJars...)
-	srcJars = append(srcJars, extraSrcJars...)
+	if aaptSrcJar != nil {
+		srcJars = append(srcJars, aaptSrcJar)
+	}
 
 	// Collect source files from compiledJavaSrcs, compiledSrcJars and filter out Exclude_srcs
 	// that IDEInfo struct will use
@@ -1170,7 +1178,10 @@
 		j.resourceJar = resourceJars[0]
 	}
 
-	jars = append(jars, deps.staticJars...)
+	if len(deps.staticJars) > 0 {
+		jars = append(jars, deps.staticJars...)
+		hasSrcs = true
+	}
 
 	manifest := j.overrideManifest
 	if !manifest.Valid() && j.properties.Manifest != nil {
@@ -1281,7 +1292,8 @@
 
 	j.implementationAndResourcesJar = implementationAndResourcesJar
 
-	if ctx.Device() && (Bool(j.properties.Installable) || Bool(j.deviceProperties.Compile_dex)) {
+	if ctx.Device() && hasSrcs &&
+		(Bool(j.properties.Installable) || Bool(j.deviceProperties.Compile_dex)) {
 		// Dex compilation
 		var dexOutputFile android.ModuleOutPath
 		dexOutputFile = j.compileDex(ctx, flags, outputFile, jarName)
@@ -1514,7 +1526,7 @@
 	j.dexpreopter.isInstallable = Bool(j.properties.Installable)
 	j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter)
 	j.deviceProperties.UncompressDex = j.dexpreopter.uncompressedDex
-	j.compile(ctx)
+	j.compile(ctx, nil)
 
 	if (Bool(j.properties.Installable) || ctx.Host()) && !android.DirectlyInAnyApex(ctx, ctx.ModuleName()) {
 		j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
diff --git a/java/java_test.go b/java/java_test.go
index 370e796..50b1c34 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -93,10 +93,10 @@
 	ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
 	ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
-	ctx.PreArchMutators(android.RegisterOverridePreArchMutators)
 	ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.TopDown("prebuilt_apis", PrebuiltApisMutator).Parallel()
 	})
+	ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
 	ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory))
 	ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(sdkPreSingletonFactory))
 
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 72c5cfc..5b65c0c 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -126,6 +126,9 @@
 	// If set to true, the path of dist files is apistubs/core. Defaults to false.
 	Core_lib *bool
 
+	// don't create dist rules.
+	No_dist *bool `blueprint:"mutated"`
+
 	// TODO: determines whether to create HTML doc or not
 	//Html_doc *bool
 }
@@ -212,52 +215,54 @@
 		android.WriteAndroidMkData(w, data)
 
 		module.Library.AndroidMkHostDex(w, name, data)
-		// Create a phony module that installs the impl library, for the case when this lib is
-		// in PRODUCT_PACKAGES.
-		owner := module.ModuleBase.Owner()
-		if owner == "" {
-			if Bool(module.sdkLibraryProperties.Core_lib) {
-				owner = "core"
-			} else {
-				owner = "android"
+		if !Bool(module.sdkLibraryProperties.No_dist) {
+			// Create a phony module that installs the impl library, for the case when this lib is
+			// in PRODUCT_PACKAGES.
+			owner := module.ModuleBase.Owner()
+			if owner == "" {
+				if Bool(module.sdkLibraryProperties.Core_lib) {
+					owner = "core"
+				} else {
+					owner = "android"
+				}
 			}
-		}
-		// Create dist rules to install the stubs libs to the dist dir
-		if len(module.publicApiStubsPath) == 1 {
-			fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
-				module.publicApiStubsImplPath.Strings()[0]+
-				":"+path.Join("apistubs", owner, "public",
-				module.BaseModuleName()+".jar")+")")
-		}
-		if len(module.systemApiStubsPath) == 1 {
-			fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
-				module.systemApiStubsImplPath.Strings()[0]+
-				":"+path.Join("apistubs", owner, "system",
-				module.BaseModuleName()+".jar")+")")
-		}
-		if len(module.testApiStubsPath) == 1 {
-			fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
-				module.testApiStubsImplPath.Strings()[0]+
-				":"+path.Join("apistubs", owner, "test",
-				module.BaseModuleName()+".jar")+")")
-		}
-		if module.publicApiFilePath != nil {
-			fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
-				module.publicApiFilePath.String()+
-				":"+path.Join("apistubs", owner, "public", "api",
-				module.BaseModuleName()+".txt")+")")
-		}
-		if module.systemApiFilePath != nil {
-			fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
-				module.systemApiFilePath.String()+
-				":"+path.Join("apistubs", owner, "system", "api",
-				module.BaseModuleName()+".txt")+")")
-		}
-		if module.testApiFilePath != nil {
-			fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
-				module.testApiFilePath.String()+
-				":"+path.Join("apistubs", owner, "test", "api",
-				module.BaseModuleName()+".txt")+")")
+			// Create dist rules to install the stubs libs to the dist dir
+			if len(module.publicApiStubsPath) == 1 {
+				fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
+					module.publicApiStubsImplPath.Strings()[0]+
+					":"+path.Join("apistubs", owner, "public",
+					module.BaseModuleName()+".jar")+")")
+			}
+			if len(module.systemApiStubsPath) == 1 {
+				fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
+					module.systemApiStubsImplPath.Strings()[0]+
+					":"+path.Join("apistubs", owner, "system",
+					module.BaseModuleName()+".jar")+")")
+			}
+			if len(module.testApiStubsPath) == 1 {
+				fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
+					module.testApiStubsImplPath.Strings()[0]+
+					":"+path.Join("apistubs", owner, "test",
+					module.BaseModuleName()+".jar")+")")
+			}
+			if module.publicApiFilePath != nil {
+				fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
+					module.publicApiFilePath.String()+
+					":"+path.Join("apistubs", owner, "public", "api",
+					module.BaseModuleName()+".txt")+")")
+			}
+			if module.systemApiFilePath != nil {
+				fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
+					module.systemApiFilePath.String()+
+					":"+path.Join("apistubs", owner, "system", "api",
+					module.BaseModuleName()+".txt")+")")
+			}
+			if module.testApiFilePath != nil {
+				fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
+					module.testApiFilePath.String()+
+					":"+path.Join("apistubs", owner, "test", "api",
+					module.BaseModuleName()+".txt")+")")
+			}
 		}
 	}
 	return data
@@ -641,6 +646,10 @@
 	}
 }
 
+func (module *SdkLibrary) SetNoDist() {
+	module.sdkLibraryProperties.No_dist = proptools.BoolPtr(true)
+}
+
 var javaSdkLibrariesKey = android.NewOnceKey("javaSdkLibraries")
 
 func javaSdkLibraries(config android.Config) *[]string {
diff --git a/java/testing.go b/java/testing.go
index 1be3768..22831c9 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -44,6 +44,8 @@
 		"core.current.stubs",
 		"core.platform.api.stubs",
 		"kotlin-stdlib",
+		"kotlin-stdlib-jdk7",
+		"kotlin-stdlib-jdk8",
 		"kotlin-annotations",
 	}
 
diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py
index 4ad9afa..7ec8999 100755
--- a/scripts/manifest_fixer_test.py
+++ b/scripts/manifest_fixer_test.py
@@ -231,7 +231,7 @@
 
   def run_test(self, input_manifest, new_uses_libraries):
     doc = minidom.parseString(input_manifest)
-    manifest_fixer.add_uses_libraries(doc, new_uses_libraries)
+    manifest_fixer.add_uses_libraries(doc, new_uses_libraries, True)
     output = StringIO.StringIO()
     manifest_fixer.write_xml(output, doc)
     return output.getvalue()
diff --git a/scripts/strip.sh b/scripts/strip.sh
index 0f77da8..bd62619 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -28,6 +28,7 @@
 #   --add-gnu-debuglink
 #   --keep-mini-debug-info
 #   --keep-symbols
+#   --keep-symbols-and-debug-frame
 #   --use-gnu-strip
 #   --remove-build-id
 
@@ -39,11 +40,12 @@
     cat <<EOF
 Usage: strip.sh [options] -k symbols -i in-file -o out-file -d deps-file
 Options:
-        --add-gnu-debuglink     Add a gnu-debuglink section to out-file
-        --keep-mini-debug-info  Keep compressed debug info in out-file
-        --keep-symbols          Keep symbols in out-file
-        --use-gnu-strip         Use strip/objcopy instead of llvm-{strip,objcopy}
-        --remove-build-id       Remove the gnu build-id section in out-file
+        --add-gnu-debuglink             Add a gnu-debuglink section to out-file
+        --keep-mini-debug-info          Keep compressed debug info in out-file
+        --keep-symbols                  Keep symbols in out-file
+        --keep-symbols-and-debug-frame  Keep symbols and .debug_frame in out-file
+        --use-gnu-strip                 Use strip/objcopy instead of llvm-{strip,objcopy}
+        --remove-build-id               Remove the gnu build-id section in out-file
 EOF
     exit 1
 }
@@ -63,6 +65,15 @@
     fi
 }
 
+do_strip_keep_symbols_and_debug_frame() {
+    REMOVE_SECTIONS=`"${CROSS_COMPILE}readelf" -S "${infile}" | awk '/.debug_/ {if ($2 != ".debug_frame") {print "--remove-section " $2}}' | xargs`
+    if [ -z "${use_gnu_strip}" ]; then
+        "${CLANG_BIN}/llvm-objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
+    else
+        "${CROSS_COMPILE}objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
+    fi
+}
+
 do_strip_keep_symbols() {
     REMOVE_SECTIONS=`"${CROSS_COMPILE}readelf" -S "${infile}" | awk '/.debug_/ {print "--remove-section " $2}' | xargs`
     if [ -z "${use_gnu_strip}" ]; then
@@ -148,6 +159,7 @@
                 add-gnu-debuglink) add_gnu_debuglink=true ;;
                 keep-mini-debug-info) keep_mini_debug_info=true ;;
                 keep-symbols) keep_symbols=true ;;
+                keep-symbols-and-debug-frame) keep_symbols_and_debug_frame=true ;;
                 remove-build-id) remove_build_id=true ;;
                 use-gnu-strip) use_gnu_strip=true ;;
                 *) echo "Unknown option --${OPTARG}"; usage ;;
@@ -177,6 +189,16 @@
     usage
 fi
 
+if [ ! -z "${keep_symbols}" -a ! -z "${keep_symbols_and_debug_frame}" ]; then
+    echo "--keep-symbols and --keep-symbols-and-debug-frame cannot be used together"
+    usage
+fi
+
+if [ ! -z "${keep_mini_debug_info}" -a ! -z "${keep_symbols_and_debug_frame}" ]; then
+    echo "--keep-symbols-mini-debug-info and --keep-symbols-and-debug-frame cannot be used together"
+    usage
+fi
+
 if [ ! -z "${symbols_to_keep}" -a ! -z "${keep_symbols}" ]; then
     echo "--keep-symbols and -k cannot be used together"
     usage
@@ -195,6 +217,8 @@
     do_strip_keep_symbol_list
 elif [ ! -z "${keep_mini_debug_info}" ]; then
     do_strip_keep_mini_debug_info
+elif [ ! -z "${keep_symbols_and_debug_frame}" ]; then
+    do_strip_keep_symbols_and_debug_frame
 else
     do_strip
 fi
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 0313ecd..3f2709e 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -72,6 +72,7 @@
 		&m.syspropLibraryProperties,
 	)
 	m.InitSdkLibraryProperties()
+	m.SetNoDist()
 	android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, "common")
 	android.AddLoadHook(m, func(ctx android.LoadHookContext) { syspropLibraryHook(ctx, m) })
 	android.AddLoadHook(m, func(ctx android.LoadHookContext) { m.SdkLibrary.CreateInternalModules(ctx) })