Merge "Add support for exclude_srcs in genrule"
diff --git a/Android.bp b/Android.bp
index ef42c84..76f6798 100644
--- a/Android.bp
+++ b/Android.bp
@@ -145,6 +145,7 @@
         "cc/util.go",
         "cc/vndk.go",
         "cc/vndk_prebuilt.go",
+        "cc/xom.go",
 
         "cc/cmakelists.go",
         "cc/compdb.go",
@@ -352,6 +353,9 @@
         "apex/apex.go",
         "apex/key.go",
     ],
+    testSrcs: [
+        "apex/apex_test.go",
+    ],
     pluginFor: ["soong_build"],
 }
 
@@ -435,7 +439,7 @@
             src: "prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/lib/libwinpthread.a",
         },
     },
-    notice: "../../prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/licenses/mingw-w64-svn-r5861/mingw-w64-libraries/winpthreads/COPYING",
+    notice: ":mingw-libwinpthread-notice",
 }
 
 toolchain_library {
diff --git a/android/androidmk.go b/android/androidmk.go
index 493ba97..18b26d9 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -40,6 +40,7 @@
 type AndroidMkData struct {
 	Class      string
 	SubName    string
+	DistFile   OptionalPath
 	OutputFile OptionalPath
 	Disabled   bool
 	Include    string
@@ -220,6 +221,45 @@
 		}
 	}
 
+	if len(amod.commonProperties.Dist.Targets) > 0 {
+		distFile := data.DistFile
+		if !distFile.Valid() {
+			distFile = data.OutputFile
+		}
+		if distFile.Valid() {
+			dest := filepath.Base(distFile.String())
+
+			if amod.commonProperties.Dist.Dest != nil {
+				var err error
+				dest, err = validateSafePath(*amod.commonProperties.Dist.Dest)
+				if err != nil {
+					// This was checked in ModuleBase.GenerateBuildActions
+					panic(err)
+				}
+			}
+
+			if amod.commonProperties.Dist.Suffix != nil {
+				ext := filepath.Ext(dest)
+				suffix := *amod.commonProperties.Dist.Suffix
+				dest = strings.TrimSuffix(dest, ext) + suffix + ext
+			}
+
+			if amod.commonProperties.Dist.Dir != nil {
+				var err error
+				dest, err = validateSafePath(*amod.commonProperties.Dist.Dir, dest)
+				if err != nil {
+					// This was checked in ModuleBase.GenerateBuildActions
+					panic(err)
+				}
+			}
+
+			goals := strings.Join(amod.commonProperties.Dist.Targets, " ")
+			fmt.Fprintln(&data.preamble, ".PHONY:", goals)
+			fmt.Fprintf(&data.preamble, "$(call dist-for-goals,%s,%s:%s)\n",
+				goals, distFile.String(), dest)
+		}
+	}
+
 	fmt.Fprintln(&data.preamble, "\ninclude $(CLEAR_VARS)")
 	fmt.Fprintln(&data.preamble, "LOCAL_PATH :=", filepath.Dir(ctx.BlueprintFile(mod)))
 	fmt.Fprintln(&data.preamble, "LOCAL_MODULE :=", name+data.SubName)
@@ -277,8 +317,8 @@
 		}
 	}
 
-	if amod.commonProperties.Notice != nil {
-		fmt.Fprintln(&data.preamble, "LOCAL_NOTICE_FILE :=", "$(LOCAL_PATH)/"+*amod.commonProperties.Notice)
+	if amod.noticeFile != nil {
+		fmt.Fprintln(&data.preamble, "LOCAL_NOTICE_FILE :=", amod.noticeFile.String())
 	}
 
 	if host {
diff --git a/android/apex.go b/android/apex.go
index dae88ce..3a191cf 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -14,6 +14,8 @@
 
 package android
 
+import "sync"
+
 // ApexModule is the interface that a module type is expected to implement if
 // the module has to be built differently depending on whether the module
 // is destined for an apex or not (installed to one of the regular partitions).
@@ -94,6 +96,68 @@
 	return false
 }
 
+// This structure maps a module name to the set of APEX bundle names that the module
+// should be built for. Examples:
+//
+// ...["foo"]["bar"] == true: module foo is directly depended on by APEX bar
+// ...["foo"]["bar"] == false: module foo is indirectly depended on by APEX bar
+// ...["foo"]["bar"] doesn't exist: foo is not built for APEX bar
+// ...["foo"] doesn't exist: foo is not built for any APEX
+func apexBundleNamesMap(config Config) map[string]map[string]bool {
+	return config.Once("apexBundleNames", func() interface{} {
+		return make(map[string]map[string]bool)
+	}).(map[string]map[string]bool)
+}
+
+var bundleNamesMapMutex sync.Mutex
+
+// Mark that a module named moduleName should be built for an apex named bundleName
+// directDep should be set to true if the module is a direct dependency of the apex.
+func BuildModuleForApexBundle(ctx BaseModuleContext, moduleName string, bundleName string, directDep bool) {
+	bundleNamesMapMutex.Lock()
+	defer bundleNamesMapMutex.Unlock()
+	bundleNames, ok := apexBundleNamesMap(ctx.Config())[moduleName]
+	if !ok {
+		bundleNames = make(map[string]bool)
+		apexBundleNamesMap(ctx.Config())[moduleName] = bundleNames
+	}
+	bundleNames[bundleName] = bundleNames[bundleName] || directDep
+}
+
+// Returns the list of apex bundle names that the module named moduleName
+// should be built for.
+func GetApexBundlesForModule(ctx BaseModuleContext, moduleName string) map[string]bool {
+	bundleNamesMapMutex.Lock()
+	defer bundleNamesMapMutex.Unlock()
+	return apexBundleNamesMap(ctx.Config())[moduleName]
+}
+
+// Tests if moduleName is directly depended on by bundleName (i.e. referenced in
+// native_shared_libs, etc.)
+func DirectlyInApex(config Config, bundleName string, moduleName string) bool {
+	bundleNamesMapMutex.Lock()
+	defer bundleNamesMapMutex.Unlock()
+	if bundleNames, ok := apexBundleNamesMap(config)[moduleName]; ok {
+		return bundleNames[bundleName]
+	}
+	return false
+}
+
+// Tests if moduleName is directly depended on by any APEX. If this returns true,
+// that means the module is part of the platform.
+func DirectlyInAnyApex(config Config, moduleName string) bool {
+	bundleNamesMapMutex.Lock()
+	defer bundleNamesMapMutex.Unlock()
+	if bundleNames, ok := apexBundleNamesMap(config)[moduleName]; ok {
+		for bn := range bundleNames {
+			if bundleNames[bn] {
+				return true
+			}
+		}
+	}
+	return false
+}
+
 func InitApexModule(m ApexModule) {
 	base := m.apexModuleBase()
 	base.canHaveApexVariants = true
diff --git a/android/arch.go b/android/arch.go
index 7fe1b18..bee09b0 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1080,20 +1080,20 @@
 		{"arm", "armv7-a-neon", "cortex-a73", []string{"armeabi-v7a"}},
 		{"arm", "armv7-a-neon", "cortex-a75", []string{"armeabi-v7a"}},
 		{"arm", "armv7-a-neon", "cortex-a76", []string{"armeabi-v7a"}},
-		{"arm", "armv7-a-neon", "denver", []string{"armeabi-v7a"}},
 		{"arm", "armv7-a-neon", "krait", []string{"armeabi-v7a"}},
 		{"arm", "armv7-a-neon", "kryo", []string{"armeabi-v7a"}},
+		{"arm", "armv7-a-neon", "kryo385", []string{"armeabi-v7a"}},
 		{"arm", "armv7-a-neon", "exynos-m1", []string{"armeabi-v7a"}},
 		{"arm", "armv7-a-neon", "exynos-m2", []string{"armeabi-v7a"}},
 		{"arm64", "armv8-a", "cortex-a53", []string{"arm64-v8a"}},
 		{"arm64", "armv8-a", "cortex-a72", []string{"arm64-v8a"}},
 		{"arm64", "armv8-a", "cortex-a73", []string{"arm64-v8a"}},
-		{"arm64", "armv8-a", "denver64", []string{"arm64-v8a"}},
 		{"arm64", "armv8-a", "kryo", []string{"arm64-v8a"}},
 		{"arm64", "armv8-a", "exynos-m1", []string{"arm64-v8a"}},
 		{"arm64", "armv8-a", "exynos-m2", []string{"arm64-v8a"}},
 		{"arm64", "armv8-2a", "cortex-a75", []string{"arm64-v8a"}},
 		{"arm64", "armv8-2a", "cortex-a76", []string{"arm64-v8a"}},
+		{"arm64", "armv8-2a", "kryo385", []string{"arm64-v8a"}},
 		{"mips", "mips32-fp", "", []string{"mips"}},
 		{"mips", "mips32r2-fp", "", []string{"mips"}},
 		{"mips", "mips32r2-fp-xburst", "", []string{"mips"}},
diff --git a/android/config.go b/android/config.go
index 50c1413..54c9da8 100644
--- a/android/config.go
+++ b/android/config.go
@@ -482,7 +482,7 @@
 }
 
 func (c *config) MinSupportedSdkVersion() int {
-	return 14
+	return 16
 }
 
 func (c *config) DefaultAppTargetSdkInt() int {
@@ -581,6 +581,10 @@
 	return Bool(c.productVariables.Debuggable)
 }
 
+func (c *config) Eng() bool {
+	return Bool(c.productVariables.Eng)
+}
+
 func (c *config) DevicePrefer32BitApps() bool {
 	return Bool(c.productVariables.DevicePrefer32BitApps)
 }
@@ -626,6 +630,14 @@
 	}
 }
 
+func (c *config) EnableXOM() bool {
+	if c.productVariables.EnableXOM == nil {
+		return false
+	} else {
+		return Bool(c.productVariables.EnableXOM)
+	}
+}
+
 func (c *config) Android64() bool {
 	for _, t := range c.Targets[Android] {
 		if t.Arch.ArchType.Multilib == "lib64" {
@@ -863,6 +875,13 @@
 	return PrefixInList(path, *c.productVariables.CFIIncludePaths)
 }
 
+func (c *config) XOMDisabledForPath(path string) bool {
+	if c.productVariables.XOMExcludePaths == nil {
+		return false
+	}
+	return PrefixInList(path, *c.productVariables.XOMExcludePaths)
+}
+
 func (c *config) VendorConfig(name string) VendorConfig {
 	return vendorConfig(c.productVariables.VendorVars[name])
 }
@@ -885,6 +904,10 @@
 	return Bool(c.productVariables.Ndk_abis)
 }
 
+func (c *config) ExcludeDraftNdkApis() bool {
+	return Bool(c.productVariables.Exclude_draft_ndk_apis)
+}
+
 func (c *config) FlattenApex() bool {
 	return Bool(c.productVariables.FlattenApex)
 }
diff --git a/android/module.go b/android/module.go
index bf49ca2..dc0c856 100644
--- a/android/module.go
+++ b/android/module.go
@@ -265,6 +265,24 @@
 	// relative path to a file to include in the list of notices for the device
 	Notice *string
 
+	Dist struct {
+		// copy the output of this module to the $DIST_DIR when `dist` is specified on the
+		// command line and  any of these targets are also on the command line, or otherwise
+		// built
+		Targets []string `android:"arch_variant"`
+
+		// The name of the output artifact. This defaults to the basename of the output of
+		// the module.
+		Dest *string `android:"arch_variant"`
+
+		// The directory within the dist directory to store the artifact. Defaults to the
+		// top level directory ("").
+		Dir *string `android:"arch_variant"`
+
+		// A suffix to add to the artifact file name (before any extension).
+		Suffix *string `android:"arch_variant"`
+	} `android:"arch_variant"`
+
 	// Set by TargetMutator
 	CompileTarget       Target   `blueprint:"mutated"`
 	CompileMultiTargets []Target `blueprint:"mutated"`
@@ -441,6 +459,7 @@
 	noAddressSanitizer bool
 	installFiles       Paths
 	checkbuildFiles    Paths
+	noticeFile         Path
 
 	// Used by buildTargetSingleton to create checkbuild and per-directory build targets
 	// Only set on the final variant of each module
@@ -781,6 +800,25 @@
 	}
 	ctx.Variable(pctx, "moduleDescSuffix", s)
 
+	// Some common property checks for properties that will be used later in androidmk.go
+	if a.commonProperties.Dist.Dest != nil {
+		_, err := validateSafePath(*a.commonProperties.Dist.Dest)
+		if err != nil {
+			ctx.PropertyErrorf("dist.dest", "%s", err.Error())
+		}
+	}
+	if a.commonProperties.Dist.Dir != nil {
+		_, err := validateSafePath(*a.commonProperties.Dist.Dir)
+		if err != nil {
+			ctx.PropertyErrorf("dist.dir", "%s", err.Error())
+		}
+	}
+	if a.commonProperties.Dist.Suffix != nil {
+		if strings.Contains(*a.commonProperties.Dist.Suffix, "/") {
+			ctx.PropertyErrorf("dist.suffix", "Suffix may not contain a '/' character.")
+		}
+	}
+
 	if a.Enabled() {
 		a.module.GenerateAndroidBuildActions(ctx)
 		if ctx.Failed() {
@@ -789,6 +827,11 @@
 
 		a.installFiles = append(a.installFiles, ctx.installFiles...)
 		a.checkbuildFiles = append(a.checkbuildFiles, ctx.checkbuildFiles...)
+
+		if a.commonProperties.Notice != nil {
+			// For filegroup-based notice file references.
+			a.noticeFile = ctx.ExpandSource(*a.commonProperties.Notice, "notice")
+		}
 	}
 
 	if a == ctx.FinalModule().(Module).base() {
@@ -1310,6 +1353,13 @@
 	srcFiles := ctx.ExpandSourcesSubDir([]string{srcFile}, nil, "")
 	if len(srcFiles) == 1 {
 		return srcFiles[0]
+	} else if len(srcFiles) == 0 {
+		if ctx.Config().AllowMissingDependencies() {
+			ctx.AddMissingDependencies([]string{srcFile})
+		} else {
+			ctx.PropertyErrorf(prop, "%s path %s does not exist", prop, srcFile)
+		}
+		return nil
 	} else {
 		ctx.PropertyErrorf(prop, "module providing %s must produce exactly one file", prop)
 		return nil
diff --git a/android/mutator.go b/android/mutator.go
index b9c44e8..b77c2f0 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -207,6 +207,11 @@
 func depsMutator(ctx BottomUpMutatorContext) {
 	if m, ok := ctx.Module().(Module); ok && m.Enabled() {
 		m.DepsMutator(ctx)
+
+		// For filegroup-based notice file references.
+		if m.base().commonProperties.Notice != nil {
+			ExtractSourceDeps(ctx, m.base().commonProperties.Notice)
+		}
 	}
 }
 
diff --git a/android/variable.go b/android/variable.go
index 2763bf2..f496008 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -54,17 +54,19 @@
 			Cflags []string
 		}
 
-		Device_uses_hwc2 struct {
-			Cflags []string
-		}
-
 		Override_rs_driver struct {
 			Cflags []string
 		}
 
 		// Product_is_iot is true for Android Things devices.
 		Product_is_iot struct {
-			Cflags []string
+			Cflags       []string
+			Enabled      bool
+			Exclude_srcs []string
+			Init_rc      []string
+			Shared_libs  []string
+			Srcs         []string
+			Static_libs  []string
 		}
 
 		// treble_linker_namespaces is true when the system/vendor linker namespace separation is
@@ -184,7 +186,6 @@
 	UseGoma                    *bool `json:",omitempty"`
 	Debuggable                 *bool `json:",omitempty"`
 	Eng                        *bool `json:",omitempty"`
-	Device_uses_hwc2           *bool `json:",omitempty"`
 	Treble_linker_namespaces   *bool `json:",omitempty"`
 	Enforce_vintf_manifest     *bool `json:",omitempty"`
 	Pdk                        *bool `json:",omitempty"`
@@ -205,6 +206,9 @@
 	CFIExcludePaths *[]string `json:",omitempty"`
 	CFIIncludePaths *[]string `json:",omitempty"`
 
+	EnableXOM       *bool     `json:",omitempty"`
+	XOMExcludePaths *[]string `json:",omitempty"`
+
 	VendorPath          *string `json:",omitempty"`
 	OdmPath             *string `json:",omitempty"`
 	ProductPath         *string `json:",omitempty"`
@@ -249,7 +253,8 @@
 
 	VendorVars map[string]map[string]string `json:",omitempty"`
 
-	Ndk_abis *bool `json:",omitempty"`
+	Ndk_abis               *bool `json:",omitempty"`
+	Exclude_draft_ndk_apis *bool `json:",omitempty"`
 
 	FlattenApex *bool `json:",omitempty"`
 }
diff --git a/apex/apex.go b/apex/apex.go
index 33143d6..f412d86 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -38,7 +38,7 @@
 	// TODO(b/113082813) make this configurable using config.fs syntax
 	generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
 		Command: `echo '/ 1000 1000 0755' > ${out} && ` +
-			`echo '/manifest.json 1000 1000 0644' >> ${out} && ` +
+			`echo '/apex_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}`,
 		Description: "fs_config ${out}",
@@ -52,9 +52,10 @@
 		Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
 			`(${copy_commands}) && ` +
 			`APEXER_TOOL_PATH=${tool_path} ` +
-			`${apexer} --verbose --force --manifest ${manifest} ` +
+			`${apexer} --force --manifest ${manifest} ` +
 			`--file_contexts ${file_contexts} ` +
 			`--canned_fs_config ${canned_fs_config} ` +
+			`--payload_type image ` +
 			`--key ${key} ${image_dir} ${out} `,
 		CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}",
 			"${mke2fs}", "${resize2fs}", "${sefcontext_compile}",
