Merge "Remove perl from the allowed PATH tools list"
diff --git a/Android.bp b/Android.bp
index eefa149..2037818 100644
--- a/Android.bp
+++ b/Android.bp
@@ -40,6 +40,7 @@
     ],
     srcs: [
         "android/androidmk.go",
+        "android/apex.go",
         "android/api_levels.go",
         "android/arch.go",
         "android/config.go",
@@ -335,6 +336,22 @@
     pluginFor: ["soong_build"],
 }
 
+bootstrap_go_package {
+    name: "soong-apex",
+    pkgPath: "android/soong/apex",
+    deps: [
+        "blueprint",
+        "soong",
+        "soong-android",
+        "soong-cc",
+        "soong-java",
+    ],
+    srcs: [
+        "apex/apex.go",
+    ],
+    pluginFor: ["soong_build"],
+}
+
 //
 // Defaults to enable various configurations of host bionic
 //
diff --git a/android/apex.go b/android/apex.go
new file mode 100644
index 0000000..dae88ce
--- /dev/null
+++ b/android/apex.go
@@ -0,0 +1,102 @@
+// 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 android
+
+// 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).
+//
+// Native shared libraries are one such module type; when it is built for an
+// APEX, it should depend only on stable interfaces such as NDK, stable AIDL,
+// or C APIs from other APEXs.
+//
+// A module implementing this interface will be mutated into multiple
+// variations by the apex mutator if it is directly or indirectly included
+// in one or more APEXs. Specifically, if a module is included in apex.foo and
+// apex.bar then three apex variants are created: platform, apex.foo and
+// apex.bar. The platform variant is for the regular partitions
+// (e.g., /system or /vendor, etc.) while the other two are for the APEXs,
+// respectively.
+type ApexModule interface {
+	Module
+	apexModuleBase() *ApexModuleBase
+
+	// Marks that this module should be built for the APEX of the specified name
+	BuildForApex(apexName string)
+
+	// Tests whether this module will be built for the platform or not (= APEXs)
+	IsForPlatform() bool
+
+	// Returns the name of APEX that this module will be built for. Empty string
+	// is returned when 'IsForPlatform() == true'. Note that a module can be
+	// included to multiple APEXs, in which case, the module is mutated into
+	// multiple modules each of which for an APEX. This method returns the
+	// name of the APEX that a variant module is for.
+	ApexName() string
+
+	// Tests if this module can have APEX variants. APEX variants are
+	// created only for the modules that returns true here. This is useful
+	// for not creating APEX variants for shared libraries such as NDK stubs.
+	CanHaveApexVariants() bool
+
+	// Tests if this module can be installed to APEX as a file. For example,
+	// this would return true for shared libs while return false for static
+	// libs.
+	IsInstallableToApex() bool
+}
+
+type ApexProperties struct {
+	ApexName string `blueprint:"mutated"`
+}
+
+// Provides default implementation for the ApexModule interface. APEX-aware
+// modules are expected to include this struct and call InitApexModule().
+type ApexModuleBase struct {
+	ApexProperties ApexProperties
+
+	canHaveApexVariants bool
+}
+
+func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase {
+	return m
+}
+
+func (m *ApexModuleBase) BuildForApex(apexName string) {
+	m.ApexProperties.ApexName = apexName
+}
+
+func (m *ApexModuleBase) IsForPlatform() bool {
+	return m.ApexProperties.ApexName == ""
+}
+
+func (m *ApexModuleBase) ApexName() string {
+	return m.ApexProperties.ApexName
+}
+
+func (m *ApexModuleBase) CanHaveApexVariants() bool {
+	return m.canHaveApexVariants
+}
+
+func (m *ApexModuleBase) IsInstallableToApex() bool {
+	// should be overriden if needed
+	return false
+}
+
+func InitApexModule(m ApexModule) {
+	base := m.apexModuleBase()
+	base.canHaveApexVariants = true
+
+	m.AddProperties(&base.ApexProperties)
+}
diff --git a/android/arch.go b/android/arch.go
index 6516558..3378317 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1012,6 +1012,7 @@
 		{"arm", "armv7-a-neon", "cortex-a72", []string{"armeabi-v7a"}},
 		{"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"}},
@@ -1025,6 +1026,7 @@
 		{"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"}},
 		{"mips", "mips32-fp", "", []string{"mips"}},
 		{"mips", "mips32r2-fp", "", []string{"mips"}},
 		{"mips", "mips32r2-fp-xburst", "", []string{"mips"}},
diff --git a/android/neverallow.go b/android/neverallow.go
index a7f4f82..d3a2801 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -56,7 +56,9 @@
 		without("vendor", "true").
 		without("owner", "").
 		because("a VNDK module can never have an owner."),
-	neverallow().notIn("libcore", "development", "external/conscrypt").with("no_standard_libs", "true"),
+	neverallow().
+		notIn("libcore", "development", "external/apache-harmony", "external/apache-xml", "external/bouncycastle", "external/conscrypt", "external/icu", "external/okhttp", "external/wycheproof").
+		with("no_standard_libs", "true"),
 
 	// TODO(b/67974785): always enforce the manifest
 	neverallow().
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index 10e5b0a..b3d5aec 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -51,6 +51,7 @@
 	"LOCAL_MODULE_HOST_OS":        hostOs,
 	"LOCAL_SANITIZE":              sanitize(""),
 	"LOCAL_SANITIZE_DIAG":         sanitize("diag."),
+	"LOCAL_STRIP_MODULE":          strip(),
 	"LOCAL_CFLAGS":                cflags,
 	"LOCAL_UNINSTALLABLE_MODULE":  invert("installable"),
 	"LOCAL_PROGUARD_ENABLED":      proguardEnabled,
@@ -81,7 +82,6 @@
 		map[string]string{
 			"LOCAL_MODULE":                  "name",
 			"LOCAL_CXX_STL":                 "stl",
-			"LOCAL_STRIP_MODULE":            "strip",
 			"LOCAL_MULTILIB":                "compile_multilib",
 			"LOCAL_ARM_MODE_HACK":           "instruction_set",
 			"LOCAL_SDK_VERSION":             "sdk_version",
@@ -463,6 +463,29 @@
 	}
 }
 
