Merge "Revert "ATest: GTest auto gen config support run_test_as in Android.bp .""
diff --git a/Android.bp b/Android.bp
index 2037818..5faefe6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -173,6 +173,7 @@
     testSrcs: [
         "cc/cc_test.go",
         "cc/gen_test.go",
+        "cc/genrule_test.go",
         "cc/library_test.go",
         "cc/test_data_test.go",
         "cc/util_test.go",
@@ -348,6 +349,7 @@
     ],
     srcs: [
         "apex/apex.go",
+        "apex/key.go",
     ],
     pluginFor: ["soong_build"],
 }
@@ -481,7 +483,7 @@
 }
 
 cc_genrule {
-    name: "host_bionic_linker_script",
+    name: "host_bionic_linker_flags",
     host_supported: true,
     device_supported: false,
     target: {
@@ -496,7 +498,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/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..3b7b477 100644
--- a/android/config.go
+++ b/android/config.go
@@ -41,7 +41,6 @@
 // config file. These will be included in the config struct.
 type FileConfigurableOptions struct {
 	Mega_device *bool `json:",omitempty"`
-	Ndk_abis    *bool `json:",omitempty"`
 	Host_bionic *bool `json:",omitempty"`
 }
 
@@ -90,7 +89,7 @@
 	ConfigFileName           string
 	ProductVariablesFileName string
 
-	Targets              map[OsClass][]Target
+	Targets              map[OsType][]Target
 	BuildOsVariant       string
 	BuildOsCommonVariant string
 
@@ -230,18 +229,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
 }
@@ -299,21 +298,21 @@
 	var archConfig []archConfig
 	if Bool(config.Mega_device) {
 		archConfig = getMegaDeviceConfig()
-	} else if Bool(config.Ndk_abis) {
+	} else if config.NdkAbis() {
 		archConfig = getNdkAbisConfig()
 	}
 
 	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 +586,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 +623,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 +645,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 +662,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 +710,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
@@ -866,6 +861,10 @@
 	return ok
 }
 
