Merge "Split out osMutator from archMutator"
diff --git a/Android.bp b/Android.bp
index 1dfac87..dd53818 100644
--- a/Android.bp
+++ b/Android.bp
@@ -491,6 +491,7 @@
     ],
     srcs: [
         "sdk/sdk.go",
+        "sdk/update.go",
     ],
     testSrcs: [
         "sdk/sdk_test.go",
diff --git a/android/apex.go b/android/apex.go
index 557febf..d3c0710 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -19,7 +19,6 @@
 	"sync"
 
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/proptools"
 )
 
 // ApexModule is the interface that a module type is expected to implement if
@@ -76,18 +75,11 @@
 	// CreateApexVariations.
 	setApexName(apexName string)
 
-	// Return the no_apex property
-	NoApex() bool
-
 	// Tests if this module is available for the specified APEX or ":platform"
 	AvailableFor(what string) bool
 }
 
 type ApexProperties struct {
-	// Whether this module should not be part of any APEX. Default is false.
-	// TODO(b/128708192): remove this as this is equal to apex_available: [":platform"]
-	No_apex *bool
-
 	// Availability of this module in APEXes. Only the listed APEXes can include this module.
 	// "//apex_available:anyapex" is a pseudo APEX name that matches to any APEX.
 	// "//apex_available:platform" refers to non-APEX partitions like "system.img".
@@ -143,23 +135,23 @@
 	return false
 }
 
-func (m *ApexModuleBase) NoApex() bool {
-	return proptools.Bool(m.ApexProperties.No_apex)
-}
-
 const (
 	availableToPlatform = "//apex_available:platform"
 	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) checkApexAvailableProperty(mctx BaseModuleContext) {
@@ -167,7 +159,7 @@
 		if n == availableToPlatform || n == availableToAnyApex {
 			continue
 		}
-		if !mctx.OtherModuleExists(n) {
+		if !mctx.OtherModuleExists(n) && !mctx.Config().AllowMissingDependencies() {
 			mctx.PropertyErrorf("apex_available", "%q is not a valid module name", n)
 		}
 	}
@@ -178,7 +170,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/config.go b/android/config.go
index 57737f1..e208dcd 100644
--- a/android/config.go
+++ b/android/config.go
@@ -391,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/sdk.go b/android/sdk.go
index 52c392f..616fbe1 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -39,25 +39,17 @@
 	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()
-}
+// 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
+// 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 +57,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 +67,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 +98,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 +113,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/apex/apex.go b/apex/apex.go
index b02346a..8a29ef0 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -149,15 +149,6 @@
 	androidAppTag  = dependencyTag{name: "androidApp"}
 )
 
-var (
-	whitelistNoApex = map[string][]string{
-		"apex_test_build_features":       []string{"libbinder"},
-		"com.android.media.swcodec":      []string{"libbinder"},
-		"test_com.android.media.swcodec": []string{"libbinder"},
-		"com.android.vndk":               []string{"libbinder"},
-	}
-)
-
 func init() {
 	pctx.Import("android/soong/android")
 	pctx.Import("android/soong/java")
@@ -196,6 +187,12 @@
 		ctx.BottomUp("apex_vndk_add_deps", apexVndkAddDepsMutator).Parallel()
 	})
 	android.PostDepsMutators(RegisterPostDepsMutators)
+
+	android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
+		apexFileContextsInfos := apexFileContextsInfos(ctx.Config())
+		sort.Strings(*apexFileContextsInfos)
+		ctx.Strict("APEX_FILE_CONTEXTS_INFOS", strings.Join(*apexFileContextsInfos, " "))
+	})
 }
 
 func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
@@ -282,14 +279,40 @@
 func apexMutator(mctx android.BottomUpMutatorContext) {
 	if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
 		am.CreateApexVariations(mctx)
-	} else if _, ok := mctx.Module().(*apexBundle); ok {
+	} else if a, ok := mctx.Module().(*apexBundle); ok {
 		// apex bundle itself is mutated so that it and its modules have same
 		// apex variant.
 		apexBundleName := mctx.ModuleName()
 		mctx.CreateVariations(apexBundleName)
+
+		// collects APEX list
+		if mctx.Device() && a.installable() {
+			addApexFileContextsInfos(mctx, a)
+		}
 	}
 }
 