+func strip() func(ctx variableAssignmentContext) error {
+	return func(ctx variableAssignmentContext) error {
+		val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.StringType)
+		if err != nil {
+			return err
+		}
+
+		if _, ok := val.(*bpparser.String); !ok {
+			return fmt.Errorf("unsupported strip expression")
+		}
+
+		bpTrue := &bpparser.Bool{
+			Value: true,
+		}
+		v := val.(*bpparser.String).Value
+		sub := (map[string]string{"false": "none", "true": "all", "keep_symbols": "keep_symbols"})[v]
+		if sub == "" {
+			return fmt.Errorf("unexpected strip option: %s", v)
+		}
+		return setVariable(ctx.file, false, ctx.prefix, "strip."+sub, bpTrue, true)
+	}
+}
+
 func prebuiltClass(ctx variableAssignmentContext) error {
 	class := ctx.mkvalue.Value(ctx.file.scope)
 	if v, ok := prebuiltTypes[class]; ok {
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index 80e7a75..0f6c5ac 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -692,6 +692,47 @@
 			}
 		`,
 	},
+	{
+		desc: "LOCAL_STRIP_MODULE",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := libtest
+LOCAL_STRIP_MODULE := false
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libtest2
+LOCAL_STRIP_MODULE := true
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libtest3
+LOCAL_STRIP_MODULE := keep_symbols
+include $(BUILD_SHARED_LIBRARY)
+`,
+		expected: `
+cc_library_shared {
+    name: "libtest",
+    strip: {
+        none: true,
+    }
+}
+
+cc_library_shared {
+    name: "libtest2",
+    strip: {
+        all: true,
+    }
+}
+
+cc_library_shared {
+    name: "libtest3",
+    strip: {
+        keep_symbols: true,
+    }
+}
+`,
+	},
 }
 
 func TestEndToEnd(t *testing.T) {
diff --git a/apex/apex.go b/apex/apex.go
new file mode 100644
index 0000000..68d9cb8
--- /dev/null
+++ b/apex/apex.go
@@ -0,0 +1,395 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package apex
+
+import (
+	"fmt"
+	"io"
+	"path/filepath"
+	"runtime"
+	"sort"
+	"strings"
+
+	"android/soong/android"
+	"android/soong/cc"
+	"android/soong/java"
+
+	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
+)
+
+var (
+	pctx = android.NewPackageContext("android/apex")
+
+	// Create a canned fs config file where all files and directories are
+	// by default set to (uid/gid/mode) = (1000/1000/0644)
+	// TODO(b/113082813) make this configurable using config.fs syntax
+	generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
+		Command: `echo '/ 1000 1000 0644' > ${out} && ` +
+			`echo '/manifest.json 1000 1000 0644' >> ${out} && ` +
+			`echo ${ro_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 1000 1000 0644"}' >> ${out} && ` +
+			`echo ${exec_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 1000 1000 0755"}' >> ${out}`,
+		Description: "fs_config ${out}",
+	}, "ro_paths", "exec_paths")
+
+	// TODO(b/113233103): make sure that file_contexts is sane, i.e., validate
+	// against the binary policy using sefcontext_compiler -p <policy>.
+
+	// TODO(b/114327326): automate the generation of file_contexts
+	apexRule = pctx.StaticRule("apexRule", blueprint.RuleParams{
+		Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
+			`(${copy_commands}) && ` +
+			`APEXER_TOOL_PATH=${tool_path} ` +
+			`${apexer} --verbose --force --manifest ${manifest} ` +
+			`--file_contexts ${file_contexts} ` +
+			`--canned_fs_config ${canned_fs_config} ` +
+			`--key ${key} ${image_dir} ${out} `,
+		CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}",
+			"${mke2fs}", "${resize2fs}", "${sefcontext_compile}",
+			"${soong_zip}", "${zipalign}", "${aapt2}"},
+		Description: "APEX ${image_dir} => ${out}",
+	}, "tool_path", "image_dir", "copy_commands", "manifest", "file_contexts", "canned_fs_config", "key")
+)
+
+var apexSuffix = ".apex"
+
+type dependencyTag struct {
+	blueprint.BaseDependencyTag
+	name string
+}
+
+var (
+	sharedLibTag  = dependencyTag{name: "sharedLib"}
+	executableTag = dependencyTag{name: "executable"}
+	javaLibTag    = dependencyTag{name: "javaLib"}
+	prebuiltTag   = dependencyTag{name: "prebuilt"}
+)
+
+func init() {
+	pctx.Import("android/soong/common")
+	pctx.HostBinToolVariable("apexer", "apexer")
+	pctx.HostBinToolVariable("aapt2", "aapt2")
+	pctx.HostBinToolVariable("avbtool", "avbtool")
+	pctx.HostBinToolVariable("e2fsdroid", "e2fsdroid")
+	pctx.HostBinToolVariable("merge_zips", "merge_zips")
+	pctx.HostBinToolVariable("mke2fs", "mke2fs")
+	pctx.HostBinToolVariable("resize2fs", "resize2fs")
+	pctx.HostBinToolVariable("sefcontext_compile", "sefcontext_compile")
+	pctx.HostBinToolVariable("soong_zip", "soong_zip")
+	pctx.HostBinToolVariable("zipalign", "zipalign")
+
+	android.RegisterModuleType("apex", apexBundleFactory)
+
+	android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.TopDown("apex_deps", apexDepsMutator)
+		ctx.BottomUp("apex", apexMutator)
+	})
+}
+
+// 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) {
+	if _, ok := mctx.Module().(*apexBundle); ok {
+		apexBundleName := mctx.Module().Name()
+		mctx.WalkDeps(func(child, parent android.Module) bool {
+			if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() {
+				moduleName := am.Name()
+				bundleNames, ok := apexBundleNamesFor(mctx.Config())[moduleName]
+				if !ok {
+					bundleNames = make(map[string]bool)
+					apexBundleNamesFor(mctx.Config())[moduleName] = bundleNames
+				}
+				bundleNames[apexBundleName] = true
+				return true
+			} else {
+				return false
+			}
+		})
+	}
+}
+
+// Create apex variations if a module is included in APEX(s).
+func apexMutator(mctx android.BottomUpMutatorContext) {
+	if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
+		moduleName := am.Name()
+		if bundleNames, ok := apexBundleNamesFor(mctx.Config())[moduleName]; ok {
+			variations := []string{"platform"}
+			for bn := range bundleNames {
+				variations = append(variations, bn)
+			}
+			modules := mctx.CreateVariations(variations...)
+			for i, m := range modules {
+				if i == 0 {
+					continue // platform
+				}
+				m.(android.ApexModule).BuildForApex(variations[i])
+			}
+		}
+	} else if _, ok := mctx.Module().(*apexBundle); ok {
+		// apex bundle itself is mutated so that it and its modules have same
+		// apex variant.
+		apexBundleName := mctx.ModuleName()
+		mctx.CreateVariations(apexBundleName)
+	}
+}
+
+type apexBundleProperties struct {
+	// Json manifest file describing meta info of this APEX bundle. Default:
+	// "manifest.json"
+	Manifest *string
+
+	// File contexts file for setting security context to each file in this APEX bundle
+	// Default: "file_contexts".
+	File_contexts *string
+
+	// List of native shared libs that are embedded inside this APEX bundle
+	Native_shared_libs []string
+
+	// List of native executables that are embedded inside this APEX bundle
+	Binaries []string
+
+	// List of java libraries that are embedded inside this APEX bundle
+	Java_libs []string
+
+	// List of prebuilt files that are embedded inside this APEX bundle
+	Prebuilts []string
+}
+
+type apexBundle struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	properties apexBundleProperties
+
+	outputFile android.WritablePath
+	installDir android.OutputPath
+}
+
+func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
+	// Native shared libs are added for all architectures of the device
+	// i.e., native_shared_lib_modules: ["libc"] adds both 64 and 32 variation
+	// of the module
+	arches := ctx.DeviceConfig().Arches()
+	if len(arches) == 0 {
+		panic("device build with no primary arch")
+	}
+
+	for _, arch := range ctx.MultiTargets() {
+		// Use *FarVariation* to be able to depend on modules having
+		// conflicting variations with this module. This is required since
+		// arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
+		// for native shared libs.
+		ctx.AddFarVariationDependencies([]blueprint.Variation{
+			{Mutator: "arch", Variation: arch.String()},
+			{Mutator: "image", Variation: "core"},
+			{Mutator: "link", Variation: "shared"},
+		}, sharedLibTag, a.properties.Native_shared_libs...)
+
+		ctx.AddFarVariationDependencies([]blueprint.Variation{
+			{Mutator: "arch", Variation: arch.String()},
+			{Mutator: "image", Variation: "core"},
+		}, executableTag, a.properties.Binaries...)
+
+		ctx.AddFarVariationDependencies([]blueprint.Variation{
+			{Mutator: "arch", Variation: "android_common"},
+		}, javaLibTag, a.properties.Java_libs...)
+
+		ctx.AddFarVariationDependencies([]blueprint.Variation{
+			{Mutator: "arch", Variation: "android_common"},
+		}, prebuiltTag, a.properties.Prebuilts...)
+	}
+
+}
+
+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.
+	switch cc.Arch().ArchType.Multilib {
+	case "lib32":
+		dirInApex = "lib"
+	case "lib64":
+		dirInApex = "lib64"
+	}
+	if !cc.Arch().Native {
+		dirInApex = filepath.Join(dirInApex, cc.Arch().ArchType.String())
+	}
+
+	fileToCopy = cc.OutputFile().Path()
+	return
+}
+
+func getCopyManifestForExecutable(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
+	dirInApex = "bin"
+	fileToCopy = cc.OutputFile().Path()
+	return
+}
+
+func getCopyManifestForJavaLibrary(java *java.Library) (fileToCopy android.Path, dirInApex string) {
+	dirInApex = "javalib"
+	fileToCopy = java.Srcs()[0]
+	return
+}
+
+func getCopyManifestForPrebuiltEtc(prebuilt *android.PrebuiltEtc) (fileToCopy android.Path, dirInApex string) {
+	dirInApex = filepath.Join("etc", prebuilt.SubDir())
+	fileToCopy = prebuilt.OutputFile()
+	return
+}
+
+func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	// files to copy -> dir in apex
+	copyManifest := make(map[android.Path]string)
+
+	ctx.WalkDeps(func(child, parent android.Module) bool {
+		if _, ok := parent.(*apexBundle); ok {
+			// direct dependencies
+			depTag := ctx.OtherModuleDependencyTag(child)
+			switch depTag {
+			case sharedLibTag:
+				if cc, ok := child.(*cc.Module); ok {
+					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
+					copyManifest[fileToCopy] = dirInApex
+					return true
+				}
+			case executableTag:
+				if cc, ok := child.(*cc.Module); ok {
+					fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
+					copyManifest[fileToCopy] = dirInApex
+					return true
+				}
+			case javaLibTag:
+				if java, ok := child.(*java.Library); ok {
+					fileToCopy, dirInApex := getCopyManifestForJavaLibrary(java)
+					copyManifest[fileToCopy] = dirInApex
+					return true
+				}
+			case prebuiltTag:
+				if prebuilt, ok := child.(*android.PrebuiltEtc); ok {
+					fileToCopy, dirInApex := getCopyManifestForPrebuiltEtc(prebuilt)
+					copyManifest[fileToCopy] = dirInApex
+					return true
+				}
+			}
+		} else {
+			// indirect dependencies
+			if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() && am.IsInstallableToApex() {
+				if cc, ok := child.(*cc.Module); ok {
+					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
+					copyManifest[fileToCopy] = dirInApex
+					return true
+				}
+			}
+		}
+		return false
+	})
+
+	// files and dirs that will be created in apex
+	var readOnlyPaths []string
+	var executablePaths []string // this also includes dirs
+	for fileToCopy, dirInApex := range copyManifest {
+		pathInApex := filepath.Join(dirInApex, fileToCopy.Base())
+		if dirInApex == "bin" {
+			executablePaths = append(executablePaths, pathInApex)
+		} else {
+			readOnlyPaths = append(readOnlyPaths, pathInApex)
+		}
+		if !android.InList(dirInApex, executablePaths) {
+			executablePaths = append(executablePaths, dirInApex)
+		}
+	}
+	sort.Strings(readOnlyPaths)
+	sort.Strings(executablePaths)
+	cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config")
+	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+		Rule:   generateFsConfig,
+		Output: cannedFsConfig,
+		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"))
+	fileContexts := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.File_contexts, "file_contexts"))
+	// TODO(b/114488804) make this customizable
+	key := android.PathForSource(ctx, "system/apex/apexer/testdata/testkey.pem")
+
+	a.outputFile = android.PathForModuleOut(ctx, a.ModuleBase.Name()+apexSuffix)
+
+	filesToCopy := []android.Path{}
+	for file := range copyManifest {
+		filesToCopy = append(filesToCopy, file)
+	}
+	sort.Slice(filesToCopy, func(i, j int) bool {
+		return filesToCopy[i].String() < filesToCopy[j].String()
+	})
+
+	copyCommands := []string{}
+	for _, src := range filesToCopy {
+		dest := filepath.Join(copyManifest[src], src.Base())
+		dest_path := filepath.Join(android.PathForModuleOut(ctx, "image").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, key)
+	outHostBinDir := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin").String()
+	prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin")
+	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+		Rule:      apexRule,
+		Implicits: implicitInputs,
+		Output:    a.outputFile,
+		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":              key.String(),
+		},
+	})
+
+	a.installDir = android.PathForModuleInstall(ctx, "apex")
+}
+
+func (a *apexBundle) AndroidMk() android.AndroidMkData {
+	return android.AndroidMkData{
+		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+			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_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", a.installDir.RelPathString()))
+			fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name+apexSuffix)
+			fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
+		}}
+}
+
+func apexBundleFactory() android.Module {
+	module := &apexBundle{}
+	module.AddProperties(&module.properties)
+	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
+	return module
+}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 5daacb7..324b5bc 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -51,7 +51,7 @@
 }
 
 func (c *Module) AndroidMk() android.AndroidMkData {
-	if c.Properties.HideFromMake {
+	if c.Properties.HideFromMake || !c.IsForPlatform() {
 		return android.AndroidMkData{
 			Disabled: true,
 		}
diff --git a/cc/builder.go b/cc/builder.go
index d16efd0..d9a6cae 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -169,7 +169,7 @@
 	// -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information.
 	sAbiDump = pctx.AndroidStaticRule("sAbiDump",
 		blueprint.RuleParams{
-			Command:     "rm -f $out && $sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem ${config.RSIncludePath}",
+			Command:     "rm -f $out && $sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem prebuilts/clang-tools/${config.HostPrebuiltTag}/clang-headers",
 			CommandDeps: []string{"$sAbiDumper"},
 		},
 		"cFlags", "exportDirs")
diff --git a/cc/cc.go b/cc/cc.go
index 5f3baea..6320b9c 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -320,6 +320,7 @@
 type Module struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
+	android.ApexModuleBase
 
 	Properties       BaseProperties
 	VendorProperties VendorProperties
@@ -416,6 +417,8 @@
 
 	android.InitDefaultableModule(c)
 
+	android.InitApexModule(c)
+
 	return c
 }
 
@@ -794,7 +797,7 @@
 		c.outputFile = android.OptionalPathForPath(outputFile)
 	}
 
-	if c.installer != nil && !c.Properties.PreventInstall && c.outputFile.Valid() {
+	if c.installer != nil && !c.Properties.PreventInstall && c.IsForPlatform() && c.outputFile.Valid() {
 		c.installer.install(ctx, c.outputFile.Path())
 		if ctx.Failed() {
 			return
@@ -1511,12 +1514,24 @@
 	}
 }
 
+// Overrides ApexModule.IsInstallabeToApex()
+// Only shared libraries are installable to APEX.
+func (c *Module) IsInstallableToApex() bool {
+	if shared, ok := c.linker.(interface {
+		shared() bool
+	}); ok {
+		return shared.shared()
+	}
+	return false
+}
+
 //
 // Defaults
 //
 type Defaults struct {
 	android.ModuleBase
 	android.DefaultsModuleBase
+	android.ApexModuleBase
 }
 
 func (*Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1558,6 +1573,7 @@
 	)
 
 	android.InitDefaultsModule(module)
+	android.InitApexModule(module)
 
 	return module
 }
diff --git a/cc/cc_test.go b/cc/cc_test.go
index bca26ea..ead89f6 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -87,6 +87,34 @@
 		}
 
 		toolchain_library {
+			name: "libclang_rt.builtins-arm-android",
+			vendor_available: true,
+			recovery_available: true,
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libclang_rt.builtins-aarch64-android",
+			vendor_available: true,
+			recovery_available: true,
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libclang_rt.builtins-i686-android",
+			vendor_available: true,
+			recovery_available: true,
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libclang_rt.builtins-x86_64-android",
+			vendor_available: true,
+			recovery_available: true,
+			src: "",
+		}
+
+		toolchain_library {
 			name: "libgcc",
 			vendor_available: true,
 			recovery_available: true,
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index cd81eab..6a63828 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -48,7 +48,7 @@
 
 	arm64Cppflags = []string{}
 
-	arm64CpuVariantCflags = map[string][]string{
+	arm64ClangCpuVariantCflags = map[string][]string{
 		"cortex-a53": []string{
 			"-mcpu=cortex-a53",
 		},
@@ -60,10 +60,13 @@
 			// core (cortex-a55) and is sensitive to ordering.
 			"-mcpu=cortex-a55",
 		},
+		"cortex-a76": []string{
+			// Use the cortex-a55 since it is similar to the little
+			// core (cortex-a55) and is sensitive to ordering.
+			"-mcpu=cortex-a55",
+		},
 		"kryo": []string{
-			// Use the cortex-a57 cpu since some compilers
-			// don't support a Kryo specific target yet.
-			"-mcpu=cortex-a57",
+			"-mcpu=kryo",
 		},
 		"exynos-m1": []string{
 			"-mcpu=exynos-m1",
@@ -72,8 +75,6 @@
 			"-mcpu=exynos-m2",
 		},
 	}
-
-	arm64ClangCpuVariantCflags = copyVariantFlags(arm64CpuVariantCflags)
 )
 
 const (
@@ -89,23 +90,19 @@
 		"cortex-a72",
 		"cortex-a73",
 		"cortex-a75",
+		"cortex-a76",
 		"kryo",
 		"exynos-m1",
 		"exynos-m2",
 		"denver64")
 
