Merge "Add support for sysprop description files to c++"
diff --git a/Android.bp b/Android.bp
index eefa149..bcf831d 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,23 @@
     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",
+        "apex/key.go",
+    ],
+    pluginFor: ["soong_build"],
+}
+
 //
 // Defaults to enable various configurations of host bionic
 //
@@ -464,7 +482,7 @@
 }
 
 cc_genrule {
-    name: "host_bionic_linker_script",
+    name: "host_bionic_linker_flags",
     host_supported: true,
     device_supported: false,
     target: {
@@ -479,7 +497,7 @@
         },
     },
     tools: ["extract_linker"],
-    cmd: "$(location) -T $(out) $(in)",
+    cmd: "$(location) -f $(out) $(in)",
     srcs: [":linker"],
-    out: ["linker.script"],
+    out: ["linker.flags"],
 }
diff --git a/android/androidmk.go b/android/androidmk.go
index 5df4a85..7030523 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -215,7 +215,7 @@
 
 		}
 
-		if amod.Arch().ArchType != ctx.Config().Targets[amod.Os().Class][0].Arch.ArchType {
+		if amod.Arch().ArchType != ctx.Config().Targets[amod.Os()][0].Arch.ArchType {
 			prefix = "2ND_" + prefix
 		}
 	}
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..2543fca 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -194,7 +194,7 @@
 	NoOsType    OsType
 	Linux       = NewOsType("linux_glibc", Host, false)
 	Darwin      = NewOsType("darwin", Host, false)
-	LinuxBionic = NewOsType("linux_bionic", Host, true)
+	LinuxBionic = NewOsType("linux_bionic", Host, false)
 	Windows     = NewOsType("windows", HostCross, true)
 	Android     = NewOsType("android", Device, false)
 
@@ -325,37 +325,46 @@
 		return
 	}
 
-	osClasses := base.OsClassSupported()
-
 	var moduleTargets []Target
 	moduleMultiTargets := make(map[int][]Target)
 	primaryModules := make(map[int]bool)
+	osClasses := base.OsClassSupported()
 
-	for _, class := range osClasses {
-		classTargets := mctx.Config().Targets[class]
-		if len(classTargets) == 0 {
+	for _, os := range osTypeList {
+		supportedClass := false
+		for _, osClass := range osClasses {
+			if os.Class == osClass {
+				supportedClass = true
+			}
+		}
+		if !supportedClass {
+			continue
+		}
+
+		osTargets := mctx.Config().Targets[os]
+		if len(osTargets) == 0 {
 			continue
 		}
 
 		// only the primary arch in the recovery partition
-		if module.InstallInRecovery() {
-			classTargets = []Target{mctx.Config().Targets[Device][0]}
+		if os == Android && module.InstallInRecovery() {
+			osTargets = []Target{osTargets[0]}
 		}
 
 		prefer32 := false
 		if base.prefer32 != nil {
-			prefer32 = base.prefer32(mctx, base, class)
+			prefer32 = base.prefer32(mctx, base, os.Class)
 		}
 
-		multilib, extraMultilib := decodeMultilib(base, class)
-		targets, err := decodeMultilibTargets(multilib, classTargets, prefer32)
+		multilib, extraMultilib := decodeMultilib(base, os.Class)
+		targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
 		if err != nil {
 			mctx.ModuleErrorf("%s", err.Error())
 		}
 
 		var multiTargets []Target
 		if extraMultilib != "" {
-			multiTargets, err = decodeMultilibTargets(extraMultilib, classTargets, prefer32)
+			multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32)
 			if err != nil {
 				mctx.ModuleErrorf("%s", err.Error())
 			}
@@ -839,17 +848,17 @@
 			}
 
 			if (arch.ArchType == X86 && (hasArmAbi(arch) ||
-				hasArmAndroidArch(ctx.Config().Targets[Device]))) ||
+				hasArmAndroidArch(ctx.Config().Targets[Android]))) ||
 				(arch.ArchType == Arm &&
-					hasX86AndroidArch(ctx.Config().Targets[Device])) {
+					hasX86AndroidArch(ctx.Config().Targets[Android])) {
 				field := "Arm_on_x86"
 				prefix := "target.arm_on_x86"
 				a.appendProperties(ctx, genProps, targetProp, field, prefix)
 			}
 			if (arch.ArchType == X86_64 && (hasArmAbi(arch) ||
-				hasArmAndroidArch(ctx.Config().Targets[Device]))) ||
+				hasArmAndroidArch(ctx.Config().Targets[Android]))) ||
 				(arch.ArchType == Arm &&
-					hasX8664AndroidArch(ctx.Config().Targets[Device])) {
+					hasX8664AndroidArch(ctx.Config().Targets[Android])) {
 				field := "Arm_on_x86_64"
 				prefix := "target.arm_on_x86_64"
 				a.appendProperties(ctx, genProps, targetProp, field, prefix)
@@ -874,10 +883,10 @@
 }
 
 // Convert the arch product variables into a list of targets for each os class structs