+func (c *config) NdkAbis() bool {
+	return Bool(c.productVariables.Ndk_abis)
+}
+
 func stringSlice(s *[]string) []string {
 	if s != nil {
 		return *s
diff --git a/android/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/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..2eb9900 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"`
 
@@ -242,6 +239,8 @@
 	BoardPlatPrivateSepolicyDirs []string `json:",omitempty"`
 
 	VendorVars map[string]map[string]string `json:",omitempty"`
+
+	Ndk_abis *bool `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index 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
index 68d9cb8..5390114 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -75,6 +75,7 @@
 	executableTag = dependencyTag{name: "executable"}
 	javaLibTag    = dependencyTag{name: "javaLib"}
 	prebuiltTag   = dependencyTag{name: "prebuilt"}
+	keyTag        = dependencyTag{name: "key"}
 )
 
 func init() {
@@ -112,7 +113,7 @@
 		apexBundleName := mctx.Module().Name()
 		mctx.WalkDeps(func(child, parent android.Module) bool {
 			if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() {
-				moduleName := am.Name()
+				moduleName := am.Name() + "-" + am.Target().String()
 				bundleNames, ok := apexBundleNamesFor(mctx.Config())[moduleName]
 				if !ok {
 					bundleNames = make(map[string]bool)
@@ -130,7 +131,7 @@
 // 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()
+		moduleName := am.Name() + "-" + am.Target().String()
 		if bundleNames, ok := apexBundleNamesFor(mctx.Config())[moduleName]; ok {
 			variations := []string{"platform"}
 			for bn := range bundleNames {
@@ -172,6 +173,9 @@
 
 	// 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 {
@@ -185,14 +189,6 @@
 }
 
 func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
-	// Native shared libs are added for all architectures of the device
-	// i.e., native_shared_lib_modules: ["libc"] adds both 64 and 32 variation
-	// of the module
-	arches := ctx.DeviceConfig().Arches()
-	if len(arches) == 0 {
-		panic("device build with no primary arch")
-	}
-
 	for _, arch := range ctx.MultiTargets() {
 		// Use *FarVariation* to be able to depend on modules having
 		// conflicting variations with this module. This is required since
@@ -208,16 +204,21 @@
 			{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...)
 	}
 
+	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) {
@@ -259,34 +260,52 @@
 	// 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 {
@@ -330,8 +349,6 @@
 
 	manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "manifest.json"))
 	fileContexts := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.File_contexts, "file_contexts"))
-	// TODO(b/114488804) make this customizable
-	key := android.PathForSource(ctx, "system/apex/apexer/testdata/testkey.pem")
 
 	a.outputFile = android.PathForModuleOut(ctx, a.ModuleBase.Name()+apexSuffix)
 
@@ -351,7 +368,7 @@
 		copyCommands = append(copyCommands, "cp "+src.String()+" "+dest_path)
 	}
 	implicitInputs := append(android.Paths(nil), filesToCopy...)
-	implicitInputs = append(implicitInputs, cannedFsConfig, manifest, fileContexts, key)
+	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{
@@ -365,7 +382,7 @@
 			"manifest":         manifest.String(),
 			"file_contexts":    fileContexts.String(),
 			"canned_fs_config": cannedFsConfig.String(),
-			"key":              key.String(),
+			"key":              keyFile.String(),
 		},
 	})
 
@@ -382,6 +399,7 @@
 			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)")
 		}}
 }
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/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 d9a6cae..3d12538 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -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 6320b9c..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}
@@ -1062,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()
@@ -1257,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)
@@ -1358,6 +1370,8 @@
 			depPaths.CrtBegin = linkFile
 		case crtEndDepTag:
 			depPaths.CrtEnd = linkFile
+		case dynamicLinkerDepTag:
+			depPaths.DynamicLinker = linkFile
 		}
 
 		switch depTag {
diff --git a/cc/compiler.go b/cc/compiler.go
index 68d8593..5ac5d79 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -224,6 +224,10 @@
 		deps = protoDeps(ctx, deps, &compiler.Proto, Bool(compiler.Properties.Proto.Static))
 	}
 
+	if compiler.hasSrcExt(".sysprop") {
+		deps.SharedLibs = append(deps.SharedLibs, "libbase")
+	}
+
 	if Bool(compiler.Properties.Openmp) {
 		deps.StaticLibs = append(deps.StaticLibs, "libomp")
 	}
@@ -387,7 +391,7 @@
 		flags.GlobalFlags = append([]string{"${config.ClangExternalCflags}"}, flags.GlobalFlags...)
 	}
 
-	if ctx.Device() {
+	if tc.Bionic() {
 		if Bool(compiler.Properties.Rtti) {
 			flags.CppFlags = append(flags.CppFlags, "-frtti")
 		} else {
@@ -489,6 +493,11 @@
 		flags = rsFlags(ctx, flags, &compiler.Properties)
 	}
 
+	if compiler.hasSrcExt(".sysprop") {
+		flags.GlobalFlags = append(flags.GlobalFlags,
+			"-I"+android.PathForModuleGen(ctx, "sysprop", "include").String())
+	}
+
 	if len(compiler.Properties.Srcs) > 0 {
 		module := ctx.ModuleDir() + "/Android.bp:" + ctx.ModuleName()
 		if inList("-Wno-error", flags.CFlags) || inList("-Wno-error", flags.CppFlags) {
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index cacd287..bcff775 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -25,6 +25,11 @@
 	arm64Cflags = []string{
 		// Help catch common 32/64-bit errors.
 		"-Werror=implicit-function-declaration",
+
+		// Prevent use of x18 register.
+		// TODO(pcc): Remove this flag once we upgrade past LLVM r340889
+		// which does this by default on Android.
+		"-ffixed-x18",
 	}
 
 	arm64ArchVariantCflags = map[string][]string{
@@ -60,6 +65,11 @@
 			// 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{
 			"-mcpu=kryo",
 		},
@@ -85,6 +95,7 @@
 		"cortex-a72",
 		"cortex-a73",
 		"cortex-a75",
+		"cortex-a76",
 		"kryo",
 		"exynos-m1",
 		"exynos-m2",
@@ -136,6 +147,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}",
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index 95c9495..75f5962 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -117,6 +117,15 @@
 			// 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=krait",
 			"-mfpu=neon-vfpv4",
@@ -162,6 +171,7 @@
 		"cortex-a72",
 		"cortex-a73",
 		"cortex-a75",
+		"cortex-a76",
 		"krait",
 		"kryo",
 		"exynos-m1",
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/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index 8a12523..5fb88e6 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -139,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/gen.go b/cc/gen.go
index 487f662..29a2bb2 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -19,6 +19,8 @@
 // functions.
 
 import (
+	"path/filepath"
+
 	"github.com/google/blueprint"
 
 	"android/soong/android"
@@ -30,6 +32,7 @@
 	pctx.SourcePathVariable("yaccDataDir", "prebuilts/build-tools/common/bison")
 
 	pctx.HostBinToolVariable("aidlCmd", "aidl-cpp")
+	pctx.HostBinToolVariable("syspropCmd", "sysprop_cpp")
 }
 
 var (
@@ -55,6 +58,13 @@
 		},
 		"aidlFlags", "outDir")
 
+	sysprop = pctx.AndroidStaticRule("sysprop",
+		blueprint.RuleParams{
+			Command:     "$syspropCmd --header-output-dir=$headerOutDir --source-output-dir=$srcOutDir --include-name=$includeName $in",
+			CommandDeps: []string{"$syspropCmd"},
+		},
+		"headerOutDir", "srcOutDir", "includeName")
+
 	windmc = pctx.AndroidStaticRule("windmc",
 		blueprint.RuleParams{
 			Command:     "$windmcCmd -r$$(dirname $out) -h$$(dirname $out) $in",
@@ -82,7 +92,6 @@
 }
 
 func genAidl(ctx android.ModuleContext, aidlFile android.Path, outFile android.ModuleGenPath, aidlFlags string) android.Paths {
-
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        aidl,
 		Description: "aidl " + aidlFile.Rel(),
@@ -107,6 +116,26 @@
 	})
 }
 
+func genSysprop(ctx android.ModuleContext, syspropFile android.Path) (android.Path, android.Path) {
+	headerFile := android.PathForModuleGen(ctx, "sysprop", "include", syspropFile.Rel()+".h")
+	cppFile := android.PathForModuleGen(ctx, "sysprop", syspropFile.Rel()+".cpp")
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:           sysprop,
+		Description:    "sysprop " + syspropFile.Rel(),
+		Output:         cppFile,
+		ImplicitOutput: headerFile,
+		Input:          syspropFile,
+		Args: map[string]string{
+			"headerOutDir": filepath.Dir(headerFile.String()),
+			"srcOutDir":    filepath.Dir(cppFile.String()),
+			"includeName":  syspropFile.Rel() + ".h",
+		},
+	})
+
+	return cppFile, headerFile
+}
+
 func genWinMsg(ctx android.ModuleContext, srcFile android.Path, flags builderFlags) (android.Path, android.Path) {
 	headerFile := android.GenPathWithExt(ctx, "windmc", srcFile, "h")
 	rcFile := android.GenPathWithExt(ctx, "windmc", srcFile, "rc")
@@ -169,6 +198,10 @@
 			rcFile, headerFile := genWinMsg(ctx, srcFile, buildFlags)
 			srcFiles[i] = rcFile
 			deps = append(deps, headerFile)
+		case ".sysprop":
+			cppFile, headerFile := genSysprop(ctx, srcFile)
+			srcFiles[i] = cppFile
+			deps = append(deps, headerFile)
 		}
 	}
 
diff --git a/cc/genrule_test.go b/cc/genrule_test.go
new file mode 100644
index 0000000..92024ac
--- /dev/null
+++ b/cc/genrule_test.go
@@ -0,0 +1,88 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cc
+
+import (
+	"reflect"
+	"testing"
+
+	"android/soong/android"
+)
+
+func testGenruleContext(config android.Config, bp string,
+	fs map[string][]byte) *android.TestContext {
+
+	ctx := android.NewTestArchContext()
+	ctx.RegisterModuleType("cc_genrule", android.ModuleFactoryAdaptor(genRuleFactory))
+	ctx.Register()
+
+	mockFS := map[string][]byte{
+		"Android.bp": []byte(bp),
+		"tool":       nil,
+		"foo":        nil,
+		"bar":        nil,
+	}
+
+	for k, v := range fs {
+		mockFS[k] = v
+	}
+
+	ctx.MockFileSystem(mockFS)
+
+	return ctx
+}
+
+func TestArchGenruleCmd(t *testing.T) {
+	config := android.TestArchConfig(buildDir, nil)
+	bp := `
+				cc_genrule {
+					name: "gen",
+					tool_files: ["tool"],
+					cmd: "$(location tool) $(in) $(out)",
+					arch: {
+						arm: {
+							srcs: ["foo"],
+							out: ["out_arm"],
+						},
+						arm64: {
+							srcs: ["bar"],
+							out: ["out_arm64"],
+						},
+					},
+				}
+			`
+
+	ctx := testGenruleContext(config, bp, nil)
+
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	if errs == nil {
+		_, errs = ctx.PrepareBuildActions(config)
+	}
+	if errs != nil {
+		t.Fatal(errs)
+	}
+
+	gen := ctx.ModuleForTests("gen", "android_arm_armv7-a-neon").Output("out_arm")
+	expected := []string{"foo"}
+	if !reflect.DeepEqual(expected, gen.Inputs.Strings()) {
+		t.Errorf(`want arm inputs %v, got %v`, expected, gen.Inputs.Strings())
+	}
+
+	gen = ctx.ModuleForTests("gen", "android_arm64_armv8-a").Output("out_arm64")
+	expected = []string{"bar"}
+	if !reflect.DeepEqual(expected, gen.Inputs.Strings()) {
+		t.Errorf(`want arm64 inputs %v, got %v`, expected, gen.Inputs.Strings())
+	}
+}
diff --git a/cc/library.go b/cc/library.go
index 9eb3f47..920292d 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -678,6 +678,14 @@
 		}
 	}
 
+	if library.baseCompiler.hasSrcExt(".sysprop") {
+		flags := []string{
+			"-I" + android.PathForModuleGen(ctx, "sysprop", "include").String(),
+		}
+		library.reexportFlags(flags)
+		library.reuseExportedFlags = append(library.reuseExportedFlags, flags...)
+	}
+
 	return out
 }
 
diff --git a/cc/linker.go b/cc/linker.go
index 2e1828a..28f4747 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -289,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..d9d2662 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 {
@@ -113,6 +113,13 @@
 			flags.LdFlags = append(flags.LdFlags, "-Wl,-plugin-opt,-inline-threshold=0")
 			flags.LdFlags = append(flags.LdFlags, "-Wl,-plugin-opt,-unroll-threshold=0")
 		}
+
+		if ctx.Arch().ArchType == android.Arm64 {
+			// Prevent use of x18 register on arm64.
+			// TODO(pcc): Remove this flag once we upgrade past LLVM r340889
+			// which does this by default on Android.
+			flags.LdFlags = append(flags.LdFlags, "-Wl,-plugin-opt,-mattr=+reserve-x18")
+		}
 	}
 	return flags
 }
diff --git a/cc/makevars.go b/cc/makevars.go
index b590786..32674a9 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -172,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 {
@@ -186,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])
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 1cd4829..a7d6e04 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -134,7 +134,7 @@
 	// but keep them when doing regular platform build.
 	// Ndk_abis property is only set to true with build/soong/scripts/build-ndk-prebuilts.sh
 	// TODO: Revert this once MIPS is supported in NDK again.
-	if Bool(ctx.AConfig().Ndk_abis) && strings.Contains(ctx.ModuleName(), "mips") {
+	if ctx.Config().NdkAbis() && strings.Contains(ctx.ModuleName(), "mips") {
 		return
 	}
 
@@ -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 330a5e3..527ae33 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -471,6 +471,13 @@
 			diagSanitizers = append(diagSanitizers, "cfi")
 		}
 
+		if ctx.Arch().ArchType == android.Arm64 {
+			// Prevent use of x18 register on arm64.
+			// TODO(pcc): Remove this flag once we upgrade past LLVM r340889
+			// which does this by default on Android.
+			flags.LdFlags = append(flags.LdFlags, "-Wl,-plugin-opt,-mattr=+reserve-x18")
+		}
+
 		if ctx.staticBinary() {
 			_, flags.CFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.CFlags)
 			_, flags.LdFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.LdFlags)
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/genrule/genrule.go b/genrule/genrule.go
index 2824e49..e6c6efd 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -87,7 +87,7 @@
 	Export_include_dirs []string
 
 	// list of input files
-	Srcs []string
+	Srcs []string `android:"arch_variant"`
 }
 
 type Module struct {
@@ -504,7 +504,7 @@
 
 type genRuleProperties struct {
 	// names of the output files that will be generated
-	Out []string
+	Out []string `android:"arch_variant"`
 }
 
 var Bool = proptools.Bool
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 7e16ce1..a99fa18 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -27,7 +27,7 @@
 
 func setUp() {
 	var err error
-	buildDir, err = ioutil.TempDir("", "soong_java_test")
+	buildDir, err = ioutil.TempDir("", "genrule_test")
 	if err != nil {
 		panic(err)
 	}
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 85cb588..d2a8c46 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -27,8 +27,8 @@
 var (
 	pctx = android.NewPackageContext("android/soong/java/config")
 
-	DefaultBootclasspathLibraries = []string{"core-oj", "core-libart", "core-simple", "bouncycastle", "conscrypt", "okhttp"}
-	DefaultSystemModules          = "core-system-modules"
+	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/droiddoc.go b/java/droiddoc.go
index 063f2c1..fca5fc4 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -388,6 +388,7 @@
 
 	metalavaStubsFlags                string
 	metalavaAnnotationsFlags          string
+	metalavaInclusionAnnotationsFlags string
 	metalavaApiLevelsAnnotationsFlags string
 
 	metalavaApiToXmlFlags string
@@ -1382,7 +1383,6 @@
 	} else {
 		metalavaFlags += " --stubs " + android.PathForModuleOut(ctx, "stubsDir").String()
 	}
-
 	return metalavaFlags
 }
 
@@ -1419,8 +1419,15 @@
 			}
 		})
 		// TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
-		flags += " --hide HiddenTypedefConstant --hide SuperfluousPrefix --hide AnnotationExtraction "
+		flags += " --hide HiddenTypedefConstant --hide SuperfluousPrefix --hide AnnotationExtraction"
 	}
+
+	return flags
+}
+
+func (d *Droidstubs) collectInclusionAnnotationsFlags(ctx android.ModuleContext,
+	implicits *android.Paths, implicitOutputs *android.WritablePaths) string {
+	var flags string
 	ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
 		if t, ok := m.(*ExportedDroiddocDir); ok {
 			*implicits = append(*implicits, t.deps...)
@@ -1599,6 +1606,7 @@
 
 	flags.metalavaStubsFlags = d.collectStubsFlags(ctx, &implicitOutputs)
 	flags.metalavaAnnotationsFlags = d.collectAnnotationsFlags(ctx, &implicits, &implicitOutputs)
+	flags.metalavaInclusionAnnotationsFlags = d.collectInclusionAnnotationsFlags(ctx, &implicits, &implicitOutputs)
 	flags.metalavaApiLevelsAnnotationsFlags = d.collectAPILevelsAnnotationsFlags(ctx, &implicits, &implicitOutputs)
 	flags.metalavaApiToXmlFlags = d.collectApiToXmlFlags(ctx, &implicits, &implicitOutputs)
 
@@ -1610,7 +1618,7 @@
 	}
 	d.transformMetalava(ctx, implicits, implicitOutputs, javaVersion,
 		flags.bootClasspathArgs, flags.classpathArgs, flags.sourcepathArgs,
-		flags.metalavaStubsFlags+flags.metalavaAnnotationsFlags+
+		flags.metalavaStubsFlags+flags.metalavaAnnotationsFlags+flags.metalavaInclusionAnnotationsFlags+
 			flags.metalavaApiLevelsAnnotationsFlags+flags.metalavaApiToXmlFlags+" "+d.Javadoc.args)
 
 	if apiCheckEnabled(d.properties.Check_api.Current, "current") &&
@@ -1621,8 +1629,9 @@
 			"check_api.current_removed_api_file")
 
 		d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "check_current_api.timestamp")
-		opts := d.Javadoc.args + " --check-compatibility:api:current " + apiFile.String() +
-			" --check-compatibility:removed:current " + removedApiFile.String() + " "
+		opts := " " + d.Javadoc.args + " --check-compatibility:api:current " + apiFile.String() +
+			" --check-compatibility:removed:current " + removedApiFile.String() +
+			flags.metalavaInclusionAnnotationsFlags
 
 		d.transformCheckApi(ctx, apiFile, removedApiFile, metalavaCheckApiImplicits,
 			javaVersion, flags.bootClasspathArgs, flags.classpathArgs, flags.sourcepathArgs, opts,
@@ -1651,8 +1660,9 @@
 			"check_api.last_released.removed_api_file")
 
 		d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp")
-		opts := d.Javadoc.args + " --check-compatibility:api:released " + apiFile.String() +
-			" --check-compatibility:removed:released " + removedApiFile.String() + " "
+		opts := " " + d.Javadoc.args + " --check-compatibility:api:released " + apiFile.String() +
+			flags.metalavaInclusionAnnotationsFlags + " --check-compatibility:removed:released " +
+			removedApiFile.String() + " "
 
 		d.transformCheckApi(ctx, apiFile, removedApiFile, metalavaCheckApiImplicits,
 			javaVersion, flags.bootClasspathArgs, flags.classpathArgs, flags.sourcepathArgs, opts,
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 e5218bb..f651884 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 {
@@ -721,27 +725,34 @@
 	javaPlatform
 )
 
-func getLinkType(m *Module, name string) linkType {
+func getLinkType(m *Module, name string) (ret linkType, stubs bool) {
 	ver := m.sdkVersion()
-	noStdLibs := Bool(m.properties.No_standard_libs)
 	switch {
-	case name == "core.current.stubs" || ver == "core_current" ||
-		name == "core.platform.api.stubs" || ver == "core_platform_current" ||
-		noStdLibs || name == "stub-annotations" || name == "private-stub-annotations-jar":
-		return javaCore
-	case name == "android_system_stubs_current" || strings.HasPrefix(ver, "system_"):
-		return javaSystem
-	case name == "android_test_stubs_current" || strings.HasPrefix(ver, "test_"):
-		return javaPlatform
-	case name == "android_stubs_current" || ver == "current":
-		return javaSdk
+	case name == "core.current.stubs" || name == "core.platform.api.stubs" ||
+		name == "stub-annotations" || name == "private-stub-annotations-jar" ||
+		name == "core-lambda-stubs":
+		return javaCore, true
+	case ver == "core_current" || ver == "core_platform_current":
+		return javaCore, false
+	case name == "android_system_stubs_current":
+		return javaSystem, true
+	case strings.HasPrefix(ver, "system_"):
+		return javaSystem, false
+	case name == "android_test_stubs_current":
+		return javaSystem, true
+	case strings.HasPrefix(ver, "test_"):
+		return javaPlatform, false
+	case name == "android_stubs_current":
+		return javaSdk, true
+	case ver == "current":
+		return javaSdk, false
 	case ver == "":
-		return javaPlatform
+		return javaPlatform, false
 	default:
 		if _, err := strconv.Atoi(ver); err != nil {
 			panic(fmt.Errorf("expected sdk_version to be a number, got %q", ver))
 		}
-		return javaSdk
+		return javaSdk, false
 	}
 }
 
@@ -750,8 +761,11 @@
 		return
 	}
 
-	myLinkType := getLinkType(from, ctx.ModuleName())
-	otherLinkType := getLinkType(&to.Module, ctx.OtherModuleName(to))
+	myLinkType, stubs := getLinkType(from, ctx.ModuleName())
+	if stubs {
+		return
+	}
+	otherLinkType, _ := getLinkType(&to.Module, ctx.OtherModuleName(to))
 	commonMessage := "Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source."
 
 	switch myLinkType {
@@ -817,7 +831,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()...)
@@ -856,7 +870,8 @@
 		case SdkLibraryDependency:
 			switch tag {
 			case libTag:
-				deps.classpath = append(deps.classpath, dep.HeaderJars(getLinkType(j, ctx.ModuleName()))...)
+				linkType, _ := getLinkType(j, ctx.ModuleName())
+				deps.classpath = append(deps.classpath, dep.HeaderJars(linkType)...)
 				// names of sdk libs that are directly depended are exported
 				j.exportedSdkLibs = append(j.exportedSdkLibs, otherName)
 			default:
@@ -1193,8 +1208,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 +1551,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 +1574,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
diff --git a/java/java_test.go b/java/java_test.go
index 76244f0..86349fe 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -111,19 +111,14 @@
 	ctx.Register()
 
 	extraModules := []string{
-		"core-oj",
-		"core-libart",
 		"core-lambda-stubs",
-		"core-simple",
-		"bouncycastle",
-		"conscrypt",
-		"okhttp",
 		"framework",
 		"ext",
 		"android_stubs_current",
 		"android_system_stubs_current",
 		"android_test_stubs_current",
 		"core.current.stubs",
+		"core.platform.api.stubs",
 		"kotlin-stdlib",
 	}
 
@@ -134,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)
 	}
@@ -148,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",
@@ -367,15 +363,15 @@
 }{
 	{
 		name:          "default",
-		bootclasspath: []string{"core-oj", "core-libart", "core-simple", "bouncycastle", "conscrypt", "okhttp"},
-		system:        "core-system-modules",
+		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", "bouncycastle", "conscrypt", "okhttp"},
-		system:        "core-system-modules",
+		bootclasspath: []string{"core.platform.api.stubs", "core-lambda-stubs"},
+		system:        "core-platform-api-stubs-system-modules",
 		classpath:     []string{"ext", "framework"},
 	},
 	{
@@ -433,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{},
 	},
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/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index 7f6e2c9..0143d1e 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -34,11 +34,6 @@
 SOONG_NDK_OUT=${OUT_DIR}/soong/ndk
 rm -rf ${SOONG_OUT}
 mkdir -p ${SOONG_OUT}
-cat > ${SOONG_OUT}/soong.config << EOF
-{
-    "Ndk_abis": true
-}
-EOF
 
 # We only really need to set some of these variables, but soong won't merge this
 # with the defaults, so we need to write out all the defaults with our values
@@ -63,7 +58,9 @@
     ],
     "HostArch": "x86_64",
     "Malloc_not_svelte": false,
-    "Safestack": false
+    "Safestack": false,
+
+    "Ndk_abis": true
 }
 EOF
 m --skip-make ${SOONG_OUT}/ndk.timestamp
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index 80a398b..07925df 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -56,9 +56,14 @@
   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('--prefer-integrity', type=bool, dest='prefer_integrity',
+                      help=('specify if the app prefers strict integrity. Should not be conflict if ' +
+                            'already declared in the manifest.'))
   parser.add_argument('input', help='input AndroidManifest.xml file')
   parser.add_argument('output', help='output AndroidManifest.xml file')
   return parser.parse_args()
@@ -190,12 +195,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 +233,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)
@@ -266,6 +272,28 @@
     application.setAttributeNode(attr)
 
 
+def add_prefer_integrity(doc):
+  manifest = parse_manifest(doc)
+  elems = get_children_with_tag(manifest, 'application')
+  application = elems[0] if len(elems) == 1 else None
+  if len(elems) > 1:
+    raise RuntimeError('found multiple <application> tags')
+  elif not elems:
+    application = doc.createElement('application')
+    indent = get_indent(manifest.firstChild, 1)
+    first = manifest.firstChild
+    manifest.insertBefore(doc.createTextNode(indent), first)
+    manifest.insertBefore(application, first)
+
+  attr = application.getAttributeNodeNS(android_ns, 'preferIntegrity')
+  if attr is None:
+    attr = doc.createAttributeNS(android_ns, 'android:preferIntegrity')
+    attr.value = 'true'
+    application.setAttributeNode(attr)
+  elif attr.value != 'true':
+    raise RuntimeError('existing attribute mismatches the option of --prefer-integrity')
+
+
 def write_xml(f, doc):
   f.write('<?xml version="1.0" encoding="utf-8"?>\n')
   for node in doc.childNodes:
@@ -285,11 +313,17 @@
       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)
 
+    if args.prefer_integrity:
+      add_prefer_integrity(doc)
+
     with open(args.output, 'wb') as f:
       write_xml(f, doc)
 
diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py
index d1d401a..a621445 100755
--- a/scripts/manifest_fixer_test.py
+++ b/scripts/manifest_fixer_test.py
@@ -346,5 +346,40 @@
     self.assertEqual(output, expected)
 
 
+class PreferIntegrityTest(unittest.TestCase):
+  """Unit tests for add_prefer_integrity function."""
+
+  def run_test(self, input_manifest):
+    doc = minidom.parseString(input_manifest)
+    manifest_fixer.add_prefer_integrity(doc)
+    output = StringIO.StringIO()
+    manifest_fixer.write_xml(output, doc)
+    return output.getvalue()
+
+  manifest_tmpl = (
+      '<?xml version="1.0" encoding="utf-8"?>\n'
+      '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
+      '    <application%s/>\n'
+      '</manifest>\n')
+
+  def prefer_integrity(self, value):
+    return ' android:preferIntegrity="%s"' % value
+
+  def test_manifest_with_undeclared_preference(self):
+    manifest_input = self.manifest_tmpl % ''
+    expected = self.manifest_tmpl % self.prefer_integrity('true')
+    output = self.run_test(manifest_input)
+    self.assertEqual(output, expected)
+
+  def test_manifest_with_prefer_integrity(self):
+    manifest_input = self.manifest_tmpl % self.prefer_integrity('true')
+    expected = manifest_input
+    output = self.run_test(manifest_input)
+    self.assertEqual(output, expected)
+
+  def test_manifest_with_not_prefer_integrity(self):
+    manifest_input = self.manifest_tmpl % self.prefer_integrity('false')
+    self.assertRaises(RuntimeError, self.run_test, manifest_input)
+
 if __name__ == '__main__':
   unittest.main()
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 6851e8c..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":      Log,
 	"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":   Log,
 	"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...$")