-	// Clang supports specific Kryo targeting
-	replaceFirst(arm64ClangCpuVariantCflags["kryo"], "-mcpu=cortex-a57", "-mcpu=kryo")
-
 	pctx.StaticVariable("arm64GccVersion", arm64GccVersion)
 
 	pctx.SourcePathVariable("Arm64GccRoot",
 		"prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}")
 
-	pctx.StaticVariable("Arm64Cflags", strings.Join(arm64Cflags, " "))
 	pctx.StaticVariable("Arm64Ldflags", strings.Join(arm64Ldflags, " "))
 	pctx.StaticVariable("Arm64Lldflags", strings.Join(arm64Lldflags, " "))
-	pctx.StaticVariable("Arm64Cppflags", strings.Join(arm64Cppflags, " "))
 	pctx.StaticVariable("Arm64IncludeFlags", bionicHeaders("arm64"))
 
 	pctx.StaticVariable("Arm64ClangCflags", strings.Join(ClangFilterUnknownCflags(arm64Cflags), " "))
@@ -116,45 +113,23 @@
 	pctx.StaticVariable("Arm64ClangArmv8ACflags", strings.Join(arm64ArchVariantCflags["armv8-a"], " "))
 	pctx.StaticVariable("Arm64ClangArmv82ACflags", strings.Join(arm64ArchVariantCflags["armv8-2a"], " "))
 
-	pctx.StaticVariable("Arm64CortexA53Cflags",
-		strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
 	pctx.StaticVariable("Arm64ClangCortexA53Cflags",
 		strings.Join(arm64ClangCpuVariantCflags["cortex-a53"], " "))
 
-	pctx.StaticVariable("Arm64CortexA55Cflags",
-		strings.Join(arm64CpuVariantCflags["cortex-a55"], " "))
 	pctx.StaticVariable("Arm64ClangCortexA55Cflags",
 		strings.Join(arm64ClangCpuVariantCflags["cortex-a55"], " "))
 
-	pctx.StaticVariable("Arm64KryoCflags",
-		strings.Join(arm64CpuVariantCflags["kryo"], " "))
 	pctx.StaticVariable("Arm64ClangKryoCflags",
 		strings.Join(arm64ClangCpuVariantCflags["kryo"], " "))
 
-	pctx.StaticVariable("Arm64ExynosM1Cflags",
-		strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
 	pctx.StaticVariable("Arm64ClangExynosM1Cflags",
 		strings.Join(arm64ClangCpuVariantCflags["exynos-m1"], " "))
 
-	pctx.StaticVariable("Arm64ExynosM2Cflags",
-		strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
 	pctx.StaticVariable("Arm64ClangExynosM2Cflags",
 		strings.Join(arm64ClangCpuVariantCflags["exynos-m2"], " "))
 }
 
 var (
-	arm64CpuVariantCflagsVar = map[string]string{
-		"":           "",
-		"cortex-a53": "${config.Arm64CortexA53Cflags}",
-		"cortex-a55": "${config.Arm64CortexA55Cflags}",
-		"cortex-a72": "${config.Arm64CortexA53Cflags}",
-		"cortex-a73": "${config.Arm64CortexA53Cflags}",
-		"cortex-a75": "${config.Arm64CortexA55Cflags}",
-		"kryo":       "${config.Arm64KryoCflags}",
-		"exynos-m1":  "${config.Arm64ExynosM1Cflags}",
-		"exynos-m2":  "${config.Arm64ExynosM2Cflags}",
-	}
-
 	arm64ClangArchVariantCflagsVar = map[string]string{
 		"armv8-a":  "${config.Arm64ClangArmv8ACflags}",
 		"armv8-2a": "${config.Arm64ClangArmv82ACflags}",
@@ -167,6 +142,7 @@
 		"cortex-a72": "${config.Arm64ClangCortexA53Cflags}",
 		"cortex-a73": "${config.Arm64ClangCortexA53Cflags}",
 		"cortex-a75": "${config.Arm64ClangCortexA55Cflags}",
+		"cortex-a76": "${config.Arm64ClangCortexA55Cflags}",
 		"kryo":       "${config.Arm64ClangKryoCflags}",
 		"exynos-m1":  "${config.Arm64ClangExynosM1Cflags}",
 		"exynos-m2":  "${config.Arm64ClangExynosM2Cflags}",
@@ -178,7 +154,6 @@
 
 	ldflags              string
 	lldflags             string
-	toolchainCflags      string
 	toolchainClangCflags string
 }
 
@@ -198,22 +173,6 @@
 	return arm64GccVersion
 }
 
-func (t *toolchainArm64) ToolchainCflags() string {
-	return t.toolchainCflags
-}
-
-func (t *toolchainArm64) Cflags() string {
-	return "${config.Arm64Cflags}"
-}
-
-func (t *toolchainArm64) Cppflags() string {
-	return "${config.Arm64Cppflags}"
-}
-
-func (t *toolchainArm64) Ldflags() string {
-	return t.ldflags
-}
-
 func (t *toolchainArm64) IncludeFlags() string {
 	return "${config.Arm64IncludeFlags}"
 }
@@ -277,7 +236,6 @@
 			"${config.Arm64Lldflags}",
 			extraLdflags,
 		}, " "),
-		toolchainCflags:      variantOrDefault(arm64CpuVariantCflagsVar, arch.CpuVariant),
 		toolchainClangCflags: strings.Join(toolchainClangCflags, " "),
 	}
 }
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index 8dee2c8..75f5962 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -50,7 +50,7 @@
 		"-Os",
 	}
 