-func decodeTargetProductVariables(config *config) (map[OsClass][]Target, error) {
+func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) {
 	variables := config.productVariables
 
-	targets := make(map[OsClass][]Target)
+	targets := make(map[OsType][]Target)
 	var targetErr error
 
 	addTarget := func(os OsType, archName string, archVariant, cpuVariant *string, abi *[]string) {
@@ -891,7 +900,7 @@
 			return
 		}
 
-		targets[os.Class] = append(targets[os.Class],
+		targets[os] = append(targets[os],
 			Target{
 				Os:   os,
 				Arch: arch,
@@ -938,7 +947,7 @@
 				variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
 				variables.DeviceSecondaryAbi)
 
-			deviceArches := targets[Device]
+			deviceArches := targets[Android]
 			if deviceArches[0].Arch.ArchType.Multilib == deviceArches[1].Arch.ArchType.Multilib {
 				deviceArches[1].Arch.Native = false
 			}
@@ -1012,6 +1021,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 +1035,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/config.go b/android/config.go
index 5da1e0b..0aee0e3 100644
--- a/android/config.go
+++ b/android/config.go
@@ -90,7 +90,7 @@
 	ConfigFileName           string
 	ProductVariablesFileName string
 
-	Targets              map[OsClass][]Target
+	Targets              map[OsType][]Target
 	BuildOsVariant       string
 	BuildOsCommonVariant string
 
@@ -230,18 +230,18 @@
 	testConfig := TestConfig(buildDir, env)
 	config := testConfig.config
 
-	config.Targets = map[OsClass][]Target{
-		Device: []Target{
+	config.Targets = map[OsType][]Target{
+		Android: []Target{
 			{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}},
 			{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}},
 		},
-		Host: []Target{
+		BuildOs: []Target{
 			{BuildOs, Arch{ArchType: X86_64}},
 			{BuildOs, Arch{ArchType: X86}},
 		},
 	}
 
-	config.BuildOsVariant = config.Targets[Host][0].String()
+	config.BuildOsVariant = config.Targets[BuildOs][0].String()
 
 	return testConfig
 }
@@ -304,16 +304,16 @@
 	}
 
 	if archConfig != nil {
-		deviceTargets, err := decodeArchSettings(archConfig)
+		androidTargets, err := decodeArchSettings(archConfig)
 		if err != nil {
 			return Config{}, err
 		}
-		targets[Device] = deviceTargets
+		targets[Android] = androidTargets
 	}
 
 	config.Targets = targets
-	config.BuildOsVariant = targets[Host][0].String()
-	config.BuildOsCommonVariant = getCommonTargets(targets[Host])[0].String()
+	config.BuildOsVariant = targets[BuildOs][0].String()
+	config.BuildOsCommonVariant = getCommonTargets(targets[BuildOs])[0].String()
 
 	if err := config.fromEnv(); err != nil {
 		return Config{}, err
@@ -587,7 +587,7 @@
 }
 
 func (c *config) DevicePrimaryArchType() ArchType {
-	return c.Targets[Device][0].Arch.ArchType
+	return c.Targets[Android][0].Arch.ArchType
 }
 
 func (c *config) SkipDeviceInstall() bool {
@@ -624,7 +624,7 @@
 }
 
 func (c *config) Android64() bool {
-	for _, t := range c.Targets[Device] {
+	for _, t := range c.Targets[Android] {
 		if t.Arch.ArchType.Multilib == "lib64" {
 			return true
 		}
@@ -646,10 +646,6 @@
 	return c.targetOpenJDK9
 }
 
-func (c *config) UseClangLld() bool {
-	return Bool(c.productVariables.UseClangLld)
-}
-
 func (c *config) ClangTidy() bool {
 	return Bool(c.productVariables.ClangTidy)
 }
@@ -667,8 +663,8 @@
 
 func (c *config) LibartImgDeviceBaseAddress() string {
 	archType := Common
-	if len(c.Targets[Device]) > 0 {
-		archType = c.Targets[Device][0].Arch.ArchType
+	if len(c.Targets[Android]) > 0 {
+		archType = c.Targets[Android][0].Arch.ArchType
 	}
 	switch archType {
 	default:
@@ -715,7 +711,7 @@
 
 func (c *deviceConfig) Arches() []Arch {
 	var arches []Arch
-	for _, target := range c.config.Targets[Device] {
+	for _, target := range c.config.Targets[Android] {
 		arches = append(arches, target.Arch)
 	}
 	return arches
diff --git a/android/module.go b/android/module.go
index 9d9d9a9..556c73d 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1071,10 +1071,10 @@
 }
 
 func (a *androidBaseContextImpl) PrimaryArch() bool {
-	if len(a.config.Targets[a.target.Os.Class]) <= 1 {
+	if len(a.config.Targets[a.target.Os]) <= 1 {
 		return true
 	}
-	return a.target.Arch.ArchType == a.config.Targets[a.target.Os.Class][0].Arch.ArchType
+	return a.target.Arch.ArchType == a.config.Targets[a.target.Os][0].Arch.ArchType
 }
 
 func (a *androidBaseContextImpl) AConfig() Config {
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/android/paths.go b/android/paths.go
index daaf857..b22e3c7 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -725,46 +725,6 @@
 	return PathForOutput(ctx, ".intermediates", path)
 }
 
-// DistPath is a Path representing a file path rooted from the dist directory
-type DistPath struct {
-	basePath
-}
-
-func (p DistPath) withRel(rel string) DistPath {
-	p.basePath = p.basePath.withRel(rel)
-	return p
-}
-
-var _ Path = DistPath{}
-
-// PathForDist joins the provided paths and returns a DistPath that is
-// validated to not escape the dist dir.
-// On error, it will return a usable, but invalid DistPath, and report a ModuleError.
-func PathForDist(ctx PathContext, pathComponents ...string) DistPath {
-	path, err := validatePath(pathComponents...)
-	if err != nil {
-		reportPathError(ctx, err)
-	}
-	return DistPath{basePath{path, ctx.Config(), ""}}
-}
-
-func (p DistPath) writablePath() {}
-
-func (p DistPath) Valid() bool {
-	return p.config.productVariables.DistDir != nil && *p.config.productVariables.DistDir != ""
-}
-
-func (p DistPath) String() string {
-	if !p.Valid() {
-		panic("Requesting an invalid path")
-	}
-	return filepath.Join(*p.config.productVariables.DistDir, p.path)
-}
-
-func (p DistPath) RelPathString() string {
-	return p.path
-}
-
 // ModuleSrcPath is a Path representing a file rooted from a module's local source dir
 type ModuleSrcPath struct {
 	SourcePath
diff --git a/android/variable.go b/android/variable.go
index 5c4d491..476171b 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -201,8 +201,6 @@
 	ProductPath         *string `json:",omitempty"`
 	ProductServicesPath *string `json:",omitempty"`
 
-	UseClangLld *bool `json:",omitempty"`
-
 	ClangTidy  *bool   `json:",omitempty"`
 	TidyChecks *string `json:",omitempty"`
 
@@ -228,7 +226,6 @@
 	Product_is_iot *bool `json:",omitempty"`
 
 	DeviceKernelHeaders []string `json:",omitempty"`
-	DistDir             *string  `json:",omitempty"`
 
 	ExtraVndkVersions []string `json:",omitempty"`
 
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..619ac33
--- /dev/null
+++ b/apex/apex.go
@@ -0,0 +1,413 @@
+// 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"}
+	keyTag        = dependencyTag{name: "key"}
+)
+
+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
+
+	// Name of the apex_key module that provides the private key to sign APEX
+	Key *string
+}
+
+type apexBundle struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	properties apexBundleProperties
+
+	outputFile android.WritablePath
+	installDir android.OutputPath
+}
+
+func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
+	for _, arch := range ctx.MultiTargets() {
+		// Use *FarVariation* to be able to depend on modules having
+		// conflicting variations with this module. This is required since
+		// arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
+		// for native shared libs.
+		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...)
+
+	if String(a.properties.Key) == "" {
+		ctx.ModuleErrorf("key is missing")
+		return
+	}
+	ctx.AddDependency(ctx.Module(), keyTag, String(a.properties.Key))
+}
+
+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)
+
+	var keyFile android.Path
+
+	ctx.WalkDeps(func(child, parent android.Module) bool {
+		if _, ok := parent.(*apexBundle); ok {
+			// direct dependencies
+			depTag := ctx.OtherModuleDependencyTag(child)
+			depName := ctx.OtherModuleName(child)
+			switch depTag {
+			case sharedLibTag:
+				if cc, ok := child.(*cc.Module); ok {
+					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
+					copyManifest[fileToCopy] = dirInApex
+					return true
+				} else {
+					ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName)
+				}
+			case executableTag:
+				if cc, ok := child.(*cc.Module); ok {
+					fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
+					copyManifest[fileToCopy] = dirInApex
+					return true
+				} else {
+					ctx.PropertyErrorf("binaries", "%q is not a cc_binary module", depName)
+				}
+			case javaLibTag:
+				if java, ok := child.(*java.Library); ok {
+					fileToCopy, dirInApex := getCopyManifestForJavaLibrary(java)
+					copyManifest[fileToCopy] = dirInApex
+					return true
+				} else {
+					ctx.PropertyErrorf("java_libs", "%q is not a java_library module", depName)
+				}
+			case prebuiltTag:
+				if prebuilt, ok := child.(*android.PrebuiltEtc); ok {
+					fileToCopy, dirInApex := getCopyManifestForPrebuiltEtc(prebuilt)
+					copyManifest[fileToCopy] = dirInApex
+					return true
+				} else {
+					ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
+				}
+			case keyTag:
+				if key, ok := child.(*apexKey); ok {
+					keyFile = key.private_key_file
+					return false
+				} else {
+					ctx.PropertyErrorf("key", "%q is not an apex_key module", depName)
+				}
+			}
+		} 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"))
+
+	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, keyFile)
+	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":              keyFile.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, "LOCAL_REQUIRED_MODULES :=", String(a.properties.Key))
+			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/apex/key.go b/apex/key.go
new file mode 100644
index 0000000..ff348a8
--- /dev/null
+++ b/apex/key.go
@@ -0,0 +1,88 @@
+// 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"
+
+	"android/soong/android"
+	"github.com/google/blueprint/proptools"
+)
+
+var String = proptools.String
+
+func init() {
+	android.RegisterModuleType("apex_key", apexKeyFactory)
+}
+
+type apexKey struct {
+	android.ModuleBase
+
+	properties apexKeyProperties
+
+	public_key_file  android.Path
+	private_key_file android.Path
+
+	keyName string
+}
+
+type apexKeyProperties struct {
+	// Path to the public key file in avbpubkey format. Installed to the device.
+	// Base name of the file is used as the ID for the key.
+	Public_key *string
+	// Path to the private key file in pem format. Used to sign APEXs.
+	Private_key *string
+}
+
+func apexKeyFactory() android.Module {
+	module := &apexKey{}
+	module.AddProperties(&module.properties)
+	android.InitAndroidModule(module)
+	return module
+}
+
+func (m *apexKey) DepsMutator(ctx android.BottomUpMutatorContext) {
+}
+
+func (m *apexKey) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	m.public_key_file = android.PathForModuleSrc(ctx, String(m.properties.Public_key))
+	m.private_key_file = android.PathForModuleSrc(ctx, String(m.properties.Private_key))
+
+	pubKeyName := m.public_key_file.Base()[0 : len(m.public_key_file.Base())-len(m.public_key_file.Ext())]
+	privKeyName := m.private_key_file.Base()[0 : len(m.private_key_file.Base())-len(m.private_key_file.Ext())]
+
+	if pubKeyName != privKeyName {
+		ctx.ModuleErrorf("public_key %q (keyname:%q) and private_key %q (keyname:%q) do not have same keyname",
+			m.public_key_file.String(), pubKeyName, m.private_key_file, privKeyName)
+		return
+	}
+	m.keyName = pubKeyName
+
+	ctx.InstallFile(android.PathForModuleInstall(ctx, "etc/security/apex"), m.keyName, m.public_key_file)
+}
+
+func (m *apexKey) AndroidMk() android.AndroidMkData {
+	return android.AndroidMkData{
+		Class:      "ETC",
+		OutputFile: android.OptionalPathForPath(m.public_key_file),
+		Extra: []android.AndroidMkExtraFunc{
+			func(w io.Writer, outputFile android.Path) {
+				fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(TARGET_OUT)/etc/security/apex")
+				fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.keyName)
+			},
+		},
+	}
+}
diff --git a/build_test.bash b/build_test.bash
index 4c43224..ee979e7 100755
--- a/build_test.bash
+++ b/build_test.bash
@@ -27,6 +27,10 @@
 # that's detected in the Go code, which skips calculating the startup time.
 export TRACE_BEGIN_SOONG=$(date +%s%N)
 
+# Remove BUILD_NUMBER so that incremental builds on build servers don't
+# re-read makefiles every time.
+unset BUILD_NUMBER
+
 export TOP=$(cd $(dirname ${BASH_SOURCE[0]})/../..; PWD= /bin/pwd)
 cd "${TOP}"
 source "${TOP}/build/soong/scripts/microfactory.bash"
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/binary.go b/cc/binary.go
index 5fa501e..15db2ad 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -15,6 +15,8 @@
 package cc
 
 import (
+	"github.com/google/blueprint"
+
 	"android/soong/android"
 )
 
@@ -154,7 +156,8 @@
 		}
 
 		if ctx.Os() == android.LinuxBionic && !binary.static() {
-			deps.LinkerScript = "host_bionic_linker_script"
+			deps.DynamicLinker = "linker"
+			deps.LinkerFlagsFile = "host_bionic_linker_flags"
 		}
 	}
 
@@ -244,14 +247,23 @@
 					switch ctx.Os() {
 					case android.Android:
 						flags.DynamicLinker = "/system/bin/linker"
+						if flags.Toolchain.Is64Bit() {
+							flags.DynamicLinker += "64"
+						}
 					case android.LinuxBionic:
 						flags.DynamicLinker = ""
 					default:
 						ctx.ModuleErrorf("unknown dynamic linker")
 					}
-					if flags.Toolchain.Is64Bit() {
-						flags.DynamicLinker += "64"
-					}
+				}
+
+				if ctx.Os() == android.LinuxBionic {
+					// Use the dlwrap entry point, but keep _start around so
+					// that it can be used by host_bionic_inject
+					flags.LdFlags = append(flags.LdFlags,
+						"-Wl,--entry=__dlwrap__start",
+						"-Wl,--undefined=_start",
+					)
 				}
 			}
 
@@ -262,7 +274,6 @@
 				"-Wl,--gc-sections",
 				"-Wl,-z,nocopyreloc",
 			)