@@ -62,6 +63,17 @@
 		Description: "APEX ${image_dir} => ${out}",
 	}, "tool_path", "image_dir", "copy_commands", "manifest", "file_contexts", "canned_fs_config", "key")
 
+	zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{
+		Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
+			`(${copy_commands}) && ` +
+			`APEXER_TOOL_PATH=${tool_path} ` +
+			`${apexer} --force --manifest ${manifest} ` +
+			`--payload_type zip ` +
+			`${image_dir} ${out} `,
+		CommandDeps: []string{"${apexer}", "${merge_zips}", "${soong_zip}", "${zipalign}", "${aapt2}"},
+		Description: "ZipAPEX ${image_dir} => ${out}",
+	}, "tool_path", "image_dir", "copy_commands", "manifest")
+
 	apexProtoConvertRule = pctx.AndroidStaticRule("apexProtoConvertRule",
 		blueprint.RuleParams{
 			Command:     `${aapt2} convert --output-format proto $in -o $out`,
@@ -69,13 +81,20 @@
 		})
 
 	apexBundleRule = pctx.StaticRule("apexBundleRule", blueprint.RuleParams{
-		Command:     `${zip2zip} -i $in -o $out image.img:apex/${abi}.img manifest.json:root/manifest.json AndroidManifest.xml:manifest/AndroidManifest.xml`,
+		Command: `${zip2zip} -i $in -o $out ` +
+			`apex_payload.img:apex/${abi}.img ` +
+			`apex_manifest.json:root/apex_manifest.json ` +
+			`AndroidManifest.xml:manifest/AndroidManifest.xml`,
 		CommandDeps: []string{"${zip2zip}"},
 		Description: "app bundle",
 	}, "abi")
 )
 
-var apexSuffix = ".apex"
+var imageApexSuffix = ".apex"
+var zipApexSuffix = ".zipapex"
+
+var imageApexType = "image"
+var zipApexType = "zip"
 
 type dependencyTag struct {
 	blueprint.BaseDependencyTag
@@ -117,7 +136,7 @@
 	pctx.HostBinToolVariable("zip2zip", "zip2zip")
 	pctx.HostBinToolVariable("zipalign", "zipalign")
 
-	android.RegisterModuleType("apex", apexBundleFactory)
+	android.RegisterModuleType("apex", ApexBundleFactory)
 
 	android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.TopDown("apex_deps", apexDepsMutator)
@@ -125,13 +144,6 @@
 	})
 }
 
-// maps a module name to set of apex bundle names that the module should be built for
-func apexBundleNamesFor(config android.Config) map[string]map[string]bool {
-	return config.Once("apexBundleNames", func() interface{} {
-		return make(map[string]map[string]bool)
-	}).(map[string]map[string]bool)
-}
-
 // Mark the direct and transitive dependencies of apex bundles so that they
 // can be built for the apex bundles.
 func apexDepsMutator(mctx android.TopDownMutatorContext) {
@@ -140,12 +152,9 @@
 		mctx.WalkDeps(func(child, parent android.Module) bool {
 			if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() {
 				moduleName := mctx.OtherModuleName(am) + "-" + am.Target().String()
-				bundleNames, ok := apexBundleNamesFor(mctx.Config())[moduleName]
-				if !ok {
-					bundleNames = make(map[string]bool)
-					apexBundleNamesFor(mctx.Config())[moduleName] = bundleNames
-				}
-				bundleNames[apexBundleName] = true
+				// If the parent is apexBundle, this child is directly depended.
+				_, directDep := parent.(*apexBundle)
+				android.BuildModuleForApexBundle(mctx, moduleName, apexBundleName, directDep)
 				return true
 			} else {
 				return false
@@ -158,7 +167,8 @@
 func apexMutator(mctx android.BottomUpMutatorContext) {
 	if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
 		moduleName := mctx.ModuleName() + "-" + am.Target().String()
-		if bundleNames, ok := apexBundleNamesFor(mctx.Config())[moduleName]; ok {
+		bundleNames := android.GetApexBundlesForModule(mctx, moduleName)
+		if len(bundleNames) > 0 {
 			variations := []string{"platform"}
 			for bn := range bundleNames {
 				variations = append(variations, bn)
@@ -181,7 +191,7 @@
 
 type apexBundleProperties struct {
 	// Json manifest file describing meta info of this APEX bundle. Default:
-	// "manifest.json"
+	// "apex_manifest.json"
 	Manifest *string
 
 	// Determines the file contexts file for setting security context to each file in this APEX bundle.
@@ -205,6 +215,10 @@
 	// Name of the apex_key module that provides the private key to sign APEX
 	Key *string
 
+	// The type of APEX to build. Controls what the APEX payload is. Either
+	// 'image', 'zip' or 'both'. Default: 'image'.
+	Payload_type *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
@@ -252,6 +266,56 @@
 	javaSharedLib
 )
 
+type apexPackaging int
+
+const (
+	imageApex apexPackaging = iota
+	zipApex
+	both
+)
+
+func (a apexPackaging) image() bool {
+	switch a {
+	case imageApex, both:
+		return true
+	}
+	return false
+}
+
+func (a apexPackaging) zip() bool {
+	switch a {
+	case zipApex, both:
+		return true
+	}
+	return false
+}
+
+func (a apexPackaging) suffix() string {
+	switch a {
+	case imageApex:
+		return imageApexSuffix
+	case zipApex:
+		return zipApexSuffix
+	case both:
+		panic(fmt.Errorf("must be either zip or image"))
+	default:
+		panic(fmt.Errorf("unkonwn APEX type %d", a))
+	}
+}
+
+func (a apexPackaging) name() string {
+	switch a {
+	case imageApex:
+		return imageApexType
+	case zipApex:
+		return zipApexType
+	case both:
+		panic(fmt.Errorf("must be either zip or image"))
+	default:
+		panic(fmt.Errorf("unkonwn APEX type %d", a))
+	}
+}
+
 func (class apexFileClass) NameInMake() string {
 	switch class {
 	case etc:
@@ -281,8 +345,10 @@
 
 	properties apexBundleProperties
 
+	apexTypes apexPackaging
+
 	bundleModuleFile android.WritablePath
-	outputFile       android.WritablePath
+	outputFiles      map[apexPackaging]android.WritablePath
 	installDir       android.OutputPath
 
 	// list of files to be included in this apex
@@ -301,6 +367,7 @@
 		{Mutator: "arch", Variation: arch},
 		{Mutator: "image", Variation: "core"},
 		{Mutator: "link", Variation: "shared"},
+		{Mutator: "version", Variation: ""}, // "" is the non-stub variant
 	}, sharedLibTag, native_shared_libs...)
 
 	ctx.AddFarVariationDependencies([]blueprint.Variation{
@@ -390,6 +457,10 @@
 	}
 }
 
+func (a *apexBundle) Srcs() android.Paths {
+	return android.Paths{a.outputFiles[imageApex]}
+}
+
 func getCopyManifestForNativeLibrary(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
 	// Decide the APEX-local directory by the multilib of the library
 	// In the future, we may query this to the module.
@@ -431,6 +502,17 @@
 	var keyFile android.Path
 	var certificate java.Certificate
 
+	if a.properties.Payload_type == nil || *a.properties.Payload_type == "image" {
+		a.apexTypes = imageApex
+	} else if *a.properties.Payload_type == "zip" {
+		a.apexTypes = zipApex
+	} else if *a.properties.Payload_type == "both" {
+		a.apexTypes = both
+	} else {
+		ctx.PropertyErrorf("type", "%q is not one of \"image\", \"zip\", or \"both\".", *a.properties.Payload_type)
+		return
+	}
+
 	ctx.WalkDeps(func(child, parent android.Module) bool {
 		if _, ok := parent.(*apexBundle); ok {
 			// direct dependencies
@@ -492,6 +574,9 @@
 			// indirect dependencies
 			if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() && am.IsInstallableToApex() {
 				if cc, ok := child.(*cc.Module); ok {
+					if cc.IsStubs() || cc.HasStubsVariants() {
+						return false
+					}
 					depName := ctx.OtherModuleName(child)
 					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
 					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeSharedLib})
@@ -535,14 +620,20 @@
 	a.flattened = ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
 	a.installDir = android.PathForModuleInstall(ctx, "apex")
 	a.filesInfo = filesInfo
-	if ctx.Config().FlattenApex() {
-		a.buildFlattenedApex(ctx)
-	} else {
-		a.buildUnflattenedApex(ctx, keyFile, certificate)
+
+	if a.apexTypes.zip() {
+		a.buildUnflattenedApex(ctx, keyFile, certificate, zipApex)
+	}
+	if a.apexTypes.image() {
+		if ctx.Config().FlattenApex() {
+			a.buildFlattenedApex(ctx)
+		} else {
+			a.buildUnflattenedApex(ctx, keyFile, certificate, imageApex)
+		}
 	}
 }
 
-func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile android.Path, certificate java.Certificate) {
+func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile android.Path, certificate java.Certificate, apexType apexPackaging) {
 	cert := String(a.properties.Certificate)
 	if cert != "" && android.SrcIsModule(cert) == "" {
 		defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
@@ -555,45 +646,19 @@
 		certificate = java.Certificate{pem, key}
 	}
 
-	// files and dirs that will be created in apex
-	var readOnlyPaths []string
-	var executablePaths []string // this also includes dirs
-	for _, f := range a.filesInfo {
-		pathInApex := filepath.Join(f.installDir, f.builtFile.Base())
-		if f.installDir == "bin" {
-			executablePaths = append(executablePaths, pathInApex)
-		} else {
-			readOnlyPaths = append(readOnlyPaths, pathInApex)
-		}
-		if !android.InList(f.installDir, executablePaths) {
-			executablePaths = append(executablePaths, f.installDir)
+	manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json"))
+
+	var abis []string
+	for _, target := range ctx.MultiTargets() {
+		if len(target.Arch.Abi) > 0 {
+			abis = append(abis, target.Arch.Abi[0])
 		}
 	}
-	sort.Strings(readOnlyPaths)
-	sort.Strings(executablePaths)
-	cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config")
-	ctx.Build(pctx, android.BuildParams{
-		Rule:        generateFsConfig,
-		Output:      cannedFsConfig,
-		Description: "generate fs config",
-		Args: map[string]string{
-			"ro_paths":   strings.Join(readOnlyPaths, " "),
-			"exec_paths": strings.Join(executablePaths, " "),
-		},
-	})
 
-	manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "manifest.json"))
+	abis = android.FirstUniqueStrings(abis)
 
-	fcName := proptools.StringDefault(a.properties.File_contexts, ctx.ModuleName())
-	fileContextsPath := "system/sepolicy/apex/" + fcName + "-file_contexts"
-	fileContextsOptionalPath := android.ExistentPathForSource(ctx, fileContextsPath)
-	if !fileContextsOptionalPath.Valid() {
-		ctx.ModuleErrorf("Cannot find file_contexts file: %q", fileContextsPath)
-		return
-	}
-	fileContexts := fileContextsOptionalPath.Path()
-
-	unsignedOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+apexSuffix+".unsigned")
+	suffix := apexType.suffix()
+	unsignedOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+suffix+".unsigned")
 
 	filesToCopy := []android.Path{}
 	for _, f := range a.filesInfo {
@@ -603,74 +668,134 @@
 	copyCommands := []string{}
 	for i, src := range filesToCopy {
 		dest := filepath.Join(a.filesInfo[i].installDir, src.Base())
-		dest_path := filepath.Join(android.PathForModuleOut(ctx, "image").String(), dest)
+		dest_path := filepath.Join(android.PathForModuleOut(ctx, "image"+suffix).String(), dest)
 		copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(dest_path))
 		copyCommands = append(copyCommands, "cp "+src.String()+" "+dest_path)
 	}
 	implicitInputs := append(android.Paths(nil), filesToCopy...)
-	implicitInputs = append(implicitInputs, cannedFsConfig, manifest, fileContexts, keyFile)
+	implicitInputs = append(implicitInputs, manifest)
+
 	outHostBinDir := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin").String()
 	prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin")
-	ctx.Build(pctx, android.BuildParams{
-		Rule:        apexRule,
-		Implicits:   implicitInputs,
-		Output:      unsignedOutputFile,
-		Description: "apex",
-		Args: map[string]string{
-			"tool_path":        outHostBinDir + ":" + prebuiltSdkToolsBinDir,
-			"image_dir":        android.PathForModuleOut(ctx, "image").String(),
-			"copy_commands":    strings.Join(copyCommands, " && "),
-			"manifest":         manifest.String(),
-			"file_contexts":    fileContexts.String(),
-			"canned_fs_config": cannedFsConfig.String(),
-			"key":              keyFile.String(),
-		},
-	})
 
-	var abis []string
-	for _, target := range ctx.MultiTargets() {
-		abis = append(abis, target.Arch.Abi[0])
+	if apexType.image() {
+		// files and dirs that will be created in APEX
+		var readOnlyPaths []string
+		var executablePaths []string // this also includes dirs
+		for _, f := range a.filesInfo {
+			pathInApex := filepath.Join(f.installDir, f.builtFile.Base())
+			if f.installDir == "bin" {
+				executablePaths = append(executablePaths, pathInApex)
+			} else {
+				readOnlyPaths = append(readOnlyPaths, pathInApex)
+			}
+			dir := f.installDir
+			for !android.InList(dir, executablePaths) && dir != "" {
+				executablePaths = append(executablePaths, dir)
+				dir, _ = filepath.Split(dir) // move up to the parent
+				if len(dir) > 0 {
+					// remove trailing slash
+					dir = dir[:len(dir)-1]
+				}
+			}
+		}
+		sort.Strings(readOnlyPaths)
+		sort.Strings(executablePaths)
+		cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config")
+		ctx.Build(pctx, android.BuildParams{
+			Rule:        generateFsConfig,
+			Output:      cannedFsConfig,
+			Description: "generate fs config",
+			Args: map[string]string{
+				"ro_paths":   strings.Join(readOnlyPaths, " "),
+				"exec_paths": strings.Join(executablePaths, " "),
+			},
+		})
+
+		fcName := proptools.StringDefault(a.properties.File_contexts, ctx.ModuleName())
+		fileContextsPath := "system/sepolicy/apex/" + fcName + "-file_contexts"
+		fileContextsOptionalPath := android.ExistentPathForSource(ctx, fileContextsPath)
+		if !fileContextsOptionalPath.Valid() {
+			ctx.ModuleErrorf("Cannot find file_contexts file: %q", fileContextsPath)
+			return
+		}
+		fileContexts := fileContextsOptionalPath.Path()
+
+		// Additional implicit inputs.
+		implicitInputs = append(implicitInputs, cannedFsConfig, fileContexts, keyFile)
+
+		ctx.Build(pctx, android.BuildParams{
+			Rule:        apexRule,
+			Implicits:   implicitInputs,
+			Output:      unsignedOutputFile,
+			Description: "apex (" + apexType.name() + ")",
+			Args: map[string]string{
+				"tool_path":        outHostBinDir + ":" + prebuiltSdkToolsBinDir,
+				"image_dir":        android.PathForModuleOut(ctx, "image"+suffix).String(),
+				"copy_commands":    strings.Join(copyCommands, " && "),
+				"manifest":         manifest.String(),
+				"file_contexts":    fileContexts.String(),
+				"canned_fs_config": cannedFsConfig.String(),
+				"key":              keyFile.String(),
+			},
+		})
+
+		apexProtoFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".pb"+suffix)
+		bundleModuleFile := android.PathForModuleOut(ctx, ctx.ModuleName()+suffix+"-base.zip")
+		a.bundleModuleFile = bundleModuleFile
+
+		ctx.Build(pctx, android.BuildParams{
+			Rule:        apexProtoConvertRule,
+			Input:       unsignedOutputFile,
+			Output:      apexProtoFile,
+			Description: "apex proto convert",
+		})
+
+		ctx.Build(pctx, android.BuildParams{
+			Rule:        apexBundleRule,
+			Input:       apexProtoFile,
+			Output:      a.bundleModuleFile,
+			Description: "apex bundle module",
+			Args: map[string]string{
+				"abi": strings.Join(abis, "."),
+			},
+		})
+	} else {
+		ctx.Build(pctx, android.BuildParams{
+			Rule:        zipApexRule,
+			Implicits:   implicitInputs,
+			Output:      unsignedOutputFile,
+			Description: "apex (" + apexType.name() + ")",
+			Args: map[string]string{
+				"tool_path":     outHostBinDir + ":" + prebuiltSdkToolsBinDir,
+				"image_dir":     android.PathForModuleOut(ctx, "image"+suffix).String(),
+				"copy_commands": strings.Join(copyCommands, " && "),
+				"manifest":      manifest.String(),
+			},
+		})
 	}
-	abis = android.FirstUniqueStrings(abis)
 
-	apexProtoFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".pb"+apexSuffix)
-	bundleModuleFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"-base.zip")
-	a.bundleModuleFile = bundleModuleFile
-
-	ctx.Build(pctx, android.BuildParams{
-		Rule:        apexProtoConvertRule,
-		Input:       unsignedOutputFile,
-		Output:      apexProtoFile,
-		Description: "apex proto convert",
-	})
-
-	ctx.Build(pctx, android.BuildParams{
-		Rule:        apexBundleRule,
-		Input:       apexProtoFile,
-		Output:      bundleModuleFile,
-		Description: "apex bundle module",
-		Args: map[string]string{
-			"abi": strings.Join(abis, "."),
-		},
-	})
-
-	a.outputFile = android.PathForModuleOut(ctx, ctx.ModuleName()+apexSuffix)
+	a.outputFiles[apexType] = android.PathForModuleOut(ctx, ctx.ModuleName()+suffix)
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        java.Signapk,
 		Description: "signapk",
-		Output:      a.outputFile,
+		Output:      a.outputFiles[apexType],
 		Input:       unsignedOutputFile,
 		Args: map[string]string{
 			"certificates": strings.Join([]string{certificate.Pem.String(), certificate.Key.String()}, " "),
+			"flags":        "-a 4096", //alignment
 		},
 	})
+
+	// Install to $OUT/soong/{target,host}/.../apex
+	ctx.InstallFile(android.PathForModuleInstall(ctx, "apex"), ctx.ModuleName()+suffix, a.outputFiles[apexType])
 }
 
 func (a *apexBundle) buildFlattenedApex(ctx android.ModuleContext) {
-	// For flattened APEX, do nothing but make sure that manifest.json file is also copied along
+	// For flattened APEX, do nothing but make sure that apex_manifest.json file is also copied along
 	// with other ordinary files.
-	manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "manifest.json"))
-	a.filesInfo = append(a.filesInfo, apexFile{manifest, ctx.ModuleName() + ".manifest.json", android.Common, ".", etc})
+	manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json"))
+	a.filesInfo = append(a.filesInfo, apexFile{manifest, ctx.ModuleName() + ".apex_manifest.json", android.Common, ".", etc})
 
 	for _, fi := range a.filesInfo {
 		dir := filepath.Join("apex", ctx.ModuleName(), fi.installDir)
@@ -679,7 +804,24 @@
 }
 
 func (a *apexBundle) AndroidMk() android.AndroidMkData {
-	if a.flattened {
+	writers := []android.AndroidMkData{}
+	if a.apexTypes.image() {
+		writers = append(writers, a.androidMkForType(imageApex))
+	}
+	if a.apexTypes.zip() {
+		writers = append(writers, a.androidMkForType(zipApex))
+	}
+	return android.AndroidMkData{
+		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+			for _, data := range writers {
+				data.Custom(w, name, prefix, moduleDir, data)
+			}
+		}}
+}
+
+func (a *apexBundle) androidMkForType(apexType apexPackaging) android.AndroidMkData {
+	// Only image APEXes can be flattened.
+	if a.flattened && apexType.image() {
 		return android.AndroidMkData{
 			Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
 				moduleNames := []string{}
@@ -718,29 +860,37 @@
 	} else {
 		return android.AndroidMkData{
 			Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+				// zip-apex is the less common type so have the name refer to the image-apex
+				// only and use {name}.zip if you want the zip-apex
+				if apexType == zipApex && a.apexTypes == both {
+					name = name + ".zip"
+				}
 				fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
 				fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
 				fmt.Fprintln(w, "LOCAL_MODULE :=", name)
 				fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class?
-				fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFile.String())
+				fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFiles[apexType].String())
 				fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", a.installDir.RelPathString()))
-				fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name+apexSuffix)
+				fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name+apexType.suffix())
 				fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", String(a.properties.Key))
 				fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
 
-				fmt.Fprintln(w, "ALL_MODULES.$(LOCAL_MODULE).BUNDLE :=", a.bundleModuleFile.String())
+				if apexType == imageApex {
+					fmt.Fprintln(w, "ALL_MODULES.$(LOCAL_MODULE).BUNDLE :=", a.bundleModuleFile.String())
+				}
 			}}
 	}
 }
 
