Merge "Revert "Prevent clang from using the x18 register on arm64.""
diff --git a/Android.bp b/Android.bp
index 5faefe6..1b93c0d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -77,6 +77,7 @@
         "android/neverallow_test.go",
         "android/paths_test.go",
         "android/prebuilt_test.go",
+        "android/prebuilt_etc_test.go",
         "android/util_test.go",
         "android/variable_test.go",
     ],
diff --git a/OWNERS b/OWNERS
index edd2557..780a35b 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,4 @@
 per-file * = ccross@android.com,dwillemsen@google.com,nanzhang@google.com
 per-file ndk_*.go, *gen_stub_libs.py = danalbert@google.com
 per-file clang.go,global.go,tidy.go = srhines@google.com, chh@google.com
+per-file apex.go = jiyong@google.com
diff --git a/android/config.go b/android/config.go
index 0aee0e3..695a298 100644
--- a/android/config.go
+++ b/android/config.go
@@ -41,7 +41,6 @@
 // config file. These will be included in the config struct.
 type FileConfigurableOptions struct {
 	Mega_device *bool `json:",omitempty"`
-	Ndk_abis    *bool `json:",omitempty"`
 	Host_bionic *bool `json:",omitempty"`
 }
 
@@ -299,7 +298,7 @@
 	var archConfig []archConfig
 	if Bool(config.Mega_device) {
 		archConfig = getMegaDeviceConfig()
-	} else if Bool(config.Ndk_abis) {
+	} else if config.NdkAbis() {
 		archConfig = getNdkAbisConfig()
 	}
 
@@ -709,6 +708,22 @@
 	return Bool(c.productVariables.HostStaticBinaries)
 }
 