-	armArchVariantCflags = map[string][]string{
+	armClangArchVariantCflags = map[string][]string{
 		"armv7-a": []string{
 			"-march=armv7-a",
 			"-mfloat-abi=softfp",
@@ -68,7 +68,7 @@
 		},
 	}
 
-	armCpuVariantCflags = map[string][]string{
+	armClangCpuVariantCflags = map[string][]string{
 		"cortex-a7": []string{
 			"-mcpu=cortex-a7",
 			"-mfpu=neon-vfpv4",
@@ -117,8 +117,17 @@
 			// better solution comes around. See Bug 27340895
 			"-D__ARM_FEATURE_LPAE=1",
 		},
+		"cortex-a76": []string{
+			"-mcpu=cortex-a55",
+			"-mfpu=neon-fp-armv8",
+			// 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",
+		},
 		"krait": []string{
-			"-mcpu=cortex-a15",
+			"-mcpu=krait",
 			"-mfpu=neon-vfpv4",
 			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
 			// don't advertise.
@@ -138,9 +147,6 @@
 			"-D__ARM_FEATURE_LPAE=1",
 		},
 	}
-
-	armClangCpuVariantCflags  = copyVariantFlags(armCpuVariantCflags)
-	armClangArchVariantCflags = copyVariantFlags(armArchVariantCflags)
 )
 
 const (
@@ -165,6 +171,7 @@
 		"cortex-a72",
 		"cortex-a73",
 		"cortex-a75",
+		"cortex-a76",
 		"krait",
 		"kryo",
 		"exynos-m1",
@@ -174,49 +181,15 @@
 	android.RegisterArchVariantFeatures(android.Arm, "armv7-a-neon", "neon")
 	android.RegisterArchVariantFeatures(android.Arm, "armv8-a", "neon")
 
-	// Krait is not supported by GCC, but is supported by Clang, so
-	// override the definitions when building modules with Clang.
-	replaceFirst(armClangCpuVariantCflags["krait"], "-mcpu=cortex-a15", "-mcpu=krait")
-
-	// The reason we use "-march=armv8-a+crc", instead of "-march=armv8-a", for
-	// gcc is the latter would conflict with any specified/supported -mcpu!
-	// All armv8-a cores supported by gcc 4.9 support crc, so it's safe
-	// to add +crc. Besides, the use of gcc is only for legacy code.
-	replaceFirst(armArchVariantCflags["armv8-a"], "-march=armv8-a", "-march=armv8-a+crc")
-
 	pctx.StaticVariable("armGccVersion", armGccVersion)
 
 	pctx.SourcePathVariable("ArmGccRoot",
 		"prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}")
 
-	pctx.StaticVariable("ArmToolchainCflags", strings.Join(armToolchainCflags, " "))
-	pctx.StaticVariable("ArmCflags", strings.Join(armCflags, " "))
 	pctx.StaticVariable("ArmLdflags", strings.Join(armLdflags, " "))
 	pctx.StaticVariable("ArmLldflags", strings.Join(armLldflags, " "))
-	pctx.StaticVariable("ArmCppflags", strings.Join(armCppflags, " "))
 	pctx.StaticVariable("ArmIncludeFlags", bionicHeaders("arm"))
 
-	// Extended cflags
-
-	// ARM vs. Thumb instruction set flags
-	pctx.StaticVariable("ArmArmCflags", strings.Join(armArmCflags, " "))
-	pctx.StaticVariable("ArmThumbCflags", strings.Join(armThumbCflags, " "))
-
-	// Architecture variant cflags
-	pctx.StaticVariable("ArmArmv7ACflags", strings.Join(armArchVariantCflags["armv7-a"], " "))
-	pctx.StaticVariable("ArmArmv7ANeonCflags", strings.Join(armArchVariantCflags["armv7-a-neon"], " "))
-	pctx.StaticVariable("ArmArmv8ACflags", strings.Join(armArchVariantCflags["armv8-a"], " "))
-
-	// Cpu variant cflags
-	pctx.StaticVariable("ArmGenericCflags", strings.Join(armCpuVariantCflags[""], " "))
-	pctx.StaticVariable("ArmCortexA7Cflags", strings.Join(armCpuVariantCflags["cortex-a7"], " "))
-	pctx.StaticVariable("ArmCortexA8Cflags", strings.Join(armCpuVariantCflags["cortex-a8"], " "))
-	pctx.StaticVariable("ArmCortexA15Cflags", strings.Join(armCpuVariantCflags["cortex-a15"], " "))
-	pctx.StaticVariable("ArmCortexA53Cflags", strings.Join(armCpuVariantCflags["cortex-a53"], " "))
-	pctx.StaticVariable("ArmCortexA55Cflags", strings.Join(armCpuVariantCflags["cortex-a55"], " "))
-	pctx.StaticVariable("ArmKraitCflags", strings.Join(armCpuVariantCflags["krait"], " "))
-	pctx.StaticVariable("ArmKryoCflags", strings.Join(armCpuVariantCflags["kryo"], " "))
-
 	// Clang cflags
 	pctx.StaticVariable("ArmToolchainClangCflags", strings.Join(ClangFilterUnknownCflags(armToolchainCflags), " "))
 	pctx.StaticVariable("ArmClangCflags", strings.Join(ClangFilterUnknownCflags(armCflags), " "))
@@ -256,30 +229,6 @@
 }
 
 var (
-	armArchVariantCflagsVar = map[string]string{
-		"armv7-a":      "${config.ArmArmv7ACflags}",
-		"armv7-a-neon": "${config.ArmArmv7ANeonCflags}",
-		"armv8-a":      "${config.ArmArmv8ACflags}",
-	}
-
-	armCpuVariantCflagsVar = map[string]string{
-		"":               "${config.ArmGenericCflags}",
-		"cortex-a7":      "${config.ArmCortexA7Cflags}",
-		"cortex-a8":      "${config.ArmCortexA8Cflags}",
-		"cortex-a15":     "${config.ArmCortexA15Cflags}",
-		"cortex-a53":     "${config.ArmCortexA53Cflags}",
-		"cortex-a53.a57": "${config.ArmCortexA53Cflags}",
-		"cortex-a55":     "${config.ArmCortexA55Cflags}",
-		"cortex-a72":     "${config.ArmCortexA53Cflags}",
-		"cortex-a73":     "${config.ArmCortexA53Cflags}",
-		"cortex-a75":     "${config.ArmCortexA55Cflags}",
-		"krait":          "${config.ArmKraitCflags}",
-		"kryo":           "${config.ArmKryoCflags}",
-		"exynos-m1":      "${config.ArmCortexA53Cflags}",
-		"exynos-m2":      "${config.ArmCortexA53Cflags}",
-		"denver":         "${config.ArmCortexA15Cflags}",
-	}
-
 	armClangArchVariantCflagsVar = map[string]string{
 		"armv7-a":      "${config.ArmClangArmv7ACflags}",
 		"armv7-a-neon": "${config.ArmClangArmv7ANeonCflags}",
@@ -307,9 +256,9 @@
 
 type toolchainArm struct {
 	toolchain32Bit
-	ldflags                               string
-	lldflags                              string
-	toolchainCflags, toolchainClangCflags string
+	ldflags              string
+	lldflags             string
+	toolchainClangCflags string
 }
 
 func (t *toolchainArm) Name() string {
@@ -328,22 +277,6 @@
 	return armGccVersion
 }
 
-func (t *toolchainArm) ToolchainCflags() string {
-	return t.toolchainCflags
-}
-
-func (t *toolchainArm) Cflags() string {
-	return "${config.ArmCflags}"
-}
-
-func (t *toolchainArm) Cppflags() string {
-	return "${config.ArmCppflags}"
-}
-
-func (t *toolchainArm) Ldflags() string {
-	return t.ldflags
-}
-
 func (t *toolchainArm) IncludeFlags() string {
 	return "${config.ArmIncludeFlags}"
 }
@@ -395,16 +328,11 @@
 
 func armToolchainFactory(arch android.Arch) Toolchain {
 	var fixCortexA8 string
-	toolchainCflags := make([]string, 2, 3)
 	toolchainClangCflags := make([]string, 2, 3)
 
-	toolchainCflags[0] = "${config.ArmToolchainCflags}"
-	toolchainCflags[1] = armArchVariantCflagsVar[arch.ArchVariant]
 	toolchainClangCflags[0] = "${config.ArmToolchainClangCflags}"
 	toolchainClangCflags[1] = armClangArchVariantCflagsVar[arch.ArchVariant]
 
-	toolchainCflags = append(toolchainCflags,
-		variantOrDefault(armCpuVariantCflagsVar, arch.CpuVariant))
 	toolchainClangCflags = append(toolchainClangCflags,
 		variantOrDefault(armClangCpuVariantCflagsVar, arch.CpuVariant))
 
@@ -426,7 +354,6 @@
 	}
 
 	return &toolchainArm{
-		toolchainCflags: strings.Join(toolchainCflags, " "),
 		ldflags: strings.Join([]string{
 			"${config.ArmLdflags}",
 			fixCortexA8,
diff --git a/cc/config/global.go b/cc/config/global.go
index 8a3d545..330cb10 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -15,7 +15,6 @@
 package config
 
 import (
-	"fmt"
 	"runtime"
 	"strings"
 
@@ -126,8 +125,8 @@
 
 	// prebuilts/clang default settings.
 	ClangDefaultBase         = "prebuilts/clang/host"
-	ClangDefaultVersion      = "clang-r339409"
-	ClangDefaultShortVersion = "8.0.1"
+	ClangDefaultVersion      = "clang-r339409b"
+	ClangDefaultShortVersion = "8.0.2"
 
 	// Directories with warnings from Android.bp files.
 	WarningAllowedProjects = []string{
@@ -250,10 +249,3 @@
 		"-isystem bionic/libc/kernel/android/uapi",
 	}, " ")
 }
-
-func replaceFirst(slice []string, from, to string) {
-	if slice[0] != from {
-		panic(fmt.Errorf("Expected %q, found %q", from, to))
-	}
-	slice[0] = to
-}
diff --git a/cc/config/mips64_device.go b/cc/config/mips64_device.go
index 0c4640b..561d8d6 100644
--- a/cc/config/mips64_device.go
+++ b/cc/config/mips64_device.go
@@ -69,9 +69,6 @@
 	pctx.SourcePathVariable("Mips64GccRoot",
 		"prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mips64GccVersion}")
 
-	pctx.StaticVariable("Mips64Cflags", strings.Join(mips64Cflags, " "))
-	pctx.StaticVariable("Mips64Ldflags", strings.Join(mips64Ldflags, " "))
-	pctx.StaticVariable("Mips64Cppflags", strings.Join(mips64Cppflags, " "))
 	pctx.StaticVariable("Mips64IncludeFlags", bionicHeaders("mips"))
 
 	// Clang cflags
@@ -83,7 +80,6 @@
 
 	// Architecture variant cflags
 	for variant, cflags := range mips64ArchVariantCflags {
-		pctx.StaticVariable("Mips64"+variant+"VariantCflags", strings.Join(cflags, " "))
 		pctx.StaticVariable("Mips64"+variant+"VariantClangCflags",
 			strings.Join(ClangFilterUnknownCflags(cflags), " "))
 	}
@@ -91,8 +87,8 @@
 
 type toolchainMips64 struct {
 	toolchain64Bit
-	cflags, clangCflags                   string
-	toolchainCflags, toolchainClangCflags string
+	clangCflags          string
+	toolchainClangCflags string
 }
 
 func (t *toolchainMips64) Name() string {
@@ -111,22 +107,6 @@
 	return mips64GccVersion
 }
 
-func (t *toolchainMips64) ToolchainCflags() string {
-	return t.toolchainCflags
-}
-
-func (t *toolchainMips64) Cflags() string {
-	return t.cflags
-}
-
-func (t *toolchainMips64) Cppflags() string {
-	return "${config.Mips64Cppflags}"
-}
-
-func (t *toolchainMips64) Ldflags() string {
-	return "${config.Mips64Ldflags}"
-}
-
 func (t *toolchainMips64) IncludeFlags() string {
 	return "${config.Mips64IncludeFlags}"
 }
@@ -166,9 +146,7 @@
 
 func mips64ToolchainFactory(arch android.Arch) Toolchain {
 	return &toolchainMips64{
-		cflags:               "${config.Mips64Cflags}",
 		clangCflags:          "${config.Mips64ClangCflags}",
-		toolchainCflags:      "${config.Mips64" + arch.ArchVariant + "VariantCflags}",
 		toolchainClangCflags: "${config.Mips64" + arch.ArchVariant + "VariantClangCflags}",
 	}
 }
diff --git a/cc/config/mips_device.go b/cc/config/mips_device.go
index eb44fd5..8cd35b3 100644
--- a/cc/config/mips_device.go
+++ b/cc/config/mips_device.go
@@ -111,9 +111,6 @@
 		"prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mipsGccVersion}")
 
 	pctx.StaticVariable("MipsToolchainLdflags", strings.Join(mipsToolchainLdflags, " "))
-	pctx.StaticVariable("MipsCflags", strings.Join(mipsCflags, " "))
-	pctx.StaticVariable("MipsLdflags", strings.Join(mipsLdflags, " "))
-	pctx.StaticVariable("MipsCppflags", strings.Join(mipsCppflags, " "))
 	pctx.StaticVariable("MipsIncludeFlags", bionicHeaders("mips"))
 
 	// Clang cflags
@@ -125,7 +122,6 @@
 
 	// Architecture variant cflags
 	for variant, cflags := range mipsArchVariantCflags {
-		pctx.StaticVariable("Mips"+variant+"VariantCflags", strings.Join(cflags, " "))
 		pctx.StaticVariable("Mips"+variant+"VariantClangCflags",
 			strings.Join(ClangFilterUnknownCflags(cflags), " "))
 	}
@@ -133,8 +129,8 @@
 
 type toolchainMips struct {
 	toolchain32Bit
-	cflags, clangCflags                   string
-	toolchainCflags, toolchainClangCflags string
+	clangCflags          string
+	toolchainClangCflags string
 }
 
 func (t *toolchainMips) Name() string {
@@ -153,26 +149,6 @@
 	return mipsGccVersion
 }
 
-func (t *toolchainMips) ToolchainLdflags() string {
-	return "${config.MipsToolchainLdflags}"
-}
-
-func (t *toolchainMips) ToolchainCflags() string {
-	return t.toolchainCflags
-}
-
-func (t *toolchainMips) Cflags() string {
-	return t.cflags
-}
-
-func (t *toolchainMips) Cppflags() string {
-	return "${config.MipsCppflags}"
-}
-
-func (t *toolchainMips) Ldflags() string {
-	return "${config.MipsLdflags}"
-}
-
 func (t *toolchainMips) IncludeFlags() string {
 	return "${config.MipsIncludeFlags}"
 }
@@ -216,9 +192,7 @@
 
 func mipsToolchainFactory(arch android.Arch) Toolchain {
 	return &toolchainMips{
-		cflags:               "${config.MipsCflags}",
 		clangCflags:          "${config.MipsClangCflags}",
-		toolchainCflags:      "${config.Mips" + arch.ArchVariant + "VariantCflags}",
 		toolchainClangCflags: "${config.Mips" + arch.ArchVariant + "VariantClangCflags}",
 	}
 }
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index 0b9f4ed..d5e9d01 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -162,18 +162,6 @@
 	return false
 }
 
-func copyVariantFlags(m map[string][]string) map[string][]string {
-	ret := make(map[string][]string, len(m))
-	for k, v := range m {
-		l := make([]string, len(m[k]))
-		for i := range m[k] {
-			l[i] = v[i]
-		}
-		ret[k] = l
-	}
-	return ret
-}
-
 func variantOrDefault(variants map[string]string, choice string) string {
 	if ret, ok := variants[choice]; ok {
 		return ret
@@ -232,6 +220,10 @@
 	return LibclangRuntimeLibrary(t, "scudo")
 }
 
+func ScudoMinimalRuntimeLibrary(t Toolchain) string {
+	return LibclangRuntimeLibrary(t, "scudo_minimal")
+}
+
 func ToolPath(t Toolchain) string {
 	if p := t.ToolPath(); p != "" {
 		return p
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index 5e2dc49..ff8a6da 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -125,10 +125,8 @@
 	pctx.StaticVariable("X86_64ToolchainCflags", "-m64")
 	pctx.StaticVariable("X86_64ToolchainLdflags", "-m64")
 
-	pctx.StaticVariable("X86_64Cflags", strings.Join(x86_64Cflags, " "))
 	pctx.StaticVariable("X86_64Ldflags", strings.Join(x86_64Ldflags, " "))
 	pctx.StaticVariable("X86_64Lldflags", strings.Join(x86_64Lldflags, " "))
-	pctx.StaticVariable("X86_64Cppflags", strings.Join(x86_64Cppflags, " "))
 	pctx.StaticVariable("X86_64IncludeFlags", bionicHeaders("x86"))
 
 	// Clang cflags
@@ -144,7 +142,6 @@
 
 	// Architecture variant cflags
 	for variant, cflags := range x86_64ArchVariantCflags {
-		pctx.StaticVariable("X86_64"+variant+"VariantCflags", strings.Join(cflags, " "))
 		pctx.StaticVariable("X86_64"+variant+"VariantClangCflags",
 			strings.Join(ClangFilterUnknownCflags(cflags), " "))
 	}
@@ -152,7 +149,7 @@
 
 type toolchainX86_64 struct {
 	toolchain64Bit
-	toolchainCflags, toolchainClangCflags string
+	toolchainClangCflags string
 }
 
 func (t *toolchainX86_64) Name() string {
@@ -171,26 +168,6 @@
 	return x86_64GccVersion
 }
 
-func (t *toolchainX86_64) ToolchainLdflags() string {
-	return "${config.X86_64ToolchainLdflags}"
-}
-
-func (t *toolchainX86_64) ToolchainCflags() string {
-	return t.toolchainCflags
-}
-
-func (t *toolchainX86_64) Cflags() string {
-	return "${config.X86_64Cflags}"
-}
-
-func (t *toolchainX86_64) Cppflags() string {
-	return "${config.X86_64Cppflags}"
-}
-
-func (t *toolchainX86_64) Ldflags() string {
-	return "${config.X86_64Ldflags}"
-}
-
 func (t *toolchainX86_64) IncludeFlags() string {
 	return "${config.X86_64IncludeFlags}"
 }
@@ -232,23 +209,16 @@
 }
 
 func x86_64ToolchainFactory(arch android.Arch) Toolchain {
-	toolchainCflags := []string{
-		"${config.X86_64ToolchainCflags}",
-		"${config.X86_64" + arch.ArchVariant + "VariantCflags}",
-	}
-
 	toolchainClangCflags := []string{
 		"${config.X86_64ToolchainCflags}",
 		"${config.X86_64" + arch.ArchVariant + "VariantClangCflags}",
 	}
 
 	for _, feature := range arch.ArchFeatures {
-		toolchainCflags = append(toolchainCflags, x86_64ArchFeatureCflags[feature]...)
 		toolchainClangCflags = append(toolchainClangCflags, x86_64ArchFeatureCflags[feature]...)
 	}
 
 	return &toolchainX86_64{
-		toolchainCflags:      strings.Join(toolchainCflags, " "),
 		toolchainClangCflags: strings.Join(toolchainClangCflags, " "),
 	}
 }
diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go
index 694137d..09632db 100644
--- a/cc/config/x86_darwin_host.go
+++ b/cc/config/x86_darwin_host.go
@@ -117,9 +117,6 @@
 
 	pctx.StaticVariable("DarwinGccTriple", "i686-apple-darwin11")
 
-	pctx.StaticVariable("DarwinCflags", strings.Join(darwinCflags, " "))
-	pctx.StaticVariable("DarwinLdflags", strings.Join(darwinLdflags, " "))
-
 	pctx.StaticVariable("DarwinClangCflags", strings.Join(darwinClangCflags, " "))
 	pctx.StaticVariable("DarwinClangLdflags", strings.Join(darwinClangLdflags, " "))
 	pctx.StaticVariable("DarwinClangLldflags", strings.Join(darwinClangLldflags, " "))
@@ -182,18 +179,6 @@
 	return darwinGccVersion
 }
 
-func (t *toolchainDarwin) Cflags() string {
-	return "${config.DarwinCflags}"
-}
-
-func (t *toolchainDarwin) Cppflags() string {
-	return ""
-}
-
-func (t *toolchainDarwin) Ldflags() string {
-	return "${config.DarwinLdflags}"
-}
-
 func (t *toolchainDarwin) IncludeFlags() string {
 	return ""
 }
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index ffdf8ea..fc0b1d8 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -149,10 +149,8 @@
 	pctx.StaticVariable("X86ToolchainCflags", "-m32")
 	pctx.StaticVariable("X86ToolchainLdflags", "-m32")
 
-	pctx.StaticVariable("X86Cflags", strings.Join(x86Cflags, " "))
 	pctx.StaticVariable("X86Ldflags", strings.Join(x86Ldflags, " "))
 	pctx.StaticVariable("X86Lldflags", strings.Join(x86Lldflags, " "))
-	pctx.StaticVariable("X86Cppflags", strings.Join(x86Cppflags, " "))
 	pctx.StaticVariable("X86IncludeFlags", bionicHeaders("x86"))
 
 	// Clang cflags
@@ -168,7 +166,6 @@
 
 	// Architecture variant cflags
 	for variant, cflags := range x86ArchVariantCflags {
-		pctx.StaticVariable("X86"+variant+"VariantCflags", strings.Join(cflags, " "))
 		pctx.StaticVariable("X86"+variant+"VariantClangCflags",
 			strings.Join(ClangFilterUnknownCflags(cflags), " "))
 	}
@@ -176,7 +173,7 @@
 
 type toolchainX86 struct {
 	toolchain32Bit
-	toolchainCflags, toolchainClangCflags string
+	toolchainClangCflags string
 }
 
 func (t *toolchainX86) Name() string {
@@ -195,26 +192,6 @@
 	return x86GccVersion
 }
 
-func (t *toolchainX86) ToolchainLdflags() string {
-	return "${config.X86ToolchainLdflags}"
-}
-
-func (t *toolchainX86) ToolchainCflags() string {
-	return t.toolchainCflags
-}
-
-func (t *toolchainX86) Cflags() string {
-	return "${config.X86Cflags}"
-}
-
-func (t *toolchainX86) Cppflags() string {
-	return "${config.X86Cppflags}"
-}
-
-func (t *toolchainX86) Ldflags() string {
-	return "${config.X86Ldflags}"
-}
-
 func (t *toolchainX86) IncludeFlags() string {
 	return "${config.X86IncludeFlags}"
 }
@@ -256,23 +233,16 @@
 }
 
 func x86ToolchainFactory(arch android.Arch) Toolchain {
-	toolchainCflags := []string{
-		"${config.X86ToolchainCflags}",
-		"${config.X86" + arch.ArchVariant + "VariantCflags}",
-	}
-
 	toolchainClangCflags := []string{
 		"${config.X86ToolchainCflags}",
 		"${config.X86" + arch.ArchVariant + "VariantClangCflags}",
 	}
 
 	for _, feature := range arch.ArchFeatures {
-		toolchainCflags = append(toolchainCflags, x86ArchFeatureCflags[feature]...)
 		toolchainClangCflags = append(toolchainClangCflags, x86ArchFeatureCflags[feature]...)
 	}
 
 	return &toolchainX86{
-		toolchainCflags:      strings.Join(toolchainCflags, " "),
 		toolchainClangCflags: strings.Join(toolchainClangCflags, " "),
 	}
 }
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index a9fb1f6..8a12523 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -96,18 +96,6 @@
 	return "4.9"
 }
 
-func (t *toolchainLinuxBionic) Cflags() string {
-	return ""
-}
-
-func (t *toolchainLinuxBionic) Cppflags() string {
-	return ""
-}
-
-func (t *toolchainLinuxBionic) Ldflags() string {
-	return ""
-}
-
 func (t *toolchainLinuxBionic) IncludeFlags() string {
 	return "${config.LinuxBionicIncludeFlags}"
 }
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 3965cd7..8da21b3 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -122,19 +122,10 @@
 
 	pctx.StaticVariable("LinuxGccTriple", "x86_64-linux")
 
-	pctx.StaticVariable("LinuxCflags", strings.Join(linuxCflags, " "))
-	pctx.StaticVariable("LinuxLdflags", strings.Join(linuxLdflags, " "))
-
 	pctx.StaticVariable("LinuxClangCflags", strings.Join(linuxClangCflags, " "))
 	pctx.StaticVariable("LinuxClangLdflags", strings.Join(linuxClangLdflags, " "))
 	pctx.StaticVariable("LinuxClangLldflags", strings.Join(linuxClangLldflags, " "))
 
-	// Extended cflags
-	pctx.StaticVariable("LinuxX86Cflags", strings.Join(linuxX86Cflags, " "))
-	pctx.StaticVariable("LinuxX8664Cflags", strings.Join(linuxX8664Cflags, " "))
-	pctx.StaticVariable("LinuxX86Ldflags", strings.Join(linuxX86Ldflags, " "))
-	pctx.StaticVariable("LinuxX8664Ldflags", strings.Join(linuxX8664Ldflags, " "))
-
 	pctx.StaticVariable("LinuxX86ClangCflags",
 		strings.Join(ClangFilterUnknownCflags(linuxX86Cflags), " "))
 	pctx.StaticVariable("LinuxX8664ClangCflags",
@@ -182,26 +173,6 @@
 	return linuxGccVersion
 }
 
-func (t *toolchainLinuxX86) Cflags() string {
-	return "${config.LinuxCflags} ${config.LinuxX86Cflags}"
-}
-
-func (t *toolchainLinuxX8664) Cflags() string {
-	return "${config.LinuxCflags} ${config.LinuxX8664Cflags}"
-}
-
-func (t *toolchainLinux) Cppflags() string {
-	return ""
-}
-
-func (t *toolchainLinuxX86) Ldflags() string {
-	return "${config.LinuxLdflags} ${config.LinuxX86Ldflags}"
-}
-
-func (t *toolchainLinuxX8664) Ldflags() string {
-	return "${config.LinuxLdflags} ${config.LinuxX8664Ldflags}"
-}
-
 func (t *toolchainLinux) IncludeFlags() string {
 	return ""
 }
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 9573174..6300a1b 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -47,18 +47,11 @@
 		"-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include",
 	}
 
-	windowsClangCppflags = []string{
-		"-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include/c++/4.8.3",
-		"-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include/c++/4.8.3/backward",
-	}
+	windowsClangCppflags = []string{}
 
-	windowsX86ClangCppflags = []string{
-		"-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include/c++/4.8.3/${WindowsGccTriple}/32",
-	}
+	windowsX86ClangCppflags = []string{}
 
-	windowsX8664ClangCppflags = []string{
-		"-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include/c++/4.8.3/${WindowsGccTriple}",
-	}
+	windowsX8664ClangCppflags = []string{}
 
 	windowsLdflags = []string{
 		"--enable-stdcall-fixup",
@@ -80,24 +73,18 @@
 		"-m32",
 		"-Wl,--large-address-aware",
 		"-L${WindowsGccRoot}/${WindowsGccTriple}/lib32",
-		"-static-libgcc",
 	}
 	windowsX86ClangLdflags = append(ClangFilterUnknownCflags(windowsX86Ldflags), []string{
 		"-B${WindowsGccRoot}/${WindowsGccTriple}/bin",
 		"-B${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3/32",
 		"-L${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3/32",
 		"-B${WindowsGccRoot}/${WindowsGccTriple}/lib32",
-		"-pthread",
-		// Bug: http://b/109759970 - WAR until issue with ld.bfd's
-		// inability to handle Clang-generated section names is fixed.
-		"-Wl,--allow-multiple-definition",
 	}...)
 	windowsX86ClangLldflags = ClangFilterUnknownLldflags(windowsX86ClangLdflags)
 
 	windowsX8664Ldflags = []string{
 		"-m64",
 		"-L${WindowsGccRoot}/${WindowsGccTriple}/lib64",
-		"-static-libgcc",
 		"-Wl,--high-entropy-va",
 	}
 	windowsX8664ClangLdflags = append(ClangFilterUnknownCflags(windowsX8664Ldflags), []string{
@@ -105,7 +92,6 @@
 		"-B${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3",
 		"-L${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3",
 		"-B${WindowsGccRoot}/${WindowsGccTriple}/lib64",
-		"-pthread",
 	}...)
 	windowsX8664ClangLldflags = ClangFilterUnknownLldflags(windowsX8664ClangLdflags)
 
@@ -137,19 +123,11 @@
 
 	pctx.StaticVariable("WindowsGccTriple", "x86_64-w64-mingw32")
 
-	pctx.StaticVariable("WindowsCflags", strings.Join(windowsCflags, " "))
-	pctx.StaticVariable("WindowsLdflags", strings.Join(windowsLdflags, " "))
-
 	pctx.StaticVariable("WindowsClangCflags", strings.Join(windowsClangCflags, " "))
 	pctx.StaticVariable("WindowsClangLdflags", strings.Join(windowsClangLdflags, " "))
 	pctx.StaticVariable("WindowsClangLldflags", strings.Join(windowsClangLldflags, " "))
 	pctx.StaticVariable("WindowsClangCppflags", strings.Join(windowsClangCppflags, " "))
 
-	pctx.StaticVariable("WindowsX86Cflags", strings.Join(windowsX86Cflags, " "))
-	pctx.StaticVariable("WindowsX8664Cflags", strings.Join(windowsX8664Cflags, " "))
-	pctx.StaticVariable("WindowsX86Ldflags", strings.Join(windowsX86Ldflags, " "))
-	pctx.StaticVariable("WindowsX8664Ldflags", strings.Join(windowsX8664Ldflags, " "))
-
 	pctx.StaticVariable("WindowsX86ClangCflags",
 		strings.Join(ClangFilterUnknownCflags(windowsX86Cflags), " "))
 	pctx.StaticVariable("WindowsX8664ClangCflags",
@@ -198,26 +176,6 @@
 	return windowsGccVersion
 }
 
-func (t *toolchainWindowsX86) Cflags() string {
-	return "${config.WindowsCflags} ${config.WindowsX86Cflags}"
-}
-
-func (t *toolchainWindowsX8664) Cflags() string {
-	return "${config.WindowsCflags} ${config.WindowsX8664Cflags}"
-}
-
-func (t *toolchainWindows) Cppflags() string {
-	return ""
-}
-
-func (t *toolchainWindowsX86) Ldflags() string {
-	return "${config.WindowsLdflags} ${config.WindowsX86Ldflags}"
-}
-
-func (t *toolchainWindowsX8664) Ldflags() string {
-	return "${config.WindowsLdflags} ${config.WindowsX8664Ldflags}"
-}
-
 func (t *toolchainWindows) IncludeFlags() string {
 	return "${config.WindowsIncludeFlags}"
 }
diff --git a/cc/gen_stub_libs.py b/cc/gen_stub_libs.py
index 8c99bbf..c49d197 100755
--- a/cc/gen_stub_libs.py
+++ b/cc/gen_stub_libs.py
@@ -20,6 +20,7 @@
 import logging
 import os
 import re
+import sys
 
 
 ALL_ARCHITECTURES = (
@@ -107,22 +108,33 @@
     return version.endswith('_PRIVATE') or version.endswith('_PLATFORM')
 
 
-def should_omit_version(name, tags, arch, api, vndk):
+def should_omit_version(version, arch, api, vndk):
     """Returns True if the version section should be ommitted.
 
     We want to omit any sections that do not have any symbols we'll have in the
     stub library. Sections that contain entirely future symbols or only symbols
     for certain architectures.
     """
-    if version_is_private(name):
+    if version_is_private(version.name):
         return True
-    if 'platform-only' in tags:
+    if 'platform-only' in version.tags:
         return True
-    if 'vndk' in tags and not vndk:
+    if 'vndk' in version.tags and not vndk:
         return True
-    if not symbol_in_arch(tags, arch):
+    if not symbol_in_arch(version.tags, arch):
         return True
-    if not symbol_in_api(tags, arch, api):
+    if not symbol_in_api(version.tags, arch, api):
+        return True
+    return False
+
+
+def should_omit_symbol(symbol, arch, api, vndk):
+    """Returns True if the symbol should be omitted."""
+    if not vndk and 'vndk' in symbol.tags:
+        return True
+    if not symbol_in_arch(symbol.tags, arch):
+        return True
+    if not symbol_in_api(symbol.tags, arch, api):
         return True
     return False
 
@@ -189,6 +201,15 @@
     pass
 
 
+class MultiplyDefinedSymbolError(RuntimeError):
+    """A symbol name was multiply defined."""
+    def __init__(self, multiply_defined_symbols):
+        super(MultiplyDefinedSymbolError, self).__init__(
+            'Version script contains multiple definitions for: {}'.format(
+                ', '.join(multiply_defined_symbols)))
+        self.multiply_defined_symbols = multiply_defined_symbols
+
+
 class Version(object):
     """A version block of a symbol file."""
     def __init__(self, name, base, tags, symbols):
@@ -221,9 +242,12 @@
 
 class SymbolFileParser(object):
     """Parses NDK symbol files."""
-    def __init__(self, input_file, api_map):
+    def __init__(self, input_file, api_map, arch, api, vndk):
         self.input_file = input_file
         self.api_map = api_map
+        self.arch = arch
+        self.api = api
+        self.vndk = vndk
         self.current_line = None
 
     def parse(self):
@@ -235,8 +259,36 @@
             else:
                 raise ParseError(
                     'Unexpected contents at top level: ' + self.current_line)
+
+        self.check_no_duplicate_symbols(versions)
         return versions
 
+    def check_no_duplicate_symbols(self, versions):
+        """Raises errors for multiply defined symbols.
+
+        This situation is the normal case when symbol versioning is actually
+        used, but this script doesn't currently handle that. The error message
+        will be a not necessarily obvious "error: redefition of 'foo'" from
+        stub.c, so it's better for us to catch this situation and raise a
+        better error.
+        """
+        symbol_names = set()
+        multiply_defined_symbols = set()
+        for version in versions:
+            if should_omit_version(version, self.arch, self.api, self.vndk):
+                continue
+
+            for symbol in version.symbols:
+                if should_omit_symbol(symbol, self.arch, self.api, self.vndk):
+                    continue
+
+                if symbol.name in symbol_names:
+                    multiply_defined_symbols.add(symbol.name)
+                symbol_names.add(symbol.name)
+        if multiply_defined_symbols:
+            raise MultiplyDefinedSymbolError(
+                sorted(list(multiply_defined_symbols)))
+
     def parse_version(self):
         """Parses a single version section and returns a Version object."""
         name = self.current_line.split('{')[0].strip()
@@ -274,7 +326,8 @@
             elif global_scope and not cpp_symbols:
                 symbols.append(self.parse_symbol())
             else:
-                # We're in a hidden scope or in 'extern "C++"' block. Ignore everything.
+                # We're in a hidden scope or in 'extern "C++"' block. Ignore
+                # everything.
                 pass
         raise ParseError('Unexpected EOF in version block.')
 
@@ -324,20 +377,14 @@
 
     def write_version(self, version):
         """Writes a single version block's data to the output files."""
-        name = version.name
-        tags = version.tags
-        if should_omit_version(name, tags, self.arch, self.api, self.vndk):
+        if should_omit_version(version, self.arch, self.api, self.vndk):
             return
 
-        section_versioned = symbol_versioned_in_api(tags, self.api)
+        section_versioned = symbol_versioned_in_api(version.tags, self.api)
         version_empty = True
         pruned_symbols = []
         for symbol in version.symbols:
-            if not self.vndk and 'vndk' in symbol.tags:
-                continue
-            if not symbol_in_arch(symbol.tags, self.arch):
-                continue
-            if not symbol_in_api(symbol.tags, self.arch, self.api):
+            if should_omit_symbol(symbol, self.arch, self.api, self.vndk):
                 continue
 
             if symbol_versioned_in_api(symbol.tags, self.api):
@@ -432,7 +479,11 @@
     logging.basicConfig(level=verbose_map[verbosity])
 
     with open(args.symbol_file) as symbol_file:
-        versions = SymbolFileParser(symbol_file, api_map).parse()
+        try:
+            versions = SymbolFileParser(symbol_file, api_map, args.arch, api,
+                                        args.vndk).parse()
+        except MultiplyDefinedSymbolError as ex:
+            sys.exit('{}: error: {}'.format(args.symbol_file, ex))
 
     with open(args.stub_src, 'w') as src_file:
         with open(args.version_script, 'w') as version_file:
diff --git a/cc/linker.go b/cc/linker.go
index e3f1ff1..2e1828a 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/cc/config"
 	"fmt"
 
 	"github.com/google/blueprint"
@@ -58,6 +59,9 @@
 	// don't link in libgcc.a
 	No_libgcc *bool
 
+	// don't link in libclang_rt.builtins-*.a
+	No_libcrt *bool
+
 	// Use clang lld instead of gnu ld.
 	Use_clang_lld *bool `android:"arch_variant"`
 
@@ -214,12 +218,17 @@
 		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
 	}
 
-	if ctx.ModuleName() != "libcompiler_rt-extras" {
-		deps.LateStaticLibs = append(deps.LateStaticLibs, "libcompiler_rt-extras")
-	}
-
 	if ctx.toolchain().Bionic() {
-		// libgcc and libatomic have to be last on the command line
+		// Allow individual projects to opt out of libcrt,builtins
+		// b/117565638
+		if !Bool(linker.Properties.No_libcrt) {
+			// libclang_rt.builtins, libgcc and libatomic have to be last on the command line
+			// TODO: Also enable for libc and libm
+			if ctx.ModuleName() != "libc" && ctx.ModuleName() != "libm" {
+				deps.LateStaticLibs = append(deps.LateStaticLibs, config.BuiltinsRuntimeLibrary(ctx.toolchain()))
+			}
+		}
+
 		deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic")
 		if !Bool(linker.Properties.No_libgcc) {
 			deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc")
diff --git a/cc/makevars.go b/cc/makevars.go
index 47e5491..b590786 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -126,6 +126,7 @@
 	ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_STATIC_LIBRARIES", strings.Join(asanLibs, " "))
 
 	ctx.Strict("HWADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(hwasanCflags, " "))
+	ctx.Strict("HWADDRESS_SANITIZER_GLOBAL_OPTIONS", strings.Join(hwasanGlobalOptions, ","))
 
 	ctx.Strict("CFI_EXTRA_CFLAGS", strings.Join(cfiCflags, " "))
 	ctx.Strict("CFI_EXTRA_ASFLAGS", strings.Join(cfiAsflags, " "))
@@ -281,6 +282,7 @@
 		ctx.Strict(secondPrefix+"UBSAN_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain), ".a"))
 		ctx.Strict(secondPrefix+"TSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.ThreadSanitizerRuntimeLibrary(toolchain), ".so"))
 		ctx.Strict(secondPrefix+"SCUDO_RUNTIME_LIBRARY", strings.TrimSuffix(config.ScudoRuntimeLibrary(toolchain), ".so"))
+		ctx.Strict(secondPrefix+"SCUDO_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.ScudoMinimalRuntimeLibrary(toolchain), ".so"))
 	}
 
 	// This is used by external/gentoo/...
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 8262a68..330a5e3 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -52,6 +52,7 @@
 	intOverflowCflags   = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
 	minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
 		"-fno-sanitize-recover=integer,undefined"}
+	hwasanGlobalOptions = []string{"heap_history_size=4095"}
 )
 
 type sanitizerType int
@@ -531,7 +532,11 @@
 	} else if Bool(sanitize.Properties.Sanitize.Thread) {
 		runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(ctx.toolchain())
 	} else if Bool(sanitize.Properties.Sanitize.Scudo) {
-		runtimeLibrary = config.ScudoRuntimeLibrary(ctx.toolchain())
+		if len(diagSanitizers) == 0 && !sanitize.Properties.UbsanRuntimeDep {
+			runtimeLibrary = config.ScudoMinimalRuntimeLibrary(ctx.toolchain())
+		} else {
+			runtimeLibrary = config.ScudoRuntimeLibrary(ctx.toolchain())
+		}
 	} else if len(diagSanitizers) > 0 || sanitize.Properties.UbsanRuntimeDep {
 		runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(ctx.toolchain())
 	}
@@ -831,7 +836,6 @@
 func enableMinimalRuntime(sanitize *sanitize) bool {
 	if !Bool(sanitize.Properties.Sanitize.Address) &&
 		!Bool(sanitize.Properties.Sanitize.Hwaddress) &&
-		!Bool(sanitize.Properties.Sanitize.Scudo) &&
 		(Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
 			len(sanitize.Properties.Sanitize.Misc_undefined) > 0) &&
 		!(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
diff --git a/cc/stl.go b/cc/stl.go
index f44902e..8eee612 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -81,9 +81,9 @@
 			}
 		} else if ctx.Windows() {
 			switch s {
-			case "libc++", "libc++_static", "libstdc++", "":
-				// libc++ is not supported on mingw
-				return "libstdc++"
+			case "libc++", "libc++_static", "":
+				// Only use static libc++ for Windows.
+				return "libc++_static"
 			case "none":
 				return ""
 			default:
@@ -177,6 +177,20 @@
 			} else {
 				flags.LdFlags = append(flags.LdFlags, hostDynamicGccLibs[ctx.Os()]...)
 			}
+			if ctx.Windows() {
+				// Use SjLj exceptions for 32-bit.  libgcc_eh implements SjLj
+				// exception model for 32-bit.
+				if ctx.Arch().ArchType == android.X86 {
+					flags.CppFlags = append(flags.CppFlags, "-fsjlj-exceptions")
+				}
+				flags.CppFlags = append(flags.CppFlags,
+					// Disable visiblity annotations since we're using static
+					// libc++.
+					"-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+					"-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+					// Use Win32 threads in libc++.
+					"-D_LIBCPP_HAS_THREAD_API_WIN32")
+			}
 		} else {
 			if ctx.Arch().ArchType == android.Arm {
 				flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,libunwind_llvm.a")
@@ -213,9 +227,10 @@
 	hostDynamicGccLibs = map[android.OsType][]string{
 		android.Linux:  []string{"-lgcc_s", "-lgcc", "-lc", "-lgcc_s", "-lgcc"},
 		android.Darwin: []string{"-lc", "-lSystem"},
-		android.Windows: []string{"-lmingw32", "-lgcc", "-lmoldname", "-lmingwex", "-lmsvcr110",
-			"-lmsvcrt", "-ladvapi32", "-lshell32", "-luser32", "-lkernel32", "-lmingw32",
-			"-lgcc", "-lmoldname", "-lmingwex", "-lmsvcrt"},
+		android.Windows: []string{"-Wl,--start-group", "-lmingw32", "-lgcc", "-lgcc_eh",
+			"-lmoldname", "-lmingwex", "-lmsvcr110", "-lmsvcrt", "-lpthread",
+			"-ladvapi32", "-lshell32", "-luser32", "-lkernel32", "-lpsapi",
+			"-Wl,--end-group"},
 	}
 	hostStaticGccLibs = map[android.OsType][]string{
 		android.Linux:   []string{"-Wl,--start-group", "-lgcc", "-lgcc_eh", "-lc", "-Wl,--end-group"},
diff --git a/cc/test_gen_stub_libs.py b/cc/test_gen_stub_libs.py
index b20a5c7..3b5585a 100755
--- a/cc/test_gen_stub_libs.py
+++ b/cc/test_gen_stub_libs.py
@@ -15,7 +15,7 @@
 # limitations under the License.
 #
 """Tests for gen_stub_libs.py."""
-import cStringIO
+import io
 import textwrap
 import unittest
 
@@ -163,51 +163,106 @@
 
 class OmitVersionTest(unittest.TestCase):
     def test_omit_private(self):
-        self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, False))
-
-        self.assertTrue(gsl.should_omit_version(
-            'foo_PRIVATE', [], 'arm', 9, False))
-        self.assertTrue(gsl.should_omit_version(
-            'foo_PLATFORM', [], 'arm', 9, False))
-
-        self.assertTrue(gsl.should_omit_version(
-            'foo', ['platform-only'], 'arm', 9, False))
-
-    def test_omit_vndk(self):
-        self.assertTrue(gsl.should_omit_version(
-            'foo', ['vndk'], 'arm', 9, False))
-
-        self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, True))
-        self.assertFalse(gsl.should_omit_version(
-            'foo', ['vndk'], 'arm', 9, True))
-
-    def test_omit_arch(self):
-        self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, False))
-        self.assertFalse(gsl.should_omit_version(
-            'foo', ['arm'], 'arm', 9, False))
-
-        self.assertTrue(gsl.should_omit_version(
-            'foo', ['x86'], 'arm', 9, False))
-
-    def test_omit_api(self):
-        self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, False))
         self.assertFalse(
-            gsl.should_omit_version('foo', ['introduced=9'], 'arm', 9, False))
+            gsl.should_omit_version(
+                gsl.Version('foo', None, [], []), 'arm', 9, False))
 
         self.assertTrue(
-            gsl.should_omit_version('foo', ['introduced=14'], 'arm', 9, False))
+            gsl.should_omit_version(
+                gsl.Version('foo_PRIVATE', None, [], []), 'arm', 9, False))
+        self.assertTrue(
+            gsl.should_omit_version(
+                gsl.Version('foo_PLATFORM', None, [], []), 'arm', 9, False))
+
+        self.assertTrue(
+            gsl.should_omit_version(
+                gsl.Version('foo', None, ['platform-only'], []), 'arm', 9,
+                False))
+
+    def test_omit_vndk(self):
+        self.assertTrue(
+            gsl.should_omit_version(
+                gsl.Version('foo', None, ['vndk'], []), 'arm', 9, False))
+
+        self.assertFalse(
+            gsl.should_omit_version(
+                gsl.Version('foo', None, [], []), 'arm', 9, True))
+        self.assertFalse(
+            gsl.should_omit_version(
+                gsl.Version('foo', None, ['vndk'], []), 'arm', 9, True))
+
+    def test_omit_arch(self):
+        self.assertFalse(
+            gsl.should_omit_version(
+                gsl.Version('foo', None, [], []), 'arm', 9, False))
+        self.assertFalse(
+            gsl.should_omit_version(
+                gsl.Version('foo', None, ['arm'], []), 'arm', 9, False))
+
+        self.assertTrue(
+            gsl.should_omit_version(
+                gsl.Version('foo', None, ['x86'], []), 'arm', 9, False))
+
+    def test_omit_api(self):
+        self.assertFalse(
+            gsl.should_omit_version(
+                gsl.Version('foo', None, [], []), 'arm', 9, False))
+        self.assertFalse(
+            gsl.should_omit_version(
+                gsl.Version('foo', None, ['introduced=9'], []), 'arm', 9,
+                False))
+
+        self.assertTrue(
+            gsl.should_omit_version(
+                gsl.Version('foo', None, ['introduced=14'], []), 'arm', 9,
+                False))
+
+
+class OmitSymbolTest(unittest.TestCase):
+    def test_omit_vndk(self):
+        self.assertTrue(
+            gsl.should_omit_symbol(
+                gsl.Symbol('foo', ['vndk']), 'arm', 9, False))
+
+        self.assertFalse(
+            gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, True))
+        self.assertFalse(
+            gsl.should_omit_symbol(
+                gsl.Symbol('foo', ['vndk']), 'arm', 9, True))
+
+    def test_omit_arch(self):
+        self.assertFalse(
+            gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, False))
+        self.assertFalse(
+            gsl.should_omit_symbol(
+                gsl.Symbol('foo', ['arm']), 'arm', 9, False))
+
+        self.assertTrue(
+            gsl.should_omit_symbol(
+                gsl.Symbol('foo', ['x86']), 'arm', 9, False))
+
+    def test_omit_api(self):
+        self.assertFalse(
+            gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, False))
+        self.assertFalse(
+            gsl.should_omit_symbol(
+                gsl.Symbol('foo', ['introduced=9']), 'arm', 9, False))
+
+        self.assertTrue(
+            gsl.should_omit_symbol(
+                gsl.Symbol('foo', ['introduced=14']), 'arm', 9, False))
 
 
 class SymbolFileParseTest(unittest.TestCase):
     def test_next_line(self):