-func apexBundleFactory() android.Module {
-	module := &apexBundle{}
+func ApexBundleFactory() android.Module {
+	module := &apexBundle{
+		outputFiles: map[apexPackaging]android.WritablePath{},
+	}
 	module.AddProperties(&module.properties)
-	module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase,
-		class android.OsClass) bool {
+	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.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
 	return module
 }
diff --git a/apex/apex_test.go b/apex/apex_test.go
new file mode 100644
index 0000000..c01c40a
--- /dev/null
+++ b/apex/apex_test.go
@@ -0,0 +1,457 @@
+// Copyright 2018 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 apex
+
+import (
+	"android/soong/android"
+	"android/soong/cc"
+	"io/ioutil"
+	"os"
+	"strings"
+	"testing"
+)
+
+func testApex(t *testing.T, bp string) *android.TestContext {
+	config, buildDir := setup(t)
+	defer teardown(buildDir)
+
+	ctx := android.NewTestArchContext()
+	ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(ApexBundleFactory))
+	ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apexKeyFactory))
+
+	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.TopDown("apex_deps", apexDepsMutator)
+		ctx.BottomUp("apex", apexMutator)
+	})
+
+	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
+	ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(cc.LibrarySharedFactory))
+	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
+	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
+	ctx.RegisterModuleType("prebuilt_etc", android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory))
+	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.BottomUp("link", cc.LinkageMutator).Parallel()
+		ctx.BottomUp("version", cc.VersionMutator).Parallel()
+		ctx.BottomUp("begin", cc.BeginMutator).Parallel()
+	})
+
+	ctx.Register()
+
+	bp = bp + `
+		toolchain_library {
+			name: "libcompiler_rt-extras",
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libatomic",
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libgcc",
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libclang_rt.builtins-aarch64-android",
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libclang_rt.builtins-arm-android",
+			src: "",
+		}
+
+		cc_object {
+			name: "crtbegin_so",
+			stl: "none",
+		}
+
+		cc_object {
+			name: "crtend_so",
+			stl: "none",
+		}
+
+	`
+
+	ctx.MockFileSystem(map[string][]byte{
+		"Android.bp":                                []byte(bp),
+		"testkey.avbpubkey":                         nil,
+		"testkey.pem":                               nil,
+		"build/target/product/security":             nil,
+		"apex_manifest.json":                        nil,
+		"system/sepolicy/apex/myapex-file_contexts": nil,
+		"mylib.cpp":                                 nil,
+		"myprebuilt":                                nil,
+	})
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	android.FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	android.FailIfErrored(t, errs)
+
+	return ctx
+}
+
+func setup(t *testing.T) (config android.Config, buildDir string) {
+	buildDir, err := ioutil.TempDir("", "soong_apex_test")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	config = android.TestArchConfig(buildDir, nil)
+
+	return
+}
+
+func teardown(buildDir string) {
+	os.RemoveAll(buildDir)
+}
+
+// ensure that 'result' contains 'expected'
+func ensureContains(t *testing.T, result string, expected string) {
+	if !strings.Contains(result, expected) {
+		t.Errorf("%q is not found in %q", expected, result)
+	}
+}
+
+// ensures that 'result' does not contain 'notExpected'
+func ensureNotContains(t *testing.T, result string, notExpected string) {
+	if strings.Contains(result, notExpected) {
+		t.Errorf("%q is found in %q", notExpected, result)
+	}
+}
+
+func ensureListContains(t *testing.T, result []string, expected string) {
+	if !android.InList(expected, result) {
+		t.Errorf("%q is not found in %v", expected, result)
+	}
+}
+
+func ensureListNotContains(t *testing.T, result []string, notExpected string) {
+	if android.InList(notExpected, result) {
+		t.Errorf("%q is found in %v", notExpected, result)
+	}
+}
+
+// Minimal test
+func TestBasicApex(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			native_shared_libs: ["mylib"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "mylib",
+			srcs: ["mylib.cpp"],
+			shared_libs: ["mylib2"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library {
+			name: "mylib2",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+
+	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+
+	// Ensure that main rule creates an output
+	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
+
+	// Ensure that apex variant is created for the direct dep
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
+
+	// Ensure that apex variant is created for the indirect dep
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
+
+	// Ensure that both direct and indirect deps are copied into apex
+	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
+	ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so")
+}
+
+func TestBasicZipApex(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			payload_type: "zip",
+			native_shared_libs: ["mylib"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "mylib",
+			srcs: ["mylib.cpp"],
+			shared_libs: ["mylib2"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library {
+			name: "mylib2",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+
+	zipApexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("zipApexRule")
+	copyCmds := zipApexRule.Args["copy_commands"]
+
+	// Ensure that main rule creates an output
+	ensureContains(t, zipApexRule.Output.String(), "myapex.zipapex.unsigned")
+
+	// Ensure that APEX variant is created for the direct dep
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
+
+	// Ensure that APEX variant is created for the indirect dep
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
+
+	// Ensure that both direct and indirect deps are copied into apex
+	ensureContains(t, copyCmds, "image.zipapex/lib64/mylib.so")
+	ensureContains(t, copyCmds, "image.zipapex/lib64/mylib2.so")
+}
+
+func TestApexWithStubs(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			native_shared_libs: ["mylib", "mylib3"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "mylib",
+			srcs: ["mylib.cpp"],
+			shared_libs: ["mylib2", "mylib3"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library {
+			name: "mylib2",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+			stubs: {
+				versions: ["1", "2", "3"],
+			},
+		}
+
+		cc_library {
+			name: "mylib3",
+			srcs: ["mylib.cpp"],
+			shared_libs: ["mylib4"],
+			system_shared_libs: [],
+			stl: "none",
+			stubs: {
+				versions: ["10", "11", "12"],
+			},
+		}
+
+		cc_library {
+			name: "mylib4",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+
+	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+
+	// Ensure that direct non-stubs dep is always included
+	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
+
+	// Ensure that indirect stubs dep is not included
+	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
+
+	// Ensure that direct stubs dep is included
+	ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
+
+	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
+
+	// Ensure that mylib is linking with the latest version of stubs for mylib2
+	ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_3_myapex/mylib2.so")
+	// ... and not linking to the non-stub (impl) variant of mylib2
+	ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_myapex/mylib2.so")
+
+	// Ensure that mylib is linking with the non-stub (impl) of mylib3 (because mylib3 is in the same apex)
+	ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_myapex/mylib3.so")
+	// .. and not linking to the stubs variant of mylib3
+	ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12_myapex/mylib3.so")
+}
+
+func TestApexWithSystemLibsStubs(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			native_shared_libs: ["mylib", "mylib_shared", "libdl", "libm"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "mylib",
+			srcs: ["mylib.cpp"],
+			shared_libs: ["libdl#27"],
+			stl: "none",
+		}
+
+		cc_library_shared {
+			name: "mylib_shared",
+			srcs: ["mylib.cpp"],
+			shared_libs: ["libdl#27"],
+			stl: "none",
+		}
+
+		cc_library {
+			name: "libc",
+			no_libgcc: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+			stubs: {
+				versions: ["27", "28", "29"],
+			},
+		}
+
+		cc_library {
+			name: "libm",
+			no_libgcc: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+			stubs: {
+				versions: ["27", "28", "29"],
+			},
+		}
+
+		cc_library {
+			name: "libdl",
+			no_libgcc: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+			stubs: {
+				versions: ["27", "28", "29"],
+			},
+		}
+	`)
+
+	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+
+	// Ensure that mylib, libm, libdl are included.
+	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
+	ensureContains(t, copyCmds, "image.apex/lib64/libm.so")
+	ensureContains(t, copyCmds, "image.apex/lib64/libdl.so")
+
+	// Ensure that libc is not included (since it has stubs and not listed in native_shared_libs)
+	ensureNotContains(t, copyCmds, "image.apex/lib64/libc.so")
+
+	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
+	mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
+	mylibSharedCFlags := ctx.ModuleForTests("mylib_shared", "android_arm64_armv8-a_shared_myapex").Rule("cc").Args["cFlags"]
+
+	// For dependency to libc
+	// Ensure that mylib is linking with the latest version of stubs
+	ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_29_myapex/libc.so")
+	// ... and not linking to the non-stub (impl) variant
+	ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_myapex/libc.so")
+	// ... Cflags from stub is correctly exported to mylib
+	ensureContains(t, mylibCFlags, "__LIBC_API__=29")
+	ensureContains(t, mylibSharedCFlags, "__LIBC_API__=29")
+
+	// For dependency to libm
+	// Ensure that mylib is linking with the non-stub (impl) variant
+	ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_myapex/libm.so")
+	// ... and not linking to the stub variant
+	ensureNotContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_29_myapex/libm.so")
+	// ... and is not compiling with the stub
+	ensureNotContains(t, mylibCFlags, "__LIBM_API__=29")
+	ensureNotContains(t, mylibSharedCFlags, "__LIBM_API__=29")
+
+	// For dependency to libdl
+	// Ensure that mylib is linking with the specified version of stubs
+	ensureContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_27_myapex/libdl.so")
+	// ... and not linking to the other versions of stubs
+	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_28_myapex/libdl.so")
+	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_29_myapex/libdl.so")
+	// ... and not linking to the non-stub (impl) variant
+	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_myapex/libdl.so")
+	// ... Cflags from stub is correctly exported to mylib
+	ensureContains(t, mylibCFlags, "__LIBDL_API__=27")
+	ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27")
+}
+
+func TestFilesInSubDir(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			prebuilts: ["myetc"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		prebuilt_etc {
+			name: "myetc",
+			src: "myprebuilt",
+			sub_dir: "foo/bar",
+		}
+	`)
+
+	generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("generateFsConfig")
+	dirs := strings.Split(generateFsRule.Args["exec_paths"], " ")
+
+	// Ensure that etc, etc/foo, and etc/foo/bar are all listed
+	ensureListContains(t, dirs, "etc")
+	ensureListContains(t, dirs, "etc/foo")
+	ensureListContains(t, dirs, "etc/foo/bar")
+}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 5e38973..f5e04bb 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -151,6 +151,7 @@
 		ret.Class = "HEADER_LIBRARIES"
 	}
 
+	ret.DistFile = library.distFile
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
 		library.androidMkWriteExportedFlags(w)
 		fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES := ")
@@ -194,6 +195,7 @@
 	ctx.subAndroidMk(ret, binary.baseInstaller)
 
 	ret.Class = "EXECUTABLES"
+	ret.DistFile = binary.distFile
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
 		fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", binary.unstrippedOutputFile.String())
 		if len(binary.symlinks) > 0 {
diff --git a/cc/binary.go b/cc/binary.go
index 15db2ad..6923f2b 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -88,6 +88,9 @@
 
 	// Output archive of gcno coverage information
 	coverageOutputFile android.OptionalPath
+
+	// Location of the file that should be copied to dist dir when requested
+	distFile android.OptionalPath
 }
 
 var _ linker = (*binaryDecorator)(nil)
@@ -330,10 +333,23 @@
 			flagsToBuilderFlags(flags), afterPrefixSymbols)
 	}
 
-	if Bool(binary.baseLinker.Properties.Use_version_lib) && ctx.Host() {
-		versionedOutputFile := outputFile
-		outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
-		binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+	if Bool(binary.baseLinker.Properties.Use_version_lib) {
+		if ctx.Host() {
+			versionedOutputFile := outputFile
+			outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
+			binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+		} else {
+			versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
+			binary.distFile = android.OptionalPathForPath(versionedOutputFile)
+
+			if binary.stripper.needsStrip(ctx) {
+				out := android.PathForModuleOut(ctx, "versioned-stripped", fileName)
+				binary.distFile = android.OptionalPathForPath(out)
+				binary.stripper.strip(ctx, versionedOutputFile, out, builderFlags)
+			}
+
+			binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+		}
 	}
 
 	if ctx.Os() == android.LinuxBionic && !binary.static() {
diff --git a/cc/cc.go b/cc/cc.go
index ed65aa6..b8cbf26 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -39,7 +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("version", VersionMutator).Parallel()
 		ctx.BottomUp("begin", BeginMutator).Parallel()
 	})
 
@@ -53,6 +53,9 @@
 		ctx.TopDown("cfi_deps", sanitizerDepsMutator(cfi))
 		ctx.BottomUp("cfi", sanitizerMutator(cfi)).Parallel()
 
+		ctx.TopDown("scs_deps", sanitizerDepsMutator(scs))
+		ctx.BottomUp("scs", sanitizerMutator(scs)).Parallel()
+
 		ctx.TopDown("tsan_deps", sanitizerDepsMutator(tsan))
 		ctx.BottomUp("tsan", sanitizerMutator(tsan)).Parallel()
 
@@ -244,6 +247,8 @@
 	baseModuleName() string
 	getVndkExtendsModuleName() string
 	isPgoCompile() bool
+	useClangLld(actx ModuleContext) bool
+	isApex() bool
 }
 
 type ModuleContext interface {
@@ -284,6 +289,7 @@
 	linkerDeps(ctx DepsContext, deps Deps) Deps
 	linkerFlags(ctx ModuleContext, flags Flags) Flags
 	linkerProps() []interface{}
+	useClangLld(actx ModuleContext) bool
 
 	link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path
 	appendLdflags([]string)
@@ -303,6 +309,8 @@
 	library bool
 
 	reexportFlags bool
+
+	explicitlyVersioned bool
 }
 
 var (
@@ -357,6 +365,7 @@
 	vndkdep   *vndkdep
 	lto       *lto
 	pgo       *pgo
+	xom       *xom
 
 	androidMkSharedLibDeps []string
 
@@ -414,6 +423,9 @@
 	if c.pgo != nil {
 		c.AddProperties(c.pgo.props()...)
 	}
+	if c.xom != nil {
+		c.AddProperties(c.xom.props()...)
+	}
 	for _, feature := range c.features {
 		c.AddProperties(feature.props()...)
 	}
@@ -502,6 +514,20 @@
 	return c.ModuleBase.InstallInRecovery()
 }
 
+func (c *Module) IsStubs() bool {
+	if library, ok := c.linker.(*libraryDecorator); ok {
+		return library.buildStubs()
+	}
+	return false
+}
+
+func (c *Module) HasStubsVariants() bool {
+	if library, ok := c.linker.(*libraryDecorator); ok {
+		return len(library.Properties.Stubs.Versions) > 0
+	}
+	return false
+}
+
 type baseModuleContext struct {
 	android.BaseContext
 	moduleContextImpl
@@ -628,6 +654,10 @@
 	return ""
 }
 
+func (ctx *moduleContextImpl) useClangLld(actx ModuleContext) bool {
+	return ctx.mod.linker.useClangLld(actx)
+}
+
 func (ctx *moduleContextImpl) baseModuleName() string {
 	return ctx.mod.ModuleBase.BaseModuleName()
 }
@@ -636,6 +666,11 @@
 	return ctx.mod.getVndkExtendsModuleName()
 }
 
+// Tests if this module is built for APEX
+func (ctx *moduleContextImpl) isApex() bool {
+	return ctx.mod.ApexName() != ""
+}
+
 func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
 	return &Module{
 		hod:      hod,
@@ -655,6 +690,7 @@
 	module.vndkdep = &vndkdep{}
 	module.lto = &lto{}
 	module.pgo = &pgo{}
+	module.xom = &xom{}
 	return module
 }
 
@@ -771,6 +807,9 @@
 	if c.pgo != nil {
 		flags = c.pgo.flags(ctx, flags)
 	}
+	if c.xom != nil {
+		flags = c.xom.flags(ctx, flags)
+	}
 	for _, feature := range c.features {
 		flags = feature.flags(ctx, flags)
 	}
@@ -1064,6 +1103,30 @@
 		{Mutator: "link", Variation: "static"},
 	}, lateStaticDepTag, deps.LateStaticLibs...)
 
+	addSharedLibDependencies := func(depTag dependencyTag, name string, version string) {
+		var variations []blueprint.Variation
+		variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"})
+		versionVariantAvail := ctx.Os() == android.Android && !ctx.useVndk() && !c.inRecovery()
+		if version != "" && versionVariantAvail {
+			// Version is explicitly specified. i.e. libFoo#30
+			variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
+			depTag.explicitlyVersioned = true
+		}
+		actx.AddVariationDependencies(variations, depTag, name)
+
+		// If the version is not specified, add dependency to the latest stubs library.
+		// The stubs library will be used when the depending module is built for APEX and
+		// the dependent module is not in the same APEX.
+		latestVersion := latestStubsVersionFor(actx.Config(), name)
+		if version == "" && latestVersion != "" && versionVariantAvail {
+			actx.AddVariationDependencies([]blueprint.Variation{
+				{Mutator: "link", Variation: "shared"},
+				{Mutator: "version", Variation: latestVersion},
+			}, depTag, name)
+			// Note that depTag.explicitlyVersioned is false in this case.
+		}
+	}
+
 	// shared lib names without the #version suffix
 	var sharedLibNames []string
 
@@ -1074,29 +1137,17 @@
 		if inList(lib, deps.ReexportSharedLibHeaders) {
 			depTag = sharedExportDepTag
 		}
-		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)
+		addSharedLibDependencies(depTag, name, version)
 	}
 
 	for _, lib := range deps.LateSharedLibs {
-		name, version := stubsLibNameAndVersion(lib)
-		if inList(name, sharedLibNames) {
+		if inList(lib, 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)
+		addSharedLibDependencies(lateSharedDepTag, lib, "")
 	}
 
 	actx.AddVariationDependencies([]blueprint.Variation{
@@ -1272,7 +1323,8 @@
 		}
 		depIsDoubleLoadable := Bool(to.VendorProperties.Double_loadable)
 		if !depIsLlndk && !depIsVndkSp && !depIsDoubleLoadable && depIsVndk {
-			ctx.ModuleErrorf("links VNDK library %q that isn't double_loadable.",
+			ctx.ModuleErrorf("links VNDK library %q that isn't double loadable (not also LL-NDK, "+
+				"VNDK-SP, or explicitly marked as 'double_loadable').",
 				ctx.OtherModuleName(to))
 		}
 	}
@@ -1354,7 +1406,53 @@
 				return
 			}
 		}