+var (
+	apexFileContextsInfosKey   = android.NewOnceKey("apexFileContextsInfosKey")
+	apexFileContextsInfosMutex sync.Mutex
+)
+
+func apexFileContextsInfos(config android.Config) *[]string {
+	return config.Once(apexFileContextsInfosKey, func() interface{} {
+		return &[]string{}
+	}).(*[]string)
+}
+
+func addApexFileContextsInfos(ctx android.BaseModuleContext, a *apexBundle) {
+	apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
+	fileContextsName := proptools.StringDefault(a.properties.File_contexts, ctx.ModuleName())
+
+	apexFileContextsInfosMutex.Lock()
+	defer apexFileContextsInfosMutex.Unlock()
+	apexFileContextsInfos := apexFileContextsInfos(ctx.Config())
+	*apexFileContextsInfos = append(*apexFileContextsInfos, apexName+":"+fileContextsName)
+}
+
 func apexFlattenedMutator(mctx android.BottomUpMutatorContext) {
 	if ab, ok := mctx.Module().(*apexBundle); ok {
 		if !mctx.Config().FlattenApex() || mctx.Config().UnbundledBuild() {
@@ -535,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))
 	}
@@ -1159,10 +1189,6 @@
 					}
 				} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
 					ctx.ModuleErrorf("unexpected tag %q for indirect dependency %q", depTag, depName)
-				} else if depTag == android.DefaultsDepTag {
-					return false
-				} else if am.NoApex() && !android.InList(depName, whitelistNoApex[ctx.ModuleName()]) {
-					ctx.ModuleErrorf("tries to include no_apex module %s", depName)
 				}
 			}
 		}
@@ -1194,22 +1220,14 @@
 		return filesInfo[i].builtFile.String() < filesInfo[j].builtFile.String()
 	})
 
-	// check no_apex modules
-	whitelist := whitelistNoApex[ctx.ModuleName()]
-	for i := range filesInfo {
-		if am, ok := filesInfo[i].module.(android.ApexModule); ok {
-			if am.NoApex() && !android.InList(filesInfo[i].moduleName, whitelist) {
-				ctx.ModuleErrorf("tries to include no_apex module %s", filesInfo[i].moduleName)
-			}
-		}
-	}
-
 	// check apex_available requirements
