Merge "Remove support for stripping dex."
diff --git a/Android.bp b/Android.bp
index 1dfac87..20d45e5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -45,6 +45,7 @@
         "android/api_levels.go",
         "android/arch.go",
         "android/config.go",
+        "android/csuite_config.go",
         "android/defaults.go",
         "android/defs.go",
         "android/expand.go",
@@ -85,6 +86,7 @@
         "android/androidmk_test.go",
         "android/arch_test.go",
         "android/config_test.go",
+        "android/csuite_config_test.go",
         "android/expand_test.go",
         "android/module_test.go",
         "android/mutator_test.go",
@@ -294,6 +296,7 @@
         "java/support_libraries.go",
         "java/system_modules.go",
         "java/testing.go",
+        "java/tradefed.go",
     ],
     testSrcs: [
         "java/androidmk_test.go",
@@ -338,6 +341,7 @@
         "rust/config/global.go",
         "rust/config/toolchain.go",
         "rust/config/whitelist.go",
+        "rust/config/x86_darwin_host.go",
         "rust/config/x86_linux_host.go",
         "rust/config/x86_64_device.go",
     ],
@@ -491,6 +495,7 @@
     ],
     srcs: [
         "sdk/sdk.go",
+        "sdk/update.go",
     ],
     testSrcs: [
         "sdk/sdk_test.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index 9071347..b66fd18 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -199,19 +199,19 @@
 	switch amod.Os().Class {
 	case Host:
 		// Make cannot identify LOCAL_MODULE_HOST_ARCH:= common.
-		if archStr != "common" {
+		if amod.Arch().ArchType != Common {
 			a.SetString("LOCAL_MODULE_HOST_ARCH", archStr)
 		}
 		host = true
 	case HostCross:
 		// Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common.
-		if archStr != "common" {
+		if amod.Arch().ArchType != Common {
 			a.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr)
 		}
 		host = true
 	case Device:
 		// Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common.
-		if archStr != "common" {
+		if amod.Arch().ArchType != Common {
 			if amod.Target().NativeBridge {
 				hostArchStr := amod.Target().NativeBridgeHostArchName
 				if hostArchStr != "" {
diff --git a/android/apex.go b/android/apex.go
index c548095..5118a0a 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -77,6 +77,10 @@
 
 	// Tests if this module is available for the specified APEX or ":platform"
 	AvailableFor(what string) bool
+
+	// DepIsInSameApex tests if the other module 'dep' is installed to the same
+	// APEX as this module
+	DepIsInSameApex(ctx BaseModuleContext, dep Module) bool
 }
 
 type ApexProperties struct {
@@ -140,14 +144,25 @@
 	availableToAnyApex  = "//apex_available:anyapex"
 )
 
-func (m *ApexModuleBase) AvailableFor(what string) bool {
-	if len(m.ApexProperties.Apex_available) == 0 {
+func CheckAvailableForApex(what string, apex_available []string) bool {
+	if len(apex_available) == 0 {
 		// apex_available defaults to ["//apex_available:platform", "//apex_available:anyapex"],
 		// which means 'available to everybody'.
 		return true
 	}
-	return InList(what, m.ApexProperties.Apex_available) ||
-		(what != availableToPlatform && InList(availableToAnyApex, m.ApexProperties.Apex_available))
+	return InList(what, apex_available) ||
+		(what != availableToPlatform && InList(availableToAnyApex, apex_available))
+}
+
+func (m *ApexModuleBase) AvailableFor(what string) bool {
+	return CheckAvailableForApex(what, m.ApexProperties.Apex_available)
+}
+
+func (m *ApexModuleBase) DepIsInSameApex(ctx BaseModuleContext, dep Module) bool {
+	// By default, if there is a dependency from A to B, we try to include both in the same APEX,
+	// unless B is explicitly from outside of the APEX (i.e. a stubs lib). Thus, returning true.
+	// This is overridden by some module types like apex.ApexBundle, cc.Module, java.Module, etc.
+	return true
 }
 
 func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
@@ -166,7 +181,7 @@
 		m.checkApexAvailableProperty(mctx)
 		sort.Strings(m.apexVariations)
 		variations := []string{}
-		availableForPlatform := m.AvailableFor(availableToPlatform)
+		availableForPlatform := mctx.Module().(ApexModule).AvailableFor(availableToPlatform)
 		if availableForPlatform {
 			variations = append(variations, "") // Original variation for platform
 		}
diff --git a/android/arch.go b/android/arch.go
index 348b064..0519e76 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -22,9 +22,12 @@
 	"strconv"
 	"strings"
 
+	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
 
+const COMMON_VARIANT = "common"
+
 var (
 	archTypeList []ArchType
 
@@ -36,7 +39,7 @@
 	X86_64 = newArch("x86_64", "lib64")
 
 	Common = ArchType{
-		Name: "common",
+		Name: COMMON_VARIANT,
 	}
 )
 
@@ -702,11 +705,82 @@
 }
 
 func (target Target) String() string {
-	variant := ""
+	return target.OsVariation() + "_" + target.ArchVariation()
+}
+
+func (target Target) OsVariation() string {
+	return target.Os.String()
+}
+
+func (target Target) ArchVariation() string {
+	var variation string
 	if target.NativeBridge {
-		variant = "native_bridge_"
+		variation = "native_bridge_"
 	}
-	return target.Os.String() + "_" + variant + target.Arch.String()
+	variation += target.Arch.String()
+
+	return variation
+}
+
+func (target Target) Variations() []blueprint.Variation {
+	return []blueprint.Variation{
+		{Mutator: "os", Variation: target.OsVariation()},
+		{Mutator: "arch", Variation: target.ArchVariation()},
+	}
+}
+
+func osMutator(mctx BottomUpMutatorContext) {
+	var module Module
+	var ok bool
+	if module, ok = mctx.Module().(Module); !ok {
+		return
+	}
+
+	base := module.base()
+
+	if !base.ArchSpecific() {
+		return
+	}
+
+	osClasses := base.OsClassSupported()
+
+	var moduleOSList []OsType
+
+	for _, os := range osTypeList {
+		supportedClass := false
+		for _, osClass := range osClasses {
+			if os.Class == osClass {
+				supportedClass = true
+			}
+		}
+		if !supportedClass {
+			continue
+		}
+
+		if len(mctx.Config().Targets[os]) == 0 {
+			continue
+		}
+
+		moduleOSList = append(moduleOSList, os)
+	}
+
+	if len(moduleOSList) == 0 {
+		base.commonProperties.Enabled = boolPtr(false)
+		return
+	}
+
+	osNames := make([]string, len(moduleOSList))
+
+	for i, os := range moduleOSList {
+		osNames[i] = os.String()
+	}
+
+	modules := mctx.CreateVariations(osNames...)
+	for i, m := range modules {
+		m.(Module).base().commonProperties.CompileOS = moduleOSList[i]
+		m.(Module).base().setOSProperties(mctx)
+	}
+
 }
 
 // archMutator splits a module into a variant for each Target requested by the module.  Target selection
@@ -746,84 +820,63 @@
 		return
 	}
 
-	var moduleTargets []Target
-	moduleMultiTargets := make(map[int][]Target)
-	primaryModules := make(map[int]bool)
-	osClasses := base.OsClassSupported()
+	os := base.commonProperties.CompileOS
+	osTargets := mctx.Config().Targets[os]
 
-	for _, os := range osTypeList {
-		supportedClass := false
-		for _, osClass := range osClasses {
-			if os.Class == osClass {
-				supportedClass = true
+	// Filter NativeBridge targets unless they are explicitly supported
+	if os == Android && !Bool(base.commonProperties.Native_bridge_supported) {
+		var targets []Target
+		for _, t := range osTargets {
+			if !t.NativeBridge {
+				targets = append(targets, t)
 			}
 		}
-		if !supportedClass {
-			continue
-		}
 
-		osTargets := mctx.Config().Targets[os]
-		if len(osTargets) == 0 {
-			continue
-		}
+		osTargets = targets
+	}
 
-		// Filter NativeBridge targets unless they are explicitly supported
-		if os == Android && !Bool(base.commonProperties.Native_bridge_supported) {
-			var targets []Target
-			for _, t := range osTargets {
-				if !t.NativeBridge {
-					targets = append(targets, t)
-				}
-			}
+	// only the primary arch in the recovery partition
+	if os == Android && module.InstallInRecovery() {
+		osTargets = []Target{osTargets[0]}
+	}
 
-			osTargets = targets
-		}
+	prefer32 := false
+	if base.prefer32 != nil {
+		prefer32 = base.prefer32(mctx, base, os.Class)
+	}
 
-		// only the primary arch in the recovery partition
-		if os == Android && module.InstallInRecovery() {
-			osTargets = []Target{osTargets[0]}
-		}
+	multilib, extraMultilib := decodeMultilib(base, os.Class)
+	targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
+	if err != nil {
+		mctx.ModuleErrorf("%s", err.Error())
+	}
 
-		prefer32 := false
-		if base.prefer32 != nil {
-			prefer32 = base.prefer32(mctx, base, os.Class)
-		}
-
-		multilib, extraMultilib := decodeMultilib(base, os.Class)
-		targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
+	var multiTargets []Target
+	if extraMultilib != "" {
+		multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32)
 		if err != nil {
 			mctx.ModuleErrorf("%s", err.Error())
 		}
-
-		var multiTargets []Target
-		if extraMultilib != "" {
-			multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32)
-			if err != nil {
-				mctx.ModuleErrorf("%s", err.Error())
-			}
-		}
-
-		if len(targets) > 0 {
-			primaryModules[len(moduleTargets)] = true
-			moduleMultiTargets[len(moduleTargets)] = multiTargets
-			moduleTargets = append(moduleTargets, targets...)
-		}
 	}
 
-	if len(moduleTargets) == 0 {
+	if len(targets) == 0 {
 		base.commonProperties.Enabled = boolPtr(false)
 		return
 	}
 
-	targetNames := make([]string, len(moduleTargets))
+	targetNames := make([]string, len(targets))
 
-	for i, target := range moduleTargets {
-		targetNames[i] = target.String()
+	for i, target := range targets {
+		targetNames[i] = target.ArchVariation()
 	}
 
 	modules := mctx.CreateVariations(targetNames...)
 	for i, m := range modules {
-		m.(Module).base().SetTarget(moduleTargets[i], moduleMultiTargets[i], primaryModules[i])
+		m.(Module).base().commonProperties.CompileTarget = targets[i]
+		m.(Module).base().commonProperties.CompileMultiTargets = multiTargets
+		if i == 0 {
+			m.(Module).base().commonProperties.CompilePrimary = true
+		}
 		m.(Module).base().setArchProperties(mctx)
 	}
 }
@@ -1050,6 +1103,100 @@
 	return ret
 }
 
+// Rewrite the module's properties structs to contain os-specific values.
+func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) {
+	os := m.commonProperties.CompileOS
+
+	for i := range m.generalProperties {
+		genProps := m.generalProperties[i]
+		if m.archProperties[i] == nil {
+			continue
+		}
+		for _, archProperties := range m.archProperties[i] {
+			archPropValues := reflect.ValueOf(archProperties).Elem()
+
+			targetProp := archPropValues.FieldByName("Target")
+
+			// Handle host-specific properties in the form:
+			// target: {
+			//     host: {
+			//         key: value,
+			//     },
+			// },
+			if os.Class == Host || os.Class == HostCross {
+				field := "Host"
+				prefix := "target.host"
+				m.appendProperties(ctx, genProps, targetProp, field, prefix)
+			}
+
+			// Handle target OS generalities of the form:
+			// target: {
+			//     bionic: {
+			//         key: value,
+			//     },
+			// }
+			if os.Linux() {
+				field := "Linux"
+				prefix := "target.linux"
+				m.appendProperties(ctx, genProps, targetProp, field, prefix)
+			}
+
+			if os.Bionic() {
+				field := "Bionic"
+				prefix := "target.bionic"
+				m.appendProperties(ctx, genProps, targetProp, field, prefix)
+			}
+
+			// Handle target OS properties in the form:
+			// target: {
+			//     linux_glibc: {
+			//         key: value,
+			//     },
+			//     not_windows: {
+			//         key: value,
+			//     },
+			//     android {
+			//         key: value,
+			//     },
+			// },
+			field := os.Field
+			prefix := "target." + os.Name
+			m.appendProperties(ctx, genProps, targetProp, field, prefix)
+
+			if (os.Class == Host || os.Class == HostCross) && os != Windows {
+				field := "Not_windows"
+				prefix := "target.not_windows"
+				m.appendProperties(ctx, genProps, targetProp, field, prefix)
+			}
+
+			// Handle 64-bit device properties in the form:
+			// target {
+			//     android64 {
+			//         key: value,
+			//     },
+			//     android32 {
+			//         key: value,
+			//     },
+			// },
+			// WARNING: this is probably not what you want to use in your blueprints file, it selects
+			// options for all targets on a device that supports 64-bit binaries, not just the targets
+			// that are being compiled for 64-bit.  Its expected use case is binaries like linker and
+			// debuggerd that need to know when they are a 32-bit process running on a 64-bit device
+			if os.Class == Device {
+				if ctx.Config().Android64() {
+					field := "Android64"
+					prefix := "target.android64"
+					m.appendProperties(ctx, genProps, targetProp, field, prefix)
+				} else {
+					field := "Android32"
+					prefix := "target.android32"
+					m.appendProperties(ctx, genProps, targetProp, field, prefix)
+				}
+			}
+		}
+	}
+}
+
 // Rewrite the module's properties structs to contain arch-specific values.
 func (m *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
 	arch := m.Arch()
@@ -1067,9 +1214,6 @@
 			multilibProp := archPropValues.FieldByName("Multilib")
 			targetProp := archPropValues.FieldByName("Target")
 
-			var field string
-			var prefix string
-
 			// Handle arch-specific properties in the form:
 			// arch: {
 			//     arm64: {
@@ -1134,68 +1278,32 @@
 				m.appendProperties(ctx, genProps, multilibProp, field, prefix)
 			}
 
-			// Handle host-specific properties in the form:
+			// Handle combined OS-feature and arch specific properties in the form:
 			// target: {
-			//     host: {
-			//         key: value,
-			//     },
-			// },
-			if os.Class == Host || os.Class == HostCross {
-				field = "Host"
-				prefix = "target.host"
-				m.appendProperties(ctx, genProps, targetProp, field, prefix)
-			}
-
-			// Handle target OS generalities of the form:
-			// target: {
-			//     bionic: {
-			//         key: value,
-			//     },
 			//     bionic_x86: {
 			//         key: value,
 			//     },
 			// }
-			if os.Linux() {
-				field = "Linux"
-				prefix = "target.linux"
+			if os.Linux() && arch.ArchType != Common {
+				field := "Linux_" + arch.ArchType.Name
+				prefix := "target.linux_" + arch.ArchType.Name
 				m.appendProperties(ctx, genProps, targetProp, field, prefix)
-
-				if arch.ArchType != Common {
-					field = "Linux_" + arch.ArchType.Name
-					prefix = "target.linux_" + arch.ArchType.Name
-					m.appendProperties(ctx, genProps, targetProp, field, prefix)
-				}
 			}
 
-			if os.Bionic() {
-				field = "Bionic"
-				prefix = "target.bionic"
+			if os.Bionic() && arch.ArchType != Common {
+				field := "Bionic_" + t.Name
+				prefix := "target.bionic_" + t.Name
 				m.appendProperties(ctx, genProps, targetProp, field, prefix)
-
-				if arch.ArchType != Common {
-					field = "Bionic_" + t.Name
-					prefix = "target.bionic_" + t.Name
-					m.appendProperties(ctx, genProps, targetProp, field, prefix)
-				}
 			}
 
-			// Handle target OS properties in the form:
+			// Handle combined OS and arch specific properties in the form:
 			// target: {
-			//     linux_glibc: {
-			//         key: value,
-			//     },
-			//     not_windows: {
-			//         key: value,
-			//     },
 			//     linux_glibc_x86: {
 			//         key: value,
 			//     },
 			//     linux_glibc_arm: {
 			//         key: value,
 			//     },
-			//     android {
-			//         key: value,
-			//     },
 			//     android_arm {
 			//         key: value,
 			//     },
@@ -1203,46 +1311,23 @@
 			//         key: value,
 			//     },
 			// },
-			field = os.Field
-			prefix = "target." + os.Name
-			m.appendProperties(ctx, genProps, targetProp, field, prefix)
-
 			if arch.ArchType != Common {
-				field = os.Field + "_" + t.Name
-				prefix = "target." + os.Name + "_" + t.Name
+				field := os.Field + "_" + t.Name
+				prefix := "target." + os.Name + "_" + t.Name
 				m.appendProperties(ctx, genProps, targetProp, field, prefix)
 			}
 
-			if (os.Class == Host || os.Class == HostCross) && os != Windows {
-				field := "Not_windows"
-				prefix := "target.not_windows"
-				m.appendProperties(ctx, genProps, targetProp, field, prefix)
-			}
-
-			// Handle 64-bit device properties in the form:
+			// Handle arm on x86 properties in the form:
 			// target {
-			//     android64 {
+			//     arm_on_x86 {
 			//         key: value,
 			//     },
-			//     android32 {
+			//     arm_on_x86_64 {
 			//         key: value,
 			//     },
 			// },
-			// WARNING: this is probably not what you want to use in your blueprints file, it selects
-			// options for all targets on a device that supports 64-bit binaries, not just the targets
-			// that are being compiled for 64-bit.  Its expected use case is binaries like linker and
-			// debuggerd that need to know when they are a 32-bit process running on a 64-bit device
+			// TODO(ccross): is this still necessary with native bridge?
 			if os.Class == Device {
-				if ctx.Config().Android64() {
-					field := "Android64"
-					prefix := "target.android64"
-					m.appendProperties(ctx, genProps, targetProp, field, prefix)
-				} else {
-					field := "Android32"
-					prefix := "target.android32"
-					m.appendProperties(ctx, genProps, targetProp, field, prefix)
-				}
-
 				if (arch.ArchType == X86 && (hasArmAbi(arch) ||
 					hasArmAndroidArch(ctx.Config().Targets[Android]))) ||
 					(arch.ArchType == Arm &&
diff --git a/android/arch_test.go b/android/arch_test.go
index 11edb4f..52a6684 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -16,6 +16,7 @@
 
 import (
 	"reflect"
+	"runtime"
 	"testing"
 
 	"github.com/google/blueprint/proptools"
@@ -232,3 +233,139 @@
 		})
 	}
 }
+
+type archTestModule struct {
+	ModuleBase
+	props struct {
+		Deps []string
+	}
+}
+
+func (m *archTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+}
+
+func (m *archTestModule) DepsMutator(ctx BottomUpMutatorContext) {
+	ctx.AddDependency(ctx.Module(), nil, m.props.Deps...)
+}
+
+func archTestModuleFactory() Module {
+	m := &archTestModule{}
+	m.AddProperties(&m.props)
+	InitAndroidArchModule(m, HostAndDeviceSupported, MultilibBoth)
+	return m
+}
+
+func TestArchMutator(t *testing.T) {
+	var buildOSVariants []string
+	var buildOS32Variants []string
+	switch runtime.GOOS {
+	case "linux":
+		buildOSVariants = []string{"linux_glibc_x86_64", "linux_glibc_x86"}
+		buildOS32Variants = []string{"linux_glibc_x86"}
+	case "darwin":
+		buildOSVariants = []string{"darwin_x86_64"}
+		buildOS32Variants = nil
+	}
+
+	bp := `
+		module {
+			name: "foo",
+		}
+
+		module {
+			name: "bar",
+			host_supported: true,
+		}
+
+		module {
+			name: "baz",
+			device_supported: false,
+		}
+
+		module {
+			name: "qux",
+			host_supported: true,
+			compile_multilib: "32",
+		}
+	`
+
+	mockFS := map[string][]byte{
+		"Android.bp": []byte(bp),
+	}
+
+	testCases := []struct {
+		name        string
+		config      func(Config)
+		fooVariants []string
+		barVariants []string
+		bazVariants []string
+		quxVariants []string
+	}{
+		{
+			name:        "normal",
+			config:      nil,
+			fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"},
+			barVariants: append(buildOSVariants, "android_arm64_armv8-a", "android_arm_armv7-a-neon"),
+			bazVariants: nil,
+			quxVariants: append(buildOS32Variants, "android_arm_armv7-a-neon"),
+		},
+		{
+			name: "host-only",
+			config: func(config Config) {
+				config.BuildOSTarget = Target{}
+				config.BuildOSCommonTarget = Target{}
+				config.Targets[Android] = nil
+			},
+			fooVariants: nil,
+			barVariants: buildOSVariants,
+			bazVariants: nil,
+			quxVariants: buildOS32Variants,
+		},
+	}
+
+	enabledVariants := func(ctx *TestContext, name string) []string {
+		var ret []string
+		variants := ctx.ModuleVariantsForTests(name)
+		for _, variant := range variants {
+			m := ctx.ModuleForTests(name, variant)
+			if m.Module().Enabled() {
+				ret = append(ret, variant)
+			}
+		}
+		return ret
+	}
+
+	for _, tt := range testCases {
+		t.Run(tt.name, func(t *testing.T) {
+			ctx := NewTestArchContext()
+			ctx.RegisterModuleType("module", ModuleFactoryAdaptor(archTestModuleFactory))
+			ctx.MockFileSystem(mockFS)
+			ctx.Register()
+			config := TestArchConfig(buildDir, nil)
+			if tt.config != nil {
+				tt.config(config)
+			}
+
+			_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+			FailIfErrored(t, errs)
+			_, errs = ctx.PrepareBuildActions(config)
+			FailIfErrored(t, errs)
+
+			if g, w := enabledVariants(ctx, "foo"), tt.fooVariants; !reflect.DeepEqual(w, g) {
+				t.Errorf("want foo variants:\n%q\ngot:\n%q\n", w, g)
+			}
+
+			if g, w := enabledVariants(ctx, "bar"), tt.barVariants; !reflect.DeepEqual(w, g) {
+				t.Errorf("want bar variants:\n%q\ngot:\n%q\n", w, g)
+			}
+
+			if g, w := enabledVariants(ctx, "baz"), tt.bazVariants; !reflect.DeepEqual(w, g) {
+				t.Errorf("want baz variants:\n%q\ngot:\n%q\n", w, g)
+			}
+
+			if g, w := enabledVariants(ctx, "qux"), tt.quxVariants; !reflect.DeepEqual(w, g) {
+				t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g)
+			}
+		})
+	}
+}
diff --git a/android/config.go b/android/config.go
index 26c4e6e..e208dcd 100644
--- a/android/config.go
+++ b/android/config.go
@@ -89,9 +89,10 @@
 	ConfigFileName           string
 	ProductVariablesFileName string
 
-	Targets              map[OsType][]Target
-	BuildOsVariant       string
-	BuildOsCommonVariant string
+	Targets             map[OsType][]Target
+	BuildOSTarget       Target // the Target for tools run on the build machine
+	BuildOSCommonTarget Target // the Target for common (java) tools run on the build machine
+	AndroidCommonTarget Target // the Target for common modules for the Android device
 
 	// multilibConflicts for an ArchType is true if there is earlier configured device architecture with the same
 	// multilib value.
@@ -289,8 +290,9 @@
 		config.Targets[BuildOs] = config.Targets[BuildOs][:1]
 	}
 
-	config.BuildOsVariant = config.Targets[BuildOs][0].String()
-	config.BuildOsCommonVariant = getCommonTargets(config.Targets[BuildOs])[0].String()
+	config.BuildOSTarget = config.Targets[BuildOs][0]
+	config.BuildOSCommonTarget = getCommonTargets(config.Targets[BuildOs])[0]
+	config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
 	config.TestProductVariables.DeviceArch = proptools.StringPtr("arm64")
 	config.TestProductVariables.DeviceArchVariant = proptools.StringPtr("armv8-a")
 	config.TestProductVariables.DeviceSecondaryArch = proptools.StringPtr("arm")
@@ -374,8 +376,11 @@
 	}
 
 	config.Targets = targets
-	config.BuildOsVariant = targets[BuildOs][0].String()
-	config.BuildOsCommonVariant = getCommonTargets(targets[BuildOs])[0].String()
+	config.BuildOSTarget = config.Targets[BuildOs][0]
+	config.BuildOSCommonTarget = getCommonTargets(config.Targets[BuildOs])[0]
+	if len(config.Targets[Android]) > 0 {
+		config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
+	}
 
 	if err := config.fromEnv(); err != nil {
 		return Config{}, err
@@ -386,13 +391,14 @@
 
 func (c *config) fromEnv() error {
 	switch c.Getenv("EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9") {
-	case "":
-		// Nothing, this is the default
-	case "true":
-		// Use -source 9 -target 9
+	case "", "true":
+		// Use -source 9 -target 9. This is the default.
 		c.targetOpenJDK9 = true
+	case "false":
+		// Use -source 8 -target 8. This is the legacy behaviour.
+		c.targetOpenJDK9 = false
 	default:
-		return fmt.Errorf(`Invalid value for EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9, should be "" or "true"`)
+		return fmt.Errorf(`Invalid value for EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9, should be "", "true", or "false"`)
 	}
 
 	return nil
diff --git a/android/csuite_config.go b/android/csuite_config.go
new file mode 100644
index 0000000..15c518a
--- /dev/null
+++ b/android/csuite_config.go
@@ -0,0 +1,70 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+	"fmt"
+	"io"
+)
+
+func init() {
+	RegisterModuleType("csuite_config", CSuiteConfigFactory)
+}
+
+type csuiteConfigProperties struct {
+	// Override the default (AndroidTest.xml) test manifest file name.
+	Test_config *string
+}
+
+type CSuiteConfig struct {
+	ModuleBase
+	properties     csuiteConfigProperties
+	OutputFilePath OutputPath
+}
+
+func (me *CSuiteConfig) GenerateAndroidBuildActions(ctx ModuleContext) {
+	me.OutputFilePath = PathForModuleOut(ctx, me.BaseModuleName()).OutputPath
+}
+
+func (me *CSuiteConfig) AndroidMk() AndroidMkData {
+	androidMkData := AndroidMkData{
+		Class:      "FAKE",
+		Include:    "$(BUILD_SYSTEM)/suite_host_config.mk",
+		OutputFile: OptionalPathForPath(me.OutputFilePath),
+	}
+	androidMkData.Extra = []AndroidMkExtraFunc{
+		func(w io.Writer, outputFile Path) {
+			if me.properties.Test_config != nil {
+				fmt.Fprintf(w, "LOCAL_TEST_CONFIG := %s\n",
+					*me.properties.Test_config)
+			}
+			fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE := csuite")
+		},
+	}
+	return androidMkData
+}
+
+func InitCSuiteConfigModule(me *CSuiteConfig) {
+	me.AddProperties(&me.properties)
+}
+
+// csuite_config generates an App Compatibility Test Suite (C-Suite) configuration file from the
+// <test_config> xml file and stores it in a subdirectory of $(HOST_OUT).
+func CSuiteConfigFactory() Module {
+	module := &CSuiteConfig{}
+	InitCSuiteConfigModule(module)
+	InitAndroidArchModule(module, HostSupported, MultilibFirst)
+	return module
+}
diff --git a/android/csuite_config_test.go b/android/csuite_config_test.go
new file mode 100644
index 0000000..e534bb7
--- /dev/null
+++ b/android/csuite_config_test.go
@@ -0,0 +1,53 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+	"testing"
+)
+
+func testCSuiteConfig(test *testing.T, bpFileContents string) *TestContext {
+	config := TestArchConfig(buildDir, nil)
+
+	ctx := NewTestArchContext()
+	ctx.RegisterModuleType("csuite_config", ModuleFactoryAdaptor(CSuiteConfigFactory))
+	ctx.Register()
+	mockFiles := map[string][]byte{
+		"Android.bp": []byte(bpFileContents),
+	}
+	ctx.MockFileSystem(mockFiles)
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	FailIfErrored(test, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	FailIfErrored(test, errs)
+	return ctx
+}
+
+func TestCSuiteConfig(t *testing.T) {
+	ctx := testCSuiteConfig(t, `
+csuite_config { name: "plain"}
+csuite_config { name: "with_manifest", test_config: "manifest.xml" }
+`)
+
+	variants := ctx.ModuleVariantsForTests("plain")
+	if len(variants) > 1 {
+		t.Errorf("expected 1, got %d", len(variants))
+	}
+	expectedOutputFilename := ctx.ModuleForTests(
+		"plain", variants[0]).Module().(*CSuiteConfig).OutputFilePath.Base()
+	if expectedOutputFilename != "plain" {
+		t.Errorf("expected plain, got %q", expectedOutputFilename)
+	}
+}
diff --git a/android/module.go b/android/module.go
index 5d1a609..70b602b 100644
--- a/android/module.go
+++ b/android/module.go
@@ -417,6 +417,7 @@
 	} `android:"arch_variant"`
 
 	// Set by TargetMutator
+	CompileOS           OsType   `blueprint:"mutated"`
 	CompileTarget       Target   `blueprint:"mutated"`
 	CompileMultiTargets []Target `blueprint:"mutated"`
 	CompilePrimary      bool     `blueprint:"mutated"`
@@ -719,12 +720,6 @@
 	}
 }
 
-func (m *ModuleBase) SetTarget(target Target, multiTargets []Target, primary bool) {
-	m.commonProperties.CompileTarget = target
-	m.commonProperties.CompileMultiTargets = multiTargets
-	m.commonProperties.CompilePrimary = primary
-}
-
 func (m *ModuleBase) Target() Target {
 	return m.commonProperties.CompileTarget
 }
diff --git a/android/mutator.go b/android/mutator.go
index 88ac521..4a5338f 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -86,6 +86,7 @@
 }
 
 func registerArchMutator(ctx RegisterMutatorsContext) {
+	ctx.BottomUp("os", osMutator).Parallel()
 	ctx.BottomUp("arch", archMutator).Parallel()
 	ctx.TopDown("arch_hooks", archHookMutator).Parallel()
 }
diff --git a/android/proto.go b/android/proto.go
index c8ade45..b712258 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -52,9 +52,8 @@
 	}
 
 	if plugin := String(p.Proto.Plugin); plugin != "" {
-		ctx.AddFarVariationDependencies([]blueprint.Variation{
-			{Mutator: "arch", Variation: ctx.Config().BuildOsVariant},
-		}, ProtoPluginDepTag, "protoc-gen-"+plugin)
+		ctx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(),
+			ProtoPluginDepTag, "protoc-gen-"+plugin)
 	}
 }
 