+
+		// Extract explicitlyVersioned field from the depTag and reset it inside the struct.
+		// Otherwise, sharedDepTag and lateSharedDepTag with explicitlyVersioned set to true
+		// won't be matched to sharedDepTag and lateSharedDepTag.
+		explicitlyVersioned := false
+		if t, ok := depTag.(dependencyTag); ok {
+			explicitlyVersioned = t.explicitlyVersioned
+			t.explicitlyVersioned = false
+			depTag = t
+		}
+
 		if t, ok := depTag.(dependencyTag); ok && t.library {
+			if dependentLibrary, ok := ccDep.linker.(*libraryDecorator); ok {
+				depIsStubs := dependentLibrary.buildStubs()
+				depHasStubs := ccDep.HasStubsVariants()
+				depNameWithTarget := depName + "-" + ccDep.Target().String()
+				depInSameApex := android.DirectlyInApex(ctx.Config(), c.ApexName(), depNameWithTarget)
+				depInPlatform := !android.DirectlyInAnyApex(ctx.Config(), depNameWithTarget)
+
+				var useThisDep bool
+				if depIsStubs && explicitlyVersioned {
+					// Always respect dependency to the versioned stubs (i.e. libX#10)
+					useThisDep = true
+				} else if !depHasStubs {
+					// Use non-stub variant if that is the only choice
+					// (i.e. depending on a lib without stubs.version property)
+					useThisDep = true
+				} else if c.IsForPlatform() {
+					// If not building for APEX, use stubs only when it is from
+					// an APEX (and not from platform)
+					useThisDep = (depInPlatform != depIsStubs)
+					if c.inRecovery() {
+						// However, for recovery modules, since there is no APEX there,
+						// always link to non-stub variant
+						useThisDep = !depIsStubs
+					}
+				} else {
+					// If building for APEX, use stubs only when it is not from
+					// the same APEX
+					useThisDep = (depInSameApex != depIsStubs)
+				}
+
+				if !useThisDep {
+					return // stop processing this dep
+				}
+			}
+
 			if i, ok := ccDep.linker.(exportedFlagsProducer); ok {
 				flags := i.exportedFlags()
 				deps := i.exportedFlagsDeps()
@@ -1638,6 +1736,7 @@
 		&VndkProperties{},
 		&LTOProperties{},
 		&PgoProperties{},
+		&XomProperties{},
 		&android.ProtoProperties{},
 	)
 
@@ -1738,6 +1837,7 @@
 
 	// Sanity check
 	vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
+	productSpecific := mctx.ProductSpecific()
 
 	if m.VendorProperties.Vendor_available != nil && vendorSpecific {
 		mctx.PropertyErrorf("vendor_available",
@@ -1747,6 +1847,11 @@
 
 	if vndkdep := m.vndkdep; vndkdep != nil {
 		if vndkdep.isVndk() {
+			if productSpecific {
+				mctx.PropertyErrorf("product_specific",
+					"product_specific must not be true when `vndk: {enabled: true}`")
+				return
+			}
 			if vendorSpecific {
 				if !vndkdep.isVndkExt() {
 					mctx.PropertyErrorf("vndk",
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 3e78ec7..e368fb3 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -66,7 +66,7 @@
 		ctx.BottomUp("image", imageMutator).Parallel()
 		ctx.BottomUp("link", LinkageMutator).Parallel()
 		ctx.BottomUp("vndk", vndkMutator).Parallel()
-		ctx.BottomUp("version", versionMutator).Parallel()
+		ctx.BottomUp("version", VersionMutator).Parallel()
 		ctx.BottomUp("begin", BeginMutator).Parallel()
 	})
 	ctx.Register()
@@ -492,6 +492,21 @@
 	`)
 }
 
+func TestVndkMustNotBeProductSpecific(t *testing.T) {
+	// Check whether an error is emitted when a vndk lib has 'product_specific: true'.
+	testCcError(t, "product_specific must not be true when `vndk: {enabled: true}`", `
+		cc_library {
+			name: "libvndk",
+			product_specific: true,  // Cause error
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+	`)
+}
+
 func TestVndkExt(t *testing.T) {
 	// This test checks the VNDK-Ext properties.
 	ctx := testCc(t, `
diff --git a/cc/compiler.go b/cc/compiler.go
index 5ac5d79..63d2ade 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -75,6 +75,10 @@
 	// be added to the include path using -I
 	Local_include_dirs []string `android:"arch_variant,variant_prepend"`
 
+	// Add the directory containing the Android.bp file to the list of include
+	// directories. Defaults to true.
+	Include_build_directory *bool
+
 	// list of generated sources to compile. These are the names of gensrcs or
 	// genrule modules.
 	Generated_sources []string `android:"arch_variant"`
@@ -288,8 +292,11 @@
 		flags.YasmFlags = append(flags.YasmFlags, f)
 	}
 
-	flags.GlobalFlags = append(flags.GlobalFlags, "-I"+android.PathForModuleSrc(ctx).String())
-	flags.YasmFlags = append(flags.YasmFlags, "-I"+android.PathForModuleSrc(ctx).String())
+	if compiler.Properties.Include_build_directory == nil ||
+		*compiler.Properties.Include_build_directory {
+		flags.GlobalFlags = append(flags.GlobalFlags, "-I"+android.PathForModuleSrc(ctx).String())
+		flags.YasmFlags = append(flags.YasmFlags, "-I"+android.PathForModuleSrc(ctx).String())
+	}
 
 	if !(ctx.useSdk() || ctx.useVndk()) || ctx.Host() {
 		flags.SystemIncludeFlags = append(flags.SystemIncludeFlags,
@@ -299,6 +306,7 @@
 	}
 
 	if ctx.useSdk() {
+		// TODO: Switch to --sysroot.
 		// The NDK headers are installed to a common sysroot. While a more
 		// typical Soong approach would be to only make the headers for the
 		// library you're using available, we're trying to emulate the NDK
@@ -307,6 +315,7 @@
 			"-isystem "+getCurrentIncludePath(ctx).String(),
 			"-isystem "+getCurrentIncludePath(ctx).Join(ctx, config.NDKTriple(tc)).String())
 
+		// TODO: Migrate to API suffixed triple?
 		// Traditionally this has come from android/api-level.h, but with the
 		// libc headers unified it must be set by the build system since we
 		// don't have per-API level copies of that header now.
@@ -316,14 +325,6 @@
 		}
 		flags.GlobalFlags = append(flags.GlobalFlags,
 			"-D__ANDROID_API__="+version)
-
-		// Until the full NDK has been migrated to using ndk_headers, we still
-		// need to add the legacy sysroot includes to get the full set of
-		// headers.
-		legacyIncludes := fmt.Sprintf(
-			"prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/include",
-			ctx.sdkVersion(), ctx.Arch().ArchType.String())
-		flags.SystemIncludeFlags = append(flags.SystemIncludeFlags, "-isystem "+legacyIncludes)
 	}
 
 	if ctx.useVndk() {
@@ -420,9 +421,6 @@
 		cppStd = config.CppStdVersion
 	case "experimental":
 		cppStd = config.ExperimentalCppStdVersion
-	case "c++17", "gnu++17":
-		// Map c++17 and gnu++17 to their 1z equivalents, until 17 is finalized.
-		cppStd = strings.Replace(String(compiler.Properties.Cpp_std), "17", "1z", 1)
 	}
 
 	if compiler.Properties.Gnu_extensions != nil && *compiler.Properties.Gnu_extensions == false {
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 6a63828..f98e1be 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -68,6 +68,10 @@
 		"kryo": []string{
 			"-mcpu=kryo",
 		},
+		"kryo385": []string{
+			// Use cortex-a53 because kryo385 is not supported in GCC/clang.
+			"-mcpu=cortex-a53",
+		},
 		"exynos-m1": []string{
 			"-mcpu=exynos-m1",
 		},
@@ -92,9 +96,9 @@
 		"cortex-a75",
 		"cortex-a76",
 		"kryo",
+		"kryo385",
 		"exynos-m1",
-		"exynos-m2",
-		"denver64")
+		"exynos-m2")
 
 	pctx.StaticVariable("arm64GccVersion", arm64GccVersion)
 
@@ -144,6 +148,7 @@
 		"cortex-a75": "${config.Arm64ClangCortexA55Cflags}",
 		"cortex-a76": "${config.Arm64ClangCortexA55Cflags}",
 		"kryo":       "${config.Arm64ClangKryoCflags}",
+		"kryo385":    "${config.Arm64ClangCortexA53Cflags}",
 		"exynos-m1":  "${config.Arm64ClangExynosM1Cflags}",
 		"exynos-m2":  "${config.Arm64ClangExynosM2Cflags}",
 	}
@@ -220,10 +225,7 @@
 
 	var extraLdflags string
 	switch arch.CpuVariant {
-	case "cortex-a53", "cortex-a72", "cortex-a73", "kryo", "exynos-m1", "exynos-m2",
-		// This variant might not need the workaround but leave it
-		// in the list since it has had the workaround on before.
-		"denver64":
+	case "cortex-a53", "cortex-a72", "cortex-a73", "kryo", "exynos-m1", "exynos-m2":
 		extraLdflags = "-Wl,--fix-cortex-a53-843419"
 	}
 
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index d759125..60bb91a 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -151,6 +151,15 @@
 			// better solution comes around. See Bug 27340895
 			"-D__ARM_FEATURE_LPAE=1",
 		},
+		"kryo385": []string{
+			// Use cortex-a53 because kryo385 is not supported in GCC/clang.
+			"-mcpu=cortex-a53",
+			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// don't advertise.
+			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
+			// better solution comes around. See Bug 27340895
+			"-D__ARM_FEATURE_LPAE=1",
+		},
 	}
 )
 