+func (c *config) UncompressPrivAppDex() bool {
+	return Bool(c.productVariables.UncompressPrivAppDex)
+}
+
+func (c *config) ModulesLoadedByPrivilegedModules() []string {
+	return c.productVariables.ModulesLoadedByPrivilegedModules
+}
+
+func (c *config) DefaultStripDex() bool {
+	return Bool(c.productVariables.DefaultStripDex)
+}
+
+func (c *config) DisableDexPreopt(name string) bool {
+	return Bool(c.productVariables.DisableDexPreopt) || InList(name, c.productVariables.DisableDexPreoptModules)
+}
+
 func (c *deviceConfig) Arches() []Arch {
 	var arches []Arch
 	for _, target := range c.config.Targets[Android] {
@@ -862,6 +877,10 @@
 	return ok
 }
 
+func (c *config) NdkAbis() bool {
+	return Bool(c.productVariables.Ndk_abis)
+}
+
 func stringSlice(s *[]string) []string {
 	if s != nil {
 		return *s
diff --git a/android/neverallow.go b/android/neverallow.go
index d3a2801..f6caebc 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -45,35 +45,85 @@
 	ctx.BottomUp("neverallow", neverallowMutator).Parallel()
 }
 
-var neverallows = []*rule{
-	neverallow().
-		in("vendor", "device").
-		with("vndk.enabled", "true").
-		without("vendor", "true").
-		because("the VNDK can never contain a library that is device dependent."),
-	neverallow().
-		with("vndk.enabled", "true").
-		without("vendor", "true").
-		without("owner", "").
-		because("a VNDK module can never have an owner."),
-	neverallow().
-		notIn("libcore", "development", "external/apache-harmony", "external/apache-xml", "external/bouncycastle", "external/conscrypt", "external/icu", "external/okhttp", "external/wycheproof").
-		with("no_standard_libs", "true"),
+var neverallows = createNeverAllows()
 
-	// TODO(b/67974785): always enforce the manifest
-	neverallow().
-		without("name", "libhidltransport").
-		with("product_variables.enforce_vintf_manifest.cflags", "*").
-		because("manifest enforcement should be independent of ."),
+func createNeverAllows() []*rule {
+	rules := []*rule{}
+	rules = append(rules, createTrebleRules()...)
+	rules = append(rules, createLibcoreRules()...)
+	return rules
+}
 
-	// TODO(b/67975799): vendor code should always use /vendor/bin/sh
-	neverallow().
-		without("name", "libc_bionic_ndk").
-		with("product_variables.treble_linker_namespaces.cflags", "*").
-		because("nothing should care if linker namespaces are enabled or not"),
+func createTrebleRules() []*rule {
+	return []*rule{
+		neverallow().
+			in("vendor", "device").
+			with("vndk.enabled", "true").
+			without("vendor", "true").
+			because("the VNDK can never contain a library that is device dependent."),
+		neverallow().
+			with("vndk.enabled", "true").
+			without("vendor", "true").
+			without("owner", "").
+			because("a VNDK module can never have an owner."),
 
-	// Example:
-	// *neverallow().with("Srcs", "main.cpp"),
+		// TODO(b/67974785): always enforce the manifest
+		neverallow().
+			without("name", "libhidltransport").
+			with("product_variables.enforce_vintf_manifest.cflags", "*").
+			because("manifest enforcement should be independent of ."),
+
+		// TODO(b/67975799): vendor code should always use /vendor/bin/sh
+		neverallow().
+			without("name", "libc_bionic_ndk").
+			with("product_variables.treble_linker_namespaces.cflags", "*").
+			because("nothing should care if linker namespaces are enabled or not"),
+
+		// Example:
+		// *neverallow().with("Srcs", "main.cpp"))
+	}
+}
+
+func createLibcoreRules() []*rule {
+	var coreLibraryProjects = []string{
+		"libcore",
+		"external/apache-harmony",
+		"external/apache-xml",
+		"external/bouncycastle",
+		"external/conscrypt",
+		"external/icu",
+		"external/okhttp",
+		"external/wycheproof",
+	}
+
+	var coreModules = []string{
+		"core-all",
+		"core-oj",
+		"core-libart",
+		"core-simple",
+		"okhttp",
+		"bouncycastle",
+		"conscrypt",
+		"apache-xml",
+	}
+
+	// Core library constraints. Prevent targets adding dependencies on core
+	// library internals, which could lead to compatibility issues with the ART
+	// mainline module. They should use core.platform.api.stubs instead.
+	rules := []*rule{
+		neverallow().
+			notIn(append(coreLibraryProjects, "development")...).
+			with("no_standard_libs", "true"),
+	}
+
+	for _, m := range coreModules {
+		r := neverallow().
+			notIn(coreLibraryProjects...).
+			with("libs", m).
+			because("Only core libraries projects can depend on " + m)
+		rules = append(rules, r)
+	}
+	return rules
 }
 
 func neverallowMutator(ctx BottomUpMutatorContext) {
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index a278365..9e4886c 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -137,6 +137,17 @@
 		},
 		expectedError: "",
 	},
+	{
+		name: "dependency on core-libart",
+		fs: map[string][]byte{
+			"Blueprints": []byte(`
+				java_library {
+					name: "needs_core_libart",
+					libs: ["core-libart"],
+				}`),
+		},
+		expectedError: "Only core libraries projects can depend on core-libart",
+	},
 }
 
 func TestNeverallow(t *testing.T) {
@@ -164,6 +175,7 @@
 func testNeverallow(t *testing.T, config Config, fs map[string][]byte) (*TestContext, []error) {
 	ctx := NewTestContext()
 	ctx.RegisterModuleType("cc_library", ModuleFactoryAdaptor(newMockCcLibraryModule))
+	ctx.RegisterModuleType("java_library", ModuleFactoryAdaptor(newMockJavaLibraryModule))
 	ctx.PostDepsMutators(registerNeverallowMutator)
 	ctx.Register()
 
@@ -178,7 +190,7 @@
 	return ctx, errs
 }
 
-type mockProperties struct {
+type mockCcLibraryProperties struct {
 	Vendor_available *bool
 
 	Vndk struct {
@@ -200,7 +212,7 @@
 
 type mockCcLibraryModule struct {
 	ModuleBase
-	properties mockProperties
+	properties mockCcLibraryProperties
 }
 
 func newMockCcLibraryModule() Module {
@@ -215,3 +227,25 @@
 
 func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
 }
+
+type mockJavaLibraryProperties struct {
+	Libs []string
+}
+
+type mockJavaLibraryModule struct {
+	ModuleBase
+	properties mockJavaLibraryProperties
+}
+
+func newMockJavaLibraryModule() Module {
+	m := &mockJavaLibraryModule{}
+	m.AddProperties(&m.properties)
+	InitAndroidModule(m)
+	return m
+}
+
+func (p *mockJavaLibraryModule) DepsMutator(ctx BottomUpMutatorContext) {
+}
+
+func (p *mockJavaLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
+}
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
index fbc9de2..83c38db 100644
--- a/android/prebuilt_etc.go
+++ b/android/prebuilt_etc.go
@@ -37,10 +37,16 @@
 	// optional subdirectory under which this file is installed into
 	Sub_dir *string `android:"arch_variant"`
 
+	// optional name for the installed file. If unspecified, name of the module is used as the file name
+	Filename *string `android:"arch_variant"`
+
 	// Make this module available when building for recovery.
 	Recovery_available *bool
 
 	InRecovery bool `blueprint:"mutated"`
+
+	// Whether this module is directly installable to one of the partitions. Default: true.
+	Installable *bool
 }
 
 type PrebuiltEtc struct {
@@ -93,9 +99,17 @@
 	return String(p.properties.Sub_dir)
 }
 
+func (p *PrebuiltEtc) Installable() bool {
+	return p.properties.Installable == nil || Bool(p.properties.Installable)
+}
+
 func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) {
 	p.sourceFilePath = ctx.ExpandSource(String(p.properties.Src), "src")
-	p.outputFilePath = PathForModuleOut(ctx, ctx.ModuleName()).OutputPath
+	filename := String(p.properties.Filename)
+	if filename == "" {
+		filename = ctx.ModuleName()
+	}
+	p.outputFilePath = PathForModuleOut(ctx, filename).OutputPath
 	p.installDirPath = PathForModuleInstall(ctx, "etc", String(p.properties.Sub_dir))
 
 	// This ensures that outputFilePath has the same name as this module.
@@ -120,7 +134,8 @@
 			fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional")
 			fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", p.outputFilePath.String())
 			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(OUT_DIR)/"+p.installDirPath.RelPathString())
-			fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name)
+			fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", p.outputFilePath.Base())
+			fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !p.Installable())
 			if p.additionalDependencies != nil {
 				fmt.Fprint(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=")
 				for _, path := range *p.additionalDependencies {
diff --git a/android/prebuilt_etc_test.go b/android/prebuilt_etc_test.go
index 9244647..1ecdf79 100644
--- a/android/prebuilt_etc_test.go
+++ b/android/prebuilt_etc_test.go
@@ -91,3 +91,18 @@
 		t.Errorf("expected 1, got %#v", bar_variants)
 	}
 }
+
+func TestPrebuiltEtcOutputPath(t *testing.T) {
+	ctx := testPrebuiltEtc(t, `
+		prebuilt_etc {
+			name: "foo.conf",
+			src: "foo.conf",
+			filename: "foo.installed.conf",
+		}
+	`)
+
+	p := ctx.ModuleForTests("foo.conf", "android_common_core").Module().(*PrebuiltEtc)
+	if p.outputFilePath.Base() != "foo.installed.conf" {
+		t.Errorf("expected foo.installed.conf, got %q", p.outputFilePath.Base())
+	}
+}
diff --git a/android/variable.go b/android/variable.go
index 476171b..2686049 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -95,6 +95,9 @@
 			Lto      struct {
 				Never *bool
 			}
+			Sanitize struct {
+				Address *bool
+			}
 		}
 
 		Pdk struct {
@@ -190,6 +193,12 @@
 	Arc                        *bool `json:",omitempty"`
 	MinimizeJavaDebugInfo      *bool `json:",omitempty"`
 
+	UncompressPrivAppDex             *bool    `json:",omitempty"`
+	ModulesLoadedByPrivilegedModules []string `json:",omitempty"`
+	DefaultStripDex                  *bool    `json:",omitempty"`
+	DisableDexPreopt                 *bool    `json:",omitempty"`
+	DisableDexPreoptModules          []string `json:",omitempty"`
+
 	IntegerOverflowExcludePaths *[]string `json:",omitempty"`
 
 	EnableCFI       *bool     `json:",omitempty"`
@@ -239,6 +248,8 @@
 	BoardPlatPrivateSepolicyDirs []string `json:",omitempty"`
 
 	VendorVars map[string]map[string]string `json:",omitempty"`
+
+	Ndk_abis *bool `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index b3d5aec..99b3523 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -161,24 +161,25 @@
 	addStandardProperties(bpparser.BoolType,
 		map[string]string{
 			// Bool properties
-			"LOCAL_IS_HOST_MODULE":           "host",
-			"LOCAL_CLANG":                    "clang",
-			"LOCAL_FORCE_STATIC_EXECUTABLE":  "static_executable",
-			"LOCAL_NATIVE_COVERAGE":          "native_coverage",
-			"LOCAL_NO_CRT":                   "nocrt",
-			"LOCAL_ALLOW_UNDEFINED_SYMBOLS":  "allow_undefined_symbols",
-			"LOCAL_RTTI_FLAG":                "rtti",
-			"LOCAL_NO_STANDARD_LIBRARIES":    "no_standard_libs",
-			"LOCAL_PACK_MODULE_RELOCATIONS":  "pack_relocations",
-			"LOCAL_TIDY":                     "tidy",
-			"LOCAL_USE_CLANG_LLD":            "use_clang_lld",
-			"LOCAL_PROPRIETARY_MODULE":       "proprietary",
-			"LOCAL_VENDOR_MODULE":            "vendor",
-			"LOCAL_ODM_MODULE":               "device_specific",
-			"LOCAL_PRODUCT_MODULE":           "product_specific",
-			"LOCAL_PRODUCT_SERVICES_MODULE":  "product_services_specific",
-			"LOCAL_EXPORT_PACKAGE_RESOURCES": "export_package_resources",
-			"LOCAL_PRIVILEGED_MODULE":        "privileged",
+			"LOCAL_IS_HOST_MODULE":             "host",
+			"LOCAL_CLANG":                      "clang",
+			"LOCAL_FORCE_STATIC_EXECUTABLE":    "static_executable",
+			"LOCAL_NATIVE_COVERAGE":            "native_coverage",
+			"LOCAL_NO_CRT":                     "nocrt",
+			"LOCAL_ALLOW_UNDEFINED_SYMBOLS":    "allow_undefined_symbols",
+			"LOCAL_RTTI_FLAG":                  "rtti",
+			"LOCAL_NO_STANDARD_LIBRARIES":      "no_standard_libs",
+			"LOCAL_PACK_MODULE_RELOCATIONS":    "pack_relocations",
+			"LOCAL_TIDY":                       "tidy",
+			"LOCAL_USE_CLANG_LLD":              "use_clang_lld",
+			"LOCAL_PROPRIETARY_MODULE":         "proprietary",
+			"LOCAL_VENDOR_MODULE":              "vendor",
+			"LOCAL_ODM_MODULE":                 "device_specific",
+			"LOCAL_PRODUCT_MODULE":             "product_specific",
+			"LOCAL_PRODUCT_SERVICES_MODULE":    "product_services_specific",
+			"LOCAL_EXPORT_PACKAGE_RESOURCES":   "export_package_resources",
+			"LOCAL_PRIVILEGED_MODULE":          "privileged",
+			"LOCAL_AAPT_INCLUDE_ALL_RESOURCES": "aapt_include_all_resources",
 
 			"LOCAL_DEX_PREOPT":                  "dex_preopt.enabled",
 			"LOCAL_DEX_PREOPT_APP_IMAGE":        "dex_preopt.app_image",
diff --git a/apex/apex.go b/apex/apex.go
index 5390114..6819bff 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -37,7 +37,7 @@
 	// by default set to (uid/gid/mode) = (1000/1000/0644)
 	// TODO(b/113082813) make this configurable using config.fs syntax
 	generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
-		Command: `echo '/ 1000 1000 0644' > ${out} && ` +
+		Command: `echo '/ 1000 1000 0755' > ${out} && ` +
 			`echo '/manifest.json 1000 1000 0644' >> ${out} && ` +
 			`echo ${ro_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 1000 1000 0644"}' >> ${out} && ` +
 			`echo ${exec_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 1000 1000 0755"}' >> ${out}`,
@@ -71,17 +71,30 @@
 }
 
 var (
-	sharedLibTag  = dependencyTag{name: "sharedLib"}
-	executableTag = dependencyTag{name: "executable"}
-	javaLibTag    = dependencyTag{name: "javaLib"}
-	prebuiltTag   = dependencyTag{name: "prebuilt"}
-	keyTag        = dependencyTag{name: "key"}
+	sharedLibTag   = dependencyTag{name: "sharedLib"}
+	executableTag  = dependencyTag{name: "executable"}
+	javaLibTag     = dependencyTag{name: "javaLib"}
+	prebuiltTag    = dependencyTag{name: "prebuilt"}
+	keyTag         = dependencyTag{name: "key"}
+	certificateTag = dependencyTag{name: "certificate"}
 )
 
 func init() {
 	pctx.Import("android/soong/common")
+	pctx.Import("android/soong/java")
 	pctx.HostBinToolVariable("apexer", "apexer")
-	pctx.HostBinToolVariable("aapt2", "aapt2")
+	// ART minimal builds (using the master-art manifest) do not have the "frameworks/base"
+	// projects, and hence cannot built 'aapt2'. Use the SDK prebuilt instead.
+	hostBinToolVariableWithPrebuilt := func(name, prebuiltDir, tool string) {
+		pctx.VariableFunc(name, func(ctx android.PackageVarContext) string {
+			if !android.ExistentPathForSource(ctx, "frameworks/base").Valid() {
+				return filepath.Join(prebuiltDir, runtime.GOOS, "bin", tool)
+			} else {
+				return pctx.HostBinToolPath(ctx, tool).String()
+			}
+		})
+	}
+	hostBinToolVariableWithPrebuilt("aapt2", "prebuilts/sdk/tools", "aapt2")
 	pctx.HostBinToolVariable("avbtool", "avbtool")
 	pctx.HostBinToolVariable("e2fsdroid", "e2fsdroid")
 	pctx.HostBinToolVariable("merge_zips", "merge_zips")
@@ -176,6 +189,43 @@
 
 	// Name of the apex_key module that provides the private key to sign APEX
 	Key *string
+
+	// The name of a certificate in the default certificate directory, blank to use the default product certificate,
+	// or an android_app_certificate module name in the form ":module".
+	Certificate *string
+
+	Multilib struct {
+		First struct {
+			// List of native libraries whose compile_multilib is "first"
+			Native_shared_libs []string
+			// List of native executables whose compile_multilib is "first"
+			Binaries []string
+		}
+		Both struct {
+			// List of native libraries whose compile_multilib is "both"
+			Native_shared_libs []string
+			// List of native executables whose compile_multilib is "both"
+			Binaries []string
+		}
+		Prefer32 struct {
+			// List of native libraries whose compile_multilib is "prefer32"
+			Native_shared_libs []string
+			// List of native executables whose compile_multilib is "prefer32"
+			Binaries []string
+		}
+		Lib32 struct {
+			// List of native libraries whose compile_multilib is "32"
+			Native_shared_libs []string
+			// List of native executables whose compile_multilib is "32"
+			Binaries []string
+		}
+		Lib64 struct {
+			// List of native libraries whose compile_multilib is "64"
+			Native_shared_libs []string
+			// List of native executables whose compile_multilib is "64"
+			Binaries []string
+		}
+	}
 }
 
 type apexBundle struct {
@@ -188,22 +238,83 @@
 	installDir android.OutputPath
 }
 
+func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
+	native_shared_libs []string, binaries []string, arch string) {
+	// Use *FarVariation* to be able to depend on modules having
+	// conflicting variations with this module. This is required since
+	// arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
+	// for native shared libs.
+	ctx.AddFarVariationDependencies([]blueprint.Variation{
+		{Mutator: "arch", Variation: arch},
+		{Mutator: "image", Variation: "core"},
+		{Mutator: "link", Variation: "shared"},
+	}, sharedLibTag, native_shared_libs...)
+
+	ctx.AddFarVariationDependencies([]blueprint.Variation{
+		{Mutator: "arch", Variation: arch},
+		{Mutator: "image", Variation: "core"},
+	}, executableTag, binaries...)
+}
+
 func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
-	for _, arch := range ctx.MultiTargets() {
-		// Use *FarVariation* to be able to depend on modules having
-		// conflicting variations with this module. This is required since
-		// arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
-		// for native shared libs.
+	targets := ctx.MultiTargets()
+	has32BitTarget := false
+	for _, target := range targets {
+		if target.Arch.ArchType.Multilib == "lib32" {
+			has32BitTarget = true
+		}
+	}
+	for i, target := range targets {
+		// When multilib.* is omitted for native_shared_libs, it implies
+		// multilib.both.
 		ctx.AddFarVariationDependencies([]blueprint.Variation{
-			{Mutator: "arch", Variation: arch.String()},
+			{Mutator: "arch", Variation: target.String()},
 			{Mutator: "image", Variation: "core"},
 			{Mutator: "link", Variation: "shared"},
 		}, sharedLibTag, a.properties.Native_shared_libs...)
 
-		ctx.AddFarVariationDependencies([]blueprint.Variation{
-			{Mutator: "arch", Variation: arch.String()},
-			{Mutator: "image", Variation: "core"},
-		}, executableTag, a.properties.Binaries...)
+		// Add native modules targetting both ABIs
+		addDependenciesForNativeModules(ctx,
+			a.properties.Multilib.Both.Native_shared_libs,
+			a.properties.Multilib.Both.Binaries, target.String())
+
+		if i == 0 {
+			// When multilib.* is omitted for binaries, it implies
+			// multilib.first.
+			ctx.AddFarVariationDependencies([]blueprint.Variation{
+				{Mutator: "arch", Variation: target.String()},
+				{Mutator: "image", Variation: "core"},
+			}, executableTag, a.properties.Binaries...)
+
+			// Add native modules targetting the first ABI
+			addDependenciesForNativeModules(ctx,
+				a.properties.Multilib.First.Native_shared_libs,
+				a.properties.Multilib.First.Binaries, target.String())
+		}
+
+		switch target.Arch.ArchType.Multilib {
+		case "lib32":
+			// Add native modules targetting 32-bit ABI
+			addDependenciesForNativeModules(ctx,
+				a.properties.Multilib.Lib32.Native_shared_libs,
+				a.properties.Multilib.Lib32.Binaries, target.String())
+
+			addDependenciesForNativeModules(ctx,
+				a.properties.Multilib.Prefer32.Native_shared_libs,
+				a.properties.Multilib.Prefer32.Binaries, target.String())
+		case "lib64":
+			// Add native modules targetting 64-bit ABI
+			addDependenciesForNativeModules(ctx,
+				a.properties.Multilib.Lib64.Native_shared_libs,
+				a.properties.Multilib.Lib64.Binaries, target.String())
+
+			if !has32BitTarget {
+				addDependenciesForNativeModules(ctx,
+					a.properties.Multilib.Prefer32.Native_shared_libs,
+					a.properties.Multilib.Prefer32.Binaries, target.String())
+			}
+		}
+
 	}
 
 	ctx.AddFarVariationDependencies([]blueprint.Variation{
@@ -219,6 +330,11 @@
 		return
 	}
 	ctx.AddDependency(ctx.Module(), keyTag, String(a.properties.Key))
+
+	cert := android.SrcIsModule(String(a.properties.Certificate))
+	if cert != "" {
+		ctx.AddDependency(ctx.Module(), certificateTag, cert)
+	}
 }
 
 func getCopyManifestForNativeLibrary(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
@@ -261,6 +377,7 @@
 	copyManifest := make(map[android.Path]string)
 
 	var keyFile android.Path
+	var certificate java.Certificate
 
 	ctx.WalkDeps(func(child, parent android.Module) bool {
 		if _, ok := parent.(*apexBundle); ok {
@@ -307,6 +424,13 @@
 				} else {
 					ctx.PropertyErrorf("key", "%q is not an apex_key module", depName)
 				}
+			case certificateTag:
+				if dep, ok := child.(*java.AndroidAppCertificate); ok {
+					certificate = dep.Certificate
+					return false
+				} else {
+					ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", depName)
+				}
 			}
 		} else {
 			// indirect dependencies
@@ -321,6 +445,18 @@
 		return false
 	})
 
+	cert := String(a.properties.Certificate)
+	if cert != "" && android.SrcIsModule(cert) == "" {
+		defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
+		certificate = java.Certificate{
+			defaultDir.Join(ctx, cert+".x509.pem"),
+			defaultDir.Join(ctx, cert+".pk8"),
+		}
+	} else if cert == "" {
+		pem, key := ctx.Config().DefaultAppCertificate(ctx)
+		certificate = java.Certificate{pem, key}
+	}
+
 	// files and dirs that will be created in apex
 	var readOnlyPaths []string
 	var executablePaths []string // this also includes dirs
@@ -350,7 +486,7 @@
 	manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "manifest.json"))
 	fileContexts := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.File_contexts, "file_contexts"))
 