diff --git a/android/sdk.go b/android/sdk.go
index 52c392f..8e1e106 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -39,25 +39,28 @@
 	Version string
 }
 
-const (
-	// currentVersion refers to the in-development version of an SDK
-	currentVersion = "current"
-)
-
-// IsCurrentVersion determines if the SdkRef is referencing to an in-development version of an SDK
-func (s SdkRef) IsCurrentVersion() bool {
-	return s.Version == currentVersion
+// Unversioned determines if the SdkRef is referencing to the unversioned SDK module
+func (s SdkRef) Unversioned() bool {
+	return s.Version == ""
 }
 
-// IsCurrentVersionOf determines if the SdkRef is referencing to an in-development version of the
-// specified SDK
-func (s SdkRef) IsCurrentVersionOf(name string) bool {
-	return s.Name == name && s.IsCurrentVersion()
+// String returns string representation of this SdkRef for debugging purpose
+func (s SdkRef) String() string {
+	if s.Name == "" {
+		return "(No Sdk)"
+	}
+	if s.Unversioned() {
+		return s.Name
+	}
+	return s.Name + string(SdkVersionSeparator) + s.Version
 }
 
-// ParseSdkRef parses a `name#version` style string into a corresponding SdkRef struct
+// SdkVersionSeparator is a character used to separate an sdk name and its version
+const SdkVersionSeparator = '@'
+
+// ParseSdkRef parses a `name@version` style string into a corresponding SdkRef struct
 func ParseSdkRef(ctx BaseModuleContext, str string, property string) SdkRef {
-	tokens := strings.Split(str, "#")
+	tokens := strings.Split(str, string(SdkVersionSeparator))
 	if len(tokens) < 1 || len(tokens) > 2 {
 		ctx.PropertyErrorf(property, "%q does not follow name#version syntax", str)
 		return SdkRef{Name: "invalid sdk name", Version: "invalid sdk version"}
@@ -65,7 +68,7 @@
 
 	name := tokens[0]
 
-	version := currentVersion // If version is omitted, defaults to "current"
+	var version string
 	if len(tokens) == 2 {
 		version = tokens[1]
 	}
@@ -75,6 +78,7 @@
 
 type SdkRefs []SdkRef
 
+// Contains tells if the given SdkRef is in this list of SdkRef's
 func (refs SdkRefs) Contains(s SdkRef) bool {
 	for _, r := range refs {
 		if r == s {
@@ -105,7 +109,7 @@
 	return s
 }
 
-// MakeMemberof sets this module to be a member of a specific SDK
+// MakeMemberOf sets this module to be a member of a specific SDK
 func (s *SdkBase) MakeMemberOf(sdk SdkRef) {
 	s.properties.ContainingSdk = &sdk
 }
@@ -120,10 +124,10 @@
 	if s.properties.ContainingSdk != nil {
 		return *s.properties.ContainingSdk
 	}
-	return SdkRef{Name: "", Version: currentVersion}
+	return SdkRef{Name: "", Version: ""}
 }
 
-// Membername returns the name of the module that this SDK member is overriding
+// MemberName returns the name of the module that this SDK member is overriding
 func (s *SdkBase) MemberName() string {
 	return proptools.String(s.properties.Sdk_member_name)
 }
diff --git a/android/singleton.go b/android/singleton.go
index 7f9c216..33bc6d1 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -52,6 +52,10 @@
 	VisitAllModulesBlueprint(visit func(blueprint.Module))
 	VisitAllModules(visit func(Module))
 	VisitAllModulesIf(pred func(Module) bool, visit func(Module))
+
+	VisitDirectDeps(module Module, visit func(Module))
+	VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module))
+
 	// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
 	VisitDepsDepthFirst(module Module, visit func(Module))
 	// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
@@ -192,6 +196,14 @@
 	s.SingletonContext.VisitAllModulesIf(predAdaptor(pred), visitAdaptor(visit))
 }
 
+func (s *singletonContextAdaptor) VisitDirectDeps(module Module, visit func(Module)) {
+	s.SingletonContext.VisitDirectDeps(module, visitAdaptor(visit))
+}
+
+func (s *singletonContextAdaptor) VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module)) {
+	s.SingletonContext.VisitDirectDepsIf(module, predAdaptor(pred), visitAdaptor(visit))
+}
+
 func (s *singletonContextAdaptor) VisitDepsDepthFirst(module Module, visit func(Module)) {
 	s.SingletonContext.VisitDepsDepthFirst(module, visitAdaptor(visit))
 }