-
 		}
 	} else {
 		if binary.static() {
@@ -288,13 +299,15 @@
 	sharedLibs := deps.SharedLibs
 	sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
 
-	if deps.LinkerScript.Valid() {
-		flags.LdFlags = append(flags.LdFlags, "-Wl,-T,"+deps.LinkerScript.String())
-		linkerDeps = append(linkerDeps, deps.LinkerScript.Path())
+	if deps.LinkerFlagsFile.Valid() {
+		flags.LdFlags = append(flags.LdFlags, "$$(cat "+deps.LinkerFlagsFile.String()+")")
+		linkerDeps = append(linkerDeps, deps.LinkerFlagsFile.Path())
 	}
 
 	if flags.DynamicLinker != "" {
-		flags.LdFlags = append(flags.LdFlags, " -Wl,-dynamic-linker,"+flags.DynamicLinker)
+		flags.LdFlags = append(flags.LdFlags, "-Wl,-dynamic-linker,"+flags.DynamicLinker)
+	} else if ctx.toolchain().Bionic() && !binary.static() {
+		flags.LdFlags = append(flags.LdFlags, "-Wl,--no-dynamic-linker")
 	}
 
 	builderFlags := flagsToBuilderFlags(flags)
@@ -323,6 +336,17 @@
 		binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
 	}
 
+	if ctx.Os() == android.LinuxBionic && !binary.static() {
+		injectedOutputFile := outputFile
+		outputFile = android.PathForModuleOut(ctx, "prelinker", fileName)
+
+		if !deps.DynamicLinker.Valid() {
+			panic("Non-static host bionic modules must have a dynamic linker")
+		}
+
+		binary.injectHostBionicLinkerSymbols(ctx, outputFile, deps.DynamicLinker.Path(), injectedOutputFile)
+	}
+
 	linkerDeps = append(linkerDeps, deps.SharedLibsDeps...)
 	linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...)
 	linkerDeps = append(linkerDeps, objs.tidyFiles...)
@@ -367,3 +391,26 @@
 func (binary *binaryDecorator) hostToolPath() android.OptionalPath {
 	return binary.toolPath
 }
+
+func init() {
+	pctx.HostBinToolVariable("hostBionicSymbolsInjectCmd", "host_bionic_inject")
+}
+
+var injectHostBionicSymbols = pctx.AndroidStaticRule("injectHostBionicSymbols",
+	blueprint.RuleParams{
+		Command:     "$hostBionicSymbolsInjectCmd -i $in -l $linker -o $out",
+		CommandDeps: []string{"$hostBionicSymbolsInjectCmd"},
+	}, "linker")
+
+func (binary *binaryDecorator) injectHostBionicLinkerSymbols(ctx ModuleContext, in, linker android.Path, out android.WritablePath) {
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        injectHostBionicSymbols,
+		Description: "inject host bionic symbols",
+		Input:       in,
+		Implicit:    linker,
+		Output:      out,
+		Args: map[string]string{
+			"linker": linker.String(),
+		},
+	})
+}
diff --git a/cc/builder.go b/cc/builder.go
index d16efd0..3d12538 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")
@@ -191,11 +191,8 @@
 		func(ctx android.PackageRuleContext) blueprint.RuleParams {
 			// TODO(b/78139997): Add -check-all-apis back
 			commandStr := "($sAbiDiffer $allowFlags -lib $libName -arch $arch -o ${out} -new $in -old $referenceDump)"
-			distAbiDiffDir := android.PathForDist(ctx, "abidiffs")
 			commandStr += "|| (echo ' ---- Please update abi references by running $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l ${libName} ----'"
-			if distAbiDiffDir.Valid() {
-				commandStr += " && (mkdir -p " + distAbiDiffDir.String() + " && cp ${out} " + distAbiDiffDir.String() + ")"
-			}
+			commandStr += " && (mkdir -p $$DIST_DIR/abidiffs && cp ${out} $$DIST_DIR/abidiff/)"
 			commandStr += " && exit 1)"
 			return blueprint.RuleParams{
 				Command:     commandStr,
diff --git a/cc/cc.go b/cc/cc.go
index 5f3baea..8b68489 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -83,7 +83,10 @@
 	ReexportGeneratedHeaders []string
 
 	CrtBegin, CrtEnd string
-	LinkerScript     string
+
+	// Used for host bionic
+	LinkerFlagsFile string
+	DynamicLinker   string
 }
 
 type PathDeps struct {
@@ -108,7 +111,12 @@
 
 	// Paths to crt*.o files
 	CrtBegin, CrtEnd android.OptionalPath
-	LinkerScript     android.OptionalPath
+
+	// Path to the file container flags to use with the linker
+	LinkerFlagsFile android.OptionalPath
+
+	// Path to the dynamic linker binary
+	DynamicLinker android.OptionalPath
 }
 
 type Flags struct {
@@ -306,7 +314,8 @@
 	objDepTag             = dependencyTag{name: "obj"}
 	crtBeginDepTag        = dependencyTag{name: "crtbegin"}
 	crtEndDepTag          = dependencyTag{name: "crtend"}
-	linkerScriptDepTag    = dependencyTag{name: "linker script"}
+	linkerFlagsDepTag     = dependencyTag{name: "linker flags file"}
+	dynamicLinkerDepTag   = dependencyTag{name: "dynamic linker"}
 	reuseObjTag           = dependencyTag{name: "reuse objects"}
 	ndkStubDepTag         = dependencyTag{name: "ndk stub", library: true}
 	ndkLateStubDepTag     = dependencyTag{name: "ndk late stub", library: true}
@@ -320,6 +329,7 @@
 type Module struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
+	android.ApexModuleBase
 
 	Properties       BaseProperties
 	VendorProperties VendorProperties
@@ -416,6 +426,8 @@
 
 	android.InitDefaultableModule(c)
 
+	android.InitApexModule(c)
+
 	return c
 }
 
@@ -794,7 +806,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
@@ -1059,8 +1071,11 @@
 	if deps.CrtEnd != "" {
 		actx.AddVariationDependencies(nil, crtEndDepTag, deps.CrtEnd)
 	}
-	if deps.LinkerScript != "" {
-		actx.AddDependency(c, linkerScriptDepTag, deps.LinkerScript)
+	if deps.LinkerFlagsFile != "" {
+		actx.AddDependency(c, linkerFlagsDepTag, deps.LinkerFlagsFile)
+	}
+	if deps.DynamicLinker != "" {
+		actx.AddDependency(c, dynamicLinkerDepTag, deps.DynamicLinker)
 	}
 
 	version := ctx.sdkVersion()
@@ -1254,13 +1269,13 @@
 				} else {
 					ctx.ModuleErrorf("module %q is not a genrule", depName)
 				}
-			case linkerScriptDepTag:
+			case linkerFlagsDepTag:
 				if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
 					files := genRule.GeneratedSourceFiles()
 					if len(files) == 1 {
-						depPaths.LinkerScript = android.OptionalPathForPath(files[0])
+						depPaths.LinkerFlagsFile = android.OptionalPathForPath(files[0])
 					} else if len(files) > 1 {
-						ctx.ModuleErrorf("module %q can only generate a single file if used for a linker script", depName)
+						ctx.ModuleErrorf("module %q can only generate a single file if used for a linker flag file", depName)
 					}
 				} else {
 					ctx.ModuleErrorf("module %q is not a genrule", depName)
@@ -1355,6 +1370,8 @@
 			depPaths.CrtBegin = linkFile
 		case crtEndDepTag:
 			depPaths.CrtEnd = linkFile
+		case dynamicLinkerDepTag:
+			depPaths.DynamicLinker = linkFile
 		}
 
 		switch depTag {
@@ -1511,12 +1528,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 +1587,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/clang.go b/cc/config/clang.go
index 5cf2421..5c82604 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -92,12 +92,7 @@
 	"-Wl,-m,aarch64_elf64_le_vec",
 })
 
-var ClangLibToolingUnknownCflags = []string{
-	// Remove -flto and other flto dependent flags.
-	"-flto*",
-	"-fsanitize*",
-	"-fwhole-program-vtables",
-}
+var ClangLibToolingUnknownCflags []string = nil
 
 func init() {
 	pctx.StaticVariable("ClangExtraCflags", strings.Join([]string{
@@ -179,6 +174,11 @@
 		// this new warning are fixed.
 		"-Wno-null-pointer-arithmetic",
 
+		// http://b/72330874 Disable -Wenum-compare until the instances detected by this new
+		// warning are fixed.
+		"-Wno-enum-compare",
+		"-Wno-enum-compare-switch",
+
 		// Disable c++98-specific warning since Android is not concerned with C++98
 		// compatibility.
 		"-Wno-c++98-compat-extra-semi",
@@ -196,11 +196,9 @@
 		"-Wno-dangling-field",
 	}, " "))
 
-	// Extra cflags for projects under external/ directory to disable warnings that are infeasible
-	// to fix in all the external projects and their upstream repos.
+	// Extra cflags for projects under external/ directory
 	pctx.StaticVariable("ClangExtraExternalCflags", strings.Join([]string{
-		"-Wno-enum-compare",
-		"-Wno-enum-compare-switch",
+		// TODO(yikong): Move -Wno flags here
 	}, " "))
 }
 
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..5fb88e6 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}"
 }
@@ -151,6 +139,10 @@
 	return true
 }
 
+func (toolchainLinuxBionic) LibclangRuntimeLibraryArch() string {
+	return "x86_64"
+}
+
 var toolchainLinuxBionicSingleton Toolchain = &toolchainLinuxBionic{}
 
 func linuxBionicToolchainFactory(arch android.Arch) Toolchain {
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..28f4747 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")
@@ -280,7 +289,7 @@
 	if linker.Properties.Use_clang_lld != nil {
 		return Bool(linker.Properties.Use_clang_lld)
 	}
-	return ctx.Config().UseClangLld()
+	return true
 }
 
 // ModuleContext extends BaseModuleContext
diff --git a/cc/lto.go b/cc/lto.go
index fd2a869..52b9a34 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -76,7 +76,7 @@
 	if lto.Properties.Use_clang_lld != nil {
 		return Bool(lto.Properties.Use_clang_lld)
 	}
-	return ctx.Config().UseClangLld()
+	return true
 }
 
 func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags {
diff --git a/cc/makevars.go b/cc/makevars.go
index 47e5491..32674a9 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, " "))
@@ -171,13 +172,13 @@
 	sort.Strings(ndkMigratedLibs)
 	ctx.Strict("NDK_MIGRATED_LIBS", strings.Join(ndkMigratedLibs, " "))
 
-	hostTargets := ctx.Config().Targets[android.Host]
+	hostTargets := ctx.Config().Targets[android.BuildOs]
 	makeVarsToolchain(ctx, "", hostTargets[0])
 	if len(hostTargets) > 1 {
 		makeVarsToolchain(ctx, "2ND_", hostTargets[1])
 	}
 
-	crossTargets := ctx.Config().Targets[android.HostCross]
+	crossTargets := ctx.Config().Targets[android.Windows]
 	if len(crossTargets) > 0 {
 		makeVarsToolchain(ctx, "", crossTargets[0])
 		if len(crossTargets) > 1 {
@@ -185,7 +186,7 @@
 		}
 	}
 
-	deviceTargets := ctx.Config().Targets[android.Device]
+	deviceTargets := ctx.Config().Targets[android.Android]
 	makeVarsToolchain(ctx, "", deviceTargets[0])
 	if len(deviceTargets) > 1 {
 		makeVarsToolchain(ctx, "2ND_", deviceTargets[1])
@@ -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/ndk_headers.go b/cc/ndk_headers.go
index 1cd4829..cdf63d8 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -278,11 +278,7 @@
 
 	module.AddProperties(&module.properties)
 
-	// Host module rather than device module because device module install steps
-	// do not get run when embedded in make. We're not any of the existing
-	// module types that can be exposed via the Android.mk exporter, so just use
-	// a host module.
-	android.InitAndroidArchModule(module, android.HostSupportedNoCross, android.MultilibFirst)
+	android.InitAndroidModule(module)
 
 	return module
 }
@@ -362,11 +358,7 @@
 
 	module.AddProperties(&module.properties)
 
-	// Host module rather than device module because device module install steps
-	// do not get run when embedded in make. We're not any of the existing
-	// module types that can be exposed via the Android.mk exporter, so just use
-	// a host module.
-	android.InitAndroidArchModule(module, android.HostSupportedNoCross, android.MultilibFirst)
+	android.InitAndroidModule(module)
 
 	return module
 }
diff --git a/cc/sabi.go b/cc/sabi.go
index 72a3c5c..4a86499 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -73,17 +73,6 @@
 	flags.ToolingCFlags = filterOutWithPrefix(flags.CFlags, config.ClangLibToolingUnknownCflags)
 	flags.ToolingCppFlags = filterOutWithPrefix(flags.CppFlags, config.ClangLibToolingUnknownCflags)
 
-	// RSClang does not support recent mcpu option likes exynos-m2.
-	// So we need overriding mcpu option when we want to use it.
-	mappedArch := map[string]string{
-		"exynos-m2":  "cortex-a53",
-		"cortex-a55": "cortex-a53",
-		"cortex-a75": "cortex-a57",
-	}
-	if arch, ok := mappedArch[ctx.Arch().CpuVariant]; ok {
-		flags.ToolingCFlags = append(flags.ToolingCFlags, "-mcpu="+arch)
-	}
-
 	return flags
 }
 
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/cc/vndk.go b/cc/vndk.go
index 5a24a98..1a9b77a 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -15,6 +15,7 @@
 package cc
 
 import (
+	"errors"
 	"sort"
 	"strings"
 	"sync"
@@ -151,38 +152,42 @@
 	}
 
 	// Check the dependencies of VNDK shared libraries.
-	if !vndkIsVndkDepAllowed(vndk, to.vndkdep) {
-		ctx.ModuleErrorf("(%s) should not link to %q (%s)",
-			vndk.typeName(), to.Name(), to.vndkdep.typeName())
+	if err := vndkIsVndkDepAllowed(vndk, to.vndkdep); err != nil {
+		ctx.ModuleErrorf("(%s) should not link to %q (%s): %v",
+			vndk.typeName(), to.Name(), to.vndkdep.typeName(), err)
 		return
 	}
 }
 