-	a.outputFile = android.PathForModuleOut(ctx, a.ModuleBase.Name()+apexSuffix)
+	unsignedOutputFile := android.PathForModuleOut(ctx, a.ModuleBase.Name()+apexSuffix+".unsigned")
 
 	filesToCopy := []android.Path{}
 	for file := range copyManifest {
@@ -374,7 +510,7 @@
 	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
 		Rule:      apexRule,
 		Implicits: implicitInputs,
-		Output:    a.outputFile,
+		Output:    unsignedOutputFile,
 		Args: map[string]string{
 			"tool_path":        outHostBinDir + ":" + prebuiltSdkToolsBinDir,
 			"image_dir":        android.PathForModuleOut(ctx, "image").String(),
@@ -386,6 +522,17 @@
 		},
 	})
 
+	a.outputFile = android.PathForModuleOut(ctx, a.ModuleBase.Name()+apexSuffix)
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        java.Signapk,
+		Description: "signapk",
+		Output:      a.outputFile,
+		Input:       unsignedOutputFile,
+		Args: map[string]string{
+			"certificates": strings.Join([]string{certificate.Pem.String(), certificate.Key.String()}, " "),
+		},
+	})
+
 	a.installDir = android.PathForModuleInstall(ctx, "apex")
 }
 
@@ -407,6 +554,10 @@
 func apexBundleFactory() android.Module {
 	module := &apexBundle{}
 	module.AddProperties(&module.properties)
+	module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase,
+		class android.OsClass) bool {
+		return class == android.Device && ctx.Config().DevicePrefer32BitExecutables()
+	})
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
 	return module
diff --git a/cc/cc.go b/cc/cc.go
index 8b68489..0569563 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -39,6 +39,7 @@
 		ctx.BottomUp("vndk", vndkMutator).Parallel()
 		ctx.BottomUp("ndk_api", ndkApiMutator).Parallel()
 		ctx.BottomUp("test_per_src", testPerSrcMutator).Parallel()
+		ctx.BottomUp("version", versionMutator).Parallel()
 		ctx.BottomUp("begin", BeginMutator).Parallel()
 	})
 
@@ -945,6 +946,16 @@
 	c.begin(ctx)
 }
 