diff --git a/android/vts_config.go b/android/vts_config.go
index c44b3a3..86f6e72 100644
--- a/android/vts_config.go
+++ b/android/vts_config.go
@@ -41,16 +41,17 @@
 func (me *VtsConfig) AndroidMk() AndroidMkData {
 	androidMkData := AndroidMkData{
 		Class:      "FAKE",
-		Include:    "$(BUILD_SYSTEM)/android_vts_host_config.mk",
+		Include:    "$(BUILD_SYSTEM)/suite_host_config.mk",
 		OutputFile: OptionalPathForPath(me.OutputFilePath),
 	}
-	if me.properties.Test_config != nil {
-		androidMkData.Extra = []AndroidMkExtraFunc{
-			func(w io.Writer, outputFile Path) {
+	androidMkData.Extra = []AndroidMkExtraFunc{
+		func(w io.Writer, outputFile Path) {
+			if me.properties.Test_config != nil {
 				fmt.Fprintf(w, "LOCAL_TEST_CONFIG := %s\n",
 					*me.properties.Test_config)
-			},
-		}
+			}
+			fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE := vts")
+		},
 	}
 	return androidMkData
 }
diff --git a/apex/apex.go b/apex/apex.go
index bb90cb9..c9b989a 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -558,7 +558,14 @@
 	case nativeTest:
 		return "NATIVE_TESTS"
 	case app:
-		return "APPS"
+		// b/142537672 Why isn't this APP? We want to have full control over
+		// the paths and file names of the apk file under the flattend APEX.
+		// If this is set to APP, then the paths and file names are modified
+		// by the Make build system. For example, it is installed to
+		// /system/apex/<apexname>/app/<Appname>/<apexname>.<Appname>/ instead of
+		// /system/apex/<apexname>/app/<Appname> because the build system automatically
+		// appends module name (which is <apexname>.<Appname> to the path.
+		return "ETC"
 	default:
 		panic(fmt.Errorf("unknown class %d", class))
 	}
@@ -612,28 +619,25 @@
 
 func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
 	native_shared_libs []string, binaries []string, tests []string,
-	arch string, imageVariation string) {
+	target android.Target, imageVariation string) {
 	// Use *FarVariation* to be able to depend on modules having
 	// conflicting variations with this module. This is required since
 	// arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
 	// for native shared libs.
-	ctx.AddFarVariationDependencies([]blueprint.Variation{
-		{Mutator: "arch", Variation: arch},
+	ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
 		{Mutator: "image", Variation: imageVariation},
 		{Mutator: "link", Variation: "shared"},
 		{Mutator: "version", Variation: ""}, // "" is the non-stub variant
-	}, sharedLibTag, native_shared_libs...)
+	}...), sharedLibTag, native_shared_libs...)
 
-	ctx.AddFarVariationDependencies([]blueprint.Variation{
-		{Mutator: "arch", Variation: arch},
-		{Mutator: "image", Variation: imageVariation},
-	}, executableTag, binaries...)
+	ctx.AddFarVariationDependencies(append(target.Variations(),
+		blueprint.Variation{Mutator: "image", Variation: imageVariation}),
+		executableTag, binaries...)
 
-	ctx.AddFarVariationDependencies([]blueprint.Variation{
-		{Mutator: "arch", Variation: arch},
+	ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
 		{Mutator: "image", Variation: imageVariation},
 		{Mutator: "test_per_src", Variation: ""}, // "" is the all-tests variant
-	}, testTag, tests...)
+	}...), testTag, tests...)
 }
 
 func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
@@ -665,49 +669,45 @@
 	for i, target := range targets {
 		// When multilib.* is omitted for native_shared_libs, it implies
 		// multilib.both.
-		ctx.AddFarVariationDependencies([]blueprint.Variation{
-			{Mutator: "arch", Variation: target.String()},
+		ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
 			{Mutator: "image", Variation: a.getImageVariation(config)},
 			{Mutator: "link", Variation: "shared"},
-		}, sharedLibTag, a.properties.Native_shared_libs...)
+		}...), sharedLibTag, a.properties.Native_shared_libs...)
 
 		// When multilib.* is omitted for tests, it implies
 		// multilib.both.
-		ctx.AddFarVariationDependencies([]blueprint.Variation{
-			{Mutator: "arch", Variation: target.String()},
+		ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
 			{Mutator: "image", Variation: a.getImageVariation(config)},
 			{Mutator: "test_per_src", Variation: ""}, // "" is the all-tests variant
-		}, testTag, a.properties.Tests...)
+		}...), testTag, a.properties.Tests...)
 
 		// Add native modules targetting both ABIs
 		addDependenciesForNativeModules(ctx,
 			a.properties.Multilib.Both.Native_shared_libs,
 			a.properties.Multilib.Both.Binaries,
 			a.properties.Multilib.Both.Tests,
-			target.String(),
+			target,
 			a.getImageVariation(config))
 
 		isPrimaryAbi := i == 0
 		if isPrimaryAbi {
 			// When multilib.* is omitted for binaries, it implies
 			// multilib.first.
-			ctx.AddFarVariationDependencies([]blueprint.Variation{
-				{Mutator: "arch", Variation: target.String()},
-				{Mutator: "image", Variation: a.getImageVariation(config)},
-			}, executableTag, a.properties.Binaries...)
+			ctx.AddFarVariationDependencies(append(target.Variations(),
+				blueprint.Variation{Mutator: "image", Variation: a.getImageVariation(config)}),
+				executableTag, a.properties.Binaries...)
 
 			// Add native modules targetting the first ABI
 			addDependenciesForNativeModules(ctx,
 				a.properties.Multilib.First.Native_shared_libs,
 				a.properties.Multilib.First.Binaries,
 				a.properties.Multilib.First.Tests,
-				target.String(),
+				target,
 				a.getImageVariation(config))
 
 			// When multilib.* is omitted for prebuilts, it implies multilib.first.
-			ctx.AddFarVariationDependencies([]blueprint.Variation{
-				{Mutator: "arch", Variation: target.String()},
-			}, prebuiltTag, a.properties.Prebuilts...)
+			ctx.AddFarVariationDependencies(target.Variations(),
+				prebuiltTag, a.properties.Prebuilts...)
 		}
 
 		switch target.Arch.ArchType.Multilib {
@@ -717,14 +717,14 @@
 				a.properties.Multilib.Lib32.Native_shared_libs,
 				a.properties.Multilib.Lib32.Binaries,
 				a.properties.Multilib.Lib32.Tests,
-				target.String(),
+				target,
 				a.getImageVariation(config))
 
 			addDependenciesForNativeModules(ctx,
 				a.properties.Multilib.Prefer32.Native_shared_libs,
 				a.properties.Multilib.Prefer32.Binaries,
 				a.properties.Multilib.Prefer32.Tests,
-				target.String(),
+				target,
 				a.getImageVariation(config))
 		case "lib64":
 			// Add native modules targetting 64-bit ABI