@@ -180,9 +189,9 @@
 		"cortex-a76",
 		"krait",
 		"kryo",
+		"kryo385",
 		"exynos-m1",
-		"exynos-m2",
-		"denver")
+		"exynos-m2")
 
 	android.RegisterArchVariantFeatures(android.Arm, "armv7-a-neon", "neon")
 	android.RegisterArchVariantFeatures(android.Arm, "armv8-a", "neon")
@@ -242,7 +251,7 @@
 		"armv7-a":      "${config.ArmClangArmv7ACflags}",
 		"armv7-a-neon": "${config.ArmClangArmv7ANeonCflags}",
 		"armv8-a":      "${config.ArmClangArmv8ACflags}",
-		"armv8-2a":      "${config.ArmClangArmv82ACflags}",
+		"armv8-2a":     "${config.ArmClangArmv82ACflags}",
 	}
 
 	armClangCpuVariantCflagsVar = map[string]string{
@@ -258,9 +267,9 @@
 		"cortex-a75":     "${config.ArmClangCortexA55Cflags}",
 		"krait":          "${config.ArmClangKraitCflags}",
 		"kryo":           "${config.ArmClangKryoCflags}",
+		"kryo385":        "${config.ArmClangCortexA53Cflags}",
 		"exynos-m1":      "${config.ArmClangCortexA53Cflags}",
 		"exynos-m2":      "${config.ArmClangCortexA53Cflags}",
-		"denver":         "${config.ArmClangCortexA15Cflags}",
 	}
 )
 
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 0f22034..c070bf2 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -91,7 +91,7 @@
 	"-Wl,-m,aarch64_elf64_le_vec",
 })
 
-var ClangLibToolingUnknownCflags []string = nil
+var ClangLibToolingUnknownCflags = sorted([]string{})
 
 func init() {
 	pctx.StaticVariable("ClangExtraCflags", strings.Join([]string{
@@ -120,14 +120,10 @@
 		// color codes if it is not running in a terminal.
 		"-fcolor-diagnostics",
 
-		// http://b/29823425 Disable -Wexpansion-to-defined for Clang update to r271374
-		"-Wno-expansion-to-defined",
-
 		// http://b/68236239 Allow 0/NULL instead of using nullptr everywhere.
 		"-Wno-zero-as-null-pointer-constant",
 
 		// Warnings from clang-7.0
-		"-Wno-deprecated-register",
 		"-Wno-sign-compare",
 
 		// Warnings from clang-8.0
@@ -184,17 +180,8 @@
 		// compatibility.
 		"-Wno-c++98-compat-extra-semi",
 
-		// Disable this warning until we can fix all instances where it fails.
-		"-Wno-self-assign-overloaded",
-
-		// Disable this warning until we can fix all instances where it fails.
-		"-Wno-constant-logical-operand",
-
 		// Disable this warning because we don't care about behavior with older compilers.
 		"-Wno-return-std-move-in-c++11",
-
-		// Disable this warning until we can fix all instances where it fails.
-		"-Wno-dangling-field",
 	}, " "))
 
 	// Extra cflags for projects under external/ directory
diff --git a/cc/config/global.go b/cc/config/global.go
index e2377e3..13ad27c 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -87,8 +87,6 @@
 
 	deviceGlobalLldflags = append(ClangFilterUnknownLldflags(deviceGlobalLdflags),
 		[]string{
-			"-Wl,--pack-dyn-relocs=android+relr",
-			"-Wl,--use-android-relr-tags",
 			"-fuse-ld=lld",
 		}...)
 
@@ -114,16 +112,16 @@
 	}
 
 	CStdVersion               = "gnu99"
-	CppStdVersion             = "gnu++14"
+	CppStdVersion             = "gnu++17"
 	ExperimentalCStdVersion   = "gnu11"
-	ExperimentalCppStdVersion = "gnu++1z"
+	ExperimentalCppStdVersion = "gnu++2a"
 
 	NdkMaxPrebuiltVersionInt = 27
 
 	// prebuilts/clang default settings.
 	ClangDefaultBase         = "prebuilts/clang/host"
-	ClangDefaultVersion      = "clang-r344140b"
-	ClangDefaultShortVersion = "8.0.4"
+	ClangDefaultVersion      = "clang-r346389b"
+	ClangDefaultShortVersion = "8.0.6"
 
 	// Directories with warnings from Android.bp files.
 	WarningAllowedProjects = []string{
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 6300a1b..dfdd40c 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -33,9 +33,9 @@
 
 		// Use C99-compliant printf functions (%zd).
 		"-D__USE_MINGW_ANSI_STDIO=1",
-		// Admit to using >= Vista. Both are needed because of <_mingw.h>.
-		"-D_WIN32_WINNT=0x0600",
-		"-DWINVER=0x0600",
+		// Admit to using >= Windows 7. Both are needed because of <_mingw.h>.
+		"-D_WIN32_WINNT=0x0601",
+		"-DWINVER=0x0601",
 		// Get 64-bit off_t and related functions.
 		"-D_FILE_OFFSET_BITS=64",
 
@@ -140,6 +140,9 @@
 	pctx.StaticVariable("WindowsX8664ClangCppflags", strings.Join(windowsX8664ClangCppflags, " "))
 
 	pctx.StaticVariable("WindowsIncludeFlags", strings.Join(windowsIncludeFlags, " "))
+	// Yasm flags
+	pctx.StaticVariable("WindowsX86YasmFlags", "-f win32 -m x86")
+	pctx.StaticVariable("WindowsX8664YasmFlags", "-f win64 -m amd64")
 }
 
 type toolchainWindows struct {
@@ -228,6 +231,14 @@
 	return "${config.WindowsClangLldflags} ${config.WindowsX8664ClangLldflags}"
 }
 
+func (t *toolchainWindowsX86) YasmFlags() string {
+	return "${config.WindowsX86YasmFlags}"
+}
+
+func (t *toolchainWindowsX8664) YasmFlags() string {
+	return "${config.WindowsX8664YasmFlags}"
+}
+
 func (t *toolchainWindows) ShlibSuffix() string {
 	return ".dll"
 }
diff --git a/cc/libbuildversion/libbuildversion.cpp b/cc/libbuildversion/libbuildversion.cpp
index d80d587..5242025 100644
--- a/cc/libbuildversion/libbuildversion.cpp
+++ b/cc/libbuildversion/libbuildversion.cpp
@@ -23,9 +23,19 @@
 namespace android {
 namespace build {
 
+#define PLACEHOLDER "SOONG BUILD NUMBER PLACEHOLDER"
+
+extern "C" {
+  char soong_build_number[128] = PLACEHOLDER;
+}
+
 #ifdef __ANDROID__
 
 std::string GetBuildNumber() {
+  if (strcmp(PLACEHOLDER, soong_build_number) != 0) {
+    return soong_build_number;
+  }
+
   const prop_info* pi = __system_property_find("ro.build.version.incremental");
   if (pi == nullptr) return "";
 
@@ -42,10 +52,6 @@
 
 #else
 
-extern "C" {
-  char soong_build_number[128] = "SOONG BUILD NUMBER PLACEHOLDER";
-}
-
 std::string GetBuildNumber() {
   return soong_build_number;
 }
diff --git a/cc/libbuildversion/tests/Android.bp b/cc/libbuildversion/tests/Android.bp
index a18bc6c..b3b2061 100644
--- a/cc/libbuildversion/tests/Android.bp
+++ b/cc/libbuildversion/tests/Android.bp
@@ -2,10 +2,53 @@
     name: "build_version_test_defaults",
     use_version_lib: true,
     host_supported: true,
+    dist: {
+        targets: ["test_build_version_test"],
+    },
     target: {
+        android_arm: {
+            dist: {
+                dir: "android/arm",
+            },
+        },
+        android_arm64: {
+            dist: {
+                dir: "android/arm64",
+            },
+        },
+        android_x86: {
+            dist: {
+                dir: "android/x86",
+            },
+        },
+        android_x86_64: {
+            dist: {
+                dir: "android/x86_64",
+            },
+        },
+        darwin: {
+            dist: {
+                dir: "host/",
+            },
+        },
+        linux_glibc_x86: {
+            dist: {
+                dir: "host32/",
+            },
+        },
+        linux_glibc_x86_64: {
+            dist: {
+                dir: "host/",
+            },
+        },
         windows: {
             enabled: true,
         },
+        windows_x86_64: {
+            dist: {
+                dest: "win64/build_ver_test.exe",
+            },
+        },
     },
 }
 
@@ -20,6 +63,11 @@
         not_windows: {
             shared_libs: ["libbuild_version_test"],
         },
+        host: {
+            dist: {
+                suffix: "_host",
+            },
+        },
     },
 }
 
diff --git a/cc/library.go b/cc/library.go
index abaa6c4..bd43043 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -16,6 +16,8 @@
 
 import (
 	"regexp"
+	"sort"
+	"strconv"
 	"strings"
 	"sync"
 
@@ -32,19 +34,21 @@
 		Srcs   []string `android:"arch_variant"`
 		Cflags []string `android:"arch_variant"`
 
-		Enabled           *bool    `android:"arch_variant"`
-		Whole_static_libs []string `android:"arch_variant"`
-		Static_libs       []string `android:"arch_variant"`
-		Shared_libs       []string `android:"arch_variant"`
+		Enabled            *bool    `android:"arch_variant"`
+		Whole_static_libs  []string `android:"arch_variant"`
+		Static_libs        []string `android:"arch_variant"`
+		Shared_libs        []string `android:"arch_variant"`
+		System_shared_libs []string `android:"arch_variant"`
 	} `android:"arch_variant"`
 	Shared struct {
 		Srcs   []string `android:"arch_variant"`
 		Cflags []string `android:"arch_variant"`
 
-		Enabled           *bool    `android:"arch_variant"`
-		Whole_static_libs []string `android:"arch_variant"`
-		Static_libs       []string `android:"arch_variant"`
-		Shared_libs       []string `android:"arch_variant"`
+		Enabled            *bool    `android:"arch_variant"`
+		Whole_static_libs  []string `android:"arch_variant"`
+		Static_libs        []string `android:"arch_variant"`
+		Shared_libs        []string `android:"arch_variant"`
+		System_shared_libs []string `android:"arch_variant"`
 	} `android:"arch_variant"`
 
 	// local file name to pass to the linker as -unexported_symbols_list
@@ -267,6 +271,9 @@
 	// Location of the linked, unstripped library for shared libraries
 	unstrippedOutputFile android.Path
 
+	// Location of the file that should be copied to dist dir when requested
+	distFile android.OptionalPath
+
 	versionScriptPath android.ModuleGenPath
 
 	// Decorated interafaces