+// Split name#version into name and version
+func stubsLibNameAndVersion(name string) (string, string) {
+	if sharp := strings.LastIndex(name, "#"); sharp != -1 && sharp != len(name)-1 {
+		version := name[sharp+1:]
+		libname := name[:sharp]
+		return libname, version
+	}
+	return name, ""
+}
+
 func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
 	ctx := &depsContext{
 		BottomUpMutatorContext: actx,
@@ -979,25 +990,28 @@
 			variantLibs = []string{}
 			nonvariantLibs = []string{}
 			for _, entry := range list {
-				if ctx.useSdk() && inList(entry, ndkPrebuiltSharedLibraries) {
-					if !inList(entry, ndkMigratedLibs) {
-						nonvariantLibs = append(nonvariantLibs, entry+".ndk."+version)
+				// strip #version suffix out
+				name, _ := stubsLibNameAndVersion(entry)
+				if ctx.useSdk() && inList(name, ndkPrebuiltSharedLibraries) {
+					if !inList(name, ndkMigratedLibs) {
+						nonvariantLibs = append(nonvariantLibs, name+".ndk."+version)
 					} else {
-						variantLibs = append(variantLibs, entry+ndkLibrarySuffix)
+						variantLibs = append(variantLibs, name+ndkLibrarySuffix)
 					}
-				} else if ctx.useVndk() && inList(entry, llndkLibraries) {
-					nonvariantLibs = append(nonvariantLibs, entry+llndkLibrarySuffix)
-				} else if (ctx.Platform() || ctx.ProductSpecific()) && inList(entry, vendorPublicLibraries) {
-					vendorPublicLib := entry + vendorPublicLibrarySuffix
+				} else if ctx.useVndk() && inList(name, llndkLibraries) {
+					nonvariantLibs = append(nonvariantLibs, name+llndkLibrarySuffix)
+				} else if (ctx.Platform() || ctx.ProductSpecific()) && inList(name, vendorPublicLibraries) {
+					vendorPublicLib := name + vendorPublicLibrarySuffix
 					if actx.OtherModuleExists(vendorPublicLib) {
 						nonvariantLibs = append(nonvariantLibs, vendorPublicLib)
 					} else {
 						// This can happen if vendor_public_library module is defined in a
 						// namespace that isn't visible to the current module. In that case,
 						// link to the original library.
-						nonvariantLibs = append(nonvariantLibs, entry)
+						nonvariantLibs = append(nonvariantLibs, name)
 					}
 				} else {
+					// put name#version back
 					nonvariantLibs = append(nonvariantLibs, entry)
 				}
 			}
@@ -1009,6 +1023,15 @@
 		deps.ReexportSharedLibHeaders, _ = rewriteNdkLibs(deps.ReexportSharedLibHeaders)
 	}
 
+	if c.linker != nil {
+		if library, ok := c.linker.(*libraryDecorator); ok {
+			if library.buildStubs() {
+				// Stubs lib does not have dependency to other libraries. Don't proceed.
+				return
+			}
+		}
+	}
+
 	for _, lib := range deps.HeaderLibs {
 		depTag := headerDepTag
 		if inList(lib, deps.ReexportHeaderLibHeaders) {
@@ -1035,19 +1058,40 @@
 		{Mutator: "link", Variation: "static"},
 	}, lateStaticDepTag, deps.LateStaticLibs...)
 
+	// shared lib names without the #version suffix
+	var sharedLibNames []string
+
 	for _, lib := range deps.SharedLibs {
+		name, version := stubsLibNameAndVersion(lib)
+		sharedLibNames = append(sharedLibNames, name)
 		depTag := sharedDepTag
 		if inList(lib, deps.ReexportSharedLibHeaders) {
 			depTag = sharedExportDepTag
 		}
-		actx.AddVariationDependencies([]blueprint.Variation{
-			{Mutator: "link", Variation: "shared"},
-		}, depTag, lib)
+		var variations []blueprint.Variation
+		variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"})
+		if version != "" && ctx.Os() == android.Android && !ctx.useVndk() && !c.inRecovery() {
+			variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
+		}
+		actx.AddVariationDependencies(variations, depTag, name)
 	}
 
-	actx.AddVariationDependencies([]blueprint.Variation{
-		{Mutator: "link", Variation: "shared"},
-	}, lateSharedDepTag, deps.LateSharedLibs...)
+	for _, lib := range deps.LateSharedLibs {
+		name, version := stubsLibNameAndVersion(lib)
+		if inList(name, sharedLibNames) {
+			// This is to handle the case that some of the late shared libs (libc, libdl, libm, ...)
+			// are added also to SharedLibs with version (e.g., libc#10). If not skipped, we will be
+			// linking against both the stubs lib and the non-stubs lib at the same time.
+			continue
+		}
+		depTag := lateSharedDepTag
+		var variations []blueprint.Variation
+		variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"})
+		if version != "" && ctx.Os() == android.Android && !ctx.useVndk() && !c.inRecovery() {
+			variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
+		}
+		actx.AddVariationDependencies(variations, depTag, name)
+	}
 
 	actx.AddVariationDependencies([]blueprint.Variation{
 		{Mutator: "link", Variation: "shared"},
@@ -1629,8 +1673,8 @@
 		return
 	}
 
-	if genrule, ok := mctx.Module().(*genrule.Module); ok {
-		if props, ok := genrule.Extra.(*GenruleExtraProperties); ok {
+	if g, ok := mctx.Module().(*genrule.Module); ok {
+		if props, ok := g.Extra.(*GenruleExtraProperties); ok {
 			var coreVariantNeeded bool = false
 			var vendorVariantNeeded bool = false
 			var recoveryVariantNeeded bool = false
@@ -1650,7 +1694,7 @@
 
 			if recoveryVariantNeeded {
 				primaryArch := mctx.Config().DevicePrimaryArchType()
-				moduleArch := genrule.Target().Arch.ArchType
+				moduleArch := g.Target().Arch.ArchType
 				if moduleArch != primaryArch {
 					recoveryVariantNeeded = false
 				}
@@ -1666,7 +1710,13 @@
 			if recoveryVariantNeeded {
 				variants = append(variants, recoveryMode)
 			}
-			mctx.CreateVariations(variants...)
+			mod := mctx.CreateVariations(variants...)
+			for i, v := range variants {
+				if v == recoveryMode {
+					m := mod[i].(*genrule.Module)
+					m.Extra.(*GenruleExtraProperties).InRecovery = true
+				}
+			}
 		}
 	}
 
diff --git a/cc/cc_test.go b/cc/cc_test.go
index ead89f6..d6ffe51 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -66,6 +66,7 @@
 		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.Register()
@@ -205,12 +206,13 @@
 `
 
 	ctx.MockFileSystem(map[string][]byte{
-		"Android.bp": []byte(bp),
-		"foo.c":      nil,
-		"bar.c":      nil,
-		"a.proto":    nil,
-		"b.aidl":     nil,
-		"my_include": nil,
+		"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
@@ -892,9 +894,7 @@
 		}
 	`)
 
-	// The pattern should be "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\""
-	// but target.vendor.shared_libs has not been supported yet.
-	testCcError(t, "unrecognized property \"target.vendor.shared_libs\"", `
+	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
 		cc_library {
 			name: "libvndk",
 			vendor_available: true,
@@ -963,9 +963,7 @@
 		}
 	`)
 
-	// The pattern should be "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\""
-	// but target.vendor.shared_libs has not been supported yet.
-	testCcError(t, "unrecognized property \"target.vendor.shared_libs\"", `
+	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
 		cc_library {
 			name: "libvndk_sp",
 			vendor_available: true,
@@ -1730,5 +1728,68 @@
 	if !recoveryModule.Platform() {
 		t.Errorf("recovery variant of libHalInRecovery must not specific to device, soc, or product")
 	}
+}
 
+func TestVersionedStubs(t *testing.T) {
+	ctx := testCc(t, `
+		cc_library_shared {
+			name: "libFoo",
+			srcs: ["foo.c"],
+			stubs: {
+				symbol_file: "foo.map.txt",
+				versions: ["1", "2", "3"],
+			},
+		}
+
+		cc_library_shared {
+			name: "libBar",
+			srcs: ["bar.c"],
+			shared_libs: ["libFoo#1"],
+		}`)
+
+	variants := ctx.ModuleVariantsForTests("libFoo")
+	expectedVariants := []string{
+		"android_arm64_armv8-a_core_shared",
+		"android_arm64_armv8-a_core_shared_1",
+		"android_arm64_armv8-a_core_shared_2",
+		"android_arm64_armv8-a_core_shared_3",
+		"android_arm_armv7-a-neon_core_shared",
+		"android_arm_armv7-a-neon_core_shared_1",
+		"android_arm_armv7-a-neon_core_shared_2",
+		"android_arm_armv7-a-neon_core_shared_3",
+	}
+	variantsMismatch := false
+	if len(variants) != len(expectedVariants) {
+		variantsMismatch = true
+	} else {
+		for _, v := range expectedVariants {
+			if !inList(v, variants) {
+				variantsMismatch = false
+			}
+		}
+	}
+	if variantsMismatch {
+		t.Errorf("variants of libFoo expected:\n")
+		for _, v := range expectedVariants {
+			t.Errorf("%q\n", v)
+		}
+		t.Errorf(", but got:\n")
+		for _, v := range variants {
+			t.Errorf("%q\n", v)
+		}
+	}
+
+	libBarLinkRule := ctx.ModuleForTests("libBar", "android_arm64_armv8-a_core_shared").Rule("ld")
+	libFlags := libBarLinkRule.Args["libFlags"]
+	libFoo1StubPath := "libFoo/android_arm64_armv8-a_core_shared_1/libFoo.so"
+	if !strings.Contains(libFlags, libFoo1StubPath) {
+		t.Errorf("%q is not found in %q", libFoo1StubPath, libFlags)
+	}
+
+	libBarCompileRule := ctx.ModuleForTests("libBar", "android_arm64_armv8-a_core_shared").Rule("cc")
+	cFlags := libBarCompileRule.Args["cFlags"]
+	libFoo1VersioningMacro := "-D__LIBFOO_API__=1"
+	if !strings.Contains(cFlags, libFoo1VersioningMacro) {
+		t.Errorf("%q is not found in %q", libFoo1VersioningMacro, cFlags)
+	}
 }
diff --git a/cc/compdb.go b/cc/compdb.go
index acfc924..4dfc55b 100644
--- a/cc/compdb.go
+++ b/cc/compdb.go
@@ -126,28 +126,32 @@
 	return out
 }
 
-func getArguments(src android.Path, ctx android.SingletonContext, ccModule *Module) []string {
+func getArguments(src android.Path, ctx android.SingletonContext, ccModule *Module, ccPath string, cxxPath string) []string {
 	var args []string
 	isCpp := false
 	isAsm := false
 	// TODO It would be better to ask soong for the types here.
+	var clangPath string
 	switch src.Ext() {
 	case ".S", ".s", ".asm":
 		isAsm = true
 		isCpp = false
+		clangPath = ccPath
 	case ".c":
 		isAsm = false
 		isCpp = false
+		clangPath = ccPath
 	case ".cpp", ".cc", ".mm":
 		isAsm = false
 		isCpp = true
+		clangPath = cxxPath
 	default:
 		log.Print("Unknown file extension " + src.Ext() + " on file " + src.String())
 		isAsm = true
 		isCpp = false
+		clangPath = ccPath
 	}
-	// The executable for the compilation doesn't matter but we need something there.
-	args = append(args, "/bin/false")
+	args = append(args, clangPath)
 	args = append(args, expandAllVars(ctx, ccModule.flags.GlobalFlags)...)
 	args = append(args, expandAllVars(ctx, ccModule.flags.CFlags)...)
 	if isCpp {
@@ -166,12 +170,19 @@
 		return
 	}
 
+	pathToCC, err := ctx.Eval(pctx, "${config.ClangBin}/")
+	ccPath := "/bin/false"
+	cxxPath := "/bin/false"
+	if err == nil {
+		ccPath = pathToCC + "clang"
+		cxxPath = pathToCC + "clang++"
+	}
 	rootDir := getCompdbAndroidSrcRootDirectory(ctx)
 	for _, src := range srcs {
 		if _, ok := builds[src.String()]; !ok {
 			builds[src.String()] = compDbEntry{
 				Directory: rootDir,
-				Arguments: getArguments(src, ctx, ccModule),
+				Arguments: getArguments(src, ctx, ccModule, ccPath, cxxPath),
 				File:      src.String(),
 			}
 		}
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 5c82604..0f22034 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -86,7 +86,6 @@
 // Ldflags that should be filtered out when linking with clang lld
 var ClangUnknownLldflags = sorted([]string{
 	"-fuse-ld=gold",
-	"-Wl,--icf=safe",
 	"-Wl,--fix-cortex-a8",
 	"-Wl,--no-fix-cortex-a8",
 	"-Wl,-m,aarch64_elf64_le_vec",
@@ -98,9 +97,8 @@
 	pctx.StaticVariable("ClangExtraCflags", strings.Join([]string{
 		"-D__compiler_offsetof=__builtin_offsetof",
 
-		// Make implicit fallthrough an error in the future.
+		// -Wimplicit fallthrough is not enabled by -Wall.
 		"-Wimplicit-fallthrough",
-		"-Wno-error=implicit-fallthrough",
 
 		// Help catch common 32/64-bit errors.
 		"-Werror=int-conversion",
@@ -131,6 +129,9 @@
 		// Warnings from clang-7.0
 		"-Wno-deprecated-register",
 		"-Wno-sign-compare",
+
+		// Warnings from clang-8.0
+		"-Wno-defaulted-function-deleted",
 	}, " "))
 
 	pctx.StaticVariable("ClangExtraCppflags", strings.Join([]string{
diff --git a/cc/config/global.go b/cc/config/global.go
index 330cb10..057e08a 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -91,7 +91,8 @@
 			// TODO(b/109657296): needs --no-rosegment until Android
 			// stack unwinder can handle the read-only segment.
 			"-Wl,--no-rosegment",
-			"-Wl,--pack-dyn-relocs=android",
+			"-Wl,--pack-dyn-relocs=android+relr",
+			"-Wl,--use-android-relr-tags",
 			"-fuse-ld=lld",
 		}...)
 
@@ -125,8 +126,8 @@
 
 	// prebuilts/clang default settings.
 	ClangDefaultBase         = "prebuilts/clang/host"
-	ClangDefaultVersion      = "clang-r339409b"
-	ClangDefaultShortVersion = "8.0.2"
+	ClangDefaultVersion      = "clang-r344140"
+	ClangDefaultShortVersion = "8.0.3"
 
 	// Directories with warnings from Android.bp files.
 	WarningAllowedProjects = []string{
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index 5fb88e6..fb1cdeb 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -124,7 +124,7 @@
 func (t *toolchainLinuxBionic) ToolchainClangCflags() string {
 	return "-m64 -march=x86-64" +
 		// TODO: We're not really android, but we don't have a triple yet b/31393676
-		" -U__ANDROID__ -fno-emulated-tls"
+		" -U__ANDROID__"
 }
 
 func (t *toolchainLinuxBionic) ToolchainClangLdflags() string {
diff --git a/cc/genrule.go b/cc/genrule.go
index a672992..decf6ea 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -26,6 +26,9 @@
 type GenruleExtraProperties struct {
 	Vendor_available   *bool
 	Recovery_available *bool
+
+	// This genrule is for recovery variant
+	InRecovery bool `blueprint:"mutated"`
 }
 
 // cc_genrule is a genrule that can depend on other cc_* objects.
diff --git a/cc/library.go b/cc/library.go
index 920292d..975f325 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -15,13 +15,16 @@
 package cc
 
 import (
+	"regexp"
 	"strings"
+	"sync"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/pathtools"
 
 	"android/soong/android"
 	"android/soong/cc/config"
+	"android/soong/genrule"
 )
 
 type LibraryProperties struct {
@@ -65,6 +68,15 @@
 	}
 
 	Static_ndk_lib *bool
+
+	Stubs struct {
+		// Relative path to the symbol map. The symbol map provides the list of
+		// symbols that are exported for stubs variant of this library.
+		Symbol_file *string
+
+		// List versions to generate stubs libs for.
+		Versions []string
+	}
 }
 
 type LibraryMutatedProperties struct {
@@ -78,6 +90,11 @@
 	VariantIsShared bool `blueprint:"mutated"`
 	// This variant is static
 	VariantIsStatic bool `blueprint:"mutated"`
+
+	// This variant is a stubs lib
+	BuildStubs bool `blueprint:"mutated"`
+	// Version of the stubs lib
+	StubsVersion string `blueprint:"mutated"`
 }
 
 type FlagExporterProperties struct {
@@ -240,6 +257,8 @@
 	// Location of the linked, unstripped library for shared libraries
 	unstrippedOutputFile android.Path
 
+	versionScriptPath android.ModuleGenPath
+
 	// Decorated interafaces
 	*baseCompiler
 	*baseLinker
@@ -313,7 +332,11 @@
 		flags.YasmFlags = append(flags.YasmFlags, f)
 	}
 
-	return library.baseCompiler.compilerFlags(ctx, flags, deps)
+	flags = library.baseCompiler.compilerFlags(ctx, flags, deps)
+	if library.buildStubs() {
+		flags = addStubLibraryCompilerFlags(flags)
+	}
+	return flags
 }
 
 func extractExportIncludesFromFlags(flags []string) []string {
@@ -336,6 +359,12 @@
 }
 
 func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
+	if library.buildStubs() {
+		objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Stubs.Symbol_file), library.MutatedProperties.StubsVersion, "")
+		library.versionScriptPath = versionScript
+		return objs
+	}
+
 	if !library.buildShared() && !library.buildStatic() {
 		if len(library.baseCompiler.Properties.Srcs) > 0 {
 			ctx.PropertyErrorf("srcs", "cc_library_headers must not have any srcs")
@@ -416,14 +445,30 @@
 	return name + library.MutatedProperties.VariantName
 }
 
+var versioningMacroNamesListMutex sync.Mutex
+
 func (library *libraryDecorator) linkerInit(ctx BaseModuleContext) {
 	location := InstallInSystem
 	if library.baseLinker.sanitize.inSanitizerDir() {
 		location = InstallInSanitizerDir
 	}
 	library.baseInstaller.location = location
-
 	library.baseLinker.linkerInit(ctx)
+	// Let baseLinker know whether this variant is for stubs or not, so that
+	// it can omit things that are not required for linking stubs.
+	library.baseLinker.dynamicProperties.BuildStubs = library.buildStubs()
+
+	if library.buildStubs() {
+		macroNames := versioningMacroNamesList(ctx.Config())
+		myName := versioningMacroName(ctx.ModuleName())
+		versioningMacroNamesListMutex.Lock()
+		defer versioningMacroNamesListMutex.Unlock()
+		if (*macroNames)[myName] == "" {
+			(*macroNames)[myName] = ctx.ModuleName()
+		} else if (*macroNames)[myName] != ctx.ModuleName() {
+			ctx.ModuleErrorf("Macro name %q for versioning conflicts with macro name from module %q ", myName, (*macroNames)[myName])
+		}
+	}
 }
 
 func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
@@ -686,6 +731,10 @@
 		library.reuseExportedFlags = append(library.reuseExportedFlags, flags...)
 	}
 
+	if library.buildStubs() {
+		library.reexportFlags([]string{"-D" + versioningMacroName(ctx.ModuleName()) + "=" + library.stubsVersion()})
+	}
+
 	return out
 }
 
@@ -735,7 +784,8 @@
 
 	if Bool(library.Properties.Static_ndk_lib) && library.static() &&
 		!ctx.useVndk() && !ctx.inRecovery() && ctx.Device() &&
-		library.baseLinker.sanitize.isUnsanitizedVariant() {
+		library.baseLinker.sanitize.isUnsanitizedVariant() &&
+		!library.buildStubs() {
 		installPath := getNdkSysrootBase(ctx).Join(
 			ctx, "usr/lib", config.NDKTriple(ctx.toolchain()), file.Base())
 
@@ -785,6 +835,31 @@
 	library.MutatedProperties.BuildStatic = false
 }
 
+func (library *libraryDecorator) buildStubs() bool {
+	return library.MutatedProperties.BuildStubs
+}
+
+func (library *libraryDecorator) stubsVersion() string {
+	return library.MutatedProperties.StubsVersion
+}
+
+func versioningMacroNamesList(config android.Config) *map[string]string {
+	return config.Once("versioningMacroNamesList", func() interface{} {
+		m := make(map[string]string)
+		return &m
+	}).(*map[string]string)
+}
+
+// alphanumeric and _ characters are preserved.
+// other characters are all converted to _
+var charsNotForMacro = regexp.MustCompile("[^a-zA-Z0-9_]+")
+
+func versioningMacroName(moduleName string) string {
+	macroName := charsNotForMacro.ReplaceAllString(moduleName, "_")
+	macroName = strings.ToUpper(moduleName)
+	return "__" + macroName + "_API__"
+}
+
 func NewLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
 	module := newModule(hod, android.MultilibBoth)
 
@@ -847,3 +922,41 @@
 		}
 	}
 }
+
+// Version mutator splits a module into the mandatory non-stubs variant
+// (which is named "impl") and zero or more stubs variants.
+func versionMutator(mctx android.BottomUpMutatorContext) {
+	if mctx.Os() != android.Android {
+		return
+	}
+
+	if m, ok := mctx.Module().(*Module); ok && !m.inRecovery() && m.linker != nil {
+		if library, ok := m.linker.(*libraryDecorator); ok && library.buildShared() {
+			versions := []string{""}
+			for _, v := range library.Properties.Stubs.Versions {
+				versions = append(versions, v)
+			}
+			modules := mctx.CreateVariations(versions...)
+			for i, m := range modules {
+				l := m.(*Module).linker.(*libraryDecorator)
+				if i == 0 {
+					l.MutatedProperties.BuildStubs = false
+					continue
+				}
+				// Mark that this variant is for stubs.
+				l.MutatedProperties.BuildStubs = true
+				l.MutatedProperties.StubsVersion = versions[i]
+				m.(*Module).Properties.HideFromMake = true
+			}
+		} else {
+			mctx.CreateVariations("")
+		}
+		return
+	}
+	if genrule, ok := mctx.Module().(*genrule.Module); ok {
+		if props, ok := genrule.Extra.(*GenruleExtraProperties); ok && !props.InRecovery {
+			mctx.CreateVariations("")
+			return
+		}
+	}
+}
diff --git a/cc/linker.go b/cc/linker.go
index 28f4747..a1593ee 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -99,6 +99,10 @@
 
 	Target struct {
 		Vendor struct {
+			// list of shared libs that only should be used to build the vendor
+			// variant of the C/C++ module.
+			Shared_libs []string
+
 			// list of shared libs that should not be used to build the vendor variant
 			// of the C/C++ module.
 			Exclude_shared_libs []string
@@ -116,6 +120,10 @@
 			Exclude_runtime_libs []string
 		}
 		Recovery struct {
+			// list of shared libs that only should be used to build the recovery
+			// variant of the C/C++ module.
+			Shared_libs []string
+
 			// list of shared libs that should not be used to build
 			// the recovery variant of the C/C++ module.
 			Exclude_shared_libs []string
@@ -160,7 +168,8 @@
 	Properties        BaseLinkerProperties
 	MoreProperties    MoreBaseLinkerProperties
 	dynamicProperties struct {
-		RunPaths []string `blueprint:"mutated"`
+		RunPaths   []string `blueprint:"mutated"`
+		BuildStubs bool     `blueprint:"mutated"`
 	}
 
 	sanitize *sanitize
@@ -199,6 +208,7 @@
 	}
 
 	if ctx.useVndk() {
+		deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Vendor.Shared_libs...)
 		deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Vendor.Exclude_shared_libs)
 		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Vendor.Exclude_shared_libs)
 		deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs)
@@ -209,6 +219,7 @@
 	}
 
 	if ctx.inRecovery() {
+		deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Recovery.Shared_libs...)
 		deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Recovery.Exclude_shared_libs)
 		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Recovery.Exclude_shared_libs)
 		deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
@@ -269,9 +280,13 @@
 		deps.LateStaticLibs = append(deps.LateStaticLibs, "libwinpthread")
 	}
 
-	android.ExtractSourceDeps(ctx, linker.MoreProperties.Version_script)
-	android.ExtractSourceDeps(ctx,
-		linker.MoreProperties.Target.Vendor.Version_script)
+	// Version_script is not needed when linking stubs lib where the version
+	// script is created from the symbol map file.
+	if !linker.dynamicProperties.BuildStubs {
+		android.ExtractSourceDeps(ctx, linker.MoreProperties.Version_script)
+		android.ExtractSourceDeps(ctx,
+			linker.MoreProperties.Target.Vendor.Version_script)
+	}
 
 	return deps
 }
@@ -375,28 +390,32 @@
 		flags.GroupStaticLibs = true
 	}
 
-	versionScript := ctx.ExpandOptionalSource(
-		linker.MoreProperties.Version_script, "version_script")
+	// Version_script is not needed when linking stubs lib where the version
+	// script is created from the symbol map file.
+	if !linker.dynamicProperties.BuildStubs {
+		versionScript := ctx.ExpandOptionalSource(
+			linker.MoreProperties.Version_script, "version_script")
 
-	if ctx.useVndk() && linker.MoreProperties.Target.Vendor.Version_script != nil {
-		versionScript = ctx.ExpandOptionalSource(
-			linker.MoreProperties.Target.Vendor.Version_script,
-			"target.vendor.version_script")
-	}
+		if ctx.useVndk() && linker.MoreProperties.Target.Vendor.Version_script != nil {
+			versionScript = ctx.ExpandOptionalSource(
+				linker.MoreProperties.Target.Vendor.Version_script,
+				"target.vendor.version_script")
+		}
 
-	if versionScript.Valid() {
-		if ctx.Darwin() {
-			ctx.PropertyErrorf("version_script", "Not supported on Darwin")
-		} else {
-			flags.LdFlags = append(flags.LdFlags,
-				"-Wl,--version-script,"+versionScript.String())
-			flags.LdFlagsDeps = append(flags.LdFlagsDeps, versionScript.Path())
-
-			if linker.sanitize.isSanitizerEnabled(cfi) {
-				cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath)
+		if versionScript.Valid() {
+			if ctx.Darwin() {
+				ctx.PropertyErrorf("version_script", "Not supported on Darwin")
+			} else {
 				flags.LdFlags = append(flags.LdFlags,
-					"-Wl,--version-script,"+cfiExportsMap.String())
-				flags.LdFlagsDeps = append(flags.LdFlagsDeps, cfiExportsMap)
+					"-Wl,--version-script,"+versionScript.String())
+				flags.LdFlagsDeps = append(flags.LdFlagsDeps, versionScript.Path())
+
+				if linker.sanitize.isSanitizerEnabled(cfi) {
+					cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath)
+					flags.LdFlags = append(flags.LdFlags,
+						"-Wl,--version-script,"+cfiExportsMap.String())
+					flags.LdFlagsDeps = append(flags.LdFlagsDeps, cfiExportsMap)
+				}
 			}
 		}
 	}
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index cdf63d8..8177ff1 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -44,7 +44,7 @@
 )
 
 func init() {
-	pctx.HostBinToolVariable("versionerCmd", "versioner")
+	pctx.SourcePathVariable("versionerCmd", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/versioner")
 }
 
 // Returns the NDK base include path for use with sdk_version current. Usable with -I.
@@ -134,7 +134,7 @@
 	// but keep them when doing regular platform build.
 	// Ndk_abis property is only set to true with build/soong/scripts/build-ndk-prebuilts.sh
 	// TODO: Revert this once MIPS is supported in NDK again.
-	if Bool(ctx.AConfig().Ndk_abis) && strings.Contains(ctx.ModuleName(), "mips") {
+	if ctx.Config().NdkAbis() && strings.Contains(ctx.ModuleName(), "mips") {
 		return
 	}
 
diff --git a/cc/object.go b/cc/object.go
index 0010621..552f639 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -39,6 +39,10 @@
 		baseLinker: NewBaseLinker(nil),
 	}
 	module.compiler = NewBaseCompiler()
+
+	// Clang's address-significance tables are incompatible with ld -r.
+	module.compiler.appendCflags([]string{"-fno-addrsig"})
+
 	module.stl = &stl{}
 	return module.Init()
 }
diff --git a/cc/test.go b/cc/test.go
index e6251d3..96049db 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -31,12 +31,6 @@
 	Isolated *bool
 }
 
-// Test option struct.
-type TestOptions struct {
-	// the UID that you want to run in device.
-	Run_test_as string `android:"arch_variant"`
-}
-
 type TestBinaryProperties struct {
 	// Create a separate binary for each source file.  Useful when there is
 	// global state that can not be torn down and reset between each test suite.
@@ -62,9 +56,6 @@
 	// 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"`
-
-	// Test options.
-	Test_options *TestOptions
 }
 
 func init() {
@@ -253,16 +244,8 @@
 
 func (test *testBinary) install(ctx ModuleContext, file android.Path) {
 	test.data = ctx.ExpandSources(test.Properties.Data, nil)
-
-	// Append new line in template like below
-	// <option name="run-test-as" value="1234" />
-	optionsMap := map[string]string{}
-	if test.Properties.Test_options != nil {
-		optionsMap["run-test-as"] = string(test.Properties.Test_options.Run_test_as)
-	}
-
 	test.testConfig = tradefed.AutoGenNativeTestConfig(ctx, test.Properties.Test_config,
-		test.Properties.Test_config_template, optionsMap)
+		test.Properties.Test_config_template)
 
 	test.binaryDecorator.baseInstaller.dir = "nativetest"
 	test.binaryDecorator.baseInstaller.dir64 = "nativetest64"
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 9cb75fa..6a3d579 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -393,6 +393,9 @@
 
 	config := build.NewConfig(ctx, flag.Args()...)
 	config.Environment().Set("OUT_DIR", outDir)
+	if !*keepArtifacts {
+		config.Environment().Set("EMPTY_NINJA_FILE", "true")
+	}
 	build.FindSources(ctx, config, mpctx.Finder)
 	config.Lunch(ctx, product, *buildVariant)
 
@@ -413,12 +416,7 @@
 				log.Fatalf("Error zipping artifacts: %v", err)
 			}
 		}
-		if *incremental {
-			// Save space, Kati doesn't notice
-			if f := config.KatiBuildNinjaFile(); f != "" {
-				os.Truncate(f, 0)
-			}
-		} else {
+		if !*incremental {
 			os.RemoveAll(outDir)
 		}
 	}()
diff --git a/cmd/zip2zip/zip2zip.go b/cmd/zip2zip/zip2zip.go
index c4fb3d6..491267b 100644
--- a/cmd/zip2zip/zip2zip.go
+++ b/cmd/zip2zip/zip2zip.go
@@ -148,8 +148,13 @@
 				} else {
 					if pathtools.IsGlob(input) {
 						// If the input is a glob then the output is a directory.
-						_, name := filepath.Split(file.Name)
-						newName = filepath.Join(output, name)
+						rel, err := filepath.Rel(constantPartOfPattern(input), file.Name)
+						if err != nil {
+							return err
+						} else if strings.HasPrefix("../", rel) {
+							return fmt.Errorf("globbed path %q was not in %q", file.Name, constantPartOfPattern(input))
+						}
+						newName = filepath.Join(output, rel)
 					} else {
 						// Otherwise it is a file.
 						newName = output
@@ -277,3 +282,24 @@
 	}
 	return false, nil
 }
+
+func constantPartOfPattern(pattern string) string {
+	ret := ""
+	for pattern != "" {
+		var first string
+		first, pattern = splitFirst(pattern)
+		if pathtools.IsGlob(first) {
+			return ret
+		}
+		ret = filepath.Join(ret, first)
+	}
+	return ret
+}
+
+func splitFirst(path string) (string, string) {
+	i := strings.IndexRune(path, filepath.Separator)
+	if i < 0 {
+		return path, ""
+	}
+	return path[:i], path[i+1:]
+}
diff --git a/cmd/zip2zip/zip2zip_test.go b/cmd/zip2zip/zip2zip_test.go
index ae16494..2c4e005 100644
--- a/cmd/zip2zip/zip2zip_test.go
+++ b/cmd/zip2zip/zip2zip_test.go
@@ -352,6 +352,60 @@
 			"a/b",
 		},
 	},
+	{
+		name: "recursive glob",
+
+		inputFiles: []string{
+			"a/a/a",
+			"a/a/b",
+		},
+		args: []string{"a/**/*:b"},
+		outputFiles: []string{
+			"b/a/a",
+			"b/a/b",
+		},
+	},
+	{
+		name: "glob",
+
+		inputFiles: []string{
+			"a/a/a",
+			"a/a/b",
+			"a/b",
+			"a/c",
+		},
+		args: []string{"a/*:b"},
+		outputFiles: []string{
+			"b/b",
+			"b/c",
+		},
+	},
+	{
+		name: "top level glob",
+
+		inputFiles: []string{
+			"a",
+			"b",
+		},
+		args: []string{"*:b"},
+		outputFiles: []string{
+			"b/a",
+			"b/b",
+		},
+	},
+	{
+		name: "multilple glob",
+
+		inputFiles: []string{
+			"a/a/a",
+			"a/a/b",
+		},
+		args: []string{"a/*/*:b"},
+		outputFiles: []string{
+			"b/a/a",
+			"b/a/b",
+		},
+	},
 }
 
 func errorString(e error) string {
@@ -416,3 +470,45 @@
 		})
 	}
 }