@@ -732,7 +732,7 @@
 				a.properties.Multilib.Lib64.Native_shared_libs,
 				a.properties.Multilib.Lib64.Binaries,
 				a.properties.Multilib.Lib64.Tests,
-				target.String(),
+				target,
 				a.getImageVariation(config))
 
 			if !has32BitTarget {
@@ -740,7 +740,7 @@
 					a.properties.Multilib.Prefer32.Native_shared_libs,
 					a.properties.Multilib.Prefer32.Binaries,
 					a.properties.Multilib.Prefer32.Tests,
-					target.String(),
+					target,
 					a.getImageVariation(config))
 			}
 
@@ -749,7 +749,7 @@
 					if sanitizer == "hwaddress" {
 						addDependenciesForNativeModules(ctx,
 							[]string{"libclang_rt.hwasan-aarch64-android"},
-							nil, nil, target.String(), a.getImageVariation(config))
+							nil, nil, target, a.getImageVariation(config))
 						break
 					}
 				}
@@ -758,13 +758,11 @@
 
 	}
 
-	ctx.AddFarVariationDependencies([]blueprint.Variation{
-		{Mutator: "arch", Variation: "android_common"},
-	}, javaLibTag, a.properties.Java_libs...)
+	ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
+		javaLibTag, a.properties.Java_libs...)
 
-	ctx.AddFarVariationDependencies([]blueprint.Variation{
-		{Mutator: "arch", Variation: "android_common"},
-	}, androidAppTag, a.properties.Apps...)
+	ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
+		androidAppTag, a.properties.Apps...)
 
 	if String(a.properties.Key) == "" {
 		ctx.ModuleErrorf("key is missing")
@@ -788,6 +786,11 @@
 	}
 }
 
+func (a *apexBundle) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+	// direct deps of an APEX bundle are all part of the APEX bundle
+	return true
+}
+
 func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string {
 	certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName())
 	if overridden {
@@ -969,7 +972,11 @@
 }
 
 func getCopyManifestForAndroidApp(app *java.AndroidApp, pkgName string) (fileToCopy android.Path, dirInApex string) {
-	dirInApex = filepath.Join("app", pkgName)
+	appDir := "app"
+	if app.Privileged() {
+		appDir = "priv-app"
+	}
+	dirInApex = filepath.Join(appDir, pkgName)
 	fileToCopy = app.OutputFile()
 	return
 }