-func vndkIsVndkDepAllowed(from *vndkdep, to *vndkdep) bool {
+func vndkIsVndkDepAllowed(from *vndkdep, to *vndkdep) error {
 	// Check the dependencies of VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext and vendor modules.
 	if from.isVndkExt() {
 		if from.isVndkSp() {
-			// VNDK-SP-Ext may depend on VNDK-SP, VNDK-SP-Ext, or vendor libs (excluding
-			// VNDK and VNDK-Ext).
-			return to.isVndkSp() || !to.isVndk()
+			if to.isVndk() && !to.isVndkSp() {
+				return errors.New("VNDK-SP extensions must not depend on VNDK or VNDK extensions")
+			}
+			return nil
 		}
 		// VNDK-Ext may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs.
-		return true
+		return nil
 	}
 	if from.isVndk() {
 		if to.isVndkExt() {
-			// VNDK-core and VNDK-SP must not depend on VNDK extensions.
-			return false
+			return errors.New("VNDK-core and VNDK-SP must not depend on VNDK extensions")
 		}
 		if from.isVndkSp() {
-			// VNDK-SP must only depend on VNDK-SP.
-			return to.isVndkSp()
+			if !to.isVndkSp() {
+				return errors.New("VNDK-SP must only depend on VNDK-SP")
+			}
+			return nil
 		}
-		// VNDK-core may depend on VNDK-core or VNDK-SP.
-		return to.isVndk()
+		if !to.isVndk() {
+			return errors.New("VNDK-core must only depend on VNDK-core or VNDK-SP")
+		}
+		return nil
 	}
 	// Vendor modules may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs.
-	return true
+	return nil
 }
 
 var (
diff --git a/cmd/extract_linker/main.go b/cmd/extract_linker/main.go
index 3f24ab2..ea0bf4e 100644
--- a/cmd/extract_linker/main.go
+++ b/cmd/extract_linker/main.go
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 // This tool extracts ELF LOAD segments from our linker binary, and produces an
-// assembly file and linker script which will embed those segments as sections
+// assembly file and linker flags which will embed those segments as sections
 // in another binary.
 package main
 
@@ -26,38 +26,15 @@
 	"io/ioutil"
 	"log"
 	"os"
-	"text/template"
+	"strings"
 )
 
-var linkerScriptTemplate = template.Must(template.New("linker_script").Parse(`
-ENTRY(__dlwrap__start)
-SECTIONS {
-	__dlwrap_original_start = _start;
-	/DISCARD/ : { *(.interp) }
-
-{{range .}}
-	. = {{ printf "0x%x" .Vaddr }};
-	{{.Name}} : { KEEP(*({{.Name}})) }
-{{end}}
-
-	.text : { *(.text .text.*) }
-	.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
-	.data : { *(.data .data.* .gnu.linkonce.d.*) }
-	.bss : { *(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) }
-}
-`))
-
-type LinkerSection struct {
-	Name  string
-	Vaddr uint64
-}
-
 func main() {
 	var asmPath string
-	var scriptPath string
+	var flagsPath string
 
 	flag.StringVar(&asmPath, "s", "", "Path to save the assembly file")
-	flag.StringVar(&scriptPath, "T", "", "Path to save the linker script")
+	flag.StringVar(&flagsPath, "f", "", "Path to save the linker flags")
 	flag.Parse()
 
 	f, err := os.Open(flag.Arg(0))
@@ -72,19 +49,21 @@
 	}
 
 	asm := &bytes.Buffer{}
-
-	fmt.Fprintln(asm, ".globl __dlwrap_linker_entry")
-	fmt.Fprintf(asm, ".set __dlwrap_linker_entry, 0x%x\n\n", ef.Entry)
-
 	baseLoadAddr := uint64(0x1000)
-	sections := []LinkerSection{}
 	load := 0
+	linkFlags := []string{}
+
+	fmt.Fprintln(asm, ".globl __dlwrap_linker_offset")
+	fmt.Fprintf(asm, ".set __dlwrap_linker_offset, 0x%x\n", baseLoadAddr)
+
 	for _, prog := range ef.Progs {
 		if prog.Type != elf.PT_LOAD {
 			continue
 		}
 
 		sectionName := fmt.Sprintf(".linker.sect%d", load)
+		symName := fmt.Sprintf("__dlwrap_linker_sect%d", load)
+
 		flags := ""
 		if prog.Flags&elf.PF_W != 0 {
 			flags += "w"
@@ -94,10 +73,12 @@
 		}
 		fmt.Fprintf(asm, ".section %s, \"a%s\"\n", sectionName, flags)
 
-		if load == 0 {
-			fmt.Fprintln(asm, ".globl __dlwrap_linker_code_start")
-			fmt.Fprintln(asm, "__dlwrap_linker_code_start:")
-		}
+		fmt.Fprintf(asm, ".globl %s\n%s:\n\n", symName, symName)
+
+		linkFlags = append(linkFlags,
+			fmt.Sprintf("-Wl,--undefined=%s", symName),
+			fmt.Sprintf("-Wl,--section-start=%s=0x%x",
+				sectionName, baseLoadAddr+prog.Vaddr))
 
 		buffer, _ := ioutil.ReadAll(prog.Open())
 		bytesToAsm(asm, buffer)
@@ -113,11 +94,6 @@
 		}
 		fmt.Fprintln(asm)
 
-		sections = append(sections, LinkerSection{
-			Name:  sectionName,
-			Vaddr: baseLoadAddr + prog.Vaddr,
-		})
-
 		load += 1
 	}
 
@@ -127,13 +103,10 @@
 		}
 	}
 
-	if scriptPath != "" {
-		buf := &bytes.Buffer{}
-		if err := linkerScriptTemplate.Execute(buf, sections); err != nil {
-			log.Fatalf("Failed to create linker script: %v", err)
-		}
-		if err := ioutil.WriteFile(scriptPath, buf.Bytes(), 0777); err != nil {
-			log.Fatalf("Unable to write %q: %v", scriptPath, err)
+	if flagsPath != "" {
+		flags := strings.Join(linkFlags, " ")
+		if err := ioutil.WriteFile(flagsPath, []byte(flags), 0777); err != nil {
+			log.Fatalf("Unable to write %q: %v", flagsPath, err)
 		}
 	}
 }
diff --git a/cmd/symbol_inject/Android.bp b/cmd/host_bionic_inject/Android.bp
similarity index 63%
copy from cmd/symbol_inject/Android.bp
copy to cmd/host_bionic_inject/Android.bp
index a2ea12b..acce683 100644
--- a/cmd/symbol_inject/Android.bp
+++ b/cmd/host_bionic_inject/Android.bp
@@ -13,20 +13,7 @@
 // limitations under the License.
 
 blueprint_go_binary {
-    name: "symbol_inject",
-    srcs: [
-        "symbol_inject.go",
-        "elf.go",
-        "macho.go",
-        "pe.go",
-    ],
-    testSrcs: [
-        "elf_symboldata_test.go",
-        "elf_test.go",
-        "macho_symboldata_test.go",
-        "macho_test.go",
-        "pe_symboldata_test.go",
-        "pe_test.go",
-        "symbol_inject_test.go",
-    ],
+    name: "host_bionic_inject",
+    deps: ["soong-symbol_inject"],
+    srcs: ["host_bionic_inject.go"],
 }
diff --git a/cmd/host_bionic_inject/host_bionic_inject.go b/cmd/host_bionic_inject/host_bionic_inject.go
new file mode 100644
index 0000000..0dabbba
--- /dev/null
+++ b/cmd/host_bionic_inject/host_bionic_inject.go
@@ -0,0 +1,174 @@
+// 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.
+
+// Verifies a host bionic executable with an embedded linker, then injects
+// the address of the _start function for the linker_wrapper to use.
+package main
+
+import (
+	"debug/elf"
+	"flag"
+	"fmt"
+	"io"
+	"os"
+
+	"android/soong/symbol_inject"
+)
+
+func main() {
+	var inputFile, linkerFile, outputFile string
+
+	flag.StringVar(&inputFile, "i", "", "Input file")
+	flag.StringVar(&linkerFile, "l", "", "Linker file")
+	flag.StringVar(&outputFile, "o", "", "Output file")
+	flag.Parse()
+
+	if inputFile == "" || linkerFile == "" || outputFile == "" || flag.NArg() != 0 {
+		flag.Usage()
+		os.Exit(1)
+	}
+
+	r, err := os.Open(inputFile)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err.Error())
+		os.Exit(2)
+	}
+	defer r.Close()
+
+	file, err := symbol_inject.OpenFile(r)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err.Error())
+		os.Exit(3)
+	}
+
+	linker, err := elf.Open(linkerFile)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err.Error())
+		os.Exit(4)
+	}
+
+	start_addr, err := parseElf(r, linker)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err.Error())
+		os.Exit(5)
+	}
+
+	w, err := os.OpenFile(outputFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err.Error())
+		os.Exit(6)
+	}
+	defer w.Close()
+
+	err = symbol_inject.InjectUint64Symbol(file, w, "__dlwrap_original_start", start_addr)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err.Error())
+		os.Exit(7)
+	}
+}
+
+// Check the ELF file, and return the address to the _start function
+func parseElf(r io.ReaderAt, linker *elf.File) (uint64, error) {
+	file, err := elf.NewFile(r)
+	if err != nil {
+		return 0, err
+	}
+
+	symbols, err := file.Symbols()
+	if err != nil {
+		return 0, err
+	}
+
+	for _, prog := range file.Progs {
+		if prog.Type == elf.PT_INTERP {
+			return 0, fmt.Errorf("File should not have a PT_INTERP header")
+		}
+	}
+
+	if dlwrap_start, err := findSymbol(symbols, "__dlwrap__start"); err != nil {
+		return 0, err
+	} else if dlwrap_start.Value != file.Entry {
+		return 0, fmt.Errorf("Expected file entry(0x%x) to point to __dlwrap_start(0x%x)",
+			file.Entry, dlwrap_start.Value)
+	}
+
+	err = checkLinker(file, linker, symbols)
+	if err != nil {
+		return 0, err
+	}
+
+	start, err := findSymbol(symbols, "_start")
+	if err != nil {
+		return 0, fmt.Errorf("Failed to find _start symbol")
+	}
+	return start.Value, nil
+}
+
+func findSymbol(symbols []elf.Symbol, name string) (elf.Symbol, error) {
+	for _, sym := range symbols {
+		if sym.Name == name {
+			return sym, nil
+		}
+	}
+	return elf.Symbol{}, fmt.Errorf("Failed to find symbol %q", name)
+}
+
+// Check that all of the PT_LOAD segments have been embedded properly
+func checkLinker(file, linker *elf.File, fileSyms []elf.Symbol) error {
+	dlwrap_linker_offset, err := findSymbol(fileSyms, "__dlwrap_linker_offset")
+	if err != nil {
+		return err
+	}
+
+	for i, lprog := range linker.Progs {
+		if lprog.Type != elf.PT_LOAD {
+			continue
+		}
+
+		found := false
+		for j, prog := range file.Progs {
+			if prog.Type != elf.PT_LOAD {
+				continue
+			}
+
+			if lprog.Vaddr+dlwrap_linker_offset.Value != prog.Vaddr {
+				continue
+			}
+			found = true
+
+			if lprog.Memsz != prog.Memsz {
+				return fmt.Errorf("Linker prog %d (0x%x) memsz (0x%x) does not match (0x%x)",
+					i, lprog.Vaddr, lprog.Memsz, prog.Memsz)
+			}
+
+			// The linker shouldn't be using BSS, since only one
+			// BSS section is supported per ELF file.
+			if prog.Memsz != prog.Filesz {
+				return fmt.Errorf("Embedded prog %d (0x%x) memsz (0x%x) does not match filesz (0x%x)",
+					j, prog.Vaddr, prog.Memsz, prog.Filesz)
+			}
+
+			if lprog.Flags != prog.Flags {
+				return fmt.Errorf("Linker prog %d (0x%x) flags (%s) do not match (%s)",
+					i, lprog.Vaddr, lprog.Flags, prog.Flags)
+			}
+		}
+		if !found {
+			return fmt.Errorf("Linker prog %d (0x%x) not found at offset 0x%x",
+				i, lprog.Vaddr, dlwrap_linker_offset.Value)
+		}
+	}
+
+	return nil
+}
diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go
index f383de9..8e71a97 100644
--- a/cmd/merge_zips/merge_zips.go
+++ b/cmd/merge_zips/merge_zips.go
@@ -173,6 +173,10 @@
 	return ze.content.FileHeader.CRC32
 }
 