+
+func TestConstantPartOfPattern(t *testing.T) {
+	testCases := []struct{ in, out string }{
+		{
+			in:  "",
+			out: "",
+		},
+		{
+			in:  "a",
+			out: "a",
+		},
+		{
+			in:  "*",
+			out: "",
+		},
+		{
+			in:  "a/a",
+			out: "a/a",
+		},
+		{
+			in:  "a/*",
+			out: "a",
+		},
+		{
+			in:  "a/*/a",
+			out: "a",
+		},
+		{
+			in:  "a/**/*",
+			out: "a",
+		},
+	}
+
+	for _, test := range testCases {
+		t.Run(test.in, func(t *testing.T) {
+			got := constantPartOfPattern(test.in)
+			if got != test.out {
+				t.Errorf("want %q, got %q", test.out, got)
+			}
+		})
+	}
+}
diff --git a/java/aapt2.go b/java/aapt2.go
index 5553bfd..86eb9c8 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -188,3 +188,18 @@
 		},
 	})
 }
+
+var aapt2ConvertRule = pctx.AndroidStaticRule("aapt2Convert",
+	blueprint.RuleParams{
+		Command:     `${config.Aapt2Cmd} convert --output-format proto $in -o $out`,
+		CommandDeps: []string{"${config.Aapt2Cmd}"},
+	})
+
+func aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in android.Path) {
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        aapt2ConvertRule,
+		Input:       in,
+		Output:      out,
+		Description: "convert to proto",
+	})
+}
diff --git a/java/aar.go b/java/aar.go
index a06d191..a49aef0 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -47,6 +47,10 @@
 	// flags passed to aapt when creating the apk
 	Aaptflags []string
 