-        input_file = cStringIO.StringIO(textwrap.dedent("""\
+        input_file = io.StringIO(textwrap.dedent("""\
             foo
 
             bar
             # baz
             qux
         """))
-        parser = gsl.SymbolFileParser(input_file, {})
+        parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
         self.assertIsNone(parser.current_line)
 
         self.assertEqual('foo', parser.next_line().strip())
@@ -223,7 +278,7 @@
         self.assertEqual('', parser.current_line)
 
     def test_parse_version(self):
-        input_file = cStringIO.StringIO(textwrap.dedent("""\
+        input_file = io.StringIO(textwrap.dedent("""\
             VERSION_1 { # foo bar
                 baz;
                 qux; # woodly doodly
@@ -232,7 +287,7 @@
             VERSION_2 {
             } VERSION_1; # asdf
         """))
-        parser = gsl.SymbolFileParser(input_file, {})
+        parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
 
         parser.next_line()
         version = parser.parse_version()
@@ -253,31 +308,31 @@
         self.assertEqual([], version.tags)
 
     def test_parse_version_eof(self):
-        input_file = cStringIO.StringIO(textwrap.dedent("""\
+        input_file = io.StringIO(textwrap.dedent("""\
             VERSION_1 {
         """))
-        parser = gsl.SymbolFileParser(input_file, {})
+        parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
         parser.next_line()
         with self.assertRaises(gsl.ParseError):
             parser.parse_version()
 
     def test_unknown_scope_label(self):
-        input_file = cStringIO.StringIO(textwrap.dedent("""\
+        input_file = io.StringIO(textwrap.dedent("""\
             VERSION_1 {
                 foo:
             }
         """))
-        parser = gsl.SymbolFileParser(input_file, {})
+        parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
         parser.next_line()
         with self.assertRaises(gsl.ParseError):
             parser.parse_version()
 
     def test_parse_symbol(self):
-        input_file = cStringIO.StringIO(textwrap.dedent("""\
+        input_file = io.StringIO(textwrap.dedent("""\
             foo;
             bar; # baz qux
         """))
-        parser = gsl.SymbolFileParser(input_file, {})
+        parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
 
         parser.next_line()
         symbol = parser.parse_symbol()
@@ -290,47 +345,47 @@
         self.assertEqual(['baz', 'qux'], symbol.tags)
 
     def test_wildcard_symbol_global(self):
-        input_file = cStringIO.StringIO(textwrap.dedent("""\
+        input_file = io.StringIO(textwrap.dedent("""\
             VERSION_1 {
                 *;
             };
         """))
-        parser = gsl.SymbolFileParser(input_file, {})
+        parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
         parser.next_line()
         with self.assertRaises(gsl.ParseError):
             parser.parse_version()
 
     def test_wildcard_symbol_local(self):
-        input_file = cStringIO.StringIO(textwrap.dedent("""\
+        input_file = io.StringIO(textwrap.dedent("""\
             VERSION_1 {
                 local:
                     *;
             };
         """))
-        parser = gsl.SymbolFileParser(input_file, {})
+        parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
         parser.next_line()
         version = parser.parse_version()
         self.assertEqual([], version.symbols)
 
     def test_missing_semicolon(self):
-        input_file = cStringIO.StringIO(textwrap.dedent("""\
+        input_file = io.StringIO(textwrap.dedent("""\
             VERSION_1 {
                 foo
             };
         """))
-        parser = gsl.SymbolFileParser(input_file, {})
+        parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
         parser.next_line()
         with self.assertRaises(gsl.ParseError):
             parser.parse_version()
 
     def test_parse_fails_invalid_input(self):
         with self.assertRaises(gsl.ParseError):
-            input_file = cStringIO.StringIO('foo')
-            parser = gsl.SymbolFileParser(input_file, {})
+            input_file = io.StringIO('foo')
+            parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
             parser.parse()
 
     def test_parse(self):
-        input_file = cStringIO.StringIO(textwrap.dedent("""\
+        input_file = io.StringIO(textwrap.dedent("""\
             VERSION_1 {
                 local:
                     hidden1;
@@ -347,7 +402,7 @@
                     qwerty;
             } VERSION_1;
         """))
-        parser = gsl.SymbolFileParser(input_file, {})
+        parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
         versions = parser.parse()
 
         expected = [
@@ -368,8 +423,8 @@
     def test_omit_version(self):
         # Thorough testing of the cases involved here is handled by
         # OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest.
-        src_file = cStringIO.StringIO()
-        version_file = cStringIO.StringIO()
+        src_file = io.StringIO()
+        version_file = io.StringIO()
         generator = gsl.Generator(src_file, version_file, 'arm', 9, False)
 
         version = gsl.Version('VERSION_PRIVATE', None, [], [
@@ -396,8 +451,8 @@
     def test_omit_symbol(self):
         # Thorough testing of the cases involved here is handled by
         # SymbolPresenceTest.
-        src_file = cStringIO.StringIO()
-        version_file = cStringIO.StringIO()
+        src_file = io.StringIO()
+        version_file = io.StringIO()
         generator = gsl.Generator(src_file, version_file, 'arm', 9, False)
 
         version = gsl.Version('VERSION_1', None, [], [
@@ -422,8 +477,8 @@
         self.assertEqual('', version_file.getvalue())
 
     def test_write(self):
-        src_file = cStringIO.StringIO()
-        version_file = cStringIO.StringIO()
+        src_file = io.StringIO()
+        version_file = io.StringIO()
         generator = gsl.Generator(src_file, version_file, 'arm', 9, False)
 
         versions = [
@@ -475,7 +530,7 @@
             'P': 9001,
         }
 
-        input_file = cStringIO.StringIO(textwrap.dedent("""\
+        input_file = io.StringIO(textwrap.dedent("""\
             VERSION_1 {
                 global:
                     foo; # var
@@ -505,11 +560,11 @@
                 wobble;
             } VERSION_4;
         """))
-        parser = gsl.SymbolFileParser(input_file, api_map)
+        parser = gsl.SymbolFileParser(input_file, api_map, 'arm', 9, False)
         versions = parser.parse()
 
-        src_file = cStringIO.StringIO()
-        version_file = cStringIO.StringIO()
+        src_file = io.StringIO()
+        version_file = io.StringIO()
         generator = gsl.Generator(src_file, version_file, 'arm', 9, False)
         generator.write(versions)
 
@@ -545,7 +600,7 @@
             'Q': 9002,
         }
 
-        input_file = cStringIO.StringIO(textwrap.dedent("""\
+        input_file = io.StringIO(textwrap.dedent("""\
             VERSION_1 {
                 global:
                     foo; # introduced=O
@@ -555,11 +610,11 @@
                     *;
             };
         """))
-        parser = gsl.SymbolFileParser(input_file, api_map)
+        parser = gsl.SymbolFileParser(input_file, api_map, 'arm', 9001, False)
         versions = parser.parse()
 
-        src_file = cStringIO.StringIO()
-        version_file = cStringIO.StringIO()
+        src_file = io.StringIO()
+        version_file = io.StringIO()
         generator = gsl.Generator(src_file, version_file, 'arm', 9001, False)
         generator.write(versions)
 
@@ -578,6 +633,38 @@
         """)
         self.assertEqual(expected_version, version_file.getvalue())
 
+    def test_multiple_definition(self):
+        input_file = io.StringIO(textwrap.dedent("""\
+            VERSION_1 {
+                global:
+                    foo;
+                    foo;
+                    bar;
+                    baz;
+                    qux; # arm
+                local:
+                    *;
+            };
+
+            VERSION_2 {
+                global:
+                    bar;
+                    qux; # arm64
+            } VERSION_1;
+
+            VERSION_PRIVATE {
+                global:
+                    baz;
+            } VERSION_2;
+
+        """))
+        parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
+
+        with self.assertRaises(gsl.MultiplyDefinedSymbolError) as cm:
+            parser.parse()
+        self.assertEquals(['bar', 'foo'],
+                          cm.exception.multiply_defined_symbols)
+
 
 def main():
     suite = unittest.TestLoader().loadTestsFromName(__name__)
diff --git a/java/config/config.go b/java/config/config.go
index 3d27b70..85cb588 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -27,9 +27,9 @@
 var (
 	pctx = android.NewPackageContext("android/soong/java/config")
 
-	DefaultBootclasspathLibraries = []string{"core-oj", "core-libart", "core-simple"}
+	DefaultBootclasspathLibraries = []string{"core-oj", "core-libart", "core-simple", "bouncycastle", "conscrypt", "okhttp"}
 	DefaultSystemModules          = "core-system-modules"
-	DefaultLibraries              = []string{"ext", "framework", "okhttp"}
+	DefaultLibraries              = []string{"ext", "framework"}
 	DefaultLambdaStubsLibrary     = "core-lambda-stubs"
 	SdkLambdaStubsPath            = "prebuilts/sdk/tools/core-lambda-stubs.jar"
 
diff --git a/java/java.go b/java/java.go
index c5414f4..e5218bb 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1757,7 +1757,7 @@
 	// solution to get the Import name.
 	name := j.Name()
 	if strings.HasPrefix(name, removedPrefix) {
-		name = strings.Trim(name, removedPrefix)
+		name = strings.TrimPrefix(name, removedPrefix)
 	}
 	return name
 }
diff --git a/java/java_test.go b/java/java_test.go
index 1bfd24b..76244f0 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -115,9 +115,11 @@
 		"core-libart",
 		"core-lambda-stubs",
 		"core-simple",
+		"bouncycastle",
+		"conscrypt",
+		"okhttp",
 		"framework",
 		"ext",
-		"okhttp",
 		"android_stubs_current",
 		"android_system_stubs_current",
 		"android_test_stubs_current",
@@ -365,16 +367,16 @@
 }{
 	{
 		name:          "default",
-		bootclasspath: []string{"core-oj", "core-libart", "core-simple"},
+		bootclasspath: []string{"core-oj", "core-libart", "core-simple", "bouncycastle", "conscrypt", "okhttp"},
 		system:        "core-system-modules",
-		classpath:     []string{"ext", "framework", "okhttp"},
+		classpath:     []string{"ext", "framework"},
 	},
 	{
 		name:          "blank sdk version",
 		properties:    `sdk_version: "",`,
-		bootclasspath: []string{"core-oj", "core-libart", "core-simple"},
+		bootclasspath: []string{"core-oj", "core-libart", "core-simple", "bouncycastle", "conscrypt", "okhttp"},
 		system:        "core-system-modules",
-		classpath:     []string{"ext", "framework", "okhttp"},
+		classpath:     []string{"ext", "framework"},
 	},
 	{
 
@@ -1062,12 +1064,6 @@
 			name: "droiddoc-templates-sdk",
 			path: ".",
 		}
-		java_library {
-			name: "conscrypt",
-		}
-		java_library {
-			name: "bouncycastle",
-		}
 		java_sdk_library {
 			name: "foo",
 			srcs: ["a.java", "b.java"],
diff --git a/java/sdk_library.go b/java/sdk_library.go
index a8c3b11..e513a59 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -128,6 +128,11 @@
 	// Defaults to "android.annotation".
 	Srcs_lib_whitelist_pkgs []string
 
+	// if set to true, create stubs through Metalava instead of Doclava. Javadoc/Doclava is
+	// currently still used for documentation generation, and will be replaced by Dokka soon.
+	// Defaults to true.
+	Metalava_enabled *bool
+
 	// TODO: determines whether to create HTML doc or not
 	//Html_doc *bool
 }
@@ -417,7 +422,6 @@
 	props := struct {
 		Name                    *string
 		Srcs                    []string
-		Custom_template         *string
 		Installable             *bool
 		Srcs_lib                *string
 		Srcs_lib_whitelist_dirs []string
@@ -436,11 +440,13 @@
 			Local_include_dirs []string
 		}
 	}{}
+	droiddocProps := struct {
+		Custom_template *string
+	}{}
 
 	props.Name = proptools.StringPtr(module.docsName(apiScope))
 	props.Srcs = append(props.Srcs, module.properties.Srcs...)
 	props.Srcs = append(props.Srcs, module.properties.Api_srcs...)
-	props.Custom_template = proptools.StringPtr("droiddoc-templates-sdk")
 	props.Installable = proptools.BoolPtr(false)
 	// A droiddoc module has only one Libs property and doesn't distinguish between
 	// shared libs and static libs. So we need to add both of these libs to Libs property.
@@ -449,10 +455,26 @@
 	props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
 	props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
 
-	droiddocArgs := " -hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128" +
-		" -stubpackages " + strings.Join(module.properties.Api_packages, ":") +
-		" " + android.JoinWithPrefix(module.properties.Hidden_api_packages, "-hidePackage ") +
-		" " + android.JoinWithPrefix(module.properties.Droiddoc_options, "-") + " -nodocs"
+	if module.properties.Metalava_enabled == nil {
+		module.properties.Metalava_enabled = proptools.BoolPtr(true)
+	}
+
+	droiddocArgs := ""
+	if Bool(module.properties.Metalava_enabled) == true {
+		droiddocArgs = " --stub-packages " + strings.Join(module.properties.Api_packages, ":") +
+			" " + android.JoinWithPrefix(module.properties.Hidden_api_packages, " --hide-package ") +
+			" " + android.JoinWithPrefix(module.properties.Droiddoc_options, " ") +
+			" --hide MissingPermission --hide BroadcastBehavior " +
+			"--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
+			"--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo"
+	} else {
+		droiddocProps.Custom_template = proptools.StringPtr("droiddoc-templates-sdk")
+		droiddocArgs = " -stubpackages " + strings.Join(module.properties.Api_packages, ":") +
+			" " + android.JoinWithPrefix(module.properties.Hidden_api_packages, " -hidePackage ") +
+			" " + android.JoinWithPrefix(module.properties.Droiddoc_options, " ") +
+			" -hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128 -nodocs"
+	}
+
 	switch apiScope {
 	case apiScopeSystem:
 		droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.SystemApi"
@@ -484,44 +506,52 @@
 	// check against the not-yet-release API
 	props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
 	props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
-	// any change is reported as error
-	props.Check_api.Current.Args = proptools.StringPtr("-error 2 -error 3 -error 4 -error 5 " +
-		"-error 6 -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 " +
-		"-error 14 -error 15 -error 16 -error 17 -error 18 -error 19 -error 20 " +
-		"-error 21 -error 23 -error 24 -error 25 -error 26 -error 27")
 
 	// check against the latest released API
 	props.Check_api.Last_released.Api_file = proptools.StringPtr(
 		module.latestApiFilegroupName(apiScope))
 	props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
 		module.latestRemovedApiFilegroupName(apiScope))
-	// backward incompatible changes are reported as error
-	props.Check_api.Last_released.Args = proptools.StringPtr("-hide 2 -hide 3 -hide 4 -hide 5 " +
-		"-hide 6 -hide 24 -hide 25 -hide 26 -hide 27 " +
-		"-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 " +
-		"-error 15 -error 16 -error 17 -error 18")
+	if Bool(module.properties.Metalava_enabled) == false {
+		// any change is reported as error
+		props.Check_api.Current.Args = proptools.StringPtr("-error 2 -error 3 -error 4 -error 5 " +
+			"-error 6 -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 " +
+			"-error 14 -error 15 -error 16 -error 17 -error 18 -error 19 -error 20 " +
+			"-error 21 -error 23 -error 24 -error 25 -error 26 -error 27")
 
-	// Include the part of the framework source. This is required for the case when
-	// API class is extending from the framework class. In that case, doclava needs
-	// to know whether the base class is hidden or not. Since that information is
-	// encoded as @hide string in the comment, we need source files for the classes,
-	// not the compiled ones.
-	props.Srcs_lib = proptools.StringPtr("framework")
-	props.Srcs_lib_whitelist_dirs = []string{"core/java"}
-	// Add android.annotation package to give access to the framework-defined
-	// annotations such as SystemApi, NonNull, etc.
-	if module.properties.Srcs_lib_whitelist_pkgs != nil {
-		props.Srcs_lib_whitelist_pkgs = module.properties.Srcs_lib_whitelist_pkgs
-	} else {
-		props.Srcs_lib_whitelist_pkgs = []string{"android.annotation"}
+		// backward incompatible changes are reported as error
+		props.Check_api.Last_released.Args = proptools.StringPtr("-hide 2 -hide 3 -hide 4 -hide 5 " +
+			"-hide 6 -hide 24 -hide 25 -hide 26 -hide 27 " +
+			"-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 " +
+			"-error 15 -error 16 -error 17 -error 18")
+
+		// Include the part of the framework source. This is required for the case when
+		// API class is extending from the framework class. In that case, doclava needs
+		// to know whether the base class is hidden or not. Since that information is
+		// encoded as @hide string in the comment, we need source files for the classes,
+		// not the compiled ones.
+		props.Srcs_lib = proptools.StringPtr("framework")
+		props.Srcs_lib_whitelist_dirs = []string{"core/java"}
+
+		// Add android.annotation package to give access to the framework-defined
+		// annotations such as SystemApi, NonNull, etc.
+		if module.properties.Srcs_lib_whitelist_pkgs != nil {
+			props.Srcs_lib_whitelist_pkgs = module.properties.Srcs_lib_whitelist_pkgs
+		} else {
+			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, "conscrypt", "bouncycastle", "okhttp", "framework")
+	props.Libs = append(props.Libs, "framework")
 
-	mctx.CreateModule(android.ModuleFactoryAdaptor(DroiddocFactory), &props)
+	if Bool(module.properties.Metalava_enabled) == true {
+		mctx.CreateModule(android.ModuleFactoryAdaptor(DroidstubsFactory), &props)
+	} else {
+		mctx.CreateModule(android.ModuleFactoryAdaptor(DroiddocFactory), &props, &droiddocProps)
+	}
 }
 
 // Creates the runtime library. This is not directly linkable from other modules.
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index 80a398b..05bd66e 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -191,7 +191,7 @@
 
 
 def add_uses_libraries(doc, new_uses_libraries):
-  """Add additional <uses-library> tags with android:required=true.
+  """Add additional <uses-library> tags with android:required=false.
 
   Args:
     doc: The XML document. May be modified by this function.
@@ -227,7 +227,7 @@
 
     ul = doc.createElement('uses-library')
     ul.setAttributeNS(android_ns, 'android:name', name)
-    ul.setAttributeNS(android_ns, 'android:required', 'true')
+    ul.setAttributeNS(android_ns, 'android:required', 'false')
 
     application.insertBefore(doc.createTextNode(indent), last)
     application.insertBefore(ul, last)