+func (ze zipEntry) Size() uint64 {
+	return ze.content.FileHeader.UncompressedSize64
+}
+
 func (ze zipEntry) WriteToZip(dest string, zw *zip.Writer) error {
 	return zw.CopyFrom(ze.content, dest)
 }
@@ -195,6 +199,10 @@
 	return crc32.ChecksumIEEE(be.content)
 }
 
+func (be bufferEntry) Size() uint64 {
+	return uint64(len(be.content))
+}
+
 func (be bufferEntry) WriteToZip(dest string, zw *zip.Writer) error {
 	w, err := zw.CreateHeader(be.fh)
 	if err != nil {
@@ -215,6 +223,7 @@
 	String() string
 	IsDir() bool
 	CRC32() uint32
+	Size() uint64
 	WriteToZip(dest string, zw *zip.Writer) error
 }
 
@@ -369,25 +378,27 @@
 					return fmt.Errorf("Directory/file mismatch at %v from %v and %v\n",
 						dest, existingSource, source)
 				}
+
 				if ignoreDuplicates {
 					continue
 				}
+
 				if emulateJar &&
 					file.Name == jar.ManifestFile || file.Name == jar.ModuleInfoClass {
 					// Skip manifest and module info files that are not from the first input file
 					continue
 				}
-				if !source.IsDir() {
-					if emulateJar {
-						if existingSource.CRC32() != source.CRC32() {
-							fmt.Fprintf(os.Stdout, "WARNING: Duplicate path %v found in %v and %v\n",
-								dest, existingSource, source)
-						}
-					} else {
-						return fmt.Errorf("Duplicate path %v found in %v and %v\n",
-							dest, existingSource, source)
-					}
+
+				if source.IsDir() {
+					continue
 				}
+
+				if existingSource.CRC32() == source.CRC32() && existingSource.Size() == source.Size() {
+					continue
+				}
+
+				return fmt.Errorf("Duplicate path %v found in %v and %v\n",
+					dest, existingSource, source)
 			}
 		}
 	}
diff --git a/cmd/merge_zips/merge_zips_test.go b/cmd/merge_zips/merge_zips_test.go
index f91111f..19fa5ed 100644
--- a/cmd/merge_zips/merge_zips_test.go
+++ b/cmd/merge_zips/merge_zips_test.go
@@ -88,6 +88,14 @@
 			ignoreDuplicates: true,
 		},
 		{
+			name: "duplicates identical",
+			in: [][]testZipEntry{
+				{a},
+				{a},
+			},
+			out: []testZipEntry{a},
+		},
+		{
 			name: "sort",
 			in: [][]testZipEntry{
 				{be, bc, bDir, bbDir, bbb, A, metainfDir, manifestFile},
diff --git a/java/aapt2.go b/java/aapt2.go
index 70c7507..5553bfd 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -111,7 +111,8 @@
 
 var aapt2LinkRule = pctx.AndroidStaticRule("aapt2Link",
 	blueprint.RuleParams{
-		Command: `${config.Aapt2Cmd} link -o $out $flags --java $genDir --proguard $proguardOptions ` +
+		Command: `rm -rf $genDir && ` +
+			`${config.Aapt2Cmd} link -o $out $flags --java $genDir --proguard $proguardOptions ` +
 			`--output-text-symbols ${rTxt} $inFlags && ` +
 			`${config.SoongZipCmd} -write_if_changed -jar -o $genJar -C $genDir -D $genDir &&` +
 			`${config.ExtractJarPackagesCmd} -i $genJar -o $extraPackages --prefix '--extra-packages '`,
diff --git a/java/aar.go b/java/aar.go
index 35fb96f..a06d191 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -250,6 +250,8 @@
 		}
 
 		switch ctx.OtherModuleDependencyTag(module) {
+		case instrumentationForTag:
+			// Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2.
 		case libTag, frameworkResTag:
 			if exportPackage != nil {
 				sharedLibs = append(sharedLibs, exportPackage)
diff --git a/java/app.go b/java/app.go
index d21b62a..5d25dcf 100644
--- a/java/app.go
+++ b/java/app.go
@@ -318,12 +318,6 @@
 }
 
 func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	if String(a.appTestProperties.Instrumentation_for) != "" {
-		a.AndroidApp.extraLinkFlags = append(a.AndroidApp.extraLinkFlags,
-			"--rename-instrumentation-target-package",
-			String(a.appTestProperties.Instrumentation_for))
-	}
-
 	a.generateAndroidBuildActions(ctx)
 
 	a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, a.testProperties.Test_config_template, a.manifestPath)
@@ -335,6 +329,12 @@
 	android.ExtractSourceDeps(ctx, a.testProperties.Test_config_template)
 	android.ExtractSourcesDeps(ctx, a.testProperties.Data)
 	a.AndroidApp.DepsMutator(ctx)
+	if a.appTestProperties.Instrumentation_for != nil {
+		// The android_app dependency listed in instrumentation_for needs to be added to the classpath for javac,
+		// but not added to the aapt2 link includes like a normal android_app or android_library dependency, so
+		// use instrumentationForTag instead of libTag.
+		ctx.AddVariationDependencies(nil, instrumentationForTag, String(a.appTestProperties.Instrumentation_for))
+	}
 }
 
 func AndroidTestFactory() android.Module {
diff --git a/java/builder.go b/java/builder.go
index f55a7c7..cefb916 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -399,6 +399,17 @@
 	})
 }
 
+func GenerateMainClassManifest(ctx android.ModuleContext, outputFile android.WritablePath, mainClass string) {
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        android.WriteFile,
+		Description: "manifest",
+		Output:      outputFile,
+		Args: map[string]string{
+			"content": "Main-Class: " + mainClass + "\n",
+		},
+	})
+}
+
 type classpath []android.Path
 
 func (x *classpath) FormJavaClassPath(optName string) string {
diff --git a/java/config/config.go b/java/config/config.go
index 3d27b70..d2a8c46 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"}
-	DefaultSystemModules          = "core-system-modules"
-	DefaultLibraries              = []string{"ext", "framework", "okhttp"}
+	DefaultBootclasspathLibraries = []string{"core.platform.api.stubs", "core-lambda-stubs"}
+	DefaultSystemModules          = "core-platform-api-stubs-system-modules"
+	DefaultLibraries              = []string{"ext", "framework"}
 	DefaultLambdaStubsLibrary     = "core-lambda-stubs"
 	SdkLambdaStubsPath            = "prebuilts/sdk/tools/core-lambda-stubs.jar"
 
diff --git a/java/dex.go b/java/dex.go
index ce0c18e..625fb83 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -157,6 +157,8 @@
 	if !Bool(opt.Obfuscate) {
 		r8Flags = append(r8Flags, "-dontobfuscate")
 	}
+	// TODO(ccross): if this is an instrumentation test of an obfuscated app, use the
+	// dictionary of the app and move the app from libraryjars to injars.
 
 	return r8Flags, r8Deps
 }
@@ -171,8 +173,6 @@
 	outDir := android.PathForModuleOut(ctx, "dex")
 
 	if useR8 {
-		// TODO(ccross): if this is an instrumentation test of an obfuscated app, use the
-		// dictionary of the app and move the app from libraryjars to injars.
 		proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
 		j.proguardDictionary = proguardDictionary
 		r8Flags, r8Deps := j.r8Flags(ctx, flags)
diff --git a/java/gen.go b/java/gen.go
index a993829..993e6d1 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -26,6 +26,7 @@
 
 func init() {
 	pctx.HostBinToolVariable("aidlCmd", "aidl")
+	pctx.HostBinToolVariable("syspropCmd", "sysprop_java")
 	pctx.SourcePathVariable("logtagsCmd", "build/tools/java-event-log-tags.py")
 	pctx.SourcePathVariable("mergeLogtagsCmd", "build/tools/merge-event-log-tags.py")
 }
@@ -49,6 +50,17 @@
 			Command:     "$mergeLogtagsCmd -o $out $in",
 			CommandDeps: []string{"$mergeLogtagsCmd"},
 		})
+
+	sysprop = pctx.AndroidStaticRule("sysprop",
+		blueprint.RuleParams{
+			Command: `rm -rf $out.tmp && mkdir -p $out.tmp && ` +
+				`$syspropCmd --java-output-dir $out.tmp $in && ` +
+				`${config.SoongZipCmd} -jar -o $out -C $out.tmp -D $out.tmp && rm -rf $out.tmp`,
+			CommandDeps: []string{
+				"$syspropCmd",
+				"${config.SoongZipCmd}",
+			},
+		})
 )
 
 func genAidl(ctx android.ModuleContext, aidlFile android.Path, aidlFlags string) android.Path {
@@ -82,6 +94,19 @@
 	return javaFile
 }
 
+func genSysprop(ctx android.ModuleContext, syspropFile android.Path) android.Path {
+	srcJarFile := android.GenPathWithExt(ctx, "sysprop", syspropFile, "srcjar")
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        sysprop,
+		Description: "sysprop_java " + syspropFile.Rel(),
+		Output:      srcJarFile,
+		Input:       syspropFile,
+	})
+
+	return srcJarFile
+}
+
 func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths,
 	flags javaBuilderFlags) android.Paths {
 
@@ -99,6 +124,9 @@
 		case ".proto":
 			srcJarFile := genProto(ctx, srcFile, flags)
 			outSrcFiles = append(outSrcFiles, srcJarFile)
+		case ".sysprop":
+			srcJarFile := genSysprop(ctx, srcFile)
+			outSrcFiles = append(outSrcFiles, srcJarFile)
 		default:
 			outSrcFiles = append(outSrcFiles, srcFile)
 		}
diff --git a/java/java.go b/java/java.go
index c5414f4..d7068c6 100644
--- a/java/java.go
+++ b/java/java.go
@@ -309,6 +309,9 @@
 	// list of extra progurad flag files
 	extraProguardFlagFiles android.Paths
 
+	// manifest file to use instead of properties.Manifest
+	overrideManifest android.OptionalPath
+
 	// list of SDK lib names that this java moudule is exporting
 	exportedSdkLibs []string
 