+	// include all resource configurations, not just the product-configured
+	// ones.
+	Aapt_include_all_resources *bool
+
 	// list of directories relative to the Blueprints file containing assets.
 	// Defaults to "assets"
 	Asset_dirs []string
@@ -409,6 +413,10 @@
 	return a.sdkVersion()
 }
 
+func (a *AARImport) targetSdkVersion() string {
+	return a.sdkVersion()
+}
+
 var _ AndroidLibraryDependency = (*AARImport)(nil)
 
 func (a *AARImport) ExportPackage() android.Path {
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 168a22d..36f24ff 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -58,7 +58,7 @@
 		Output: fixedManifest,
 		Args: map[string]string{
 			"minSdkVersion":    sdkVersionOrDefault(ctx, sdkContext.minSdkVersion()),
-			"targetSdkVersion": sdkVersionOrDefault(ctx, sdkContext.sdkVersion()),
+			"targetSdkVersion": sdkVersionOrDefault(ctx, sdkContext.targetSdkVersion()),
 			"args":             strings.Join(args, " "),
 		},
 	})
diff --git a/java/androidmk.go b/java/androidmk.go
index 359594c..0700b58 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -209,6 +209,9 @@
 				if app.headerJarFile != nil {
 					fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", app.headerJarFile.String())
 				}
+				if app.bundleFile != nil {
+					fmt.Fprintln(w, "LOCAL_SOONG_BUNDLE :=", app.bundleFile.String())
+				}
 				if app.jacocoReportClassesFile != nil {
 					fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", app.jacocoReportClassesFile.String())
 				}
@@ -239,7 +242,7 @@
 					fmt.Fprintln(w, "LOCAL_PRIVILEGED_MODULE := true")
 				}
 
-				fmt.Fprintln(w, "LOCAL_CERTIFICATE :=", app.certificate.pem.String())
+				fmt.Fprintln(w, "LOCAL_CERTIFICATE :=", app.certificate.Pem.String())
 				if len(app.appProperties.Overrides) > 0 {
 					fmt.Fprintln(w, "LOCAL_OVERRIDES_PACKAGES := "+strings.Join(app.appProperties.Overrides, " "))
 				}
@@ -290,6 +293,9 @@
 	data := a.Library.AndroidMk()
 
 	data.Extra = append(data.Extra, func(w io.Writer, outputFile android.Path) {
+		if a.aarFile != nil {
+			fmt.Fprintln(w, "LOCAL_SOONG_AAR :=", a.aarFile.String())
+		}
 		if a.proguardDictionary != nil {
 			fmt.Fprintln(w, "LOCAL_SOONG_PROGUARD_DICT :=", a.proguardDictionary.String())
 		}
@@ -448,6 +454,14 @@
 					fmt.Fprintln(w, dstubs.Name()+"-check-last-released-api:",
 						dstubs.checkLastReleasedApiTimestamp.String())
 				}
+				if dstubs.checkNullabilityWarningsTimestamp != nil {
+					fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-check-nullability-warnings")
+					fmt.Fprintln(w, dstubs.Name()+"-check-nullability-warnings:",
+						dstubs.checkNullabilityWarningsTimestamp.String())
+
+					fmt.Fprintln(w, ".PHONY:", "droidcore")
+					fmt.Fprintln(w, "droidcore: ", dstubs.Name()+"-check-nullability-warnings")
+				}
 				apiFilePrefix := "INTERNAL_PLATFORM_"
 				if String(dstubs.properties.Api_tag_name) != "" {
 					apiFilePrefix += String(dstubs.properties.Api_tag_name) + "_"
diff --git a/java/app.go b/java/app.go
index 5d25dcf..392ad3f 100644
--- a/java/app.go
+++ b/java/app.go
@@ -67,20 +67,24 @@
 	// list of native libraries that will be provided in or alongside the resulting jar
 	Jni_libs []string `android:"arch_variant"`
 
-	EmbedJNI bool `blueprint:"mutated"`
+	AllowDexPreopt bool `blueprint:"mutated"`
+	EmbedJNI       bool `blueprint:"mutated"`
+	StripDex       bool `blueprint:"mutated"`
 }
 
 type AndroidApp struct {
 	Library
 	aapt
 
-	certificate certificate
+	certificate Certificate
 
 	appProperties appProperties
 
 	extraLinkFlags []string
 
 	installJniLibs []jniLib
+
+	bundleFile android.Path
 }
 
 func (a *AndroidApp) ExportedProguardFlagFiles() android.Paths {
@@ -97,8 +101,8 @@
 
 var _ AndroidLibraryDependency = (*AndroidApp)(nil)
 
-type certificate struct {
-	pem, key android.Path
+type Certificate struct {
+	Pem, Key android.Path
 }
 
 func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -139,6 +143,44 @@
 	a.generateAndroidBuildActions(ctx)
 }
 
+// Returns whether this module should have the dex file stored uncompressed in the APK, or stripped completely.  If
+// stripped, the code will still be present on the device in the dexpreopted files.
+// This is only necessary for APKs, and not jars, because APKs are signed and the dex file should not be uncompressed
+// or removed after the signature has been generated.  For jars, which are not signed, the dex file is uncompressed
+// or removed at installation time in Make.
+func (a *AndroidApp) uncompressOrStripDex(ctx android.ModuleContext) (uncompress, strip bool) {
+	if ctx.Config().UnbundledBuild() {
+		return false, false
+	}
+
+	strip = ctx.Config().DefaultStripDex()
+	// TODO(ccross): don't strip dex installed on partitions that may be updated separately (like vendor)
+	// TODO(ccross): don't strip dex on modules with LOCAL_APK_LIBRARIES equivalent
+
+	// Uncompress dex in APKs of privileged apps, and modules used by privileged apps.
+	if ctx.Config().UncompressPrivAppDex() &&
+		(Bool(a.appProperties.Privileged) ||
+			inList(ctx.ModuleName(), ctx.Config().ModulesLoadedByPrivilegedModules())) {
+
+		uncompress = true
+		// If the dex files is store uncompressed, don't strip it, we will reuse the uncompressed dex from the APK
+		// instead of copying it into the odex file.
+		strip = false
+	}
+
+	// If dexpreopt is disabled, don't strip the dex file
+	if !a.appProperties.AllowDexPreopt ||
+		!BoolDefault(a.deviceProperties.Dex_preopt.Enabled, true) ||
+		ctx.Config().DisableDexPreopt(ctx.ModuleName()) {
+		strip = false
+	}
+
+	// TODO(ccross): strip dexpropted modules that are not propted to system_other
+	strip = false
+
+	return uncompress, strip
+}
+
 func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
 	linkFlags := append([]string(nil), a.extraLinkFlags...)
 
@@ -154,14 +196,16 @@
 		linkFlags = append(linkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
 	}
 
-	// Product AAPT config
-	for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
-		linkFlags = append(linkFlags, "-c", aaptConfig)
-	}
+	if !Bool(a.aaptProperties.Aapt_include_all_resources) {
+		// Product AAPT config
+		for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
+			linkFlags = append(linkFlags, "-c", aaptConfig)
+		}
 
-	// Product AAPT preferred config
-	if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
-		linkFlags = append(linkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
+		// Product AAPT preferred config
+		if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
+			linkFlags = append(linkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
+		}
 	}
 
 	// TODO: LOCAL_PACKAGE_OVERRIDES
@@ -184,13 +228,18 @@
 	a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, staticLibProguardFlagFiles...)
 	a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, a.proguardOptionsFile)
 
+	a.deviceProperties.UncompressDex, a.appProperties.StripDex = a.uncompressOrStripDex(ctx)
+
 	if ctx.ModuleName() != "framework-res" {
 		a.Module.compile(ctx, a.aaptSrcJar)
 	}
+	dexJarFile := a.dexJarFile
 
-	packageFile := android.PathForModuleOut(ctx, "package.apk")
+	if a.appProperties.StripDex {
+		dexJarFile = nil
+	}
 
-	var certificates []certificate
+	var certificates []Certificate
 
 	var jniJarFile android.WritablePath
 	jniLibs, certificateDeps := a.collectAppDeps(ctx)
@@ -215,21 +264,25 @@
 		certificateDeps = certificateDeps[1:]
 	} else if cert != "" {
 		defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
-		a.certificate = certificate{
+		a.certificate = Certificate{
 			defaultDir.Join(ctx, cert+".x509.pem"),
 			defaultDir.Join(ctx, cert+".pk8"),
 		}
 	} else {
 		pem, key := ctx.Config().DefaultAppCertificate(ctx)
-		a.certificate = certificate{pem, key}
+		a.certificate = Certificate{pem, key}
 	}
 
-	certificates = append([]certificate{a.certificate}, certificateDeps...)
+	certificates = append([]Certificate{a.certificate}, certificateDeps...)
 
-	CreateAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, a.outputFile, certificates)
-
+	packageFile := android.PathForModuleOut(ctx, "package.apk")
+	CreateAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates)
 	a.outputFile = packageFile
 
+	bundleFile := android.PathForModuleOut(ctx, "base.zip")
+	BuildBundleModule(ctx, bundleFile, a.exportPackage, jniJarFile, dexJarFile)
+	a.bundleFile = bundleFile
+
 	if ctx.ModuleName() == "framework-res" {
 		// framework-res.apk is installed as system/framework/framework-res.apk
 		ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".apk", a.outputFile)
@@ -240,9 +293,9 @@
 	}
 }
 