-	for _, fi := range filesInfo {
-		if am, ok := fi.module.(android.ApexModule); ok {
-			if !am.AvailableFor(ctx.ModuleName()) {
-				ctx.ModuleErrorf("requires %q that is not available for the APEX", fi.module.Name())
-				return
+	if !ctx.Host() {
+		for _, fi := range filesInfo {
+			if am, ok := fi.module.(android.ApexModule); ok {
+				if !am.AvailableFor(ctx.ModuleName()) {
+					ctx.ModuleErrorf("requires %q that is not available for the APEX", fi.module.Name())
+					return
+				}
 			}
 		}
 	}
@@ -1254,7 +1272,8 @@
 	// instead of `android.PathForOutput`) to return the correct path to the flattened
 	// APEX (as its contents is installed by Make, not Soong).
 	factx := flattenedApexContext{ctx}
-	a.flattenedOutput = android.PathForModuleInstall(&factx, "apex", factx.ModuleName())
+	apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
+	a.flattenedOutput = android.PathForModuleInstall(&factx, "apex", apexName)
 
 	if a.apexTypes.zip() {
 		a.buildUnflattenedApex(ctx, zipApex)
@@ -1554,8 +1573,9 @@
 		a.filesInfo = append(a.filesInfo, apexFile{copiedPubkey, ctx.ModuleName() + ".apex_pubkey", ".", etc, nil, nil})
 
 		if ctx.Config().FlattenApex() {
+			apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
 			for _, fi := range a.filesInfo {
-				dir := filepath.Join("apex", ctx.ModuleName(), fi.installDir)
+				dir := filepath.Join("apex", apexName, fi.installDir)
 				target := ctx.InstallFile(android.PathForModuleInstall(ctx, dir), fi.builtFile.Base(), fi.builtFile)
 				for _, sym := range fi.symlinks {
 					ctx.InstallSymlink(android.PathForModuleInstall(ctx, dir), sym, target)
@@ -1586,7 +1606,7 @@
 		}}
 }
 
-func (a *apexBundle) androidMkForFiles(w io.Writer, name, moduleDir string, apexType apexPackaging) []string {
+func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string, apexType apexPackaging) []string {
 	moduleNames := []string{}
 
 	for _, fi := range a.filesInfo {
@@ -1610,12 +1630,11 @@
 		fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
 		fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName+suffix)
 		// /apex/<apex_name>/{lib|framework|...}
-		pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex",
-			proptools.StringDefault(a.properties.Apex_name, name), fi.installDir)
+		pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex", apexName, fi.installDir)
 		if a.properties.Flattened && apexType.image() {
 			// /system/apex/<name>/{lib|framework|...}
 			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join(a.installDir.ToMakePath().String(),
-				name, fi.installDir))
+				apexName, fi.installDir))
 			if !a.isFlattenedVariant() {
 				fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated)
 			}
@@ -1695,7 +1714,8 @@
 		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
 			moduleNames := []string{}
 			if a.installable() {
-				moduleNames = a.androidMkForFiles(w, name, moduleDir, apexType)
+				apexName := proptools.StringDefault(a.properties.Apex_name, name)
+				moduleNames = a.androidMkForFiles(w, apexName, moduleDir, apexType)
 			}
 
 			if a.isFlattenedVariant() {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index ddf0459..d1cd969 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -102,9 +102,6 @@
 	ctx.RegisterModuleType("apex_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
 	ctx.RegisterModuleType("prebuilt_apex", android.ModuleFactoryAdaptor(PrebuiltFactory))
 
-	ctx.RegisterModuleType("cc_defaults", android.ModuleFactoryAdaptor(func() android.Module {
-		return cc.DefaultsFactory()
-	}))
 	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
 	ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(cc.LibrarySharedFactory))
 	ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(cc.LibraryHeaderFactory))
@@ -2183,200 +2180,6 @@
 	`)
 }
 
-func TestApexUsesFailsIfUseNoApex(t *testing.T) {
-	// 'no_apex' prevents a module to be included in an apex
-	testApexError(t, `tries to include no_apex module mylib2`, `
-		apex {
-			name: "commonapex",
-			key: "myapex.key",
-			native_shared_libs: ["mylib"],
-		}
-
-		apex_key {
-			name: "myapex.key",
-			public_key: "testkey.avbpubkey",
-			private_key: "testkey.pem",
-		}
-
-		cc_library {
-			name: "mylib",
-			srcs: ["mylib.cpp"],
-			shared_libs: ["mylib2"],
-			system_shared_libs: [],
-			stl: "none",
-		}
-
-		cc_library {
-			name: "mylib2",
-			srcs: ["mylib.cpp"],
-			system_shared_libs: [],
-			stl: "none",
-			no_apex: true,
-		}
-	`)
-
-	// respect 'no_apex' even with static link
-	testApexError(t, `tries to include no_apex module mylib2`, `
-		apex {
-			name: "commonapex",
-			key: "myapex.key",
-			native_shared_libs: ["mylib"],
-		}
-
-		apex_key {
-			name: "myapex.key",
-			public_key: "testkey.avbpubkey",
-			private_key: "testkey.pem",
-		}
-
-		cc_library {
-			name: "mylib",
-			srcs: ["mylib.cpp"],
-			static_libs: ["mylib2"],
-			system_shared_libs: [],
-			stl: "none",
-		}
-
-		cc_library {
-			name: "mylib2",
-			srcs: ["mylib.cpp"],
-			system_shared_libs: [],
-			stl: "none",
-			no_apex: true,
-		}
-	`)
-
-	// 'no_apex' can be applied via defaults
-	testApexError(t, `tries to include no_apex module mylib2`, `
-		apex {
-			name: "commonapex",
-			key: "myapex.key",
-			native_shared_libs: ["mylib"],
-		}
-
-		apex_key {
-			name: "myapex.key",
-			public_key: "testkey.avbpubkey",
-			private_key: "testkey.pem",
-		}
-
-		cc_library {
-			name: "mylib",
-			srcs: ["mylib.cpp"],
-			static_libs: ["mylib2"],
-			system_shared_libs: [],
-			stl: "none",
-		}
-
-		cc_defaults {
-			name: "mylib2_defaults",
-			system_shared_libs: [],
-			stl: "none",
-			no_apex: true,
-		}
-
-		cc_library {
-			name: "mylib2",
-			srcs: ["mylib.cpp"],
-			defaults: ["mylib2_defaults"],
-		}
-	`)
-}
-
-func TestNoApexWorksWithWhitelist(t *testing.T) {
-
-	testApex(t, `
-		apex {
-			name: "myapex",
-			key: "myapex.key",
-			native_shared_libs: ["mylib"],
-		}
-
-		apex_key {
-			name: "myapex.key",
-			public_key: "testkey.avbpubkey",
-			private_key: "testkey.pem",
-		}
-
-		cc_library {
-			name: "mylib",
-			srcs: ["mylib.cpp"],
-			shared_libs: ["mylib2"],
-			system_shared_libs: [],
-			stl: "none",
-		}
-
-		cc_defaults {
-			name: "mylib2_defaults",
-			system_shared_libs: [],
-			stl: "none",
-			no_apex: true,
-		}
-
-		cc_library {
-			name: "mylib2",
-			srcs: ["mylib.cpp"],
-			defaults: ["mylib2_defaults"],
-		}
-	`, func(fs map[string][]byte, config android.Config) {
-		whitelistNoApex = map[string][]string{
-			"myapex": []string{"mylib2"},
-		}
-	})
-}
-
-func TestNoApexCanBeDependedOnViaStubs(t *testing.T) {
-	ctx, _ := testApex(t, `
-		apex {
-			name: "myapex",
-			key: "myapex.key",
-			native_shared_libs: ["mylib"],
-		}
-
-		apex_key {
-			name: "myapex.key",
-			public_key: "testkey.avbpubkey",
-			private_key: "testkey.pem",
-		}
-
-		cc_library {
-			name: "mylib",
-			srcs: ["mylib.cpp"],
-			shared_libs: ["mylib2"],
-			system_shared_libs: [],
-			stl: "none",
-		}
-
-		cc_library {
-			name: "mylib2",
-			srcs: ["mylib.cpp"],
-			shared_libs: ["mylib3"],
-			system_shared_libs: [],
-			stl: "none",
-			stubs: {
-				versions: ["1", "2", "3"],
-			},
-		}
-
-		// this won't be included in "myapex", so 'no_apex' is still valid in this case.
-		cc_library {
-			name: "mylib3",
-			srcs: ["mylib.cpp"],
-			system_shared_libs: [],
-			stl: "none",
-			no_apex: true,
-		}
-	`)
-
-	module := ctx.ModuleForTests("myapex", "android_common_myapex")
-	apexRule := module.Rule("apexRule")
-	copyCmds := apexRule.Args["copy_commands"]
-
-	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
-	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
-	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib3.so")
-}
-
 func TestErrorsIfDepsAreNotEnabled(t *testing.T) {
 	testApexError(t, `module "myapex" .* depends on disabled module "libfoo"`, `
 		apex {
@@ -2604,6 +2407,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/cc.go b/cc/cc.go
index 5c0aeb2..d609b94 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -552,8 +552,10 @@
 		}
 	})
 	android.InitAndroidArchModule(c, c.hod, c.multilib)