@@ -368,16 +371,17 @@
 }
 
 var (
-	staticLibTag     = dependencyTag{name: "staticlib"}
-	libTag           = dependencyTag{name: "javalib"}
-	annoTag          = dependencyTag{name: "annotation processor"}
-	bootClasspathTag = dependencyTag{name: "bootclasspath"}
-	systemModulesTag = dependencyTag{name: "system modules"}
-	frameworkResTag  = dependencyTag{name: "framework-res"}
-	frameworkApkTag  = dependencyTag{name: "framework-apk"}
-	kotlinStdlibTag  = dependencyTag{name: "kotlin-stdlib"}
-	proguardRaiseTag = dependencyTag{name: "proguard-raise"}
-	certificateTag   = dependencyTag{name: "certificate"}
+	staticLibTag          = dependencyTag{name: "staticlib"}
+	libTag                = dependencyTag{name: "javalib"}
+	annoTag               = dependencyTag{name: "annotation processor"}
+	bootClasspathTag      = dependencyTag{name: "bootclasspath"}
+	systemModulesTag      = dependencyTag{name: "system modules"}
+	frameworkResTag       = dependencyTag{name: "framework-res"}
+	frameworkApkTag       = dependencyTag{name: "framework-apk"}
+	kotlinStdlibTag       = dependencyTag{name: "kotlin-stdlib"}
+	proguardRaiseTag      = dependencyTag{name: "proguard-raise"}
+	certificateTag        = dependencyTag{name: "certificate"}
+	instrumentationForTag = dependencyTag{name: "instrumentation_for"}
 )
 
 type sdkDep struct {
@@ -817,7 +821,7 @@
 			switch tag {
 			case bootClasspathTag:
 				deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...)
-			case libTag:
+			case libTag, instrumentationForTag:
 				deps.classpath = append(deps.classpath, dep.HeaderJars()...)
 				// sdk lib names from dependencies are re-exported
 				j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
@@ -1193,8 +1197,8 @@
 	jars = append(jars, deps.staticJars...)
 	jars = append(jars, deps.staticResourceJars...)
 
-	var manifest android.OptionalPath
-	if j.properties.Manifest != nil {
+	manifest := j.overrideManifest
+	if !manifest.Valid() && j.properties.Manifest != nil {
 		manifest = android.OptionalPathForPath(ctx.ExpandSource(*j.properties.Manifest, "manifest"))
 	}
 
@@ -1536,6 +1540,9 @@
 type binaryProperties struct {
 	// installable script to execute the resulting jar
 	Wrapper *string
+
+	// Name of the class containing main to be inserted into the manifest as Main-Class.
+	Main_class *string
 }
 
 type Binary struct {
@@ -1556,6 +1563,15 @@
 func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	if ctx.Arch().ArchType == android.Common {
 		// Compile the jar
+		if j.binaryProperties.Main_class != nil {
+			if j.properties.Manifest != nil {
+				ctx.PropertyErrorf("main_class", "main_class cannot be used when manifest is set")
+			}
+			manifestFile := android.PathForModuleOut(ctx, "manifest.txt")
+			GenerateMainClassManifest(ctx, manifestFile, String(j.binaryProperties.Main_class))
+			j.overrideManifest = android.OptionalPathForPath(manifestFile)
+		}
+
 		j.Library.GenerateAndroidBuildActions(ctx)
 	} else {
 		// Handle the binary wrapper
@@ -1757,7 +1773,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..86349fe 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -111,17 +111,14 @@
 	ctx.Register()
 
 	extraModules := []string{
-		"core-oj",
-		"core-libart",
 		"core-lambda-stubs",
-		"core-simple",
 		"framework",
 		"ext",
-		"okhttp",
 		"android_stubs_current",
 		"android_system_stubs_current",
 		"android_test_stubs_current",
 		"core.current.stubs",
+		"core.platform.api.stubs",
 		"kotlin-stdlib",
 	}
 
@@ -132,7 +129,7 @@
 				srcs: ["a.java"],
 				no_standard_libs: true,
 				sdk_version: "core_current",
-				system_modules: "core-system-modules",
+				system_modules: "core-platform-api-stubs-system-modules",
 			}
 		`, extra)
 	}
@@ -146,6 +143,7 @@
 
 	systemModules := []string{
 		"core-system-modules",
+		"core-platform-api-stubs-system-modules",
 		"android_stubs_current_system_modules",
 		"android_system_stubs_current_system_modules",
 		"android_test_stubs_current_system_modules",
@@ -365,16 +363,16 @@
 }{
 	{
 		name:          "default",
-		bootclasspath: []string{"core-oj", "core-libart", "core-simple"},
-		system:        "core-system-modules",
-		classpath:     []string{"ext", "framework", "okhttp"},
+		bootclasspath: []string{"core.platform.api.stubs", "core-lambda-stubs"},
+		system:        "core-platform-api-stubs-system-modules",
+		classpath:     []string{"ext", "framework"},
 	},
 	{
 		name:          "blank sdk version",
 		properties:    `sdk_version: "",`,
-		bootclasspath: []string{"core-oj", "core-libart", "core-simple"},
-		system:        "core-system-modules",
-		classpath:     []string{"ext", "framework", "okhttp"},
+		bootclasspath: []string{"core.platform.api.stubs", "core-lambda-stubs"},
+		system:        "core-platform-api-stubs-system-modules",
+		classpath:     []string{"ext", "framework"},
 	},
 	{
 
@@ -431,8 +429,8 @@
 	{
 
 		name:          "nostdlib system_modules",
-		properties:    `no_standard_libs: true, system_modules: "core-system-modules"`,
-		system:        "core-system-modules",
+		properties:    `no_standard_libs: true, system_modules: "core-platform-api-stubs-system-modules"`,
+		system:        "core-platform-api-stubs-system-modules",
 		bootclasspath: []string{`""`},
 		classpath:     []string{},
 	},
@@ -1062,12 +1060,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/python/scripts/stub_template_host.txt b/python/scripts/stub_template_host.txt
index e686211..213401d 100644
--- a/python/scripts/stub_template_host.txt
+++ b/python/scripts/stub_template_host.txt
@@ -41,6 +41,7 @@
   args = sys.argv[1:]
 
   new_env = {}
+  runfiles_path = None
 
   try:
     runfiles_path = ExtractRunfiles()
@@ -82,7 +83,8 @@
   except:
     raise
   finally:
-    shutil.rmtree(runfiles_path, True)
+    if runfiles_path is not None:
+      shutil.rmtree(runfiles_path, True)
 
 if __name__ == '__main__':
   Main()
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index 80a398b..9256cb2 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -56,7 +56,9 @@
   parser.add_argument('--library', dest='library', action='store_true',
                       help='manifest is for a static library')
   parser.add_argument('--uses-library', dest='uses_libraries', action='append',
-                      help='specify additional <uses-library> tag to add')
+                      help='specify additional <uses-library> tag to add. android:requred is set to true')
+  parser.add_argument('--optional-uses-library', dest='optional_uses_libraries', action='append',
+                      help='specify additional <uses-library> tag to add. android:requred is set to false')
   parser.add_argument('--uses-non-sdk-api', dest='uses_non_sdk_api', action='store_true',
                       help='manifest is for a package built against the platform')
   parser.add_argument('input', help='input AndroidManifest.xml file')
@@ -190,12 +192,13 @@
     element.setAttributeNode(target_attr)
 
 
-def add_uses_libraries(doc, new_uses_libraries):
-  """Add additional <uses-library> tags with android:required=true.
+def add_uses_libraries(doc, new_uses_libraries, required):
+  """Add additional <uses-library> tags
 
   Args:
     doc: The XML document. May be modified by this function.
     new_uses_libraries: The names of libraries to be added by this function.
+    required: The value of android:required attribute. Can be true or false.
   Raises:
     RuntimeError: Invalid manifest
   """
@@ -227,7 +230,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', str(required).lower())
 
     application.insertBefore(doc.createTextNode(indent), last)
     application.insertBefore(ul, last)
@@ -285,7 +288,10 @@
       raise_min_sdk_version(doc, args.min_sdk_version, args.target_sdk_version, args.library)
 
     if args.uses_libraries:
-      add_uses_libraries(doc, args.uses_libraries)
+      add_uses_libraries(doc, args.uses_libraries, True)
+
+    if args.optional_uses_libraries:
+      add_uses_libraries(doc, args.optional_uses_libraries, False)
 
     if args.uses_non_sdk_api:
       add_uses_non_sdk_api(doc)
diff --git a/scripts/strip.sh b/scripts/strip.sh
index 29594dc..4634c18 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -98,6 +98,7 @@
         else
             "${CROSS_COMPILE}objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp"
         fi
+        rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo" "${outfile}.mini_debuginfo.xz"
     else
         cp -f "${infile}" "${outfile}.tmp"
     fi
diff --git a/cmd/symbol_inject/Android.bp b/symbol_inject/Android.bp
similarity index 90%
rename from cmd/symbol_inject/Android.bp
rename to symbol_inject/Android.bp
index a2ea12b..8308043 100644
--- a/cmd/symbol_inject/Android.bp
+++ b/symbol_inject/Android.bp
@@ -12,8 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-blueprint_go_binary {
-    name: "symbol_inject",
+bootstrap_go_package {
+    name: "soong-symbol_inject",
+    pkgPath: "android/soong/symbol_inject",
     srcs: [
         "symbol_inject.go",
         "elf.go",
diff --git a/cmd/symbol_inject/Android.bp b/symbol_inject/cmd/Android.bp
similarity index 71%
copy from cmd/symbol_inject/Android.bp
copy to symbol_inject/cmd/Android.bp
index a2ea12b..ee2f259 100644
--- a/cmd/symbol_inject/Android.bp
+++ b/symbol_inject/cmd/Android.bp
@@ -14,19 +14,8 @@
 
 blueprint_go_binary {
     name: "symbol_inject",
+    deps: ["soong-symbol_inject"],
     srcs: [
         "symbol_inject.go",
-        "elf.go",
-        "macho.go",
-        "pe.go",
-    ],
-    testSrcs: [
-        "elf_symboldata_test.go",
-        "elf_test.go",
-        "macho_symboldata_test.go",
-        "macho_test.go",
-        "pe_symboldata_test.go",
-        "pe_test.go",
-        "symbol_inject_test.go",
     ],
 }
diff --git a/symbol_inject/cmd/symbol_inject.go b/symbol_inject/cmd/symbol_inject.go
new file mode 100644
index 0000000..1397b37
--- /dev/null
+++ b/symbol_inject/cmd/symbol_inject.go
@@ -0,0 +1,97 @@
+// 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 main
+
+import (
+	"flag"
+	"fmt"
+	"os"
+
+	"android/soong/symbol_inject"
+)
+
+var (
+	input  = flag.String("i", "", "input file")
+	output = flag.String("o", "", "output file")
+	symbol = flag.String("s", "", "symbol to inject into")
+	from   = flag.String("from", "", "optional existing value of the symbol for verification")
+	value  = flag.String("v", "", "value to inject into symbol")
+
+	dump = flag.Bool("dump", false, "dump the symbol table for copying into a test")
+)
+
+func main() {
+	flag.Parse()
+
+	usageError := func(s string) {
+		fmt.Fprintln(os.Stderr, s)
+		flag.Usage()
+		os.Exit(1)
+	}
+
+	if *input == "" {
+		usageError("-i is required")
+	}
+
+	if !*dump {
+		if *output == "" {
+			usageError("-o is required")
+		}
+
+		if *symbol == "" {
+			usageError("-s is required")
+		}
+
+		if *value == "" {
+			usageError("-v is required")
+		}
+	}
+
+	r, err := os.Open(*input)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err.Error())
+		os.Exit(2)
+	}
+	defer r.Close()
+
+	if *dump {
+		err := symbol_inject.DumpSymbols(r)
+		if err != nil {
+			fmt.Fprintln(os.Stderr, err.Error())
+			os.Exit(6)
+		}
+		return
+	}
+
+	w, err := os.OpenFile(*output, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err.Error())
+		os.Exit(3)
+	}
+	defer w.Close()
+
+	file, err := symbol_inject.OpenFile(r)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err.Error())
+		os.Exit(4)
+	}
+
+	err = symbol_inject.InjectStringSymbol(file, w, *symbol, *value, *from)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err.Error())
+		os.Remove(*output)
+		os.Exit(5)
+	}
+}
diff --git a/cmd/symbol_inject/elf.go b/symbol_inject/elf.go
similarity index 99%
rename from cmd/symbol_inject/elf.go
rename to symbol_inject/elf.go
index d94877d..8742cbd 100644
--- a/cmd/symbol_inject/elf.go
+++ b/symbol_inject/elf.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package symbol_inject
 
 import (
 	"debug/elf"
diff --git a/cmd/symbol_inject/elf_symboldata_test.go b/symbol_inject/elf_symboldata_test.go
similarity index 99%
rename from cmd/symbol_inject/elf_symboldata_test.go
rename to symbol_inject/elf_symboldata_test.go
index 9ba7153..b2f1148 100644
--- a/cmd/symbol_inject/elf_symboldata_test.go
+++ b/symbol_inject/elf_symboldata_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package symbol_inject
 
 import "debug/elf"
 
diff --git a/cmd/symbol_inject/elf_test.go b/symbol_inject/elf_test.go
similarity index 98%
rename from cmd/symbol_inject/elf_test.go
rename to symbol_inject/elf_test.go
index 30b46a5..aceee44 100644
--- a/cmd/symbol_inject/elf_test.go
+++ b/symbol_inject/elf_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package symbol_inject
 
 import (
 	"strconv"
diff --git a/cmd/symbol_inject/macho.go b/symbol_inject/macho.go
similarity index 98%
rename from cmd/symbol_inject/macho.go
rename to symbol_inject/macho.go
index be49f8b..6ee3f4f 100644
--- a/cmd/symbol_inject/macho.go
+++ b/symbol_inject/macho.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package symbol_inject
 
 import (
 	"debug/macho"
diff --git a/cmd/symbol_inject/macho_symboldata_test.go b/symbol_inject/macho_symboldata_test.go
similarity index 99%
rename from cmd/symbol_inject/macho_symboldata_test.go
rename to symbol_inject/macho_symboldata_test.go
index 3100a81..7336a27 100644
--- a/cmd/symbol_inject/macho_symboldata_test.go
+++ b/symbol_inject/macho_symboldata_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package symbol_inject
 
 import (
 	"debug/macho"
diff --git a/cmd/symbol_inject/macho_test.go b/symbol_inject/macho_test.go
similarity index 98%
rename from cmd/symbol_inject/macho_test.go
rename to symbol_inject/macho_test.go
index 7acab23..50df131 100644
--- a/cmd/symbol_inject/macho_test.go
+++ b/symbol_inject/macho_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package symbol_inject
 
 import (
 	"debug/macho"
diff --git a/cmd/symbol_inject/pe.go b/symbol_inject/pe.go
similarity index 98%
rename from cmd/symbol_inject/pe.go
rename to symbol_inject/pe.go
index 12f35ee..58cf91a 100644
--- a/cmd/symbol_inject/pe.go
+++ b/symbol_inject/pe.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package symbol_inject
 
 import (
 	"debug/pe"
diff --git a/cmd/symbol_inject/pe_symboldata_test.go b/symbol_inject/pe_symboldata_test.go
similarity index 99%
rename from cmd/symbol_inject/pe_symboldata_test.go
rename to symbol_inject/pe_symboldata_test.go
index edc1c97..5c0fd70 100644
--- a/cmd/symbol_inject/pe_symboldata_test.go
+++ b/symbol_inject/pe_symboldata_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package symbol_inject
 
 import (
 	"debug/pe"
diff --git a/cmd/symbol_inject/pe_test.go b/symbol_inject/pe_test.go
similarity index 99%
rename from cmd/symbol_inject/pe_test.go
rename to symbol_inject/pe_test.go
index 21a0bc4..df7bac3 100644
--- a/cmd/symbol_inject/pe_test.go
+++ b/symbol_inject/pe_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package symbol_inject
 
 import (
 	"debug/pe"
diff --git a/cmd/symbol_inject/symbol_inject.go b/symbol_inject/symbol_inject.go
similarity index 70%
rename from cmd/symbol_inject/symbol_inject.go
rename to symbol_inject/symbol_inject.go
index d0f01c5..2a3d67e 100644
--- a/cmd/symbol_inject/symbol_inject.go
+++ b/symbol_inject/symbol_inject.go
@@ -12,25 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package symbol_inject
 
 import (
 	"bytes"
-	"flag"
+	"encoding/binary"
 	"fmt"
 	"io"
 	"math"
-	"os"
-)
-
-var (
-	input  = flag.String("i", "", "input file")
-	output = flag.String("o", "", "output file")
-	symbol = flag.String("s", "", "symbol to inject into")
-	from   = flag.String("from", "", "optional existing value of the symbol for verification")
-	value  = flag.String("v", "", "value to inject into symbol")
-
-	dump = flag.Bool("dump", false, "dump the symbol table for copying into a test")
 )
 
 var maxUint64 uint64 = math.MaxUint64
@@ -39,71 +28,7 @@
 	error
 }
 
-func main() {
-	flag.Parse()
-
-	usageError := func(s string) {
-		fmt.Fprintln(os.Stderr, s)
-		flag.Usage()
-		os.Exit(1)
-	}
-
-	if *input == "" {
-		usageError("-i is required")
-	}
-
-	if !*dump {
-		if *output == "" {
-			usageError("-o is required")
-		}
-
-		if *symbol == "" {
-			usageError("-s is required")
-		}
-
-		if *value == "" {
-			usageError("-v is required")
-		}
-	}
-
-	r, err := os.Open(*input)
-	if err != nil {
-		fmt.Fprintln(os.Stderr, err.Error())
-		os.Exit(2)
-	}
-	defer r.Close()
-
-	if *dump {
-		err := dumpSymbols(r)
-		if err != nil {
-			fmt.Fprintln(os.Stderr, err.Error())
-			os.Exit(6)
-		}
-		return
-	}
-
-	w, err := os.OpenFile(*output, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)
-	if err != nil {
-		fmt.Fprintln(os.Stderr, err.Error())
-		os.Exit(3)
-	}
-	defer w.Close()
-
-	file, err := openFile(r)
-	if err != nil {
-		fmt.Fprintln(os.Stderr, err.Error())
-		os.Exit(4)
-	}
-
-	err = injectSymbol(file, w, *symbol, *value, *from)
-	if err != nil {
-		fmt.Fprintln(os.Stderr, err.Error())
-		os.Remove(*output)
-		os.Exit(5)
-	}
-}
-
-func openFile(r io.ReaderAt) (*File, error) {
+func OpenFile(r io.ReaderAt) (*File, error) {
 	file, err := elfSymbolsFromFile(r)
 	if elfError, ok := err.(cantParseError); ok {
 		// Try as a mach-o file
@@ -126,7 +51,7 @@
 	return file, err
 }
 
-func injectSymbol(file *File, w io.Writer, symbol, value, from string) error {
+func InjectStringSymbol(file *File, w io.Writer, symbol, value, from string) error {
 	offset, size, err := findSymbol(file, symbol)
 	if err != nil {
 		return err
@@ -151,13 +76,29 @@
 		}
 	}
 
-	return copyAndInject(file.r, w, offset, size, value)
-}
-
-func copyAndInject(r io.ReaderAt, w io.Writer, offset, size uint64, value string) (err error) {
 	buf := make([]byte, size)
 	copy(buf, value)
 
+	return copyAndInject(file.r, w, offset, buf)
+}
+
+func InjectUint64Symbol(file *File, w io.Writer, symbol string, value uint64) error {
+	offset, size, err := findSymbol(file, symbol)
+	if err != nil {
+		return err
+	}
+
+	if size != 8 {
+		return fmt.Errorf("symbol %q is not a uint64, it is %d bytes long", symbol, size)
+	}
+
+	buf := make([]byte, 8)
+	binary.LittleEndian.PutUint64(buf, value)
+
+	return copyAndInject(file.r, w, offset, buf)
+}
+
+func copyAndInject(r io.ReaderAt, w io.Writer, offset uint64, buf []byte) (err error) {
 	// Copy the first bytes up to the symbol offset
 	_, err = io.Copy(w, io.NewSectionReader(r, 0, int64(offset)))
 
@@ -167,7 +108,7 @@
 	}
 
 	// Write the remainder of the file
-	pos := int64(offset + size)
+	pos := int64(offset) + int64(len(buf))
 	if err == nil {
 		_, err = io.Copy(w, io.NewSectionReader(r, pos, 1<<63-1-pos))
 	}
@@ -239,7 +180,7 @@
 	Size   uint64
 }
 
-func dumpSymbols(r io.ReaderAt) error {
+func DumpSymbols(r io.ReaderAt) error {
 	err := dumpElfSymbols(r)
 	if elfError, ok := err.(cantParseError); ok {
 		// Try as a mach-o file
diff --git a/cmd/symbol_inject/symbol_inject_test.go b/symbol_inject/symbol_inject_test.go
similarity index 77%
rename from cmd/symbol_inject/symbol_inject_test.go
rename to symbol_inject/symbol_inject_test.go
index dbee39a..6607e65 100644
--- a/cmd/symbol_inject/symbol_inject_test.go
+++ b/symbol_inject/symbol_inject_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package main
+package symbol_inject
 
 import (
 	"bytes"
@@ -23,32 +23,23 @@
 func TestCopyAndInject(t *testing.T) {
 	s := "abcdefghijklmnopqrstuvwxyz"
 	testCases := []struct {
-		offset, size uint64
-		value        string
-		expected     string
+		offset   uint64
+		buf      string
+		expected string
 	}{
 		{
 			offset:   0,
-			size:     1,
-			value:    "A",
+			buf:      "A",
 			expected: "Abcdefghijklmnopqrstuvwxyz",
 		},
 		{
 			offset:   1,
-			size:     1,
-			value:    "B",
-			expected: "aBcdefghijklmnopqrstuvwxyz",
-		},
-		{
-			offset:   1,
-			size:     1,
-			value:    "BCD",
+			buf:      "B",
 			expected: "aBcdefghijklmnopqrstuvwxyz",
 		},
 		{
 			offset:   25,
-			size:     1,
-			value:    "Z",
+			buf:      "Z",
 			expected: "abcdefghijklmnopqrstuvwxyZ",
 		},
 	}
@@ -57,7 +48,7 @@
 		t.Run(strconv.Itoa(i), func(t *testing.T) {
 			in := bytes.NewReader([]byte(s))
 			out := &bytes.Buffer{}
-			copyAndInject(in, out, testCase.offset, testCase.size, testCase.value)
+			copyAndInject(in, out, testCase.offset, []byte(testCase.buf))
 
 			if out.String() != testCase.expected {
 				t.Errorf("expected %s, got %s", testCase.expected, out.String())
diff --git a/ui/build/build.go b/ui/build/build.go
index 377481b..c902a0f 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -40,9 +40,10 @@
 pool local_pool
  depth = {{.Parallel}}
 build _kati_always_build_: phony
-{{if .HasKatiSuffix}}include {{.KatiBuildNinjaFile}}
+{{if .HasKatiSuffix}}subninja {{.KatiBuildNinjaFile}}
+subninja {{.KatiPackageNinjaFile}}
 {{end -}}
-include {{.SoongNinjaFile}}
+subninja {{.SoongNinjaFile}}
 `))
 
 func createCombinedBuildNinjaFile(ctx Context, config Config) {
@@ -180,6 +181,7 @@
 		genKatiSuffix(ctx, config)
 		runKatiCleanSpec(ctx, config)
 		runKatiBuild(ctx, config)
+		runKatiPackage(ctx, config)
 
 		ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0777)
 	} else {
diff --git a/ui/build/config.go b/ui/build/config.go
index d470b96..840f505 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -34,6 +34,7 @@
 	arguments []string
 	goma      bool
 	environ   *Environment
+	distDir   string
 
 	// From the arguments
 	parallel   int
@@ -86,6 +87,12 @@
 		ret.environ.Set("OUT_DIR", outDir)
 	}
 