@@ -408,11 +415,11 @@
 	buildFlags := flagsToBuilderFlags(flags)
 
 	if library.static() {
-		srcs := android.PathsForModuleSrc(ctx, library.Properties.Static.Srcs)
+		srcs := ctx.ExpandSources(library.Properties.Static.Srcs, nil)
 		objs = objs.Append(compileObjs(ctx, buildFlags, android.DeviceStaticLibrary,
 			srcs, library.baseCompiler.pathDeps, library.baseCompiler.cFlagsDeps))
 	} else if library.shared() {
-		srcs := android.PathsForModuleSrc(ctx, library.Properties.Shared.Srcs)
+		srcs := ctx.ExpandSources(library.Properties.Shared.Srcs, nil)
 		objs = objs.Append(compileObjs(ctx, buildFlags, android.DeviceSharedLibrary,
 			srcs, library.baseCompiler.pathDeps, library.baseCompiler.cFlagsDeps))
 	}
@@ -484,7 +491,29 @@
 	}
 }
 
+func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
+	deps = library.baseCompiler.compilerDeps(ctx, deps)
+
+	if library.static() {
+		android.ExtractSourcesDeps(ctx, library.Properties.Static.Srcs)
+	} else if library.shared() {
+		android.ExtractSourcesDeps(ctx, library.Properties.Shared.Srcs)
+	}
+
+	return deps
+}
+
 func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
+	if library.static() {
+		if library.Properties.Static.System_shared_libs != nil {
+			library.baseLinker.Properties.System_shared_libs = library.Properties.Static.System_shared_libs
+		}
+	} else if library.shared() {
+		if library.Properties.Shared.System_shared_libs != nil {
+			library.baseLinker.Properties.System_shared_libs = library.Properties.Shared.System_shared_libs
+		}
+	}
+
 	deps = library.baseLinker.linkerDeps(ctx, deps)
 
 	if library.static() {
@@ -542,10 +571,16 @@
 	outputFile := android.PathForModuleOut(ctx, fileName)
 	builderFlags := flagsToBuilderFlags(flags)
 
-	if Bool(library.baseLinker.Properties.Use_version_lib) && ctx.Host() {
-		versionedOutputFile := outputFile
-		outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
-		library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+	if Bool(library.baseLinker.Properties.Use_version_lib) {
+		if ctx.Host() {
+			versionedOutputFile := outputFile
+			outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
+			library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+		} else {
+			versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
+			library.distFile = android.OptionalPathForPath(versionedOutputFile)
+			library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+		}
 	}
 
 	TransformObjToStaticLib(ctx, library.objects.objFiles, builderFlags, outputFile, objs.tidyFiles)
@@ -619,10 +654,23 @@
 
 	library.unstrippedOutputFile = outputFile
 
-	if Bool(library.baseLinker.Properties.Use_version_lib) && ctx.Host() {
-		versionedOutputFile := outputFile
-		outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
-		library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+	if Bool(library.baseLinker.Properties.Use_version_lib) {
+		if ctx.Host() {
+			versionedOutputFile := outputFile
+			outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
+			library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+		} else {
+			versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
+			library.distFile = android.OptionalPathForPath(versionedOutputFile)
+
+			if library.stripper.needsStrip(ctx) {
+				out := android.PathForModuleOut(ctx, "versioned-stripped", fileName)
+				library.distFile = android.OptionalPathForPath(out)
+				library.stripper.strip(ctx, versionedOutputFile, out, builderFlags)
+			}
+
+			library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+		}
 	}
 
 	sharedLibs := deps.SharedLibs
@@ -899,8 +947,19 @@
 func reuseStaticLibrary(mctx android.BottomUpMutatorContext, static, shared *Module) {
 	if staticCompiler, ok := static.compiler.(*libraryDecorator); ok {
 		sharedCompiler := shared.compiler.(*libraryDecorator)
+
+		// Check libraries in addition to cflags, since libraries may be exporting different
+		// include directories.
 		if len(staticCompiler.Properties.Static.Cflags) == 0 &&
-			len(sharedCompiler.Properties.Shared.Cflags) == 0 {
+			len(sharedCompiler.Properties.Shared.Cflags) == 0 &&
+			len(staticCompiler.Properties.Static.Whole_static_libs) == 0 &&
+			len(sharedCompiler.Properties.Shared.Whole_static_libs) == 0 &&
+			len(staticCompiler.Properties.Static.Static_libs) == 0 &&
+			len(sharedCompiler.Properties.Shared.Static_libs) == 0 &&
+			len(staticCompiler.Properties.Static.Shared_libs) == 0 &&
+			len(sharedCompiler.Properties.Shared.Shared_libs) == 0 &&
+			staticCompiler.Properties.Static.System_shared_libs == nil &&
+			sharedCompiler.Properties.Shared.System_shared_libs == nil {
 
 			mctx.AddInterVariantDependency(reuseObjTag, shared, static)
 			sharedCompiler.baseCompiler.Properties.OriginalSrcs =
@@ -936,30 +995,68 @@
 	}
 }
 
+// maps a module name to the list of stubs versions available for the module
+func stubsVersionsFor(config android.Config) map[string][]string {
+	return config.Once("stubVersions", func() interface{} {
+		return make(map[string][]string)
+	}).(map[string][]string)
+}
+
+var stubsVersionsLock sync.Mutex
+
+func latestStubsVersionFor(config android.Config, name string) string {
+	versions, ok := stubsVersionsFor(config)[name]
+	if ok && len(versions) > 0 {
+		// the versions are alreay sorted in ascending order
+		return versions[len(versions)-1]
+	}
+	return ""
+}
+
 // 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) {
+// (which is unnamed) 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{""}
+		if library, ok := m.linker.(*libraryDecorator); ok && library.buildShared() &&
+			len(library.Properties.Stubs.Versions) > 0 {
+			versions := []string{}
 			for _, v := range library.Properties.Stubs.Versions {
+				if _, err := strconv.Atoi(v); err != nil {
+					mctx.PropertyErrorf("versions", "%q is not a number", v)
+				}
 				versions = append(versions, v)
 			}
+			sort.Slice(versions, func(i, j int) bool {
+				left, _ := strconv.Atoi(versions[i])
+				right, _ := strconv.Atoi(versions[j])
+				return left < right
+			})
+
+			// save the list of versions for later use
+			copiedVersions := make([]string, len(versions))
+			copy(copiedVersions, versions)
+			stubsVersionsLock.Lock()
+			defer stubsVersionsLock.Unlock()
+			stubsVersionsFor(mctx.Config())[mctx.ModuleName()] = copiedVersions
+
+			// "" is for the non-stubs variant
+			versions = append(versions, "")
+
 			modules := mctx.CreateVariations(versions...)
 			for i, m := range modules {
 				l := m.(*Module).linker.(*libraryDecorator)
-				if i == 0 {
-					l.MutatedProperties.BuildStubs = false
-					continue
+				if versions[i] != "" {
+					l.MutatedProperties.BuildStubs = true
+					l.MutatedProperties.StubsVersion = versions[i]
+					m.(*Module).Properties.HideFromMake = true
+					m.(*Module).sanitize = nil
+					m.(*Module).stl = nil
+					m.(*Module).Properties.PreventInstall = true
 				}
-				// Mark that this variant is for stubs.
-				l.MutatedProperties.BuildStubs = true
-				l.MutatedProperties.StubsVersion = versions[i]
-				m.(*Module).Properties.HideFromMake = true
 			}
 		} else {
 			mctx.CreateVariations("")
diff --git a/cc/linker.go b/cc/linker.go
index 3053609..854dfc5 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -18,6 +18,7 @@
 	"android/soong/android"
 	"android/soong/cc/config"
 	"fmt"
+	"strconv"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
@@ -48,7 +49,7 @@
 	// list of system libraries that will be dynamically linked to
 	// shared library and executable modules.  If unset, generally defaults to libc,
 	// libm, and libdl.  Set to [] to prevent linking against the defaults.
-	System_shared_libs []string
+	System_shared_libs []string `android:"arch_variant"`
 
 	// allow the module to contain undefined symbols.  By default,
 	// modules cannot contain undefined symbols that are not satisified by their immediate
@@ -236,35 +237,34 @@
 			deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc")
 		}
 
-		if !ctx.static() {
-			systemSharedLibs := linker.Properties.System_shared_libs
-			if systemSharedLibs == nil {
-				systemSharedLibs = []string{"libc", "libm", "libdl"}
-			}
-
-			if inList("libdl", deps.SharedLibs) {
-				// If system_shared_libs has libc but not libdl, make sure shared_libs does not
-				// have libdl to avoid loading libdl before libc.
-				if inList("libc", systemSharedLibs) {
-					if !inList("libdl", systemSharedLibs) {
-						ctx.PropertyErrorf("shared_libs",
-							"libdl must be in system_shared_libs, not shared_libs")
-					}
-					_, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs)
-				}
-			}
-
-			// If libc and libdl are both in system_shared_libs make sure libd comes after libc
-			// to avoid loading libdl before libc.
-			if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) &&
-				indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) {
-				ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc")
-			}
-
-			deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...)
-		} else if ctx.useSdk() || ctx.useVndk() {
-			deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm", "libdl")
+		var systemSharedLibs []string
+		if !ctx.useSdk() && !ctx.useVndk() {
+			systemSharedLibs = linker.Properties.System_shared_libs
 		}
+		if systemSharedLibs == nil {
+			systemSharedLibs = []string{"libc", "libm", "libdl"}
+		}
+
+		if inList("libdl", deps.SharedLibs) {
+			// If system_shared_libs has libc but not libdl, make sure shared_libs does not
+			// have libdl to avoid loading libdl before libc.
+			if inList("libc", systemSharedLibs) {
+				if !inList("libdl", systemSharedLibs) {
+					ctx.PropertyErrorf("shared_libs",
+						"libdl must be in system_shared_libs, not shared_libs")
+				}
+				_, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs)
+			}
+		}
+
+		// If libc and libdl are both in system_shared_libs make sure libdl comes after libc
+		// to avoid loading libdl before libc.
+		if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) &&
+			indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) {
+			ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc")
+		}
+
+		deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...)
 	}
 
 	if ctx.Windows() {
@@ -298,6 +298,23 @@
 	return true
 }
 
+// Check whether the SDK version is not older than the specific one
+func CheckSdkVersionAtLeast(ctx ModuleContext, SdkVersion int) bool {
+	if ctx.sdkVersion() == "current" {
+		return true
+	}
+	parsedSdkVersion, err := strconv.Atoi(ctx.sdkVersion())
+	if err != nil {
+		ctx.PropertyErrorf("sdk_version",
+			"Invalid sdk_version value (must be int or current): %q",
+			ctx.sdkVersion())
+	}
+	if parsedSdkVersion < SdkVersion {
+		return false
+	}
+	return true
+}
+
 // ModuleContext extends BaseModuleContext
 // BaseModuleContext should know if LLD is used?
 func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
@@ -312,6 +329,13 @@
 		flags.LdFlags = append(flags.LdFlags, fmt.Sprintf("${config.%sGlobalLldflags}", hod))
 		if !BoolDefault(linker.Properties.Pack_relocations, true) {
 			flags.LdFlags = append(flags.LdFlags, "-Wl,--pack-dyn-relocs=none")
+		} else if ctx.Device() {
+			// The SHT_RELR relocations is only supported by API level >= 28.
+			// Do not turn this on if older version NDK is used.
+			if !ctx.useSdk() || CheckSdkVersionAtLeast(ctx, 28) {
+				flags.LdFlags = append(flags.LdFlags, "-Wl,--pack-dyn-relocs=android+relr")
+				flags.LdFlags = append(flags.LdFlags, "-Wl,--use-android-relr-tags")
+			}
 		}
 	} else {
 		flags.LdFlags = append(flags.LdFlags, fmt.Sprintf("${config.%sGlobalLdflags}", hod))
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 8177ff1..504a6a0 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -77,6 +77,11 @@
 
 	// Path to the NOTICE file associated with the headers.
 	License *string
+
+	// True if this API is not yet ready to be shipped in the NDK. It will be
+	// available in the platform for testing, but will be excluded from the
+	// sysroot provided to the NDK proper.
+	Draft bool
 }
 
 type headerModule struct {
@@ -182,6 +187,11 @@
 
 	// Path to the NOTICE file associated with the headers.
 	License *string
+
+	// True if this API is not yet ready to be shipped in the NDK. It will be
+	// available in the platform for testing, but will be excluded from the
+	// sysroot provided to the NDK proper.
+	Draft bool
 }
 
 // Like ndk_headers, but preprocesses the headers with the bionic versioner:
@@ -309,6 +319,11 @@
 
 	// Path to the NOTICE file associated with the headers.
 	License *string