-	android.InitApexModule(c)
+
 	android.InitDefaultableModule(c)
+
+	android.InitApexModule(c)
 	android.InitSdkAwareModule(c)
 
 	return c
@@ -2149,6 +2151,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()
 }
@@ -2228,8 +2240,8 @@
 		&android.ProtoProperties{},
 	)
 
-	android.InitApexModule(module)
 	android.InitDefaultsModule(module)
+	android.InitApexModule(module)
 
 	return module
 }
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/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..e65e8de 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -148,10 +148,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 +215,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/sanitize.go b/cc/sanitize.go
index f568d5a..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)
 		}
 
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 40644a3..511b840 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -581,7 +581,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 aca5e63..bf692fe 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -122,13 +122,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"},
 			},
 		},
 	}
@@ -148,7 +147,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/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 bc61297..955f22b 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,
 		}
@@ -598,6 +598,18 @@
 						fmt.Fprintln(w, "droidcore: checkapi")
 					}
 				}
+				if dstubs.apiLintTimestamp != nil {
+					fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-api-lint")
+					fmt.Fprintln(w, dstubs.Name()+"-api-lint:",
+						dstubs.apiLintTimestamp.String())
+
+					fmt.Fprintln(w, ".PHONY: checkapi")
+					fmt.Fprintln(w, "checkapi:",
+						dstubs.apiLintTimestamp.String())
+
+					fmt.Fprintln(w, ".PHONY: droidcore")
+					fmt.Fprintln(w, "droidcore: checkapi")
+				}
 				if dstubs.checkNullabilityWarningsTimestamp != nil {
 					fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-check-nullability-warnings")
 					fmt.Fprintln(w, dstubs.Name()+"-check-nullability-warnings:",
diff --git a/java/config/config.go b/java/config/config.go
index ce62b93..f418ee7 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -86,6 +86,14 @@
 		// This is set up and guaranteed by soong_ui
 		return ctx.Config().Getenv("ANDROID_JAVA_HOME")
 	})