-func (a *AndroidApp) collectAppDeps(ctx android.ModuleContext) ([]jniLib, []certificate) {
+func (a *AndroidApp) collectAppDeps(ctx android.ModuleContext) ([]jniLib, []Certificate) {
 	var jniLibs []jniLib
-	var certificates []certificate
+	var certificates []Certificate
 
 	ctx.VisitDirectDeps(func(module android.Module) {
 		otherName := ctx.OtherModuleName(module)
@@ -266,7 +319,7 @@
 			}
 		} else if tag == certificateTag {
 			if dep, ok := module.(*AndroidAppCertificate); ok {
-				certificates = append(certificates, dep.certificate)
+				certificates = append(certificates, dep.Certificate)
 			} else {
 				ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName)
 			}
@@ -284,6 +337,7 @@
 
 	module.Module.properties.Instrument = true
 	module.Module.properties.Installable = proptools.BoolPtr(true)
+	module.appProperties.AllowDexPreopt = true
 
 	module.AddProperties(
 		&module.Module.properties,
@@ -345,6 +399,7 @@
 	module.Module.properties.Instrument = true
 	module.Module.properties.Installable = proptools.BoolPtr(true)
 	module.appProperties.EmbedJNI = true
+	module.appProperties.AllowDexPreopt = false
 
 	module.AddProperties(
 		&module.Module.properties,
@@ -379,6 +434,7 @@
 
 	module.Module.properties.Installable = proptools.BoolPtr(true)
 	module.appProperties.EmbedJNI = true
+	module.appProperties.AllowDexPreopt = false
 
 	module.AddProperties(
 		&module.Module.properties,
@@ -396,7 +452,7 @@
 type AndroidAppCertificate struct {
 	android.ModuleBase
 	properties  AndroidAppCertificateProperties
-	certificate certificate
+	Certificate Certificate
 }
 
 type AndroidAppCertificateProperties struct {
@@ -416,7 +472,7 @@
 
 func (c *AndroidAppCertificate) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	cert := String(c.properties.Certificate)
-	c.certificate = certificate{
+	c.Certificate = Certificate{
 		android.PathForModuleSrc(ctx, cert+".x509.pem"),
 		android.PathForModuleSrc(ctx, cert+".pk8"),
 	}
diff --git a/java/app_builder.go b/java/app_builder.go
index b9b5f43..b0983bd 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -29,7 +29,7 @@
 )
 
 var (
-	signapk = pctx.AndroidStaticRule("signapk",
+	Signapk = pctx.AndroidStaticRule("signapk",
 		blueprint.RuleParams{
 			Command: `${config.JavaCmd} -Djava.library.path=$$(dirname $signapkJniLibrary) ` +
 				`-jar $signapkCmd $certificates $in $out`,
@@ -63,7 +63,7 @@
 	})
 
 func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
-	resJarFile, jniJarFile, dexJarFile android.Path, certificates []certificate) {
+	packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate) {
 
 	unsignedApk := android.PathForModuleOut(ctx, "unsigned.apk")
 
@@ -71,7 +71,7 @@
 	if dexJarFile != nil {
 		inputs = append(inputs, dexJarFile)
 	}
-	inputs = append(inputs, resJarFile)
+	inputs = append(inputs, packageFile)
 	if jniJarFile != nil {
 		inputs = append(inputs, jniJarFile)
 	}
@@ -84,14 +84,11 @@
 
 	var certificateArgs []string
 	for _, c := range certificates {
-		certificateArgs = append(certificateArgs, c.pem.String(), c.key.String())
+		certificateArgs = append(certificateArgs, c.Pem.String(), c.Key.String())
 	}
 
-	// TODO(ccross): sometimes uncompress dex
-	// TODO(ccross): sometimes strip dex
-
 	ctx.Build(pctx, android.BuildParams{
-		Rule:        signapk,
+		Rule:        Signapk,
 		Description: "signapk",
 		Output:      outputFile,
 		Input:       unsignedApk,
@@ -137,6 +134,70 @@
 	})
 }
 
+var buildBundleModule = pctx.AndroidStaticRule("buildBundleModule",
+	blueprint.RuleParams{
+		Command:     `${config.MergeZipsCmd} ${out} ${in}`,
+		CommandDeps: []string{"${config.MergeZipsCmd}"},
+	})
+
+var bundleMungePackage = pctx.AndroidStaticRule("bundleMungePackage",
+	blueprint.RuleParams{
+		Command:     `${config.Zip2ZipCmd} -i ${in} -o ${out} AndroidManifest.xml:manifest/AndroidManifest.xml resources.pb "res/**/*" "assets/**/*"`,
+		CommandDeps: []string{"${config.Zip2ZipCmd}"},
+	})
+
+var bundleMungeDexJar = pctx.AndroidStaticRule("bundleMungeDexJar",
+	blueprint.RuleParams{
+		Command: `${config.Zip2ZipCmd} -i ${in} -o ${out} "classes*.dex:dex/" && ` +
+			`${config.Zip2ZipCmd} -i ${in} -o ${resJar} -x "classes*.dex" "**/*:root/"`,
+		CommandDeps: []string{"${config.Zip2ZipCmd}"},
+	}, "resJar")
+
+// Builds an app into a module suitable for input to bundletool
+func BuildBundleModule(ctx android.ModuleContext, outputFile android.WritablePath,
+	packageFile, jniJarFile, dexJarFile android.Path) {
+
+	protoResJarFile := android.PathForModuleOut(ctx, "package-res.pb.apk")
+	aapt2Convert(ctx, protoResJarFile, packageFile)
+
+	var zips android.Paths
+
+	mungedPackage := android.PathForModuleOut(ctx, "bundle", "apk.zip")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        bundleMungePackage,
+		Input:       protoResJarFile,
+		Output:      mungedPackage,
+		Description: "bundle apk",
+	})
+	zips = append(zips, mungedPackage)
+
+	if dexJarFile != nil {
+		mungedDexJar := android.PathForModuleOut(ctx, "bundle", "dex.zip")
+		mungedResJar := android.PathForModuleOut(ctx, "bundle", "res.zip")
+		ctx.Build(pctx, android.BuildParams{
+			Rule:           bundleMungeDexJar,
+			Input:          dexJarFile,
+			Output:         mungedDexJar,
+			ImplicitOutput: mungedResJar,
+			Description:    "bundle dex",
+			Args: map[string]string{
+				"resJar": mungedResJar.String(),
+			},
+		})
+		zips = append(zips, mungedDexJar, mungedResJar)
+	}
+	if jniJarFile != nil {
+		zips = append(zips, jniJarFile)
+	}
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        buildBundleModule,
+		Inputs:      zips,
+		Output:      outputFile,
+		Description: "bundle",
+	})
+}
+
 func TransformJniLibsToJar(ctx android.ModuleContext, outputFile android.WritablePath,
 	jniLibs []jniLib) {
 
diff --git a/java/dex.go b/java/dex.go
index 625fb83..5cec325 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -26,7 +26,7 @@
 	blueprint.RuleParams{
 		Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
 			`${config.D8Cmd} --output $outDir $d8Flags $in && ` +
-			`${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
+			`${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
 			`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
 		CommandDeps: []string{
 			"${config.D8Cmd}",
@@ -34,7 +34,7 @@
 			"${config.MergeZipsCmd}",
 		},
 	},
-	"outDir", "d8Flags")
+	"outDir", "d8Flags", "zipFlags")
 
 var r8 = pctx.AndroidStaticRule("r8",
 	blueprint.RuleParams{
@@ -46,7 +46,7 @@
 			`-printmapping $outDict ` +
 			`$r8Flags && ` +
 			`touch "$outDict" && ` +
-			`${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
+			`${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
 			`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
 		CommandDeps: []string{
 			"${config.R8Cmd}",
@@ -54,7 +54,7 @@
 			"${config.MergeZipsCmd}",
 		},
 	},
-	"outDir", "outDict", "r8Flags")
+	"outDir", "outDict", "r8Flags", "zipFlags")
 
 func (j *Module) dexCommonFlags(ctx android.ModuleContext) []string {
 	flags := j.deviceProperties.Dxflags
@@ -172,6 +172,11 @@
 	javalibJar := android.PathForModuleOut(ctx, "dex", jarName)
 	outDir := android.PathForModuleOut(ctx, "dex")
 
+	zipFlags := ""
+	if j.deviceProperties.UncompressDex {
+		zipFlags = "-L 0"
+	}
+
 	if useR8 {
 		proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
 		j.proguardDictionary = proguardDictionary
@@ -184,9 +189,10 @@
 			Input:          classesJar,
 			Implicits:      r8Deps,
 			Args: map[string]string{
-				"r8Flags": strings.Join(r8Flags, " "),
-				"outDict": j.proguardDictionary.String(),
-				"outDir":  outDir.String(),
+				"r8Flags":  strings.Join(r8Flags, " "),
+				"zipFlags": zipFlags,
+				"outDict":  j.proguardDictionary.String(),
+				"outDir":   outDir.String(),
 			},
 		})
 	} else {
@@ -198,8 +204,9 @@
 			Input:       classesJar,
 			Implicits:   d8Deps,
 			Args: map[string]string{
-				"d8Flags": strings.Join(d8Flags, " "),
-				"outDir":  outDir.String(),
+				"d8Flags":  strings.Join(d8Flags, " "),
+				"zipFlags": zipFlags,
+				"outDir":   outDir.String(),
 			},
 		})
 	}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index fca5fc4..9dadb30 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -106,6 +106,12 @@
 		},
 		"srcJarDir", "srcJars", "javaVersion", "bootclasspathArgs", "classpathArgs", "sourcepathArgs", "opts", "msg")
 