+	if distDir, ok := ret.environ.Get("DIST_DIR"); ok {
+		ret.distDir = filepath.Clean(distDir)
+	} else {
+		ret.distDir = filepath.Join(ret.OutDir(), "dist")
+	}
+
 	ret.environ.Unset(
 		// We're already using it
 		"USE_SOONG_UI",
@@ -107,6 +114,9 @@
 		// We handle this above
 		"OUT_DIR_COMMON_BASE",
 
+		// This is handled above too, and set for individual commands later
+		"DIST_DIR",
+
 		// Variables that have caused problems in the past
 		"CDPATH",
 		"DISPLAY",
@@ -248,10 +258,10 @@
 			}
 		} else if k, v, ok := decodeKeyValue(arg); ok && len(k) > 0 {
 			c.environ.Set(k, v)
+		} else if arg == "dist" {
+			c.dist = true
 		} else {
-			if arg == "dist" {
-				c.dist = true
-			} else if arg == "checkbuild" {
+			if arg == "checkbuild" {
 				c.checkbuild = true
 			}
 			c.arguments = append(c.arguments, arg)
@@ -375,10 +385,7 @@
 }
 
 func (c *configImpl) DistDir() string {
-	if distDir, ok := c.environ.Get("DIST_DIR"); ok {
-		return filepath.Clean(distDir)
-	}
-	return filepath.Join(c.OutDir(), "dist")
+	return c.distDir
 }
 
 func (c *configImpl) NinjaArgs() []string {
@@ -505,6 +512,10 @@
 	return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiBuildSuffix+".ninja")
 }
 