@@ -1657,17 +1664,17 @@
 			host := false
 			switch fi.module.Target().Os.Class {
 			case android.Host:
-				if archStr != "common" {
+				if fi.module.Target().Arch.ArchType != android.Common {
 					fmt.Fprintln(w, "LOCAL_MODULE_HOST_ARCH :=", archStr)
 				}
 				host = true
 			case android.HostCross:
-				if archStr != "common" {
+				if fi.module.Target().Arch.ArchType != android.Common {
 					fmt.Fprintln(w, "LOCAL_MODULE_HOST_CROSS_ARCH :=", archStr)
 				}
 				host = true
 			case android.Device:
-				if archStr != "common" {
+				if fi.module.Target().Arch.ArchType != android.Common {
 					fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", archStr)
 				}
 			}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index ae0ea7d..7a51bb6 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -2232,6 +2232,7 @@
 			key: "myapex.key",
 			apps: [
 				"AppFoo",
+				"AppFooPriv",
 			],
 		}
 
@@ -2247,6 +2248,14 @@
 			sdk_version: "none",
 			system_modules: "none",
 		}
+
+		android_app {
+			name: "AppFooPriv",
+			srcs: ["foo/bar/MyClass.java"],
+			sdk_version: "none",
+			system_modules: "none",
+			privileged: true,
+		}
 	`)
 
 	module := ctx.ModuleForTests("myapex", "android_common_myapex")
@@ -2254,6 +2263,7 @@
 	copyCmds := apexRule.Args["copy_commands"]
 
 	ensureContains(t, copyCmds, "image.apex/app/AppFoo/AppFoo.apk")
+	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv/AppFooPriv.apk")
 
 }
 
@@ -2407,6 +2417,36 @@
 	// check that libfoo is created only for the platform
 	ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared_myapex")
 	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared")
+
+	ctx, _ = testApex(t, `
+	apex {
+		name: "myapex",
+		key: "myapex.key",
+		native_shared_libs: ["libfoo"],
+	}
+
+	apex_key {
+		name: "myapex.key",
+		public_key: "testkey.avbpubkey",
+		private_key: "testkey.pem",
+	}
+
+	cc_library {
+		name: "libfoo",
+		stl: "none",
+		system_shared_libs: [],
+		apex_available: ["myapex"],
+		static: {
+			apex_available: ["//apex_available:platform"],
+		},
+	}`)
+
+	// shared variant of libfoo is only available to myapex
+	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared_myapex")
+	ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared")
+	// but the static variant is available to both myapex and the platform
+	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_static_myapex")
+	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_static")
 }
 
 func TestMain(m *testing.M) {
diff --git a/cc/androidmk.go b/cc/androidmk.go
index f1d329f..9a98b0e 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -308,15 +308,13 @@
 
 	var fuzzFiles []string
 	for _, d := range fuzz.corpus {
-		rel := d.Rel()
-		path := d.String()
-		path = strings.TrimSuffix(path, rel)
-		fuzzFiles = append(fuzzFiles, path+":corpus/"+d.Base())
+		fuzzFiles = append(fuzzFiles,
+			filepath.Dir(fuzz.corpusIntermediateDir.String())+":corpus/"+d.Base())
 	}
 
 	if fuzz.dictionary != nil {
-		path := strings.TrimSuffix(fuzz.dictionary.String(), fuzz.dictionary.Rel())
-		fuzzFiles = append(fuzzFiles, path+":"+fuzz.dictionary.Base())
+		fuzzFiles = append(fuzzFiles,
+			filepath.Dir(fuzz.dictionary.String())+":"+fuzz.dictionary.Base())
 	}
 
 	if len(fuzzFiles) > 0 {
diff --git a/cc/cc.go b/cc/cc.go
index 9031afe..806a6ed 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1389,10 +1389,9 @@
 			depTag = headerExportDepTag
 		}
 		if buildStubs {
-			actx.AddFarVariationDependencies([]blueprint.Variation{
-				{Mutator: "arch", Variation: ctx.Target().String()},
-				{Mutator: "image", Variation: c.imageVariation()},
-			}, depTag, lib)
+			actx.AddFarVariationDependencies(append(ctx.Target().Variations(),
+				blueprint.Variation{Mutator: "image", Variation: c.imageVariation()}),
+				depTag, lib)
 		} else {
 			actx.AddVariationDependencies(nil, depTag, lib)
 		}
@@ -1934,7 +1933,11 @@
 
 		if ptr != nil {
 			if !linkFile.Valid() {
-				ctx.ModuleErrorf("module %q missing output file", depName)
+				if !ctx.Config().AllowMissingDependencies() {
+					ctx.ModuleErrorf("module %q missing output file", depName)
+				} else {
+					ctx.AddMissingDependencies([]string{depName})
+				}
 				return
 			}
 			*ptr = append(*ptr, linkFile.Path())
@@ -2152,6 +2155,16 @@
 	return false
 }
 
+func (c *Module) AvailableFor(what string) bool {
+	if linker, ok := c.linker.(interface {
+		availableFor(string) bool
+	}); ok {
+		return c.ApexModuleBase.AvailableFor(what) || linker.availableFor(what)
+	} else {
+		return c.ApexModuleBase.AvailableFor(what)
+	}
+}
+
 func (c *Module) installable() bool {
 	return c.installer != nil && !c.Properties.PreventInstall && c.IsForPlatform() && c.outputFile.Valid()
 }
@@ -2181,6 +2194,16 @@
 	}
 }
 
+func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+	if depTag, ok := ctx.OtherModuleDependencyTag(dep).(dependencyTag); ok {
+		if cc, ok := dep.(*Module); ok && cc.IsStubs() && depTag.shared {
+			// dynamic dep to a stubs lib crosses APEX boundary
+			return false
+		}
+	}
+	return true
+}
+
 //
 // Defaults
 //
diff --git a/cc/compiler.go b/cc/compiler.go
index 85ff400..ffb6ad2 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -309,7 +309,6 @@
 		flags.SystemIncludeFlags = append(flags.SystemIncludeFlags,
 			"-isystem "+getCurrentIncludePath(ctx).String(),
 			"-isystem "+getCurrentIncludePath(ctx).Join(ctx, config.NDKTriple(tc)).String())
-		flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_NDK__")
 	}
 
 	if ctx.useVndk() {
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index d7d8955..3e8abac 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -65,6 +65,7 @@
 	"android.hardware.neuralnetworks@1.0",
 	"android.hardware.neuralnetworks@1.1",
 	"android.hardware.neuralnetworks@1.2",
+	"android.hardware.neuralnetworks@1.3",
 	"android.hardware.nfc@1.0",
 	"android.hardware.nfc@1.1",
 	"android.hardware.nfc@1.2",
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 0f500b6..43e8c85 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -73,6 +73,7 @@
 		"-m32",
 		"-Wl,--large-address-aware",
 		"-L${WindowsGccRoot}/${WindowsGccTriple}/lib32",
+		"-static-libgcc",
 	}
 	windowsX86ClangLdflags = append(ClangFilterUnknownCflags(windowsX86Ldflags), []string{
 		"-B${WindowsGccRoot}/${WindowsGccTriple}/bin",
@@ -86,6 +87,7 @@
 		"-m64",
 		"-L${WindowsGccRoot}/${WindowsGccTriple}/lib64",
 		"-Wl,--high-entropy-va",
+		"-static-libgcc",
 	}
 	windowsX8664ClangLdflags = append(ClangFilterUnknownCflags(windowsX8664Ldflags), []string{
 		"-B${WindowsGccRoot}/${WindowsGccTriple}/bin",
diff --git a/cc/fuzz.go b/cc/fuzz.go
index c19fdc5..a99b0bb 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -53,9 +53,10 @@
 	*binaryDecorator
 	*baseCompiler
 
-	Properties FuzzProperties
-	corpus     android.Paths
-	dictionary android.Path
+	Properties            FuzzProperties
+	dictionary            android.Path
+	corpus                android.Paths
+	corpusIntermediateDir android.Path
 }
 
 func (fuzz *fuzzBinary) linkerProps() []interface{} {
@@ -103,6 +104,16 @@
 	fuzz.binaryDecorator.baseInstaller.install(ctx, file)
 
 	fuzz.corpus = android.PathsForModuleSrc(ctx, fuzz.Properties.Corpus)
+	builder := android.NewRuleBuilder()
+	intermediateDir := android.PathForModuleOut(ctx, "corpus")
+	for _, entry := range fuzz.corpus {
+		builder.Command().Text("cp").
+			Input(entry).
+			Output(intermediateDir.Join(ctx, entry.Base()))
+	}
+	builder.Build(pctx, ctx, "copy_corpus", "copy corpus")
+	fuzz.corpusIntermediateDir = intermediateDir
+
 	if fuzz.Properties.Dictionary != nil {
 		fuzz.dictionary = android.PathForModuleSrc(ctx, *fuzz.Properties.Dictionary)
 		if fuzz.dictionary.Ext() != ".dict" {
@@ -148,10 +159,14 @@
 	// include the STL.
 	android.AddLoadHook(module, func(ctx android.LoadHookContext) {
 		staticStlLinkage := struct {
-			Stl *string
+			Target struct {
+				Linux_glibc struct {
+					Stl *string
+				}
+			}
 		}{}
 
-		staticStlLinkage.Stl = proptools.StringPtr("libc++_static")
+		staticStlLinkage.Target.Linux_glibc.Stl = proptools.StringPtr("libc++_static")
 		ctx.AppendProperties(&staticStlLinkage)
 	})
 
@@ -211,7 +226,7 @@
 		// The corpora.
 		for _, corpusEntry := range fuzzModule.corpus {
 			archDirs[archDir] = append(archDirs[archDir],
-				fileToZip{corpusEntry, ccModule.Name() + "/corpus/" + corpusEntry.Base()})
+				fileToZip{corpusEntry, ccModule.Name() + "/corpus"})
 		}
 
 		// The dictionary.
diff --git a/cc/library.go b/cc/library.go
index 0fb3c78..80dc76c 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -131,6 +131,8 @@
 
 	Export_shared_lib_headers []string `android:"arch_variant"`
 	Export_static_lib_headers []string `android:"arch_variant"`
+
+	Apex_available []string `android:"arch_variant"`
 }
 
 type LibraryMutatedProperties struct {
@@ -573,6 +575,8 @@
 
 	// Write LOCAL_ADDITIONAL_DEPENDENCIES for ABI diff
 	androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer)
+
+	availableFor(string) bool
 }
 
 func (library *libraryDecorator) getLibName(ctx BaseModuleContext) string {
@@ -1134,6 +1138,19 @@
 	return library.MutatedProperties.StubsVersion
 }
 
+func (library *libraryDecorator) availableFor(what string) bool {
+	var list []string
+	if library.static() {
+		list = library.StaticProperties.Static.Apex_available
+	} else if library.shared() {
+		list = library.SharedProperties.Shared.Apex_available
+	}
+	if len(list) == 0 {
+		return false
+	}
+	return android.CheckAvailableForApex(what, list)
+}
+
 var versioningMacroNamesListKey = android.NewOnceKey("versioningMacroNamesList")
 
 func versioningMacroNamesList(config android.Config) *map[string]string {
diff --git a/cc/object.go b/cc/object.go
index 1f1ac8e..31729a5 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -104,7 +104,7 @@
 	var outputFile android.Path
 	builderFlags := flagsToBuilderFlags(flags)
 
-	if len(objs.objFiles) == 1 {
+	if len(objs.objFiles) == 1 && String(object.Properties.Linker_script) == "" {
 		outputFile = objs.objFiles[0]
 
 		if String(object.Properties.Prefix_symbols) != "" {
diff --git a/cc/sanitize.go b/cc/sanitize.go
index c0a7c63..5172fc8 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -465,7 +465,6 @@
 
 	if Bool(sanitize.Properties.Sanitize.Fuzzer) {
 		flags.CFlags = append(flags.CFlags, "-fsanitize=fuzzer-no-link")
-		flags.LdFlags = append(flags.LdFlags, "-fsanitize=fuzzer-no-link")
 
 		// TODO(b/131771163): LTO and Fuzzer support is mutually incompatible.
 		_, flags.LdFlags = removeFromList("-flto", flags.LdFlags)
@@ -473,6 +472,12 @@
 		flags.LdFlags = append(flags.LdFlags, "-fno-lto")
 		flags.CFlags = append(flags.CFlags, "-fno-lto")
 
+		// TODO(b/142430592): Upstream linker scripts for sanitizer runtime libraries
+		// discard the sancov_lowest_stack symbol, because it's emulated TLS (and thus
+		// doesn't match the linker script due to the "__emutls_v." prefix).
+		flags.LdFlags = append(flags.LdFlags, "-fno-sanitize-coverage=stack-depth")
+		flags.CFlags = append(flags.CFlags, "-fno-sanitize-coverage=stack-depth")
+
 		// TODO(b/133876586): Experimental PM breaks sanitizer coverage.
 		_, flags.CFlags = removeFromList("-fexperimental-new-pass-manager", flags.CFlags)
 		flags.CFlags = append(flags.CFlags, "-fno-experimental-new-pass-manager")
@@ -860,7 +865,8 @@
 			} else {
 				runtimeLibrary = config.ScudoRuntimeLibrary(toolchain)
 			}
-		} else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep {
+		} else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep ||
+			Bool(c.sanitize.Properties.Sanitize.Fuzzer) {
 			runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
 		}
 
@@ -878,18 +884,16 @@
 			// added to libFlags and LOCAL_SHARED_LIBRARIES by cc.Module
 			if c.staticBinary() {
 				// static executable gets static runtime libs
-				mctx.AddFarVariationDependencies([]blueprint.Variation{
+				mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{
 					{Mutator: "link", Variation: "static"},
 					{Mutator: "image", Variation: c.imageVariation()},
-					{Mutator: "arch", Variation: mctx.Target().String()},
-				}, staticDepTag, runtimeLibrary)
+				}...), staticDepTag, runtimeLibrary)
 			} else if !c.static() && !c.header() {
 				// dynamic executable and shared libs get shared runtime libs
-				mctx.AddFarVariationDependencies([]blueprint.Variation{
+				mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{
 					{Mutator: "link", Variation: "shared"},
 					{Mutator: "image", Variation: c.imageVariation()},
-					{Mutator: "arch", Variation: mctx.Target().String()},
-				}, earlySharedDepTag, runtimeLibrary)
+				}...), earlySharedDepTag, runtimeLibrary)
 			}
 			// static lib does not have dependency to the runtime library. The
 			// dependency will be added to the executables or shared libs using
diff --git a/cc/testing.go b/cc/testing.go
index 11a5e3b..6fa6ea7 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -190,6 +190,7 @@
 			name: "crtbegin_so",
 			recovery_available: true,
 			vendor_available: true,
+			stl: "none",
 		}
 
 		cc_object {
@@ -208,6 +209,7 @@
 			name: "crtend_so",
 			recovery_available: true,
 			vendor_available: true,
+			stl: "none",
 		}
 
 		cc_object {
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 6f92153..46e0f0a 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -495,7 +495,8 @@
 	}
 
 	for _, f := range global.PatternsOnSystemOther {
-		if makefileMatch(filepath.Join(SystemPartition, f), dexLocation) {
+		// See comment of SYSTEM_OTHER_ODEX_FILTER for details on the matching.
+		if makefileMatch("/"+f, dexLocation) || makefileMatch(filepath.Join(SystemPartition, f), dexLocation) {
 			return true
 		}
 	}
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 820f9e7..6f8120e 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -103,13 +103,12 @@
 				{module: productModule, expectedPartition: "product"},
 			},
 		},
-		// product/app/% only applies to product apps inside the system partition
 		{
 			patterns: []string{"app/%", "product/app/%"},
 			moduleTests: []moduleTest{
 				{module: systemModule, expectedPartition: "system_other/system"},
 				{module: systemProductModule, expectedPartition: "system_other/system/product"},
-				{module: productModule, expectedPartition: "product"},
+				{module: productModule, expectedPartition: "system_other/product"},
 			},
 		},
 	}
@@ -129,7 +128,7 @@
 			}
 
 			if rule.Installs().String() != wantInstalls.String() {
-				t.Errorf("\nwant installs:\n   %v\ngot:\n   %v", wantInstalls, rule.Installs())
+				t.Errorf("\npatterns: %v\nwant installs:\n   %v\ngot:\n   %v", test.patterns, wantInstalls, rule.Installs())
 			}
 		}
 	}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index c21df4c..a7c5d65 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -172,9 +172,7 @@
 			if m := android.SrcIsModule(tool); m != "" {
 				tool = m
 			}
-			ctx.AddFarVariationDependencies([]blueprint.Variation{
-				{Mutator: "arch", Variation: ctx.Config().BuildOsVariant},
-			}, tag, tool)
+			ctx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), tag, tool)
 		}
 	}
 }
diff --git a/go.mod b/go.mod
index cc328e0..1483a31 100644
--- a/go.mod
+++ b/go.mod
@@ -7,3 +7,5 @@
 replace github.com/golang/protobuf v0.0.0 => ../../external/golang-protobuf
 
 replace github.com/google/blueprint v0.0.0 => ../blueprint
+
+go 1.13
diff --git a/java/aar.go b/java/aar.go
index 6a883d3..6426ac3 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -520,6 +520,10 @@
 	return proptools.StringDefault(a.properties.Sdk_version, defaultSdkVersion(a))
 }
 
+func (a *AARImport) systemModules() string {
+	return ""
+}
+
 func (a *AARImport) minSdkVersion() string {
 	if a.properties.Min_sdk_version != nil {
 		return *a.properties.Min_sdk_version
diff --git a/java/androidmk.go b/java/androidmk.go
index 5067e2f..9e9b277 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -145,7 +145,7 @@
 }
 
 func (prebuilt *Import) AndroidMkEntries() android.AndroidMkEntries {
-	if !prebuilt.IsForPlatform() || !prebuilt.ContainingSdk().IsCurrentVersion() {
+	if !prebuilt.IsForPlatform() || !prebuilt.ContainingSdk().Unversioned() {
 		return android.AndroidMkEntries{
 			Disabled: true,
 		}
@@ -317,7 +317,7 @@
 
 				entries.SetPath("LOCAL_FULL_MANIFEST_FILE", app.manifestPath)
 
-				entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", Bool(app.appProperties.Privileged))
+				entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", app.Privileged())
 
 				entries.SetPath("LOCAL_CERTIFICATE", app.certificate.Pem)
 				entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", app.getOverriddenPackages()...)
@@ -534,6 +534,9 @@
 				if dstubs.jdiffDocZip != nil {
 					entries.SetPath("LOCAL_DROIDDOC_JDIFF_DOC_ZIP", dstubs.jdiffDocZip)
 				}
+				if dstubs.metadataZip != nil {
+					entries.SetPath("LOCAL_DROIDDOC_METADATA_ZIP", dstubs.metadataZip)
+				}
 				apiFilePrefix := "INTERNAL_PLATFORM_"
 				if String(dstubs.properties.Api_tag_name) != "" {
 					apiFilePrefix += String(dstubs.properties.Api_tag_name) + "_"
@@ -630,7 +633,7 @@
 		Include:    "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
 			func(entries *android.AndroidMkEntries) {
-				entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", Bool(a.properties.Privileged))
+				entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", a.Privileged())
 				if a.certificate != nil {
 					entries.SetPath("LOCAL_CERTIFICATE", a.certificate.Pem)
 				} else {
diff --git a/java/app.go b/java/app.go
index e033661..3dbcbf4 100644
--- a/java/app.go
+++ b/java/app.go
@@ -167,10 +167,8 @@
 
 	embedJni := a.shouldEmbedJnis(ctx)
 	for _, jniTarget := range ctx.MultiTargets() {
-		variation := []blueprint.Variation{
-			{Mutator: "arch", Variation: jniTarget.String()},
-			{Mutator: "link", Variation: "shared"},
-		}
+		variation := append(jniTarget.Variations(),
+			blueprint.Variation{Mutator: "link", Variation: "shared"})
 		tag := &jniDependencyTag{
 			target: jniTarget,
 		}
@@ -230,7 +228,7 @@
 
 	// Uncompress dex in APKs of privileged apps (even for unbundled builds, they may
 	// be preinstalled as prebuilts).
-	if ctx.Config().UncompressPrivAppDex() && Bool(a.appProperties.Privileged) {
+	if ctx.Config().UncompressPrivAppDex() && a.Privileged() {
 		return true
 	}
 
@@ -318,7 +316,7 @@
 	if ctx.ModuleName() == "framework-res" {
 		// framework-res.apk is installed as system/framework/framework-res.apk
 		installDir = "framework"
-	} else if Bool(a.appProperties.Privileged) {
+	} else if a.Privileged() {
 		installDir = filepath.Join("priv-app", a.installApkName)
 	} else {
 		installDir = filepath.Join("app", a.installApkName)
@@ -444,7 +442,7 @@
 	if ctx.ModuleName() == "framework-res" {
 		// framework-res.apk is installed as system/framework/framework-res.apk
 		a.installDir = android.PathForModuleInstall(ctx, "framework")
-	} else if Bool(a.appProperties.Privileged) {
+	} else if a.Privileged() {
 		a.installDir = android.PathForModuleInstall(ctx, "priv-app", a.installApkName)
 	} else if ctx.InstallInTestcases() {
 		a.installDir = android.PathForModuleInstall(ctx, a.installApkName)
@@ -557,6 +555,10 @@
 	return a.Library.OutputFiles(tag)
 }
 
+func (a *AndroidApp) Privileged() bool {
+	return Bool(a.appProperties.Privileged)
+}
+
 // android_app compiles sources and Android resources into an Android application package `.apk` file.
 func AndroidAppFactory() android.Module {
 	module := &AndroidApp{}
@@ -874,7 +876,7 @@
 	}
 
 	// Uncompress dex in APKs of privileged apps
-	if ctx.Config().UncompressPrivAppDex() && Bool(a.properties.Privileged) {
+	if ctx.Config().UncompressPrivAppDex() && a.Privileged() {
 		return true
 	}
 
@@ -1005,6 +1007,10 @@
 	a.AddProperties(a.archVariants)
 }
 
+func (a *AndroidAppImport) Privileged() bool {
+	return Bool(a.properties.Privileged)
+}
+
 func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
 	props := reflect.TypeOf((*AndroidAppImportProperties)(nil))
 
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 030b010..14db521 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -18,8 +18,6 @@
 	"fmt"
 	"io"
 
-	"github.com/google/blueprint"
-
 	"android/soong/android"
 )
 
@@ -83,13 +81,13 @@
 var deviceHostConverterDepTag = dependencyTag{name: "device_host_converter"}
 
 func (d *DeviceForHost) DepsMutator(ctx android.BottomUpMutatorContext) {
-	variation := []blueprint.Variation{{Mutator: "arch", Variation: "android_common"}}
-	ctx.AddFarVariationDependencies(variation, deviceHostConverterDepTag, d.properties.Libs...)
+	ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
+		deviceHostConverterDepTag, d.properties.Libs...)
 }
 
 func (d *HostForDevice) DepsMutator(ctx android.BottomUpMutatorContext) {
-	variation := []blueprint.Variation{{Mutator: "arch", Variation: ctx.Config().BuildOsCommonVariant}}
-	ctx.AddFarVariationDependencies(variation, deviceHostConverterDepTag, d.properties.Libs...)
+	ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(),
+		deviceHostConverterDepTag, d.properties.Libs...)
 }
 
 func (d *DeviceHostConverter) GenerateAndroidBuildActions(ctx android.ModuleContext) {
diff --git a/java/device_host_converter_test.go b/java/device_host_converter_test.go
index 44aae9b..3c9a0f3 100644
--- a/java/device_host_converter_test.go
+++ b/java/device_host_converter_test.go
@@ -60,7 +60,7 @@
 	deviceImportModule := ctx.ModuleForTests("device_import_module", "android_common")
 	deviceImportCombined := deviceImportModule.Output("combined/device_import_module.jar")
 
-	hostModule := ctx.ModuleForTests("host_module", config.BuildOsCommonVariant)
+	hostModule := ctx.ModuleForTests("host_module", config.BuildOSCommonTarget.String())
 	hostJavac := hostModule.Output("javac/host_module.jar")
 	hostRes := hostModule.Output("res/host_module.jar")
 	combined := hostModule.Output("combined/host_module.jar")
@@ -133,11 +133,11 @@
 
 	ctx, config := testJava(t, bp)
 
-	hostModule := ctx.ModuleForTests("host_module", config.BuildOsCommonVariant)
+	hostModule := ctx.ModuleForTests("host_module", config.BuildOSCommonTarget.String())
 	hostJavac := hostModule.Output("javac/host_module.jar")
 	hostRes := hostModule.Output("res/host_module.jar")
 
-	hostImportModule := ctx.ModuleForTests("host_import_module", config.BuildOsCommonVariant)
+	hostImportModule := ctx.ModuleForTests("host_import_module", config.BuildOSCommonTarget.String())
 	hostImportCombined := hostImportModule.Output("combined/host_import_module.jar")
 
 	deviceModule := ctx.ModuleForTests("device_module", "android_common")
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 2df2852..12335ff 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -67,9 +67,15 @@
 	// If set to false, don't allow this module(-docs.zip) to be exported. Defaults to true.
 	Installable *bool
 
-	// if not blank, set to the version of the sdk to compile against
+	// if not blank, set to the version of the sdk to compile against.
+	// Defaults to compiling against the current platform.
 	Sdk_version *string `android:"arch_variant"`
 
+	// When targeting 1.9 and above, override the modules to use with --system,
+	// otherwise provides defaults libraries to add to the bootclasspath.
+	// Defaults to "none"
+	System_modules *string
+
 	Aidl struct {
 		// Top level directories to pass to aidl tool
 		Include_dirs []string
@@ -401,6 +407,10 @@
 	return proptools.StringDefault(j.properties.Sdk_version, defaultSdkVersion(j))
 }
 
+func (j *Javadoc) systemModules() string {
+	return proptools.String(j.properties.System_modules)
+}
+
 func (j *Javadoc) minSdkVersion() string {
 	return j.sdkVersion()
 }
@@ -427,6 +437,10 @@
 				}
 				ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.modules...)
 			}
+		} else if sdkDep.systemModules != "" {
+			// Add the system modules to both the system modules and bootclasspath.
+			ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
+			ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.systemModules)
 		}
 	}
 
@@ -514,6 +528,10 @@
 		case bootClasspathTag:
 			if dep, ok := module.(Dependency); ok {
 				deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars()...)
+			} else if sm, ok := module.(*SystemModules); ok {
+				// A system modules dependency has been added to the bootclasspath
+				// so add its libs to the bootclasspath.
+				deps.bootClasspath = append(deps.bootClasspath, sm.headerJars...)
 			} else {
 				panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
 			}
@@ -1175,6 +1193,9 @@
 
 	jdiffDocZip      android.WritablePath
 	jdiffStubsSrcJar android.WritablePath
+
+	metadataZip android.WritablePath
+	metadataDir android.WritablePath
 }
 
 // droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
@@ -1286,7 +1307,8 @@
 	}
 
 	if Bool(d.properties.Write_sdk_values) {
-		cmd.FlagWithArg("--sdk-values ", android.PathForModuleOut(ctx, "out").String())
+		d.metadataDir = android.PathForModuleOut(ctx, "metadata")
+		cmd.FlagWithArg("--sdk-values ", d.metadataDir.String())
 	}
 
 	if Bool(d.properties.Create_doc_stubs) {
@@ -1493,6 +1515,18 @@
 		FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
 		FlagWithArg("-C ", stubsDir.String()).
 		FlagWithArg("-D ", stubsDir.String())
+
+	if Bool(d.properties.Write_sdk_values) {
+		d.metadataZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-metadata.zip")
+		rule.Command().
+			BuiltTool(ctx, "soong_zip").
+			Flag("-write_if_changed").
+			Flag("-d").
+			FlagWithOutput("-o ", d.metadataZip).
+			FlagWithArg("-C ", d.metadataDir.String()).
+			FlagWithArg("-D ", d.metadataDir.String())
+	}
+
 	rule.Restat()
 
 	zipSyncCleanupCmd(rule, srcJarDir)
@@ -1511,6 +1545,8 @@
 		cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList,
 			deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths)
 
+		cmd.Flag(d.Javadoc.args).Implicits(d.Javadoc.argFiles)
+
 		newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
 		if newSince.Valid() {
 			cmd.FlagWithInput("--api-lint ", newSince.Path())
diff --git a/java/java.go b/java/java.go
index 4264ba9..be48256 100644
--- a/java/java.go
+++ b/java/java.go
@@ -270,7 +270,8 @@
 		Proguard_flags_files []string `android:"path"`
 	}
 
-	// When targeting 1.9, override the modules to use with --system
+	// When targeting 1.9 and above, override the modules to use with --system,
+	// otherwise provides defaults libraries to add to the bootclasspath.
 	System_modules *string
 
 	UncompressDex bool `blueprint:"mutated"`
@@ -347,8 +348,8 @@
 	// list of SDK lib names that this java moudule is exporting
 	exportedSdkLibs []string
 
-	// list of source files, collected from compiledJavaSrcs and compiledSrcJars
-	// filter out Exclude_srcs, will be used by android.IDEInfo struct
+	// list of source files, collected from srcFiles with uniqie java and all kt files,
+	// will be used by android.IDEInfo struct
 	expandIDEInfoCompiledSrcs []string
 
 	// expanded Jarjar_rules
@@ -457,7 +458,10 @@
 type sdkDep struct {
 	useModule, useFiles, useDefaultLibs, invalidVersion bool
 
-	modules       []string
+	modules []string
+
+	// The default system modules to use. Will be an empty string if no system
+	// modules are to be used.
 	systemModules string
 
 	frameworkResModule string
@@ -496,6 +500,10 @@
 	return proptools.StringDefault(j.deviceProperties.Sdk_version, defaultSdkVersion(j))
 }
 
+func (j *Module) systemModules() string {
+	return proptools.String(j.deviceProperties.System_modules)
+}
+
 func (j *Module) minSdkVersion() string {
 	if j.deviceProperties.Min_sdk_version != nil {
 		return *j.deviceProperties.Min_sdk_version
@@ -528,13 +536,10 @@
 					ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultLibraries...)
 				}
 			}
-		} else if j.deviceProperties.System_modules == nil {
-			ctx.PropertyErrorf("sdk_version",
-				`system_modules is required to be set when sdk_version is "none", did you mean "core_platform"`)
-		} else if *j.deviceProperties.System_modules != "none" {
+		} else if sdkDep.systemModules != "" {
 			// Add the system modules to both the system modules and bootclasspath.
-			ctx.AddVariationDependencies(nil, systemModulesTag, *j.deviceProperties.System_modules)
-			ctx.AddVariationDependencies(nil, bootClasspathTag, *j.deviceProperties.System_modules)
+			ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
+			ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.systemModules)
 		}
 		if ctx.ModuleName() == "android_stubs_current" ||
 			ctx.ModuleName() == "android_system_stubs_current" ||
@@ -546,9 +551,7 @@
 	ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
 	ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
 
-	ctx.AddFarVariationDependencies([]blueprint.Variation{
-		{Mutator: "arch", Variation: ctx.Config().BuildOsCommonVariant},
-	}, pluginTag, j.properties.Plugins...)
+	ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), pluginTag, j.properties.Plugins...)
 
 	android.ProtoDeps(ctx, &j.protoProperties)
 	if j.hasSrcExt(".proto") {
@@ -1032,9 +1035,6 @@
 		srcJars = append(srcJars, aaptSrcJar)
 	}
 
-	// Collect source files and filter out Exclude_srcs that IDEInfo struct will use
-	j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, srcFiles.Strings()...)
-
 	if j.properties.Jarjar_rules != nil {
 		j.expandJarjarRules = android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
 	}
@@ -1051,6 +1051,9 @@
 		}
 	}
 
+	// Collect .java files for AIDEGen
+	j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, uniqueSrcFiles.Strings()...)
+
 	var kotlinJars android.Paths
 
 	if srcFiles.HasExt(".kt") {
@@ -1075,6 +1078,9 @@
 		kotlinSrcFiles = append(kotlinSrcFiles, uniqueSrcFiles...)
 		kotlinSrcFiles = append(kotlinSrcFiles, srcFiles.FilterByExt(".kt")...)
 
+		// Collect .kt files for AIDEGen
+		j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, srcFiles.FilterByExt(".kt").Strings()...)
+
 		flags.classpath = append(flags.classpath, deps.kotlinStdlib...)
 		flags.classpath = append(flags.classpath, deps.kotlinAnnotations...)
 
@@ -1559,12 +1565,20 @@
 	return len(srcFiles) > 0 || len(ctx.GetDirectDepsWithTag(staticLibTag)) > 0
 }
 
+func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+	depTag := ctx.OtherModuleDependencyTag(dep)
+	// dependencies other than the static linkage are all considered crossing APEX boundary
+	return depTag == staticLibTag
+}
+
 //
 // Java libraries (.jar file)
 //
 
 type Library struct {
 	Module
+
+	InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths)
 }
 
 func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bool {
@@ -1595,8 +1609,12 @@
 
 	exclusivelyForApex := android.InAnyApex(ctx.ModuleName()) && !j.IsForPlatform()
 	if (Bool(j.properties.Installable) || ctx.Host()) && !exclusivelyForApex {
+		var extraInstallDeps android.Paths
+		if j.InstallMixin != nil {
+			extraInstallDeps = j.InstallMixin(ctx, j.outputFile)
+		}
 		j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
-			ctx.ModuleName()+".jar", j.outputFile)
+			ctx.ModuleName()+".jar", j.outputFile, extraInstallDeps...)
 	}
 }
 
diff --git a/java/java_test.go b/java/java_test.go
index f0cb6f8..a3499cc 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1095,8 +1095,10 @@
 	`
 
 	t.Run("Java language level 8", func(t *testing.T) {
-		// Test default javac -source 1.8 -target 1.8
-		ctx, _ := testJava(t, bp)
+		// Test with legacy javac -source 1.8 -target 1.8
+		config := testConfig(map[string]string{"EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9": "false"})
+		ctx := testContext(bp, nil)
+		run(t, ctx, config)
 
 		checkPatchModuleFlag(t, ctx, "foo", "")
 		checkPatchModuleFlag(t, ctx, "bar", "")
@@ -1104,10 +1106,8 @@
 	})
 
 	t.Run("Java language level 9", func(t *testing.T) {
-		// Test again with javac -source 9 -target 9
-		config := testConfig(map[string]string{"EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9": "true"})
-		ctx := testContext(bp, nil)
-		run(t, ctx, config)
+		// Test with default javac -source 9 -target 9
+		ctx, _ := testJava(t, bp)
 
 		checkPatchModuleFlag(t, ctx, "foo", "")
 		expected := "java.base=.:" + buildDir
diff --git a/java/sdk.go b/java/sdk.go
index 3451774..c6a9a73 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -39,6 +39,8 @@
 type sdkContext interface {
 	// sdkVersion returns the sdk_version property of the current module, or an empty string if it is not set.
 	sdkVersion() string
+	// systemModules returns the system_modules property of the current module, or an empty string if it is not set.
+	systemModules() string
 	// minSdkVersion returns the min_sdk_version property of the current module, or sdkVersion() if it is not set.
 	minSdkVersion() string
 	// targetSdkVersion returns the target_sdk_version property of the current module, or sdkVersion() if it is not set.
@@ -185,8 +187,18 @@
 			frameworkResModule: "framework-res",
 		}
 	case "none":
+		systemModules := sdkContext.systemModules()
+		if systemModules == "" {
+			ctx.PropertyErrorf("sdk_version",
+				`system_modules is required to be set to a non-empty value when sdk_version is "none", did you mean sdk_version: "core_platform"?`)
+		} else if systemModules == "none" {
+			// Normalize no system modules to an empty string.
+			systemModules = ""
+		}
+
 		return sdkDep{
 			noStandardLibs: true,
+			systemModules:  systemModules,
 		}
 	case "core_platform":
 		return sdkDep{
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 5001b47..5e0e592 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -279,9 +279,9 @@
 				}
 			}
 
+			// Test with legacy javac -source 1.8 -target 1.8
 			t.Run("Java language level 8", func(t *testing.T) {
-				// Test default javac -source 1.8 -target 1.8
-				config := testConfig(nil)
+				config := testConfig(map[string]string{"EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9": "false"})
 				if testcase.unbundled {
 					config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
 				}
@@ -302,9 +302,9 @@
 				}
 			})
 
-			// Test again with javac -source 9 -target 9
+			// Test with default javac -source 9 -target 9
 			t.Run("Java language level 9", func(t *testing.T) {
-				config := testConfig(map[string]string{"EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9": "true"})
+				config := testConfig(nil)
 				if testcase.unbundled {
 					config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
 				}
@@ -327,7 +327,8 @@
 
 			// Test again with PLATFORM_VERSION_CODENAME=REL
 			t.Run("REL", func(t *testing.T) {
-				config := testConfig(nil)
+				// TODO(b/115604102): This test should be rewritten with language level 9
+				config := testConfig(map[string]string{"EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9": "false"})
 				config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("REL")
 				config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(true)
 
diff --git a/java/tradefed.go b/java/tradefed.go
new file mode 100644
index 0000000..ebbdec1
--- /dev/null
+++ b/java/tradefed.go
@@ -0,0 +1,37 @@
+// Copyright 2019 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 java
+
+import (
+	"android/soong/android"
+)
+
+func init() {
+	android.RegisterModuleType("tradefed_java_library_host", tradefedJavaLibraryFactory)
+}
+
+// tradefed_java_library_factory wraps java_library and installs an additional
+// copy of the output jar to $HOST_OUT/tradefed.
+func tradefedJavaLibraryFactory() android.Module {
+	module := LibraryHostFactory().(*Library)
+	module.InstallMixin = tradefedJavaLibraryInstall
+	return module
+}
+
+func tradefedJavaLibraryInstall(ctx android.ModuleContext, path android.Path) android.Paths {
+	installedPath := ctx.InstallFile(android.PathForModuleInstall(ctx, "tradefed"),
+		ctx.ModuleName()+".jar", path)
+	return android.Paths{installedPath}
+}
diff --git a/python/python.go b/python/python.go
index ad08909..1b606cb 100644
--- a/python/python.go
+++ b/python/python.go
@@ -306,22 +306,17 @@
 			if p.bootstrapper.autorun() {
 				launcherModule = "py2-launcher-autorun"
 			}
-			ctx.AddFarVariationDependencies([]blueprint.Variation{
-				{Mutator: "arch", Variation: ctx.Target().String()},
-			}, launcherTag, launcherModule)
+			ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherTag, launcherModule)
 
 			// Add py2-launcher shared lib dependencies. Ideally, these should be
 			// derived from the `shared_libs` property of "py2-launcher". However, we
 			// cannot read the property at this stage and it will be too late to add
 			// dependencies later.
-			ctx.AddFarVariationDependencies([]blueprint.Variation{
-				{Mutator: "arch", Variation: ctx.Target().String()},
-			}, launcherSharedLibTag, "libsqlite")
+			ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherSharedLibTag, "libsqlite")
 
 			if ctx.Target().Os.Bionic() {
-				ctx.AddFarVariationDependencies([]blueprint.Variation{
-					{Mutator: "arch", Variation: ctx.Target().String()},
-				}, launcherSharedLibTag, "libc", "libdl", "libm")
+				ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherSharedLibTag,
+					"libc", "libdl", "libm")
 			}
 		}
 
diff --git a/rust/config/x86_darwin_host.go b/rust/config/x86_darwin_host.go
new file mode 100644
index 0000000..7cfc59c
--- /dev/null
+++ b/rust/config/x86_darwin_host.go
@@ -0,0 +1,81 @@
+// Copyright 2019 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 config
+
+import (
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	DarwinRustFlags      = []string{}
+	DarwinRustLinkFlags  = []string{}
+	darwinX8664Rustflags = []string{}
+	darwinX8664Linkflags = []string{}
+)
+
+func init() {
+	registerToolchainFactory(android.Darwin, android.X86_64, darwinX8664ToolchainFactory)
+	pctx.StaticVariable("DarwinToolchainRustFlags", strings.Join(DarwinRustFlags, " "))
+	pctx.StaticVariable("DarwinToolchainLinkFlags", strings.Join(DarwinRustLinkFlags, " "))
+	pctx.StaticVariable("DarwinToolchainX8664RustFlags", strings.Join(darwinX8664Rustflags, " "))
+	pctx.StaticVariable("DarwinToolchainX8664LinkFlags", strings.Join(darwinX8664Linkflags, " "))
+
+}
+
+type toolchainDarwin struct {
+	toolchainRustFlags string
+	toolchainLinkFlags string
+}
+
+type toolchainDarwinX8664 struct {
+	toolchain64Bit
+	toolchainDarwin
+}
+
+func (toolchainDarwinX8664) Supported() bool {
+	return true
+}
+
+func (toolchainDarwinX8664) Bionic() bool {
+	return false
+}
+
+func (t *toolchainDarwinX8664) Name() string {
+	return "x86_64"
+}
+
+func (t *toolchainDarwinX8664) RustTriple() string {
+	return "x86_64-apple-darwin"
+}
+
+func (t *toolchainDarwin) ShlibSuffix() string {
+	return ".dylib"
+}
+
+func (t *toolchainDarwinX8664) ToolchainLinkFlags() string {
+	return "${config.DarwinToolchainLinkFlags} ${config.DarwinToolchainX8664LinkFlags}"
+}
+
+func (t *toolchainDarwinX8664) ToolchainRustFlags() string {
+	return "${config.DarwinToolchainRustFlags} ${config.DarwinToolchainX8664RustFlags}"
+}
+
+func darwinX8664ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainDarwinX8664Singleton
+}
+
+var toolchainDarwinX8664Singleton Toolchain = &toolchainDarwinX8664{}
diff --git a/rust/rust.go b/rust/rust.go
index 61b51e5..707de4b 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -164,15 +164,11 @@
 	android.AddLoadHook(mod, func(ctx android.LoadHookContext) {
 		disableTargets := struct {
 			Target struct {
-				Darwin struct {
-					Enabled *bool
-				}
 				Linux_bionic struct {
 					Enabled *bool
 				}
 			}
 		}{}
-		disableTargets.Target.Darwin.Enabled = proptools.BoolPtr(false)
 		disableTargets.Target.Linux_bionic.Enabled = proptools.BoolPtr(false)
 
 		ctx.AppendProperties(&disableTargets)
@@ -496,7 +492,7 @@
 	}
 
 	// proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.
-	actx.AddFarVariationDependencies([]blueprint.Variation{{Mutator: "arch", Variation: ctx.Config().BuildOsVariant}}, procMacroDepTag, deps.ProcMacros...)
+	actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), procMacroDepTag, deps.ProcMacros...)
 }
 
 func (mod *Module) Name() string {
diff --git a/scripts/strip.sh b/scripts/strip.sh
index f987d98..40f0184 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -67,9 +67,9 @@
 do_strip_keep_symbol_list() {
     echo "${symbols_to_keep}" | tr ',' '\n' > "${outfile}.symbolList"
 
-    KEEP_SYMBOLS="--strip-unneeded-symbol=.* --keep-symbols="
+    KEEP_SYMBOLS="--strip-unneeded-symbol=* --keep-symbols="
     KEEP_SYMBOLS+="${outfile}.symbolList"
-    "${CLANG_BIN}/llvm-objcopy" --regex "${infile}" "${outfile}.tmp" ${KEEP_SYMBOLS}
+    "${CROSS_COMPILE}objcopy" -w "${infile}" "${outfile}.tmp" ${KEEP_SYMBOLS}
 }
 
 do_strip_keep_mini_debug_info() {
diff --git a/sdk/sdk.go b/sdk/sdk.go
index fcb3fb7..d189043 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -15,6 +15,9 @@
 package sdk
 
 import (
+	"fmt"
+	"strconv"
+
 	"github.com/google/blueprint"
 
 	"android/soong/android"
@@ -25,6 +28,7 @@
 
 func init() {
 	android.RegisterModuleType("sdk", ModuleFactory)
+	android.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
 	android.PreDepsMutators(RegisterPreDepsMutators)
 	android.PostDepsMutators(RegisterPostDepsMutators)
 }
@@ -34,12 +38,18 @@
 	android.DefaultableModuleBase
 
 	properties sdkProperties
+
+	updateScript android.OutputPath
+	freezeScript android.OutputPath
 }
 
 type sdkProperties struct {
-	// The list of java_import modules that provide Java stubs for this SDK
-	Java_libs          []string
+	// The list of java libraries in this SDK
+	Java_libs []string
+	// The list of native libraries in this SDK
 	Native_shared_libs []string
+
+	Snapshot bool `blueprint:"mutated"`
 }
 
 // sdk defines an SDK which is a logical group of modules (e.g. native libs, headers, java libs, etc.)
@@ -52,8 +62,44 @@
 	return s
 }
 
+// sdk_snapshot is a versioned snapshot of an SDK. This is an auto-generated module.
+func SnapshotModuleFactory() android.Module {
+	s := ModuleFactory()
+	s.(*sdk).properties.Snapshot = true
+	return s
+}
+
+func (s *sdk) snapshot() bool {
+	return s.properties.Snapshot
+}
+
+func (s *sdk) frozenVersions(ctx android.BaseModuleContext) []string {
+	if s.snapshot() {
+		panic(fmt.Errorf("frozenVersions() called for sdk_snapshot %q", ctx.ModuleName()))
+	}
+	versions := []string{}
+	ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
+		depTag := ctx.OtherModuleDependencyTag(child)
+		if depTag == sdkMemberDepTag {
+			return true
+		}
+		if versionedDepTag, ok := depTag.(sdkMemberVesionedDepTag); ok {
+			v := versionedDepTag.version
+			if v != "current" && !android.InList(v, versions) {
+				versions = append(versions, versionedDepTag.version)
+			}
+		}
+		return false
+	})
+	return android.SortedUniqueStrings(versions)
+}
+
 func (s *sdk) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	// TODO(jiyong): add build rules for creating stubs from members of this SDK