+	pctx.VariableFunc("JlinkVersion", func(ctx android.PackageVarContext) string {
+		switch ctx.Config().Getenv("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN") {
+		case "true":
+			return "11"
+		default:
+			return "9"
+		}
+	})
 
 	pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin")
 	pctx.SourcePathVariableWithEnvOverride("JavacCmd",
diff --git a/java/config/makevars.go b/java/config/makevars.go
index c40f4fc..2fa6f89 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -38,6 +38,7 @@
 	ctx.Strict("ANDROID_JAVA_HOME", "${JavaHome}")
 	ctx.Strict("ANDROID_JAVA8_HOME", "prebuilts/jdk/jdk8/${hostPrebuiltTag}")
 	ctx.Strict("ANDROID_JAVA9_HOME", "prebuilts/jdk/jdk9/${hostPrebuiltTag}")
+	ctx.Strict("ANDROID_JAVA11_HOME", "prebuilts/jdk/jdk11/${hostPrebuiltTag}")
 	ctx.Strict("ANDROID_JAVA_TOOLCHAIN", "${JavaToolchain}")
 	ctx.Strict("JAVA", "${JavaCmd} ${JavaVmFlags}")
 	ctx.Strict("JAVAC", "${JavacCmd} ${JavacVmFlags}")
diff --git a/java/droiddoc.go b/java/droiddoc.go
index aab61c5..3b581cb 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
@@ -238,6 +244,16 @@
 		// do not perform API check against Last_released, in the case that both two specified API
 		// files by Last_released are modules which don't exist.
 		Ignore_missing_latest_api *bool `blueprint:"mutated"`
+
+		Api_lint struct {
+			Enabled *bool
+
+			// If set, performs api_lint on any new APIs not found in the given signature file
+			New_since *string `android:"path"`
+
+			// If not blank, path to the baseline txt file for approved API lint violations.
+			Baseline_file *string `android:"path"`
+		}
 	}
 
 	// user can specify the version of previous released API file in order to do compatibility check.
@@ -391,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()
 }
@@ -417,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)
 		}
 	}
 
@@ -504,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()))
 			}
@@ -1154,6 +1182,7 @@
 	checkCurrentApiTimestamp      android.WritablePath
 	updateCurrentApiTimestamp     android.WritablePath
 	checkLastReleasedApiTimestamp android.WritablePath
+	apiLintTimestamp              android.WritablePath
 
 	checkNullabilityWarningsTimestamp android.WritablePath
 
@@ -1490,6 +1519,57 @@
 
 	// Create rule for apicheck
 
+	if BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) && !ctx.Config().IsPdkBuild() {
+		rule := android.NewRuleBuilder()
+		rule.Command().Text("( true")
+
+		srcJarDir := android.PathForModuleOut(ctx, "api_lint", "srcjars")
+		srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
+
+		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())
+		} else {
+			cmd.Flag("--api-lint")
+		}
+
+		d.inclusionAnnotationsFlags(ctx, cmd)
+		d.mergeAnnoDirFlags(ctx, cmd)
+
+		baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
+		updatedBaselineOutput := android.PathForModuleOut(ctx, "api_lint_baseline.txt")
+		d.apiLintTimestamp = android.PathForModuleOut(ctx, "api_lint.timestamp")
+
+		if baselineFile.Valid() {
+			cmd.FlagWithInput("--baseline ", baselineFile.Path())
+			cmd.FlagWithOutput("--update-baseline ", updatedBaselineOutput)
+		}
+
+		zipSyncCleanupCmd(rule, srcJarDir)
+
+		msg := fmt.Sprintf(`\n******************************\n`+
+			`Your API changes are triggering API Lint warnings or errors.\n\n`+
+			`To make these errors go away, you have two choices:\n`+
+			`   1. You can suppress the errors with @SuppressLint(\"<id>\").\n\n`+
+			`   2. You can update the baseline by executing the following command:\n`+
+			`         cp \"$PWD/%s\" \"$PWD/%s\"\n\n`+
+			`******************************\n`, updatedBaselineOutput, baselineFile.Path())
+		rule.Command().
+			Text("touch").Output(d.apiLintTimestamp).
+			Text(") || (").
+			Text("echo").Flag("-e").Flag(`"` + msg + `"`).
+			Text("; exit 38").
+			Text(")")
+
+		rule.Build(pctx, ctx, "metalavaApiLint", "metalava API lint")
+
+	}
+
 	if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") &&
 		!ctx.Config().IsPdkBuild() {
 
diff --git a/java/java.go b/java/java.go
index 47fb1a7..3b95f1e 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" ||
@@ -1030,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)
 	}