+
+	// True if this API is not yet ready to be shipped in the NDK. It will be
+	// available in the platform for testing, but will be excluded from the
+	// sysroot provided to the NDK proper.
+	Draft bool
 }
 
 type preprocessedHeadersModule struct {
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 63d9f29..53fe314 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -91,6 +91,11 @@
 
 	// Private property for use by the mutator that splits per-API level.
 	ApiLevel string `blueprint:"mutated"`
+
+	// True if this API is not yet ready to be shipped in the NDK. It will be
+	// available in the platform for testing, but will be excluded from the
+	// sysroot provided to the NDK proper.
+	Draft bool
 }
 
 type stubDecorator struct {
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 80b5c6a..9265bff 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -104,22 +104,38 @@
 		}
 
 		if m, ok := module.(*headerModule); ok {
+			if ctx.Config().ExcludeDraftNdkApis() && m.properties.Draft {
+				return
+			}
+
 			installPaths = append(installPaths, m.installPaths...)
 			licensePaths = append(licensePaths, m.licensePath)
 		}
 
 		if m, ok := module.(*versionedHeaderModule); ok {
+			if ctx.Config().ExcludeDraftNdkApis() && m.properties.Draft {
+				return
+			}
+
 			installPaths = append(installPaths, m.installPaths...)
 			licensePaths = append(licensePaths, m.licensePath)
 		}
 
 		if m, ok := module.(*preprocessedHeadersModule); ok {
+			if ctx.Config().ExcludeDraftNdkApis() && m.properties.Draft {
+				return
+			}
+
 			installPaths = append(installPaths, m.installPaths...)
 			licensePaths = append(licensePaths, m.licensePath)
 		}
 
 		if m, ok := module.(*Module); ok {
 			if installer, ok := m.installer.(*stubDecorator); ok {
+				if ctx.Config().ExcludeDraftNdkApis() &&
+					installer.properties.Draft {
+					return
+				}
 				installPaths = append(installPaths, installer.installPath)
 			}
 
diff --git a/cc/rs.go b/cc/rs.go
index 7c9f5d3..5421b92 100644
--- a/cc/rs.go
+++ b/cc/rs.go
@@ -16,13 +16,22 @@
 
 import (
 	"android/soong/android"
+	"path/filepath"
+	"runtime"
 	"strings"
 
 	"github.com/google/blueprint"
 )
 
 func init() {
-	pctx.HostBinToolVariable("rsCmd", "llvm-rs-cc")
+	pctx.VariableFunc("rsCmd", func(ctx android.PackageVarContext) string {
+		if ctx.Config().UnbundledBuild() {
+			// Use RenderScript prebuilts for unbundled builds but not PDK builds
+			return filepath.Join("prebuilts/sdk/tools", runtime.GOOS, "bin/llvm-rs-cc")
+		} else {
+			return pctx.HostBinToolPath(ctx, "llvm-rs-cc").String()
+		}
+	})
 }
 
 var rsCppCmdLine = strings.Replace(`
diff --git a/cc/sanitize.go b/cc/sanitize.go
index cd3b3e9..5db6bdf 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -36,7 +36,7 @@
 	asanLdflags = []string{"-Wl,-u,__asan_preinit"}
 	asanLibs    = []string{"libasan"}
 
-	hwasanCflags = []string{"-mllvm", "-hwasan-with-ifunc=0", "-fno-omit-frame-pointer", "-Wno-frame-larger-than="}
+	hwasanCflags = []string{"-mllvm", "-hwasan-with-ifunc=0", "-fno-omit-frame-pointer", "-Wno-frame-larger-than=", "-mllvm", "-hwasan-create-frame-descriptions=0"}
 
 	cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
 		"-fsanitize-blacklist=external/compiler-rt/lib/cfi/cfi_blacklist.txt"}
@@ -49,8 +49,14 @@
 	cfiStaticLibsMutex    sync.Mutex
 	hwasanStaticLibsMutex sync.Mutex
 
-	intOverflowCflags   = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
-	minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
+	intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
+
+	// Pass -Xclang before -fsanitize-minimal-runtime to work around a driver
+	// check which rejects -fsanitize-minimal-runtime together with
+	// -fsanitize=shadow-call-stack even though this combination of flags
+	// is valid.
+	// TODO(pcc): Remove the -Xclang once LLVM r346526 is rolled into the compiler.
+	minimalRuntimeFlags = []string{"-Xclang", "-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
 		"-fno-sanitize-recover=integer,undefined"}
 	hwasanGlobalOptions = []string{"heap_history_size=4095"}
 )
@@ -71,6 +77,7 @@
 	tsan
 	intOverflow
 	cfi
+	scs
 )
 
 func (t sanitizerType) String() string {
@@ -85,6 +92,8 @@
 		return "intOverflow"
 	case cfi:
 		return "cfi"
+	case scs:
+		return "scs"
 	default:
 		panic(fmt.Errorf("unknown sanitizerType %d", t))
 	}
@@ -109,6 +118,7 @@
 		Cfi              *bool    `android:"arch_variant"`
 		Integer_overflow *bool    `android:"arch_variant"`
 		Scudo            *bool    `android:"arch_variant"`
+		Scs              *bool    `android:"arch_variant"`
 
 		// Sanitizers to run in the diagnostic mode (as opposed to the release mode).
 		// Replaces abort() on error with a human-readable error message.
@@ -118,6 +128,7 @@
 			Cfi              *bool    `android:"arch_variant"`
 			Integer_overflow *bool    `android:"arch_variant"`
 			Misc_undefined   []string `android:"arch_variant"`
+			No_recover       []string
 		}
 
 		// value to pass to -fsanitize-recover=
@@ -276,6 +287,14 @@
 		s.Hwaddress = nil
 	}
 
+	// SCS is only implemented on AArch64.
+	// We also disable SCS if ASAN, TSAN or HWASAN are enabled because Clang considers
+	// them to be incompatible, although they are in fact compatible.
+	// TODO(pcc): Remove these checks once r347282 is rolled into the compiler.
+	if ctx.Arch().ArchType != android.Arm64 || Bool(s.Address) || Bool(s.Thread) || Bool(s.Hwaddress) {
+		s.Scs = nil
+	}
+
 	// Also disable CFI if ASAN is enabled.
 	if Bool(s.Address) || Bool(s.Hwaddress) {
 		s.Cfi = nil
@@ -299,7 +318,8 @@
 	}
 
 	// HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
-	if ctx.inRecovery() {
+	// Keep libc instrumented so that recovery can run hwasan-instrumented code if necessary.
+	if ctx.inRecovery() && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") {
 		s.Hwaddress = nil
 	}
 
@@ -322,7 +342,7 @@
 
 	if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
 		Bool(s.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
-		Bool(s.Scudo) || Bool(s.Hwaddress)) {
+		Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs)) {
 		sanitize.Properties.SanitizerEnabled = true
 	}
 
@@ -357,6 +377,22 @@
 	return deps
 }
 
+func toDisableImplicitIntegerChange(flags []string) bool {
+	// Returns true if any flag is fsanitize*integer, and there is
+	// no explicit flag about sanitize=implicit-integer-sign-change.
+	for _, f := range flags {
+		if strings.Contains(f, "sanitize=implicit-integer-sign-change") {
+			return false
+		}
+	}
+	for _, f := range flags {
+		if strings.HasPrefix(f, "-fsanitize") && strings.Contains(f, "integer") {
+			return true
+		}
+	}
+	return false
+}
+
 func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
 	minimalRuntimeLib := config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(ctx.toolchain()) + ".a"
 	minimalRuntimePath := "${config.ClangAsanLibDir}/" + minimalRuntimeLib
@@ -490,6 +526,10 @@
 		sanitizers = append(sanitizers, "scudo")
 	}
 
+	if Bool(sanitize.Properties.Sanitize.Scs) {
+		sanitizers = append(sanitizers, "shadow-call-stack")
+	}
+
 	if len(sanitizers) > 0 {
 		sanitizeArg := "-fsanitize=" + strings.Join(sanitizers, ",")
 
@@ -510,6 +550,10 @@
 				flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,"+minimalRuntimeLib)
 			}
 		}
+		// http://b/119329758, Android core does not boot up with this sanitizer yet.
+		if toDisableImplicitIntegerChange(flags.CFlags) {
+			flags.CFlags = append(flags.CFlags, "-fno-sanitize=implicit-integer-sign-change")
+		}
 	}
 
 	if len(diagSanitizers) > 0 {
@@ -522,6 +566,11 @@
 			strings.Join(sanitize.Properties.Sanitize.Recover, ","))
 	}
 
+	if sanitize.Properties.Sanitize.Diag.No_recover != nil {
+		flags.CFlags = append(flags.CFlags, "-fno-sanitize-recover="+
+			strings.Join(sanitize.Properties.Sanitize.Diag.No_recover, ","))
+	}
+
 	// Link a runtime library if needed.
 	runtimeLibrary := ""
 	if Bool(sanitize.Properties.Sanitize.Address) {
@@ -553,9 +602,12 @@
 		sanitize.runtimeLibrary = runtimeLibrary
 
 		// When linking against VNDK, use the vendor variant of the runtime lib
-		sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary
 		if ctx.useVndk() {
 			sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary + vendorSuffix
+		} else if ctx.inRecovery() {
+			sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary + recoverySuffix
+		} else {
+			sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary
 		}
 	}
 
@@ -583,6 +635,9 @@
 	if ret.Class == "STATIC_LIBRARIES" && Bool(sanitize.Properties.Sanitize.Hwaddress) {
 		ret.SubName += ".hwasan"
 	}
+	if ret.Class == "STATIC_LIBRARIES" && Bool(sanitize.Properties.Sanitize.Scs) {
+		ret.SubName += ".scs"
+	}
 }
 
 func (sanitize *sanitize) inSanitizerDir() bool {
@@ -601,6 +656,8 @@
 		return sanitize.Properties.Sanitize.Integer_overflow
 	case cfi:
 		return sanitize.Properties.Sanitize.Cfi
+	case scs:
+		return sanitize.Properties.Sanitize.Scs
 	default:
 		panic(fmt.Errorf("unknown sanitizerType %d", t))
 	}
@@ -610,7 +667,8 @@
 	return !sanitize.isSanitizerEnabled(asan) &&
 		!sanitize.isSanitizerEnabled(hwasan) &&
 		!sanitize.isSanitizerEnabled(tsan) &&
-		!sanitize.isSanitizerEnabled(cfi)
+		!sanitize.isSanitizerEnabled(cfi) &&
+		!sanitize.isSanitizerEnabled(scs)
 }
 
 func (sanitize *sanitize) isVariantOnProductionDevice() bool {
@@ -634,6 +692,8 @@
 		sanitize.Properties.Sanitize.Integer_overflow = boolPtr(b)
 	case cfi:
 		sanitize.Properties.Sanitize.Cfi = boolPtr(b)
+	case scs:
+		sanitize.Properties.Sanitize.Scs = boolPtr(b)
 	default:
 		panic(fmt.Errorf("unknown sanitizerType %d", t))
 	}
@@ -683,7 +743,7 @@
 				if d, ok := child.(*Module); ok && d.sanitize != nil &&
 					!Bool(d.sanitize.Properties.Sanitize.Never) &&
 					!d.sanitize.isSanitizerExplicitlyDisabled(t) {
-					if t == cfi || t == hwasan {
+					if t == cfi || t == hwasan || t == scs {
 						if d.static() {
 							d.sanitize.Properties.SanitizeDep = true
 						}
@@ -779,6 +839,19 @@
 						modules[1].(*Module).Properties.PreventInstall = true
 						modules[1].(*Module).Properties.HideFromMake = true
 					}
+				} else if t == scs {
+					// We don't currently link any static libraries built with make into
+					// libraries built with SCS, so we don't need logic for propagating
+					// SCSness of dependencies into make.
+					if !c.static() {
+						if isSanitizerEnabled {
+							modules[0].(*Module).Properties.PreventInstall = true
+							modules[0].(*Module).Properties.HideFromMake = true
+						} else {
+							modules[1].(*Module).Properties.PreventInstall = true
+							modules[1].(*Module).Properties.HideFromMake = true
+						}
+					}
 				} else if t == hwasan {
 					if mctx.Device() {
 						// CFI and HWASAN are currently mutually exclusive so disable
diff --git a/cc/stl.go b/cc/stl.go
index 8eee612..4870870 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -17,6 +17,7 @@
 import (
 	"android/soong/android"
 	"fmt"
+	"strconv"
 )
 
 func getNdkStlFamily(m *Module) string {
@@ -110,6 +111,26 @@
 	}()
 }
 
+func needsLibAndroidSupport(ctx BaseModuleContext) bool {
+	versionStr, err := normalizeNdkApiLevel(ctx, ctx.sdkVersion(), ctx.Arch())
+	if err != nil {
+		ctx.PropertyErrorf("sdk_version", err.Error())
+	}
+
+	if versionStr == "current" {
+		return false
+	}
+
+	version, err := strconv.Atoi(versionStr)
+	if err != nil {
+		panic(fmt.Sprintf(
+			"invalid API level returned from normalizeNdkApiLevel: %q",
+			versionStr))
+	}
+
+	return version < 21
+}
+
 func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps {
 	switch stl.Properties.SelectedStl {
 	case "libstdc++":
@@ -141,7 +162,9 @@
 		} else {
 			deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl, "ndk_libc++abi")
 		}
-		deps.StaticLibs = append(deps.StaticLibs, "ndk_libandroid_support")
+		if needsLibAndroidSupport(ctx) {
+			deps.StaticLibs = append(deps.StaticLibs, "ndk_libandroid_support")
+		}
 		if ctx.Arch().ArchType == android.Arm {
 			deps.StaticLibs = append(deps.StaticLibs, "ndk_libunwind")
 		}
@@ -228,7 +251,7 @@
 		android.Linux:  []string{"-lgcc_s", "-lgcc", "-lc", "-lgcc_s", "-lgcc"},
 		android.Darwin: []string{"-lc", "-lSystem"},
 		android.Windows: []string{"-Wl,--start-group", "-lmingw32", "-lgcc", "-lgcc_eh",
-			"-lmoldname", "-lmingwex", "-lmsvcr110", "-lmsvcrt", "-lpthread",
+			"-lmoldname", "-lmingwex", "-lmsvcrt", "-lucrt", "-lpthread",
 			"-ladvapi32", "-lshell32", "-luser32", "-lkernel32", "-lpsapi",
 			"-Wl,--end-group"},
 	}
diff --git a/cc/tidy.go b/cc/tidy.go
index ddb445a..6bac846 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -108,6 +108,12 @@
 	if len(tidy.Properties.Tidy_checks) > 0 {
 		tidyChecks = tidyChecks + "," + strings.Join(esc(tidy.Properties.Tidy_checks), ",")
 	}
+	if ctx.Windows() {
+		// https://b.corp.google.com/issues/120614316
+		// mingw32 has cert-dcl16-c warning in NO_ERROR,
+		// which is used in many Android files.
+		tidyChecks = tidyChecks + ",-cert-dcl16-c"
+	}
 	flags.TidyFlags = append(flags.TidyFlags, tidyChecks)
 
 	return flags
diff --git a/cc/xom.go b/cc/xom.go
new file mode 100644
index 0000000..182069f
--- /dev/null
+++ b/cc/xom.go
@@ -0,0 +1,76 @@
+// Copyright 2018 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 (
+	"android/soong/android"
+)
+
+type XomProperties struct {
+	Xom *bool
+}
+
+type xom struct {
+	Properties XomProperties
+}
+
+func (xom *xom) props() []interface{} {
+	return []interface{}{&xom.Properties}
+}
+
+func (xom *xom) begin(ctx BaseModuleContext) {}
+
+func (xom *xom) deps(ctx BaseModuleContext, deps Deps) Deps {
+	return deps
+}
+
+func (xom *xom) flags(ctx ModuleContext, flags Flags) Flags {
+	disableXom := false
+
+	if !ctx.Config().EnableXOM() || ctx.Config().XOMDisabledForPath(ctx.ModuleDir()) {
+		disableXom = true
+	}
+
+	if xom.Properties.Xom != nil && !*xom.Properties.Xom {
+		return flags
+	}
+
+	// If any static dependencies have XOM disabled, we should disable XOM in this module,
+	// the assumption being if it's been explicitly disabled then there's probably incompatible
+	// code in the library which may get pulled in.
+	if !ctx.static() && !disableXom {
+		ctx.VisitDirectDeps(func(m android.Module) {
+			cc, ok := m.(*Module)
+			if !ok || cc.xom == nil || !cc.static() {
+				return
+			}
+			if cc.xom.Properties.Xom != nil && !*cc.xom.Properties.Xom {
+				disableXom = true
+				return
+			}
+		})
+	}
+
+	// Enable execute-only if none of the dependencies disable it,
+	// also if it's explicitly set true (allows overriding dependencies disabling it).
+	if !disableXom || (xom.Properties.Xom != nil && *xom.Properties.Xom) {
+		// XOM is only supported on AArch64 when using lld.
+		if ctx.Arch().ArchType == android.Arm64 && ctx.useClangLld(ctx) {
+			flags.LdFlags = append(flags.LdFlags, "-Wl,-execute-only")
+		}
+	}
+
+	return flags
+}
diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go
index 8e71a97..c21da44 100644
--- a/cmd/merge_zips/merge_zips.go
+++ b/cmd/merge_zips/merge_zips.go
@@ -19,6 +19,7 @@
 	"flag"
 	"fmt"
 	"hash/crc32"
+	"io"
 	"io/ioutil"
 	"log"
 	"os"
@@ -66,6 +67,7 @@
 	manifest         = flag.String("m", "", "manifest file to insert in jar")
 	pyMain           = flag.String("pm", "", "__main__.py file to insert in par")
 	entrypoint       = flag.String("e", "", "par entrypoint file to insert in par")
+	prefix           = flag.String("prefix", "", "A file to prefix to the zip file")
 	ignoreDuplicates = flag.Bool("ignore-duplicates", false, "take each entry from the first zip it exists in and don't warn")
 )
 
@@ -77,7 +79,7 @@
 
 func main() {
 	flag.Usage = func() {
-		fmt.Fprintln(os.Stderr, "usage: merge_zips [-jpsD] [-m manifest] [-e entrypoint] [-pm __main__.py] output [inputs...]")
+		fmt.Fprintln(os.Stderr, "usage: merge_zips [-jpsD] [-m manifest] [--prefix script] [-e entrypoint] [-pm __main__.py] output [inputs...]")
 		flag.PrintDefaults()
 	}
 
@@ -99,6 +101,19 @@
 		log.Fatal(err)
 	}
 	defer output.Close()
+
+	var offset int64
+	if *prefix != "" {
+		prefixFile, err := os.Open(*prefix)
+		if err != nil {
+			log.Fatal(err)
+		}
+		offset, err = io.Copy(output, prefixFile)
+		if err != nil {
+			log.Fatal(err)
+		}
+	}
+
 	writer := zip.NewWriter(output)
 	defer func() {
 		err := writer.Close()
@@ -106,6 +121,7 @@
 			log.Fatal(err)
 		}
 	}()
+	writer.SetOffset(offset)
 
 	// make readers
 	readers := []namedZipReader{}
diff --git a/java/app_builder.go b/java/app_builder.go
index b0983bd..28fc4c4 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -32,10 +32,10 @@
 	Signapk = pctx.AndroidStaticRule("signapk",
 		blueprint.RuleParams{
 			Command: `${config.JavaCmd} -Djava.library.path=$$(dirname $signapkJniLibrary) ` +
-				`-jar $signapkCmd $certificates $in $out`,
+				`-jar $signapkCmd $flags $certificates $in $out`,
 			CommandDeps: []string{"$signapkCmd", "$signapkJniLibrary"},
 		},
-		"certificates")
+		"flags", "certificates")
 
 	androidManifestMerger = pctx.AndroidStaticRule("androidManifestMerger",
 		blueprint.RuleParams{
diff --git a/java/dex.go b/java/dex.go
index 5cec325..a6d486a 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -160,6 +160,11 @@
 	// TODO(ccross): if this is an instrumentation test of an obfuscated app, use the
 	// dictionary of the app and move the app from libraryjars to injars.
 
+	// Don't strip out debug information for eng builds.
+	if ctx.Config().Eng() {
+		r8Flags = append(r8Flags, "--debug")
+	}
+
 	return r8Flags, r8Deps
 }
 
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 9dadb30..8e0a62a 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -360,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 a list of classes to do nullability validation for.
+	Validate_nullability_from_list *string
+
 	// a file containing expected warnings produced by validation of nullability annotations.
 	Check_nullability_warnings *string
 
@@ -623,7 +626,7 @@
 		case libTag:
 			switch dep := module.(type) {
 			case Dependency:
-				deps.classpath = append(deps.classpath, dep.ImplementationJars()...)
+				deps.classpath = append(deps.classpath, dep.HeaderJars()...)
 			case SdkLibraryDependency:
 				sdkVersion := j.sdkVersion()
 				linkType := javaSdk
@@ -1126,9 +1129,9 @@
 		Inputs:      d.Javadoc.srcFiles,
 		Implicits:   implicits,
 		Args: map[string]string{
-			"outDir":        android.PathForModuleOut(ctx, "out").String(),
-			"srcJarDir":     android.PathForModuleOut(ctx, "srcjars").String(),
-			"stubsDir":      android.PathForModuleOut(ctx, "stubsDir").String(),
+			"outDir":        android.PathForModuleOut(ctx, "dokka-out").String(),
+			"srcJarDir":     android.PathForModuleOut(ctx, "dokka-srcjars").String(),
+			"stubsDir":      android.PathForModuleOut(ctx, "dokka-stubsDir").String(),
 			"srcJars":       strings.Join(d.Javadoc.srcJars.Strings(), " "),
 			"classpathArgs": classpathArgs,
 			"opts":          opts,
@@ -1302,6 +1305,9 @@
 		}
 	}
 
+	if String(d.properties.Validate_nullability_from_list) != "" {
+		android.ExtractSourceDeps(ctx, d.properties.Validate_nullability_from_list)
+	}
 	if String(d.properties.Check_nullability_warnings) != "" {
 		android.ExtractSourceDeps(ctx, d.properties.Check_nullability_warnings)
 	}
@@ -1411,7 +1417,9 @@
 	var flags string
 	if Bool(d.properties.Annotations_enabled) {
 		flags += " --include-annotations"
-		validatingNullability := strings.Contains(d.Javadoc.args, "--validate-nullability-from-merged-stubs")
+		validatingNullability :=
+			strings.Contains(d.Javadoc.args, "--validate-nullability-from-merged-stubs") ||
+				String(d.properties.Validate_nullability_from_list) != ""
 		migratingNullability := String(d.properties.Previous_api) != ""
 		if !(migratingNullability || validatingNullability) {
 			ctx.PropertyErrorf("previous_api",
@@ -1422,6 +1430,9 @@
 			*implicits = append(*implicits, previousApi)
 			flags += " --migrate-nullness " + previousApi.String()
 		}
+		if s := String(d.properties.Validate_nullability_from_list); s != "" {
+			flags += " --validate-nullability-from-list " + ctx.ExpandSource(s, "validate_nullability_from_list").String()
+		}
 		if validatingNullability {
 			d.nullabilityWarningsFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_nullability_warnings.txt")
 			*implicitOutputs = append(*implicitOutputs, d.nullabilityWarningsFile)
@@ -1574,7 +1585,7 @@
 		Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile},
 			implicits...),
 		Args: map[string]string{
-			"srcJarDir":         android.PathForModuleOut(ctx, "srcjars").String(),
+			"srcJarDir":         android.PathForModuleOut(ctx, "apicheck-srcjars").String(),
 			"srcJars":           strings.Join(d.Javadoc.srcJars.Strings(), " "),
 			"javaVersion":       javaVersion,
 			"bootclasspathArgs": bootclasspathArgs,
diff --git a/java/sdk_library.go b/java/sdk_library.go
index e513a59..fdbf19d 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -229,19 +229,19 @@
 			// 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.publicApiStubsPath.Strings()[0]+
+					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.systemApiStubsPath.Strings()[0]+
+					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.testApiStubsPath.Strings()[0]+
+					module.testApiStubsImplPath.Strings()[0]+
 					":"+path.Join("apistubs", owner, "test",
 					module.BaseModuleName()+".jar")+")")
 			}
@@ -541,11 +541,6 @@
 			props.Srcs_lib_whitelist_pkgs = []string{"android.annotation"}
 		}
 	}
-	// These libs are required by doclava to parse the framework sources add via
-	// Src_lib and Src_lib_whitelist_* properties just above.
-	// If we don't add them to the classpath, errors messages are generated by doclava,
-	// though they don't break the build.
-	props.Libs = append(props.Libs, "framework")
 
 	if Bool(module.properties.Metalava_enabled) == true {
 		mctx.CreateModule(android.ModuleFactoryAdaptor(DroidstubsFactory), &props)
diff --git a/python/builder.go b/python/builder.go
index 11a792a..cbbe56e 100644
--- a/python/builder.go
+++ b/python/builder.go
@@ -45,20 +45,24 @@
 	hostPar = pctx.AndroidStaticRule("hostPar",
 		blueprint.RuleParams{
 			Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` +
-				`$mergeParCmd -p -pm $stub $mergedZip $srcsZips && echo '#!/usr/bin/env python' | cat - $mergedZip > $out && ` +
-				`chmod +x $out && (rm -f $stub; rm -f $mergedZip)`,
+				`echo "#!/usr/bin/env python" >${out}.prefix &&` +
+				`$mergeParCmd -p --prefix ${out}.prefix -pm $stub $out $srcsZips && ` +
+				`chmod +x $out && (rm -f $stub; rm -f ${out}.prefix)`,
 			CommandDeps: []string{"$mergeParCmd"},
 		},
-		"interp", "main", "template", "stub", "mergedZip", "srcsZips")
+		"interp", "main", "template", "stub", "srcsZips")
 
 	embeddedPar = pctx.AndroidStaticRule("embeddedPar",
 		blueprint.RuleParams{
-			Command: `echo '$main' > $entryPoint &&` +
-				`$mergeParCmd -p -e $entryPoint $mergedZip $srcsZips && cat $launcher | cat - $mergedZip > $out && ` +
-				`chmod +x $out && (rm -f $entryPoint; rm -f $mergedZip)`,
+			// `echo -n` to trim the newline, since the python code just wants the name.
+			// /bin/sh (used by ninja) on Mac turns off posix mode, and stops supporting -n.
+			// Explicitly use bash instead.
+			Command: `/bin/bash -c "echo -n '$main' > $entryPoint" &&` +
+				`$mergeParCmd -p --prefix $launcher -e $entryPoint $out $srcsZips && ` +
+				`chmod +x $out && (rm -f $entryPoint)`,
 			CommandDeps: []string{"$mergeParCmd"},
 		},
-		"main", "entryPoint", "mergedZip", "srcsZips", "launcher")
+		"main", "entryPoint", "srcsZips", "launcher")
 )
 
 func init() {
@@ -73,9 +77,6 @@
 	launcherPath android.OptionalPath, interpreter, main, binName string,
 	srcsZips android.Paths) android.Path {
 
-	// .intermediate output path for merged zip file.
-	mergedZip := android.PathForModuleOut(ctx, binName+".mergedzip")
-
 	// .intermediate output path for bin executable.
 	binFile := android.PathForModuleOut(ctx, binName)
 
@@ -96,12 +97,11 @@
 			Output:      binFile,
 			Implicits:   implicits,
 			Args: map[string]string{
-				"interp":    strings.Replace(interpreter, "/", `\/`, -1),
-				"main":      strings.Replace(main, "/", `\/`, -1),
-				"template":  template.String(),
-				"stub":      stub,
-				"mergedZip": mergedZip.String(),
-				"srcsZips":  strings.Join(srcsZips.Strings(), " "),
+				"interp":   strings.Replace(interpreter, "/", `\/`, -1),
+				"main":     strings.Replace(main, "/", `\/`, -1),
+				"template": template.String(),
+				"stub":     stub,
+				"srcsZips": strings.Join(srcsZips.Strings(), " "),
 			},
 		})
 	} else if launcherPath.Valid() {
@@ -117,9 +117,8 @@
 			Output:      binFile,
 			Implicits:   implicits,
 			Args: map[string]string{
-				"main":       main,
+				"main":       strings.Replace(strings.TrimSuffix(main, pyExt), "/", ".", -1),
 				"entryPoint": entryPoint,
-				"mergedZip":  mergedZip.String(),
 				"srcsZips":   strings.Join(srcsZips.Strings(), " "),
 				"launcher":   launcherPath.String(),
 			},
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index 81f8564..947458a 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -48,7 +48,8 @@
     "Malloc_not_svelte": false,
     "Safestack": false,
 
-    "Ndk_abis": true
+    "Ndk_abis": true,
+    "Exclude_draft_ndk_apis": true
 }
 EOF
 m --skip-make ${SOONG_OUT}/ndk.timestamp
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index 07925df..64f49cb 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -61,7 +61,7 @@
                       help='specify additional <uses-library> tag to add. android:requred is set to false')
   parser.add_argument('--uses-non-sdk-api', dest='uses_non_sdk_api', action='store_true',
                       help='manifest is for a package built against the platform')