+	nullabilityWarningsCheck = pctx.AndroidStaticRule("nullabilityWarningsCheck",
+		blueprint.RuleParams{
+			Command: `( diff $expected $actual && touch $out ) || ( echo -e "$msg" ; exit 38 )`,
+		},
+		"expected", "actual", "msg")
+
 	dokka = pctx.AndroidStaticRule("dokka",
 		blueprint.RuleParams{
 			Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && ` +
@@ -354,6 +360,9 @@
 	// a list of top-level directories containing Java stub files to merge show/hide annotations from.
 	Merge_inclusion_annotations_dirs []string
 
+	// a file containing expected warnings produced by validation of nullability annotations.
+	Check_nullability_warnings *string
+
 	// if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
 	Create_doc_stubs *bool
 
@@ -484,6 +493,10 @@
 	return j.sdkVersion()
 }
 
+func (j *Javadoc) targetSdkVersion() string {
+	return j.sdkVersion()
+}
+
 func (j *Javadoc) addDeps(ctx android.BottomUpMutatorContext) {
 	if ctx.Device() {
 		if !Bool(j.properties.No_standard_libs) {
@@ -1207,23 +1220,26 @@
 type Droidstubs struct {
 	Javadoc
 
-	properties             DroidstubsProperties
-	apiFile                android.WritablePath
-	apiXmlFile             android.WritablePath
-	lastReleasedApiXmlFile android.WritablePath
-	dexApiFile             android.WritablePath
-	privateApiFile         android.WritablePath
-	privateDexApiFile      android.WritablePath
-	removedApiFile         android.WritablePath
-	removedDexApiFile      android.WritablePath
-	apiMappingFile         android.WritablePath
-	exactApiFile           android.WritablePath
-	proguardFile           android.WritablePath
+	properties              DroidstubsProperties
+	apiFile                 android.WritablePath
+	apiXmlFile              android.WritablePath
+	lastReleasedApiXmlFile  android.WritablePath
+	dexApiFile              android.WritablePath
+	privateApiFile          android.WritablePath
+	privateDexApiFile       android.WritablePath
+	removedApiFile          android.WritablePath
+	removedDexApiFile       android.WritablePath
+	apiMappingFile          android.WritablePath
+	exactApiFile            android.WritablePath
+	proguardFile            android.WritablePath
+	nullabilityWarningsFile android.WritablePath
 
 	checkCurrentApiTimestamp      android.WritablePath
 	updateCurrentApiTimestamp     android.WritablePath
 	checkLastReleasedApiTimestamp android.WritablePath
 
+	checkNullabilityWarningsTimestamp android.WritablePath
+
 	annotationsZip android.WritablePath
 	apiVersionsXml android.WritablePath
 
@@ -1286,6 +1302,10 @@
 		}
 	}
 
+	if String(d.properties.Check_nullability_warnings) != "" {
+		android.ExtractSourceDeps(ctx, d.properties.Check_nullability_warnings)
+	}
+
 	if len(d.properties.Api_levels_annotations_dirs) != 0 {
 		for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
 			ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
@@ -1390,15 +1410,23 @@
 	implicits *android.Paths, implicitOutputs *android.WritablePaths) string {
 	var flags string
 	if Bool(d.properties.Annotations_enabled) {
-		if String(d.properties.Previous_api) == "" {
-			ctx.PropertyErrorf("metalava_previous_api",
-				"has to be non-empty if annotations was enabled!")
+		flags += " --include-annotations"
+		validatingNullability := strings.Contains(d.Javadoc.args, "--validate-nullability-from-merged-stubs")
+		migratingNullability := String(d.properties.Previous_api) != ""
+		if !(migratingNullability || validatingNullability) {
+			ctx.PropertyErrorf("previous_api",
+				"has to be non-empty if annotations was enabled (unless validating nullability)")
 		}
-		previousApi := ctx.ExpandSource(String(d.properties.Previous_api),
-			"metalava_previous_api")
-		*implicits = append(*implicits, previousApi)
-
-		flags += " --include-annotations --migrate-nullness " + previousApi.String()
+		if migratingNullability {
+			previousApi := ctx.ExpandSource(String(d.properties.Previous_api), "previous_api")
+			*implicits = append(*implicits, previousApi)
+			flags += " --migrate-nullness " + previousApi.String()
+		}
+		if validatingNullability {
+			d.nullabilityWarningsFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_nullability_warnings.txt")
+			*implicitOutputs = append(*implicitOutputs, d.nullabilityWarningsFile)
+			flags += " --nullability-warnings-txt " + d.nullabilityWarningsFile.String()
+		}
 
 		d.annotationsZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"_annotations.zip")
 		*implicitOutputs = append(*implicitOutputs, d.annotationsZip)
@@ -1673,6 +1701,36 @@
 			d.checkLastReleasedApiTimestamp)
 	}
 
+	if String(d.properties.Check_nullability_warnings) != "" {
+		if d.nullabilityWarningsFile == nil {
+			ctx.PropertyErrorf("check_nullability_warnings",
+				"Cannot specify check_nullability_warnings unless validating nullability")
+		}
+		checkNullabilityWarnings := ctx.ExpandSource(String(d.properties.Check_nullability_warnings),
+			"check_nullability_warnings")
+		d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, "check_nullability_warnings.timestamp")
+		msg := fmt.Sprintf(`\n******************************\n`+
+			`The warnings encountered during nullability annotation validation did\n`+
+			`not match the checked in file of expected warnings. The diffs are shown\n`+
+			`above. You have two options:\n`+
+			`   1. Resolve the differences by editing the nullability annotations.\n`+
+			`   2. Update the file of expected warnings by running:\n`+
+			`         cp %s %s\n`+
+			`       and submitting the updated file as part of your change.`,
+			d.nullabilityWarningsFile, checkNullabilityWarnings)
+		ctx.Build(pctx, android.BuildParams{
+			Rule:        nullabilityWarningsCheck,
+			Description: "Nullability Warnings Check",
+			Output:      d.checkNullabilityWarningsTimestamp,
+			Implicits:   android.Paths{checkNullabilityWarnings, d.nullabilityWarningsFile},
+			Args: map[string]string{
+				"expected": checkNullabilityWarnings.String(),
+				"actual":   d.nullabilityWarningsFile.String(),
+				"msg":      msg,
+			},
+		})
+	}
+
 	if Bool(d.properties.Jdiff_enabled) && !ctx.Config().IsPdkBuild() {
 
 		// Please sync with android-api-council@ before making any changes for the name of jdiffDocZip below
diff --git a/java/java.go b/java/java.go
index f651884..50c284a 100644
--- a/java/java.go
+++ b/java/java.go
@@ -183,6 +183,10 @@
 	// Defaults to sdk_version if not set.
 	Min_sdk_version *string
 
+	// if not blank, set the targetSdkVersion in the AndroidManifest.xml.
+	// Defaults to sdk_version if not set.
+	Target_sdk_version *string
+
 	// if true, compile against the platform APIs instead of an SDK.
 	Platform_apis *bool
 
@@ -257,6 +261,8 @@
 
 	// When targeting 1.9, override the modules to use with --system
 	System_modules *string
+
+	UncompressDex bool `blueprint:"mutated"`
 }
 
 // Module contains the properties and members used by all java module types
@@ -423,16 +429,25 @@
 	return j.sdkVersion()
 }
 
+func (j *Module) targetSdkVersion() string {
+	if j.deviceProperties.Target_sdk_version != nil {
+		return *j.deviceProperties.Target_sdk_version
+	}
+	return j.sdkVersion()
+}
+
 type sdkContext interface {
 	// sdkVersion eturns the sdk_version property of the current module, or an empty string if it is not set.
 	sdkVersion() string
 	// minSdkVersion returns the min_sdk_version property of the current module, or sdkVersion() if it is not set.
 	minSdkVersion() string
+	// targetSdkVersion returns the target_sdk_version property of the current module, or sdkVersion() if it is not set.
+	targetSdkVersion() string
 }
 
 func sdkVersionOrDefault(ctx android.BaseContext, v string) string {
 	switch v {
-	case "", "current", "system_current", "test_current", "core_current", "core_platform_current":
+	case "", "current", "system_current", "test_current", "core_current":
 		return ctx.Config().DefaultAppTargetSdk()
 	default:
 		return v
@@ -443,7 +458,7 @@
 // it returns android.FutureApiLevel (10000).
 func sdkVersionToNumber(ctx android.BaseContext, v string) (int, error) {
 	switch v {
-	case "", "current", "test_current", "system_current", "core_current", "core_platform_current":
+	case "", "current", "test_current", "system_current", "core_current":
 		return ctx.Config().DefaultAppTargetSdkInt(), nil
 	default:
 		n := android.GetNumericSdkVersion(v)
@@ -564,8 +579,6 @@
 		return toModule("android_test_stubs_current", "framework-res")
 	case "core_current":
 		return toModule("core.current.stubs", "")
-	case "core_platform_current":
-		return toModule("core.platform.api.stubs", "")
 	default:
 		return toPrebuilt(v)
 	}
@@ -732,7 +745,7 @@
 		name == "stub-annotations" || name == "private-stub-annotations-jar" ||
 		name == "core-lambda-stubs":
 		return javaCore, true
-	case ver == "core_current" || ver == "core_platform_current":
+	case ver == "core_current":
 		return javaCore, false
 	case name == "android_system_stubs_current":
 		return javaSystem, true
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index 7f6e2c9..81f8564 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -34,11 +34,6 @@
 SOONG_NDK_OUT=${OUT_DIR}/soong/ndk
 rm -rf ${SOONG_OUT}
 mkdir -p ${SOONG_OUT}
-cat > ${SOONG_OUT}/soong.config << EOF
-{
-    "Ndk_abis": true
-}
-EOF
 
 # We only really need to set some of these variables, but soong won't merge this
 # with the defaults, so we need to write out all the defaults with our values
@@ -49,21 +44,11 @@
     "Platform_version_active_codenames": ${PLATFORM_VERSION_ALL_CODENAMES},
 
     "DeviceName": "generic_arm64",
-    "DeviceArch": "arm64",
-    "DeviceArchVariant": "armv8-a",
-    "DeviceCpuVariant": "denver64",
-    "DeviceAbi": [
-        "arm64-v8a"
-    ],
-    "DeviceSecondaryArch": "arm",
-    "DeviceSecondaryArchVariant": "armv7-a-neon",
-    "DeviceSecondaryCpuVariant": "denver",
-    "DeviceSecondaryAbi": [
-        "armeabi-v7a"
-    ],
     "HostArch": "x86_64",
     "Malloc_not_svelte": false,
-    "Safestack": false
+    "Safestack": false,
+
+    "Ndk_abis": true
 }
 EOF
 m --skip-make ${SOONG_OUT}/ndk.timestamp
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index 5fb85c3..131fdc4 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -15,7 +15,6 @@
 package tradefed
 
 import (
-	"fmt"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -37,10 +36,9 @@
 }
 
 var autogenTestConfig = pctx.StaticRule("autogenTestConfig", blueprint.RuleParams{
-	Command: "sed 's&{MODULE}&${name}&g' $template > $out &&" +
-		"${optionCmd} $out",
+	Command:     "sed 's&{MODULE}&${name}&g' $template > $out",
 	CommandDeps: []string{"$template"},
-}, "name", "template", "optionCmd")
+}, "name", "template")
 
 func testConfigPath(ctx android.ModuleContext, prop *string) (path android.Path, autogenPath android.WritablePath) {
 	if p := getTestConfig(ctx, prop); p != nil {
@@ -56,44 +54,30 @@
 	}
 }
 
-func autogenTemplate(ctx android.ModuleContext, output android.WritablePath, template string, optionsMap map[string]string) {
-	// If no test option found, delete {UID_OPTION} line.
-	// If found, replace it with corresponding options format.
-	optionCmd := "sed -i '/{UID_OPTION}/d'"
-	if optionsMap != nil {
-		//Append options
-		var options []string
-		for optionName, value := range optionsMap {
-			if value != "" {
-				options = append(options, fmt.Sprintf("<option name=\"%s\" value=\"%s\" />", optionName, value))
-			}
-		}
-		optionCmd = fmt.Sprintf("sed -i 's&{UID_OPTION}&%s&g'", strings.Join(options, "\\n        "))
-	}
+func autogenTemplate(ctx android.ModuleContext, output android.WritablePath, template string) {
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        autogenTestConfig,
 		Description: "test config",
 		Output:      output,
 		Args: map[string]string{
-			"name":      ctx.ModuleName(),
-			"template":  template,
-			"optionCmd": optionCmd,
+			"name":     ctx.ModuleName(),
+			"template": template,
 		},
 	})
 }
 
 func AutoGenNativeTestConfig(ctx android.ModuleContext, testConfigProp *string,
-	testConfigTemplateProp *string, optionsMap map[string]string) android.Path {
+	testConfigTemplateProp *string) android.Path {
 	path, autogenPath := testConfigPath(ctx, testConfigProp)
 	if autogenPath != nil {
 		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
 		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String(), optionsMap)
+			autogenTemplate(ctx, autogenPath, templatePath.String())
 		} else {
 			if ctx.Device() {
-				autogenTemplate(ctx, autogenPath, "${NativeTestConfigTemplate}", optionsMap)
+				autogenTemplate(ctx, autogenPath, "${NativeTestConfigTemplate}")
 			} else {
-				autogenTemplate(ctx, autogenPath, "${NativeHostTestConfigTemplate}", optionsMap)
+				autogenTemplate(ctx, autogenPath, "${NativeHostTestConfigTemplate}")
 			}
 		}
 		return autogenPath
@@ -107,9 +91,9 @@
 	if autogenPath != nil {
 		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
 		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String(), nil)
+			autogenTemplate(ctx, autogenPath, templatePath.String())
 		} else {
-			autogenTemplate(ctx, autogenPath, "${NativeBenchmarkTestConfigTemplate}", nil)
+			autogenTemplate(ctx, autogenPath, "${NativeBenchmarkTestConfigTemplate}")
 		}
 		return autogenPath
 	}
@@ -121,12 +105,12 @@
 	if autogenPath != nil {
 		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
 		if templatePath.Valid() {
-			autogenTemplate(ctx, autogenPath, templatePath.String(), nil)
+			autogenTemplate(ctx, autogenPath, templatePath.String())
 		} else {
 			if ctx.Device() {
-				autogenTemplate(ctx, autogenPath, "${JavaTestConfigTemplate}", nil)
+				autogenTemplate(ctx, autogenPath, "${JavaTestConfigTemplate}")
 			} else {
-				autogenTemplate(ctx, autogenPath, "${JavaHostTestConfigTemplate}", nil)
+				autogenTemplate(ctx, autogenPath, "${JavaHostTestConfigTemplate}")
 			}
 		}
 		return autogenPath
diff --git a/ui/build/config.go b/ui/build/config.go
index 840f505..5a6d5db 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -143,6 +143,9 @@
 		"ANDROID_DEV_SCRIPTS",
 		"ANDROID_EMULATOR_PREBUILTS",
 		"ANDROID_PRE_BUILD_PATHS",
+
+		// Only set in multiproduct_kati after config generation
+		"EMPTY_NINJA_FILE",
 	)
 
 	// Tell python not to spam the source tree with .pyc files.
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 56e9a88..d2e9fe9 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -81,6 +81,10 @@
 		"--kati_stats",
 	}, args...)
 
+	if config.Environment().IsEnvTrue("EMPTY_NINJA_FILE") {
+		args = append(args, "--empty_ninja_file")
+	}
+
 	cmd := Command(ctx, config, "ckati", executable, args...)
 	cmd.Sandbox = katiSandbox
 	pipe, err := cmd.StdoutPipe()
diff --git a/ui/build/path.go b/ui/build/path.go
index 52658ef..8260ff9 100644
--- a/ui/build/path.go
+++ b/ui/build/path.go
@@ -19,6 +19,7 @@
 	"io/ioutil"
 	"os"
 	"path/filepath"
+	"runtime"
 	"strings"
 
 	"github.com/google/blueprint/microfactory"
@@ -144,6 +145,13 @@
 	}
 
 	myPath, _ = filepath.Abs(myPath)
+
+	// Use the toybox prebuilts on linux
+	if runtime.GOOS == "linux" {
+		toyboxPath, _ := filepath.Abs("prebuilts/build-tools/toybox/linux-x86")
+		myPath = toyboxPath + string(os.PathListSeparator) + myPath
+	}
+
 	config.Environment().Set("PATH", myPath)
 	config.pathReplaced = true
 }
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index c4fcc20..b4d76c4 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -25,6 +25,10 @@
 
 	// Whether to exit with an error instead of invoking the underlying tool.
 	Error bool
+
+	// Whether we use a toybox prebuilt for this tool. Since we don't have
+	// toybox for Darwin, we'll use the host version instead.
+	Toybox bool
 }
 
 var Allowed = PathConfig{
@@ -55,6 +59,13 @@
 	Error:   true,
 }
 
+var Toybox = PathConfig{
+	Symlink: false,
+	Log:     true,
+	Error:   true,
+	Toybox:  true,
+}
+
 func GetConfig(name string) PathConfig {
 	if config, ok := Configuration[name]; ok {
 		return config
@@ -122,7 +133,6 @@
 	"rm":        Allowed,
 	"rmdir":     Allowed,
 	"rsync":     Allowed,
-	"runalarm":  Allowed,
 	"sed":       Allowed,
 	"setsid":    Allowed,
 	"sh":        Allowed,
@@ -135,11 +145,10 @@
 	"tar":       Allowed,
 	"tail":      Allowed,
 	"tee":       Allowed,
+	"timeout":   Allowed,
 	"todos":     Allowed,
 	"touch":     Allowed,
 	"tr":        Allowed,
-	"true":      Allowed,
-	"uname":     Allowed,
 	"uniq":      Allowed,
 	"unix2dos":  Allowed,
 	"unzip":     Allowed,
@@ -166,10 +175,9 @@
 	"ld.gold":    Forbidden,
 	"pkg-config": Forbidden,
 
-	// We've got prebuilts of these
-	//"dtc":  Forbidden,
-	//"lz4":  Forbidden,
-	//"lz4c": Forbidden,
+	// On linux we'll use the toybox version of these instead
+	"true":  Toybox,
+	"uname": Toybox,
 }
 
 func init() {
@@ -177,5 +185,13 @@
 		Configuration["md5"] = Allowed
 		Configuration["sw_vers"] = Allowed
 		Configuration["xcrun"] = Allowed
+
+		// We don't have toybox prebuilts for darwin, so allow the
+		// host versions.
+		for name, config := range Configuration {
+			if config.Toybox {
+				Configuration[name] = Allowed
+			}
+		}
 	}
 }