+func (c *configImpl) KatiPackageNinjaFile() string {
+	return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja")
+}
+
 func (c *configImpl) SoongNinjaFile() string {
 	return filepath.Join(c.SoongOutDir(), "build.ninja")
 }
@@ -532,6 +543,10 @@
 	return filepath.Join(c.ProductOut(), "previous_build_config.mk")
 }
 
+func (c *configImpl) KatiPackageMkDir() string {
+	return filepath.Join(c.ProductOut(), "obj", "CONFIG", "kati_packaging")
+}
+
 func (c *configImpl) hostOutRoot() string {
 	return filepath.Join(c.OutDir(), "host")
 }
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index ffea841..ad57d02 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -32,8 +32,40 @@
 //
 // vars is the list of variables to read. The values will be put in the
 // returned map.
+//
+// variables controlled by soong_ui directly are now returned without needing
+// to call into make, to retain compatibility.
 func DumpMakeVars(ctx Context, config Config, goals, vars []string) (map[string]string, error) {
-	return dumpMakeVars(ctx, config, goals, vars, false)
+	soongUiVars := map[string]func() string{
+		"OUT_DIR":  func() string { return config.OutDir() },
+		"DIST_DIR": func() string { return config.DistDir() },
+	}
+
+	makeVars := make([]string, 0, len(vars))
+	for _, v := range vars {
+		if _, ok := soongUiVars[v]; !ok {
+			makeVars = append(makeVars, v)
+		}
+	}
+
+	var ret map[string]string
+	if len(makeVars) > 0 {
+		var err error
+		ret, err = dumpMakeVars(ctx, config, goals, makeVars, false)
+		if err != nil {
+			return ret, err
+		}
+	} else {
+		ret = make(map[string]string)
+	}
+
+	for _, v := range vars {
+		if f, ok := soongUiVars[v]; ok {
+			ret[v] = f()
+		}
+	}
+
+	return ret, nil
 }
 
 func dumpMakeVars(ctx Context, config Config, goals, vars []string, write_soong_vars bool) (map[string]string, error) {
@@ -48,7 +80,6 @@
 		"dump-many-vars",
 		"MAKECMDGOALS="+strings.Join(goals, " "))
 	cmd.Environment.Set("CALLED_FROM_SETUP", "true")
-	cmd.Environment.Set("BUILD_SYSTEM", "build/make/core")
 	if write_soong_vars {
 		cmd.Environment.Set("WRITE_SOONG_VARIABLES", "true")
 	}
diff --git a/ui/build/environment.go b/ui/build/environment.go
index cbeeb4b..d8ff7f2 100644
--- a/ui/build/environment.go
+++ b/ui/build/environment.go
@@ -75,6 +75,17 @@
 	*e = out
 }
 
+// Allow removes all keys that are not present in the input list
+func (e *Environment) Allow(keys ...string) {
+	out := (*e)[:0]
+	for _, env := range *e {
+		if key, _, ok := decodeKeyValue(env); ok && inList(key, keys) {
+			out = append(out, env)
+		}
+	}
+	*e = out
+}
+
 // Environ returns the []string required for exec.Cmd.Env
 func (e *Environment) Environ() []string {
 	return []string(*e)
diff --git a/ui/build/environment_test.go b/ui/build/environment_test.go
index 0294dac..37f500f 100644
--- a/ui/build/environment_test.go
+++ b/ui/build/environment_test.go
@@ -56,6 +56,15 @@
 	}
 }
 
+func TestEnvAllow(t *testing.T) {
+	initial := &Environment{"TEST=1", "TEST2=0", "TEST3=2"}
+	initial.Allow("TEST3", "TEST")
+	got := initial.Environ()
+	if len(got) != 2 || got[0] != "TEST=1" || got[1] != "TEST3=2" {
+		t.Errorf("Expected [TEST=1 TEST3=2], got: %v", got)
+	}
+}
+
 const testKatiEnvFileContents = `#!/bin/sh
 # Generated by kati unknown
 
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 546fd1a..56e9a88 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -28,6 +28,7 @@
 
 const katiBuildSuffix = ""
 const katiCleanspecSuffix = "-cleanspec"
+const katiPackageSuffix = "-package"
 
 // genKatiSuffix creates a suffix for kati-generated files so that we can cache
 // them based on their inputs. So this should encode all common changes to Kati
@@ -59,7 +60,7 @@
 	}
 }
 
-func runKati(ctx Context, config Config, extraSuffix string, args []string) {
+func runKati(ctx Context, config Config, extraSuffix string, args []string, envFunc func(*Environment)) {
 	executable := config.PrebuiltBuildTool("ckati")
 	args = append([]string{
 		"--ninja",
@@ -80,10 +81,6 @@
 		"--kati_stats",
 	}, args...)
 
-	args = append(args,
-		"SOONG_MAKEVARS_MK="+config.SoongMakeVarsMk(),
-		"TARGET_DEVICE_DIR="+config.TargetDeviceDir())
-
 	cmd := Command(ctx, config, "ckati", executable, args...)
 	cmd.Sandbox = katiSandbox
 	pipe, err := cmd.StdoutPipe()
@@ -92,6 +89,8 @@
 	}
 	cmd.Stderr = cmd.Stdout
 
+	envFunc(cmd.Environment)
+
 	cmd.StartOrFatal()
 	status.KatiReader(ctx.Status.StartTool(), pipe)
 	cmd.WaitOrFatal()
@@ -103,7 +102,6 @@
 
 	args := []string{
 		"--writable", config.OutDir() + "/",
-		"--writable", config.DistDir() + "/",
 		"-f", "build/make/core/main.mk",
 	}
 
@@ -125,9 +123,54 @@
 
 	args = append(args, config.KatiArgs()...)
 
-	args = append(args, "SOONG_ANDROID_MK="+config.SoongAndroidMk())
+	args = append(args,
+		"SOONG_MAKEVARS_MK="+config.SoongMakeVarsMk(),
+		"SOONG_ANDROID_MK="+config.SoongAndroidMk(),
+		"TARGET_DEVICE_DIR="+config.TargetDeviceDir(),
+		"KATI_PACKAGE_MK_DIR="+config.KatiPackageMkDir())
 
-	runKati(ctx, config, katiBuildSuffix, args)
+	runKati(ctx, config, katiBuildSuffix, args, func(env *Environment) {})
+}
+
+func runKatiPackage(ctx Context, config Config) {
+	ctx.BeginTrace("kati package")
+	defer ctx.EndTrace()
+
+	args := []string{
+		"--writable", config.DistDir() + "/",
+		"--werror_writable",
+		"--werror_implicit_rules",
+		"--werror_overriding_commands",
+		"--werror_real_to_phony",
+		"--werror_phony_looks_real",
+		"-f", "build/make/packaging/main.mk",
+		"KATI_PACKAGE_MK_DIR=" + config.KatiPackageMkDir(),
+	}
+
+	runKati(ctx, config, katiPackageSuffix, args, func(env *Environment) {
+		env.Allow([]string{
+			// Some generic basics
+			"LANG",
+			"LC_MESSAGES",
+			"PATH",
+			"PWD",
+			"TMPDIR",
+
+			// Tool configs
+			"JAVA_HOME",
+			"PYTHONDONTWRITEBYTECODE",
+
+			// Build configuration
+			"ANDROID_BUILD_SHELL",
+			"DIST_DIR",
+			"OUT_DIR",
+		}...)
+
+		if config.Dist() {
+			env.Set("DIST", "true")
+			env.Set("DIST_DIR", config.DistDir())
+		}
+	})
 }
 
 func runKatiCleanSpec(ctx Context, config Config) {
@@ -138,5 +181,7 @@
 		"--werror_implicit_rules",
 		"--werror_overriding_commands",
 		"-f", "build/make/core/cleanbuild.mk",
-	})
+		"SOONG_MAKEVARS_MK=" + config.SoongMakeVarsMk(),
+		"TARGET_DEVICE_DIR=" + config.TargetDeviceDir(),
+	}, func(env *Environment) {})
 }
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 91cb475..c8f19d1 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -60,6 +60,8 @@
 		cmd.Environment.AppendFromKati(config.KatiEnvFile())
 	}
 
+	cmd.Environment.Set("DIST_DIR", config.DistDir())
+
 	// Allow both NINJA_ARGS and NINJA_EXTRA_ARGS, since both have been
 	// used in the past to specify extra ninja arguments.
 	if extra, ok := cmd.Environment.Get("NINJA_ARGS"); ok {
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 8c51641..c4fcc20 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -41,8 +41,8 @@
 
 var Log = PathConfig{
 	Symlink: true,
-	Log: true,
-	Error: false,
+	Log:     true,
+	Error:   false,
 }
 
 // The configuration used if the tool is not listed in the config below.
@@ -101,7 +101,6 @@
 	"ls":        Allowed,
 	"lsof":      Allowed,
 	"m4":        Allowed,
-	"make":      Allowed,
 	"md5sum":    Allowed,
 	"mkdir":     Allowed,
 	"mktemp":    Allowed,
@@ -110,7 +109,6 @@
 	"openssl":   Allowed,
 	"paste":     Allowed,
 	"patch":     Allowed,
-	"perl":      Log,
 	"pgrep":     Allowed,
 	"pkill":     Allowed,
 	"ps":        Allowed,
@@ -149,7 +147,6 @@
 	"which":     Allowed,
 	"whoami":    Allowed,
 	"xargs":     Allowed,
-	"xmllint":   Allowed,
 	"xxd":       Allowed,
 	"xz":        Allowed,
 	"zip":       Allowed,
diff --git a/ui/status/kati.go b/ui/status/kati.go
index 552a9e9..7c26d42 100644
--- a/ui/status/kati.go
+++ b/ui/status/kati.go
@@ -24,7 +24,7 @@
 )
 
 var katiError = regexp.MustCompile(`^(\033\[1m)?[^ ]+:[0-9]+: (\033\[31m)?error:`)
-var katiIncludeRe = regexp.MustCompile(`^(\[(\d+)/(\d+)] )?((including [^ ]+|initializing build system|finishing build rules|writing build rules) ...)$`)
+var katiIncludeRe = regexp.MustCompile(`^(\[(\d+)/(\d+)] )?((including [^ ]+|initializing (build|packaging) system|finishing (build|packaging) rules|writing (build|packaging) rules) ...)$`)
 var katiLogRe = regexp.MustCompile(`^\*kati\*: `)
 var katiNinjaMissing = regexp.MustCompile("^[^ ]+ is missing, regenerating...$")