-  parser.add_argument('--prefer-integrity', type=bool, dest='prefer_integrity',
+  parser.add_argument('--prefer-integrity', dest='prefer_integrity', action='store_true',
                       help=('specify if the app prefers strict integrity. Should not be conflict if ' +
                             'already declared in the manifest.'))
   parser.add_argument('input', help='input AndroidManifest.xml file')
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index d48ce58..e2e4368 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -75,18 +75,14 @@
 
 var Configuration = map[string]PathConfig{
 	"awk":       Allowed,
-	"basename":  Allowed,
 	"bash":      Allowed,
 	"bc":        Allowed,
 	"bzip2":     Allowed,
 	"chmod":     Allowed,
-	"cmp":       Allowed,
 	"cp":        Allowed,
-	"cut":       Allowed,
 	"date":      Allowed,
 	"dd":        Allowed,
 	"diff":      Allowed,
-	"dirname":   Allowed,
 	"du":        Allowed,
 	"echo":      Allowed,
 	"egrep":     Allowed,
@@ -98,7 +94,6 @@
 	"git":       Allowed,
 	"grep":      Allowed,
 	"gzip":      Allowed,
-	"head":      Allowed,
 	"hexdump":   Allowed,
 	"hostname":  Allowed,
 	"jar":       Allowed,
@@ -109,28 +104,22 @@
 	"lsof":      Allowed,
 	"m4":        Allowed,
 	"md5sum":    Allowed,
-	"mkdir":     Allowed,
 	"mktemp":    Allowed,
 	"mv":        Allowed,
-	"od":        Allowed,
 	"openssl":   Allowed,
-	"paste":     Allowed,
 	"patch":     Allowed,
 	"pgrep":     Allowed,
 	"pkill":     Allowed,
 	"ps":        Allowed,
 	"pstree":    Allowed,
-	"pwd":       Allowed,
 	"python":    Allowed,
 	"python2.7": Allowed,
 	"python3":   Allowed,
 	"readlink":  Allowed,
 	"realpath":  Allowed,
 	"rm":        Allowed,
-	"rmdir":     Allowed,
 	"rsync":     Allowed,
 	"sed":       Allowed,
-	"setsid":    Allowed,
 	"sh":        Allowed,
 	"sha1sum":   Allowed,
 	"sha256sum": Allowed,
@@ -138,18 +127,12 @@
 	"sort":      Allowed,
 	"stat":      Allowed,
 	"tar":       Allowed,
-	"tail":      Allowed,
-	"tee":       Allowed,
 	"timeout":   Allowed,
-	"todos":     Allowed,
-	"touch":     Allowed,
 	"tr":        Allowed,
-	"unix2dos":  Allowed,
 	"unzip":     Allowed,
 	"wc":        Allowed,
 	"which":     Allowed,
 	"xargs":     Allowed,
-	"xxd":       Allowed,
 	"xz":        Allowed,
 	"zip":       Allowed,
 	"zipinfo":   Allowed,
@@ -169,15 +152,31 @@
 	"pkg-config": Forbidden,
 
 	// On linux we'll use the toybox version of these instead
-	"cat":    Toybox,
-	"comm":   Toybox,
-	"env":    Toybox,
-	"id":     Toybox,
-	"sleep":  Toybox,
-	"true":   Toybox,
-	"uname":  Toybox,
-	"uniq":   Toybox,
-	"whoami": Toybox,
+	"basename": Toybox,
+	"cat":      Toybox,
+	"cmp":      Toybox,
+	"comm":     Toybox,
+	"cut":      Toybox,
+	"dirname":  Toybox,
+	"env":      Toybox,
+	"head":     Toybox,
+	"id":       Toybox,
+	"mkdir":    Toybox,
+	"od":       Toybox,
+	"paste":    Toybox,
+	"pwd":      Toybox,
+	"rmdir":    Toybox,
+	"setsid":   Toybox,
+	"sleep":    Toybox,
+	"tail":     Toybox,
+	"tee":      Toybox,
+	"touch":    Toybox,
+	"true":     Toybox,
+	"uname":    Toybox,
+	"uniq":     Toybox,
+	"unix2dos": Toybox,
+	"whoami":   Toybox,
+	"xxd":      Toybox,
 }
 
 func init() {