@@ -1049,6 +1051,9 @@
 		}
 	}
 
+	// Collect .java files for AIDEGen
+	j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, uniqueSrcFiles.Strings()...)
+
 	var kotlinJars android.Paths
 
 	if srcFiles.HasExt(".kt") {
@@ -1073,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...)
 
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/system_modules.go b/java/system_modules.go
index 43e4e11..b56a401 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -36,13 +36,15 @@
 var (
 	jarsTosystemModules = pctx.AndroidStaticRule("jarsTosystemModules", blueprint.RuleParams{
 		Command: `rm -rf ${outDir} ${workDir} && mkdir -p ${workDir}/jmod && ` +
-			`${moduleInfoJavaPath} ${moduleName} $in > ${workDir}/module-info.java && ` +
+			`${moduleInfoJavaPath} java.base $in > ${workDir}/module-info.java && ` +
 			`${config.JavacCmd} --system=none --patch-module=java.base=${classpath} ${workDir}/module-info.java && ` +
 			`${config.SoongZipCmd} -jar -o ${workDir}/classes.jar -C ${workDir} -f ${workDir}/module-info.class && ` +
 			`${config.MergeZipsCmd} -j ${workDir}/module.jar ${workDir}/classes.jar $in && ` +
-			`${config.JmodCmd} create --module-version 9 --target-platform android ` +
-			`  --class-path ${workDir}/module.jar ${workDir}/jmod/${moduleName}.jmod && ` +
-			`${config.JlinkCmd} --module-path ${workDir}/jmod --add-modules ${moduleName} --output ${outDir} ` +
+			// Note: The version of the java.base module created must match the version
+			// of the jlink tool which consumes it.
+			`${config.JmodCmd} create --module-version ${config.JlinkVersion} --target-platform android ` +
+			`  --class-path ${workDir}/module.jar ${workDir}/jmod/java.base.jmod && ` +
+			`${config.JlinkCmd} --module-path ${workDir}/jmod --add-modules java.base --output ${outDir} ` +
 			// Note: The system-modules jlink plugin is disabled because (a) it is not
 			// useful on Android, and (b) it causes errors with later versions of jlink
 			// when the jdk.internal.module is absent from java.base (as it is here).
@@ -58,10 +60,10 @@
 			"${config.JrtFsJar}",
 		},
 	},
-		"moduleName", "classpath", "outDir", "workDir")
+		"classpath", "outDir", "workDir")
 )
 
-func TransformJarsToSystemModules(ctx android.ModuleContext, moduleName string, jars android.Paths) (android.Path, android.Paths) {
+func TransformJarsToSystemModules(ctx android.ModuleContext, jars android.Paths) (android.Path, android.Paths) {
 	outDir := android.PathForModuleOut(ctx, "system")
 	workDir := android.PathForModuleOut(ctx, "modules")
 	outputFile := android.PathForModuleOut(ctx, "system/lib/modules")
@@ -77,10 +79,9 @@
 		Outputs:     outputs,
 		Inputs:      jars,
 		Args: map[string]string{
-			"moduleName": moduleName,
-			"classpath":  strings.Join(jars.Strings(), ":"),
-			"workDir":    workDir.String(),
-			"outDir":     outDir.String(),
+			"classpath": strings.Join(jars.Strings(), ":"),
+			"workDir":   workDir.String(),
+			"outDir":    outDir.String(),
 		},
 	})
 
@@ -123,7 +124,7 @@
 
 	system.headerJars = jars
 