+	s.buildSnapshotGenerationScripts(ctx)
+}
+
+func (s *sdk) AndroidMkEntries() android.AndroidMkEntries {
+	return s.androidMkEntriesForScript()
 }
 
 // RegisterPreDepsMutators registers pre-deps mutators to support modules implementing SdkAware
@@ -76,6 +122,7 @@
 	// should have been mutated for the apex before the SDK requirements are set.
 	ctx.TopDown("SdkDepsMutator", sdkDepsMutator).Parallel()
 	ctx.BottomUp("SdkDepsReplaceMutator", sdkDepsReplaceMutator).Parallel()
+	ctx.TopDown("SdkRequirementCheck", sdkRequirementsMutator).Parallel()
 }
 
 type dependencyTag struct {
@@ -101,19 +148,31 @@
 
 		targets := mctx.MultiTargets()
 		for _, target := range targets {
-			mctx.AddFarVariationDependencies([]blueprint.Variation{
-				{Mutator: "arch", Variation: target.String()},
+			mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
 				{Mutator: "image", Variation: "core"},
 				{Mutator: "link", Variation: "shared"},
-			}, sdkMemberDepTag, m.properties.Native_shared_libs...)
+			}...), sdkMemberDepTag, m.properties.Native_shared_libs...)
 		}
 	}
 }
 
 // Step 2: record that dependencies of SDK modules are members of the SDK modules
 func memberDepsMutator(mctx android.TopDownMutatorContext) {
-	if _, ok := mctx.Module().(*sdk); ok {
+	if s, ok := mctx.Module().(*sdk); ok {
 		mySdkRef := android.ParseSdkRef(mctx, mctx.ModuleName(), "name")
+		if s.snapshot() && mySdkRef.Unversioned() {
+			mctx.PropertyErrorf("name", "sdk_snapshot should be named as <name>@<version>. "+
+				"Did you manually modify Android.bp?")
+		}
+		if !s.snapshot() && !mySdkRef.Unversioned() {
+			mctx.PropertyErrorf("name", "sdk shouldn't be named as <name>@<version>.")
+		}
+		if mySdkRef.Version != "" && mySdkRef.Version != "current" {
+			if _, err := strconv.Atoi(mySdkRef.Version); err != nil {
+				mctx.PropertyErrorf("name", "version %q is neither a number nor \"current\"", mySdkRef.Version)
+			}
+		}
+
 		mctx.VisitDirectDeps(func(child android.Module) {
 			if member, ok := child.(android.SdkAware); ok {
 				member.MakeMemberOf(mySdkRef)
@@ -122,7 +181,7 @@
 	}
 }
 
-// Step 3: create dependencies from the in-development version of an SDK member to frozen versions
+// Step 3: create dependencies from the unversioned SDK member to snapshot versions
 // of the same member. By having these dependencies, they are mutated for multiple Mainline modules
 // (apex and apk), each of which might want different sdks to be built with. For example, if both
 // apex A and B are referencing libfoo which is a member of sdk 'mysdk', the two APEXes can be
@@ -130,7 +189,7 @@
 // using.
 func memberInterVersionMutator(mctx android.BottomUpMutatorContext) {
 	if m, ok := mctx.Module().(android.SdkAware); ok && m.IsInAnySdk() {
-		if !m.ContainingSdk().IsCurrentVersion() {
+		if !m.ContainingSdk().Unversioned() {
 			memberName := m.MemberName()
 			tag := sdkMemberVesionedDepTag{member: memberName, version: m.ContainingSdk().Version}
 			mctx.AddReverseDependency(mctx.Module(), tag, memberName)
@@ -159,7 +218,7 @@
 // versioned module is used instead of the un-versioned (in-development) module libfoo
 func sdkDepsReplaceMutator(mctx android.BottomUpMutatorContext) {
 	if m, ok := mctx.Module().(android.SdkAware); ok && m.IsInAnySdk() {
-		if sdk := m.ContainingSdk(); !sdk.IsCurrentVersion() {
+		if sdk := m.ContainingSdk(); !sdk.Unversioned() {
 			if m.RequiredSdks().Contains(sdk) {
 				// Note that this replacement is done only for the modules that have the same
 				// variations as the current module. Since current module is already mutated for
@@ -170,3 +229,31 @@
 		}
 	}
 }
+
+// Step 6: ensure that the dependencies from outside of the APEX are all from the required SDKs
+func sdkRequirementsMutator(mctx android.TopDownMutatorContext) {
+	if m, ok := mctx.Module().(interface {
+		DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool
+		RequiredSdks() android.SdkRefs
+	}); ok {
+		requiredSdks := m.RequiredSdks()
+		if len(requiredSdks) == 0 {
+			return
+		}
+		mctx.VisitDirectDeps(func(dep android.Module) {
+			if mctx.OtherModuleDependencyTag(dep) == android.DefaultsDepTag {
+				// dependency to defaults is always okay
+				return
+			}
+
+			// If the dep is from outside of the APEX, but is not in any of the
+			// required SDKs, we know that the dep is a violation.
+			if sa, ok := dep.(android.SdkAware); ok {
+				if !m.DepIsInSameApex(mctx, dep) && !requiredSdks.Contains(sa.ContainingSdk()) {
+					mctx.ModuleErrorf("depends on %q (in SDK %q) that isn't part of the required SDKs: %v",
+						sa.Name(), sa.ContainingSdk(), requiredSdks)
+				}
+			}
+		})
+	}
+}
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 9eca72f..664bb7c 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -69,6 +69,7 @@
 
 	// from this package
 	ctx.RegisterModuleType("sdk", android.ModuleFactoryAdaptor(ModuleFactory))
+	ctx.RegisterModuleType("sdk_snapshot", android.ModuleFactoryAdaptor(SnapshotModuleFactory))
 	ctx.PreDepsMutators(RegisterPreDepsMutators)
 	ctx.PostDepsMutators(RegisterPostDepsMutators)
 
@@ -114,6 +115,23 @@
 	return ctx, config
 }
 
+func testSdkError(t *testing.T, pattern, bp string) {
+	t.Helper()
+	ctx, config := testSdkContext(t, bp)
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	if len(errs) > 0 {
+		android.FailIfNoMatchingErrors(t, pattern, errs)
+		return
+	}
+	_, errs = ctx.PrepareBuildActions(config)
+	if len(errs) > 0 {
+		android.FailIfNoMatchingErrors(t, pattern, errs)
+		return
+	}
+
+	t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
+}
+
 // ensure that 'result' contains 'expected'
 func ensureContains(t *testing.T, result string, expected string) {
 	t.Helper()
@@ -155,12 +173,17 @@
 func TestBasicSdkWithJava(t *testing.T) {
 	ctx, _ := testSdk(t, `
 		sdk {
-			name: "mysdk#1",
+			name: "mysdk",
+			java_libs: ["sdkmember"],
+		}
+
+		sdk_snapshot {
+			name: "mysdk@1",
 			java_libs: ["sdkmember_mysdk_1"],
 		}
 
-		sdk {
-			name: "mysdk#2",
+		sdk_snapshot {
+			name: "mysdk@2",
 			java_libs: ["sdkmember_mysdk_2"],
 		}
 
@@ -195,7 +218,7 @@
 		apex {
 			name: "myapex",
 			java_libs: ["myjavalib"],
-			uses_sdks: ["mysdk#1"],
+			uses_sdks: ["mysdk@1"],
 			key: "myapex.key",
 			certificate: ":myapex.cert",
 		}
@@ -203,7 +226,7 @@
 		apex {
 			name: "myapex2",
 			java_libs: ["myjavalib"],
-			uses_sdks: ["mysdk#2"],
+			uses_sdks: ["mysdk@2"],
 			key: "myapex.key",
 			certificate: ":myapex.cert",
 		}
@@ -223,12 +246,17 @@
 func TestBasicSdkWithCc(t *testing.T) {
 	ctx, _ := testSdk(t, `
 		sdk {
-			name: "mysdk#1",
+			name: "mysdk",
+			native_shared_libs: ["sdkmember"],
+		}
+
+		sdk_snapshot {
+			name: "mysdk@1",
 			native_shared_libs: ["sdkmember_mysdk_1"],
 		}
 
-		sdk {
-			name: "mysdk#2",
+		sdk_snapshot {
+			name: "mysdk@2",
 			native_shared_libs: ["sdkmember_mysdk_2"],
 		}
 
@@ -267,7 +295,7 @@
 		apex {
 			name: "myapex",
 			native_shared_libs: ["mycpplib"],
-			uses_sdks: ["mysdk#1"],
+			uses_sdks: ["mysdk@1"],
 			key: "myapex.key",
 			certificate: ":myapex.cert",
 		}
@@ -275,7 +303,7 @@
 		apex {
 			name: "myapex2",
 			native_shared_libs: ["mycpplib"],
-			uses_sdks: ["mysdk#2"],
+			uses_sdks: ["mysdk@2"],
 			key: "myapex.key",
 			certificate: ":myapex.cert",
 		}
@@ -292,6 +320,63 @@
 	ensureListContains(t, pathsToStrings(cpplibForMyApex2.Rule("ld").Implicits), sdkMemberV2.String())
 }
 
+func TestDepNotInRequiredSdks(t *testing.T) {
+	testSdkError(t, `module "myjavalib".*depends on "otherlib".*that isn't part of the required SDKs:.*`, `
+		sdk {
+			name: "mysdk",
+			java_libs: ["sdkmember"],
+		}
+
+		sdk_snapshot {
+			name: "mysdk@1",
+			java_libs: ["sdkmember_mysdk_1"],
+		}
+
+		java_import {
+			name: "sdkmember",
+			prefer: false,
+			host_supported: true,
+		}
+
+		java_import {
+			name: "sdkmember_mysdk_1",
+			sdk_member_name: "sdkmember",
+			host_supported: true,
+		}
+
+		java_library {
+			name: "myjavalib",
+			srcs: ["Test.java"],
+			libs: [
+				"sdkmember",
+				"otherlib",
+			],
+			system_modules: "none",
+			sdk_version: "none",
+			compile_dex: true,
+			host_supported: true,
+		}
+
+		// this lib is no in mysdk
+		java_library {
+			name: "otherlib",
+			srcs: ["Test.java"],
+			system_modules: "none",
+			sdk_version: "none",
+			compile_dex: true,
+			host_supported: true,
+		}
+
+		apex {
+			name: "myapex",
+			java_libs: ["myjavalib"],
+			uses_sdks: ["mysdk@1"],
+			key: "myapex.key",
+			certificate: ":myapex.cert",
+		}
+	`)
+}
+
 var buildDir string
 
 func setUp() {
diff --git a/sdk/update.go b/sdk/update.go
new file mode 100644
index 0000000..5235c9e
--- /dev/null
+++ b/sdk/update.go
@@ -0,0 +1,228 @@
+// Copyright (C) 2019 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 sdk
+
+import (
+	"fmt"
+	"io"
+	"path/filepath"
+	"strconv"
+	"strings"
+
+	"github.com/google/blueprint/proptools"
+
+	"android/soong/android"
+	"android/soong/java"
+)
+
+var pctx = android.NewPackageContext("android/soong/sdk")
+
+// generatedFile abstracts operations for writing contents into a file and emit a build rule
+// for the file.
+type generatedFile struct {
+	path    android.OutputPath
+	content strings.Builder
+}
+
+func newGeneratedFile(ctx android.ModuleContext, name string) *generatedFile {
+	return &generatedFile{
+		path: android.PathForModuleOut(ctx, name).OutputPath,
+	}
+}
+
+func (gf *generatedFile) printfln(format string, args ...interface{}) {
+	// ninja consumes newline characters in rspfile_content. Prevent it by
+	// escaping the backslash in the newline character. The extra backshash
+	// is removed when the rspfile is written to the actual script file
+	fmt.Fprintf(&(gf.content), format+"\\n", args...)
+}
+
+func (gf *generatedFile) build(pctx android.PackageContext, ctx android.BuilderContext, implicits android.Paths) {
+	rb := android.NewRuleBuilder()
+	// convert \\n to \n
+	rb.Command().
+		Implicits(implicits).
+		Text("echo").Text(proptools.ShellEscape(gf.content.String())).
+		Text("| sed 's/\\\\n/\\n/g' >").Output(gf.path)
+	rb.Command().
+		Text("chmod a+x").Output(gf.path)
+	rb.Build(pctx, ctx, gf.path.Base(), "Build "+gf.path.Base())
+}
+
+func (s *sdk) javaMemberNames(ctx android.ModuleContext) []string {
+	result := []string{}
+	ctx.VisitDirectDeps(func(m android.Module) {
+		if _, ok := m.(*java.Library); ok {
+			result = append(result, m.Name())
+		}
+	})
+	return result
+}
+
+// buildAndroidBp creates the blueprint file that defines prebuilt modules for each of
+// the SDK members, and the sdk_snapshot module for the specified version
+func (s *sdk) buildAndroidBp(ctx android.ModuleContext, version string) android.OutputPath {
+	bp := newGeneratedFile(ctx, "blueprint-"+version+".sh")
+
+	makePrebuiltName := func(name string) string {
+		return ctx.ModuleName() + "_" + name + string(android.SdkVersionSeparator) + version
+	}
+
+	javaLibs := s.javaMemberNames(ctx)
+	for _, name := range javaLibs {
+		prebuiltName := makePrebuiltName(name)
+		jar := filepath.Join("java", name, "stub.jar")
+
+		bp.printfln("java_import {")
+		bp.printfln("    name: %q,", prebuiltName)
+		bp.printfln("    jars: [%q],", jar)
+		bp.printfln("    sdk_member_name: %q,", name)
+		bp.printfln("}")
+		bp.printfln("")
+
+		// This module is for the case when the source tree for the unversioned module
+		// doesn't exist (i.e. building in an unbundled tree). "prefer:" is set to false
+		// so that this module does not eclipse the unversioned module if it exists.
+		bp.printfln("java_import {")
+		bp.printfln("    name: %q,", name)
+		bp.printfln("    jars: [%q],", jar)
+		bp.printfln("    prefer: false,")
+		bp.printfln("}")
+		bp.printfln("")
+
+	}
+
+	// TODO(jiyong): emit cc_prebuilt_library_shared for the native libs
+
+	bp.printfln("sdk_snapshot {")
+	bp.printfln("    name: %q,", ctx.ModuleName()+string(android.SdkVersionSeparator)+version)
+	bp.printfln("    java_libs: [")
+	for _, n := range javaLibs {
+		bp.printfln("        %q,", makePrebuiltName(n))
+	}
+	bp.printfln("    ],")
+	// TODO(jiyong): emit native_shared_libs
+	bp.printfln("}")
+	bp.printfln("")
+
+	bp.build(pctx, ctx, nil)
+	return bp.path
+}
+
+func (s *sdk) buildScript(ctx android.ModuleContext, version string) android.OutputPath {
+	sh := newGeneratedFile(ctx, "update_prebuilt-"+version+".sh")
+
+	snapshotRoot := filepath.Join(ctx.ModuleDir(), version)
+	aidlIncludeDir := filepath.Join(snapshotRoot, "aidl")
+	javaStubsDir := filepath.Join(snapshotRoot, "java")
+
+	sh.printfln("#!/bin/bash")
+	sh.printfln("echo Updating snapshot of %s in %s", ctx.ModuleName(), snapshotRoot)
+	sh.printfln("pushd $ANDROID_BUILD_TOP > /dev/null")
+	sh.printfln("rm -rf %s", snapshotRoot)
+	sh.printfln("mkdir -p %s", aidlIncludeDir)
+	sh.printfln("mkdir -p %s", javaStubsDir)
+	// TODO(jiyong): mkdir the 'native' dir
+
+	var implicits android.Paths
+	ctx.VisitDirectDeps(func(m android.Module) {
+		if javaLib, ok := m.(*java.Library); ok {
+			headerJars := javaLib.HeaderJars()
+			if len(headerJars) != 1 {
+				panic(fmt.Errorf("there must be only one header jar from %q", m.Name()))
+			}
+			implicits = append(implicits, headerJars...)
+
+			exportedAidlIncludeDirs := javaLib.AidlIncludeDirs()
+			for _, dir := range exportedAidlIncludeDirs {
+				// Using tar to copy with the directory structure
+				// TODO(jiyong): copy parcelable declarations only
+				sh.printfln("find %s -name \"*.aidl\" | tar cf - -T - | (cd %s; tar xf -)",
+					dir.String(), aidlIncludeDir)
+			}
+
+			copiedHeaderJar := filepath.Join(javaStubsDir, m.Name(), "stub.jar")
+			sh.printfln("mkdir -p $(dirname %s) && cp %s %s",
+				copiedHeaderJar, headerJars[0].String(), copiedHeaderJar)
+		}
+		// TODO(jiyong): emit the commands for copying the headers and stub libraries for native libs
+	})
+
+	bp := s.buildAndroidBp(ctx, version)
+	implicits = append(implicits, bp)
+	sh.printfln("cp %s %s", bp.String(), filepath.Join(snapshotRoot, "Android.bp"))
+
+	sh.printfln("popd > /dev/null")
+	sh.printfln("rm -- \"$0\"") // self deleting so that stale script is not used
+	sh.printfln("echo Done")
+
+	sh.build(pctx, ctx, implicits)
+	return sh.path
+}
+
+func (s *sdk) buildSnapshotGenerationScripts(ctx android.ModuleContext) {
+	if s.snapshot() {
+		// we don't need a script for sdk_snapshot.. as they are frozen
+		return
+	}
+
+	// script to update the 'current' snapshot
+	s.updateScript = s.buildScript(ctx, "current")
+
+	versions := s.frozenVersions(ctx)
+	newVersion := "1"
+	if len(versions) >= 1 {
+		lastVersion := versions[len(versions)-1]
+		lastVersionNum, err := strconv.Atoi(lastVersion)
+		if err != nil {
+			panic(err)
+			return
+		}
+		newVersion = strconv.Itoa(lastVersionNum + 1)
+	}
+	// script to create a new frozen version of snapshot
+	s.freezeScript = s.buildScript(ctx, newVersion)
+}
+
+func (s *sdk) androidMkEntriesForScript() android.AndroidMkEntries {
+	if s.snapshot() {
+		// we don't need a script for sdk_snapshot.. as they are frozen
+		return android.AndroidMkEntries{}
+	}
+
+	entries := android.AndroidMkEntries{
+		Class: "FAKE",
+		// TODO(jiyong): remove this? but androidmk.go expects OutputFile to be specified anyway
+		OutputFile: android.OptionalPathForPath(s.updateScript),
+		Include:    "$(BUILD_SYSTEM)/base_rules.mk",
+		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+			func(entries *android.AndroidMkEntries) {
+				entries.AddStrings("LOCAL_ADDITIONAL_DEPENDENCIES",
+					s.updateScript.String(), s.freezeScript.String())
+			},
+		},
+		ExtraFooters: []android.AndroidMkExtraFootersFunc{
+			func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
+				fmt.Fprintln(w, "$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)")
+				fmt.Fprintln(w, "	touch $@")
+				fmt.Fprintln(w, "	echo ##################################################")
+				fmt.Fprintln(w, "	echo To update current SDK: execute", s.updateScript.String())
+				fmt.Fprintln(w, "	echo To freeze current SDK: execute", s.freezeScript.String())
+				fmt.Fprintln(w, "	echo ##################################################")
+			},
+		},
+	}
+	return entries
+}
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 8581387..4270bb1 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -222,6 +222,7 @@
 		"DEFAULT_WARNING_BUILD_MODULE_TYPES",
 		"DEFAULT_ERROR_BUILD_MODULE_TYPES",
 		"BUILD_BROKEN_PREBUILT_ELF_FILES",
+		"BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW",
 		"BUILD_BROKEN_USES_BUILD_AUX_EXECUTABLE",
 		"BUILD_BROKEN_USES_BUILD_AUX_STATIC_LIBRARY",
 		"BUILD_BROKEN_USES_BUILD_COPY_HEADERS",