-	system.outputDir, system.outputDeps = TransformJarsToSystemModules(ctx, "java.base", jars)
+	system.outputDir, system.outputDeps = TransformJarsToSystemModules(ctx, jars)
 }
 
 func (system *SystemModules) DepsMutator(ctx android.BottomUpMutatorContext) {
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 3736103..e4d520b 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
@@ -111,8 +157,21 @@
 
 // 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)
@@ -121,7 +180,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
@@ -129,7 +188,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)
@@ -158,7 +217,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
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 9eca72f..942556a 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)
 
@@ -155,12 +156,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 +201,7 @@
 		apex {
 			name: "myapex",
 			java_libs: ["myjavalib"],
-			uses_sdks: ["mysdk#1"],
+			uses_sdks: ["mysdk@1"],
 			key: "myapex.key",
 			certificate: ":myapex.cert",
 		}
@@ -203,7 +209,7 @@
 		apex {
 			name: "myapex2",
 			java_libs: ["myjavalib"],
-			uses_sdks: ["mysdk#2"],
+			uses_sdks: ["mysdk@2"],
 			key: "myapex.key",
 			certificate: ":myapex.cert",
 		}
@@ -223,12 +229,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 +278,7 @@
 		apex {
 			name: "myapex",
 			native_shared_libs: ["mycpplib"],
-			uses_sdks: ["mysdk#1"],
+			uses_sdks: ["mysdk@1"],
 			key: "myapex.key",
 			certificate: ":myapex.cert",
 		}
@@ -275,7 +286,7 @@
 		apex {
 			name: "myapex2",
 			native_shared_libs: ["mycpplib"],
-			uses_sdks: ["mysdk#2"],
+			uses_sdks: ["mysdk@2"],
 			key: "myapex.key",
 			certificate: ":myapex.cert",
 		}
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/cleanbuild.go b/ui/build/cleanbuild.go
index 0a2b510..1dbeb26 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -107,6 +107,8 @@
 		productOut("obj/NOTICE_FILES"),
 		productOut("obj/PACKAGING"),
 		productOut("ramdisk"),
+		productOut("debug_ramdisk"),
+		productOut("test_harness_ramdisk"),
 		productOut("recovery"),
 		productOut("root"),
 		productOut("system"),
diff --git a/ui/build/config.go b/ui/build/config.go
index def3345..919b9ce 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -214,10 +214,14 @@
 	// Configure Java-related variables, including adding it to $PATH
 	java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
 	java9Home := filepath.Join("prebuilts/jdk/jdk9", ret.HostPrebuiltTag())
+	java11Home := filepath.Join("prebuilts/jdk/jdk11", ret.HostPrebuiltTag())
 	javaHome := func() string {
 		if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
 			return override
 		}
+		if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 == "true" {
+			return java11Home
+		}
 		return java9Home
 	}()
 	absJavaHome := absPath(ctx, javaHome)
@@ -228,11 +232,13 @@
 	if path, ok := ret.environ.Get("PATH"); ok && path != "" {
 		newPath = append(newPath, path)
 	}
+
 	ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME")
 	ret.environ.Set("JAVA_HOME", absJavaHome)
 	ret.environ.Set("ANDROID_JAVA_HOME", javaHome)
 	ret.environ.Set("ANDROID_JAVA8_HOME", java8Home)
 	ret.environ.Set("ANDROID_JAVA9_HOME", java9Home)
+	ret.environ.Set("ANDROID_JAVA11_HOME", java11Home)
 	ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
 
 	outDir := ret.OutDir()
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 1925e87..4270bb1 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -42,6 +42,7 @@
 	soongUiVars := map[string]func() string{
 		"OUT_DIR":  func() string { return config.OutDir() },
 		"DIST_DIR": func() string { return config.DistDir() },
+		"TMPDIR":   func() string { return absPath(ctx, config.TempDir()) },
 	}
 
 	makeVars := make([]string, 0, len(vars))
@@ -221,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",
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index e44600e..1af816b 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -122,6 +122,9 @@
 	"pgrep": LinuxOnlyPrebuilt,
 	"pkill": LinuxOnlyPrebuilt,
 	"ps":    LinuxOnlyPrebuilt,
+
+	// The toybox xargs is currently breaking the mac build.
+	"xargs": LinuxOnlyPrebuilt,
 }
 
 func init() {