Merge "Migrate java/androidmk.go to new system #1"
diff --git a/Android.bp b/Android.bp
index 537b58b..afbae17 100644
--- a/Android.bp
+++ b/Android.bp
@@ -67,6 +67,7 @@
         "android/proto.go",
         "android/register.go",
         "android/rule_builder.go",
+        "android/sdk.go",
         "android/sh_binary.go",
         "android/singleton.go",
         "android/testing.go",
@@ -208,7 +209,6 @@
         "cc/prebuilt_test.go",
         "cc/proto_test.go",
         "cc/test_data_test.go",
-        "cc/util_test.go",
     ],
     pluginFor: ["soong_build"],
 }
@@ -333,8 +333,11 @@
         "soong-cc-config",
     ],
     srcs: [
+        "rust/config/arm_device.go",
+        "rust/config/arm64_device.go",
         "rust/config/global.go",
         "rust/config/toolchain.go",
+        "rust/config/whitelist.go",
         "rust/config/x86_linux_host.go",
         "rust/config/x86_64_device.go",
     ],
@@ -475,6 +478,26 @@
     pluginFor: ["soong_build"],
 }
 
+bootstrap_go_package {
+    name: "soong-sdk",
+    pkgPath: "android/soong/sdk",
+    deps: [
+        "blueprint",
+        "soong",
+        "soong-android",
+        "soong-apex",
+        "soong-cc",
+        "soong-java",
+    ],
+    srcs: [
+        "sdk/sdk.go",
+    ],
+    testSrcs: [
+        "sdk/sdk_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
+
 //
 // Defaults to enable various configurations of host bionic
 //
diff --git a/OWNERS b/OWNERS
index 4ae045d..797229f 100644
--- a/OWNERS
+++ b/OWNERS
@@ -4,3 +4,4 @@
 per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
 per-file tidy.go = srhines@google.com, chh@google.com
 per-file lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
+per-file rust/config/whitelist.go = chh@google.com, ivanlozano@google.com, jeffv@google.com, jgalenson@google.com, srhines@google.com
diff --git a/android/hooks.go b/android/hooks.go
index 5810996..64ffd52 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -30,7 +30,7 @@
 	BaseModuleContext
 	AppendProperties(...interface{})
 	PrependProperties(...interface{})
-	CreateModule(blueprint.ModuleFactory, ...interface{})
+	CreateModule(ModuleFactory, ...interface{})
 }
 
 // Arch hooks are run after the module has been split into architecture variants, and can be used
diff --git a/android/module.go b/android/module.go
index dda526f..8076a99 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1495,6 +1495,11 @@
 	m.commonProperties.Native_bridge_supported = boolPtr(true)
 }
 
+// IsNativeBridgeSupported returns true if "native_bridge_supported" is explicitly set as "true"
+func (m *ModuleBase) IsNativeBridgeSupported() bool {
+	return proptools.Bool(m.commonProperties.Native_bridge_supported)
+}
+
 func (m *moduleContext) InstallInData() bool {
 	return m.module.InstallInData()
 }
diff --git a/android/mutator.go b/android/mutator.go
index e76f847..7b7859c 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -121,7 +121,7 @@
 
 	Rename(name string)
 
-	CreateModule(blueprint.ModuleFactory, ...interface{})
+	CreateModule(ModuleFactory, ...interface{})
 }
 
 type topDownMutatorContext struct {
@@ -243,9 +243,9 @@
 	t.Module().base().commonProperties.DebugName = name
 }
 
-func (t *topDownMutatorContext) CreateModule(factory blueprint.ModuleFactory, props ...interface{}) {
+func (t *topDownMutatorContext) CreateModule(factory ModuleFactory, props ...interface{}) {
 	inherited := []interface{}{&t.Module().base().commonProperties, &t.Module().base().variableProperties}
-	t.bp.CreateModule(factory, append(inherited, props...)...)
+	t.bp.CreateModule(ModuleFactoryAdaptor(factory), append(inherited, props...)...)
 }
 
 func (b *bottomUpMutatorContext) MutatorName() string {
diff --git a/android/sdk.go b/android/sdk.go
new file mode 100644
index 0000000..52c392f
--- /dev/null
+++ b/android/sdk.go
@@ -0,0 +1,146 @@
+// 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 android
+
+import (
+	"strings"
+
+	"github.com/google/blueprint/proptools"
+)
+
+// SdkAware is the interface that must be supported by any module to become a member of SDK or to be
+// built with SDK
+type SdkAware interface {
+	Module
+	sdkBase() *SdkBase
+	MakeMemberOf(sdk SdkRef)
+	IsInAnySdk() bool
+	ContainingSdk() SdkRef
+	MemberName() string
+	BuildWithSdks(sdks SdkRefs)
+	RequiredSdks() SdkRefs
+}
+
+// SdkRef refers to a version of an SDK
+type SdkRef struct {
+	Name    string
+	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
+}
+
+// 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()
+}
+
+// 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, "#")
+	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"}
+	}
+
+	name := tokens[0]
+
+	version := currentVersion // If version is omitted, defaults to "current"
+	if len(tokens) == 2 {
+		version = tokens[1]
+	}
+
+	return SdkRef{Name: name, Version: version}
+}
+
+type SdkRefs []SdkRef
+
+func (refs SdkRefs) Contains(s SdkRef) bool {
+	for _, r := range refs {
+		if r == s {
+			return true
+		}
+	}
+	return false
+}
+
+type sdkProperties struct {
+	// The SDK that this module is a member of. nil if it is not a member of any SDK
+	ContainingSdk *SdkRef `blueprint:"mutated"`
+
+	// The list of SDK names and versions that are used to build this module
+	RequiredSdks SdkRefs `blueprint:"mutated"`
+
+	// Name of the module that this sdk member is representing
+	Sdk_member_name *string
+}
+
+// SdkBase is a struct that is expected to be included in module types to implement the SdkAware
+// interface. InitSdkAwareModule should be called to initialize this struct.
+type SdkBase struct {
+	properties sdkProperties
+}
+
+func (s *SdkBase) sdkBase() *SdkBase {
+	return s
+}
+
+// MakeMemberof sets this module to be a member of a specific SDK
+func (s *SdkBase) MakeMemberOf(sdk SdkRef) {
+	s.properties.ContainingSdk = &sdk
+}
+
+// IsInAnySdk returns true if this module is a member of any SDK
+func (s *SdkBase) IsInAnySdk() bool {
+	return s.properties.ContainingSdk != nil
+}
+
+// ContainingSdk returns the SDK that this module is a member of
+func (s *SdkBase) ContainingSdk() SdkRef {
+	if s.properties.ContainingSdk != nil {
+		return *s.properties.ContainingSdk
+	}
+	return SdkRef{Name: "", Version: currentVersion}
+}
+
+// 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)
+}
+
+// BuildWithSdks is used to mark that this module has to be built with the given SDK(s).
+func (s *SdkBase) BuildWithSdks(sdks SdkRefs) {
+	s.properties.RequiredSdks = sdks
+}
+
+// RequiredSdks returns the SDK(s) that this module has to be built with
+func (s *SdkBase) RequiredSdks() SdkRefs {
+	return s.properties.RequiredSdks
+}
+
+// InitSdkAwareModule initializes the SdkBase struct. This must be called by all modules including
+// SdkBase.
+func InitSdkAwareModule(m SdkAware) {
+	base := m.sdkBase()
+	m.AddProperties(&base.properties)
+}
diff --git a/android/util.go b/android/util.go
index e02cca1..0102442 100644
--- a/android/util.go
+++ b/android/util.go
@@ -16,6 +16,7 @@
 
 import (
 	"fmt"
+	"path/filepath"
 	"reflect"
 	"regexp"
 	"runtime"
@@ -292,3 +293,29 @@
 	}
 	return strings.HasPrefix(str, pat[:i]) && strings.HasSuffix(str, pat[i+1:])
 }
+
+var shlibVersionPattern = regexp.MustCompile("(?:\\.\\d+(?:svn)?)+")
+
+// splitFileExt splits a file name into root, suffix and ext. root stands for the file name without
+// the file extension and the version number (e.g. "libexample"). suffix stands for the
+// concatenation of the file extension and the version number (e.g. ".so.1.0"). ext stands for the
+// file extension after the version numbers are trimmed (e.g. ".so").
+func SplitFileExt(name string) (string, string, string) {
+	// Extract and trim the shared lib version number if the file name ends with dot digits.
+	suffix := ""
+	matches := shlibVersionPattern.FindAllStringIndex(name, -1)
+	if len(matches) > 0 {
+		lastMatch := matches[len(matches)-1]
+		if lastMatch[1] == len(name) {
+			suffix = name[lastMatch[0]:lastMatch[1]]
+			name = name[0:lastMatch[0]]
+		}
+	}
+
+	// Extract the file name root and the file extension.
+	ext := filepath.Ext(name)
+	root := strings.TrimSuffix(name, ext)
+	suffix = ext + suffix
+
+	return root, suffix, ext
+}
diff --git a/android/util_test.go b/android/util_test.go
index 2e5eb07..1df1c5a 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -404,3 +404,68 @@
 	// b = ["foo" "bar"]
 	// c = ["foo" "baz"]
 }
+
+func TestSplitFileExt(t *testing.T) {
+	t.Run("soname with version", func(t *testing.T) {
+		root, suffix, ext := SplitFileExt("libtest.so.1.0.30")
+		expected := "libtest"
+		if root != expected {
+			t.Errorf("root should be %q but got %q", expected, root)
+		}
+		expected = ".so.1.0.30"
+		if suffix != expected {
+			t.Errorf("suffix should be %q but got %q", expected, suffix)
+		}
+		expected = ".so"
+		if ext != expected {
+			t.Errorf("ext should be %q but got %q", expected, ext)
+		}
+	})
+
+	t.Run("soname with svn version", func(t *testing.T) {
+		root, suffix, ext := SplitFileExt("libtest.so.1svn")
+		expected := "libtest"
+		if root != expected {
+			t.Errorf("root should be %q but got %q", expected, root)
+		}
+		expected = ".so.1svn"
+		if suffix != expected {
+			t.Errorf("suffix should be %q but got %q", expected, suffix)
+		}
+		expected = ".so"
+		if ext != expected {
+			t.Errorf("ext should be %q but got %q", expected, ext)
+		}
+	})
+
+	t.Run("version numbers in the middle should be ignored", func(t *testing.T) {
+		root, suffix, ext := SplitFileExt("libtest.1.0.30.so")
+		expected := "libtest.1.0.30"
+		if root != expected {
+			t.Errorf("root should be %q but got %q", expected, root)
+		}
+		expected = ".so"
+		if suffix != expected {
+			t.Errorf("suffix should be %q but got %q", expected, suffix)
+		}
+		expected = ".so"
+		if ext != expected {
+			t.Errorf("ext should be %q but got %q", expected, ext)
+		}
+	})
+
+	t.Run("no known file extension", func(t *testing.T) {
+		root, suffix, ext := SplitFileExt("test.exe")
+		expected := "test"
+		if root != expected {
+			t.Errorf("root should be %q but got %q", expected, root)
+		}
+		expected = ".exe"
+		if suffix != expected {
+			t.Errorf("suffix should be %q but got %q", expected, suffix)
+		}
+		if ext != expected {
+			t.Errorf("ext should be %q but got %q", expected, ext)
+		}
+	})
+}
diff --git a/apex/apex.go b/apex/apex.go
index 1e99ff8..4e72d09 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -21,6 +21,7 @@
 	"runtime"
 	"sort"
 	"strings"
+	"sync"
 
 	"android/soong/android"
 	"android/soong/cc"
@@ -98,7 +99,8 @@
 		Command: `${zip2zip} -i $in -o $out ` +
 			`apex_payload.img:apex/${abi}.img ` +
 			`apex_manifest.json:root/apex_manifest.json ` +
-			`AndroidManifest.xml:manifest/AndroidManifest.xml`,
+			`AndroidManifest.xml:manifest/AndroidManifest.xml ` +
+			`assets/NOTICE.html.gz:assets/NOTICE.html.gz`,
 		CommandDeps: []string{"${zip2zip}"},
 		Description: "app bundle",
 	}, "abi")
@@ -148,10 +150,10 @@
 var (
 	whitelistNoApex = map[string][]string{
 		"apex_test_build_features":       []string{"libbinder"},
-		"com.android.neuralnetworks":     []string{"libbinder"},
 		"com.android.media":              []string{"libbinder"},
 		"com.android.media.swcodec":      []string{"libbinder"},
 		"test_com.android.media.swcodec": []string{"libbinder"},
+		"com.android.vndk":               []string{"libbinder"},
 	}
 )
 
@@ -182,16 +184,69 @@
 	pctx.HostBinToolVariable("zipalign", "zipalign")
 	pctx.HostBinToolVariable("jsonmodify", "jsonmodify")
 
-	android.RegisterModuleType("apex", apexBundleFactory)
+	android.RegisterModuleType("apex", BundleFactory)
 	android.RegisterModuleType("apex_test", testApexBundleFactory)
+	android.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
 	android.RegisterModuleType("apex_defaults", defaultsFactory)
 	android.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
 
-	android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
-		ctx.TopDown("apex_deps", apexDepsMutator)
-		ctx.BottomUp("apex", apexMutator).Parallel()
-		ctx.BottomUp("apex_uses", apexUsesMutator).Parallel()
+	android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.TopDown("apex_vndk_gather", apexVndkGatherMutator).Parallel()
+		ctx.BottomUp("apex_vndk_add_deps", apexVndkAddDepsMutator).Parallel()
 	})
+	android.PostDepsMutators(RegisterPostDepsMutators)
+}
+
+func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
+	ctx.TopDown("apex_deps", apexDepsMutator)
+	ctx.BottomUp("apex", apexMutator).Parallel()
+	ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
+	ctx.BottomUp("apex_uses", apexUsesMutator).Parallel()
+}
+
+var (
+	vndkApexListKey   = android.NewOnceKey("vndkApexList")
+	vndkApexListMutex sync.Mutex
+)
+
+func vndkApexList(config android.Config) map[string]*apexBundle {
+	return config.Once(vndkApexListKey, func() interface{} {
+		return map[string]*apexBundle{}
+	}).(map[string]*apexBundle)
+}
+
+// apexVndkGatherMutator gathers "apex_vndk" modules and puts them in a map with vndk_version as a key.
+func apexVndkGatherMutator(mctx android.TopDownMutatorContext) {
+	if ab, ok := mctx.Module().(*apexBundle); ok && ab.vndkApex {
+		if ab.IsNativeBridgeSupported() {
+			mctx.PropertyErrorf("native_bridge_supported", "%q doesn't support native bridge binary.", mctx.ModuleType())
+		}
+		vndkVersion := proptools.StringDefault(ab.vndkProperties.Vndk_version, mctx.DeviceConfig().PlatformVndkVersion())
+		vndkApexListMutex.Lock()
+		defer vndkApexListMutex.Unlock()
+		vndkApexList := vndkApexList(mctx.Config())
+		if other, ok := vndkApexList[vndkVersion]; ok {
+			mctx.PropertyErrorf("vndk_version", "%v is already defined in %q", vndkVersion, other.Name())
+		}
+		vndkApexList[vndkVersion] = ab
+	}
+}
+
+// apexVndkAddDepsMutator adds (reverse) dependencies from vndk libs to apex_vndk modules.
+// It filters only libs with matching targets.
+func apexVndkAddDepsMutator(mctx android.BottomUpMutatorContext) {
+	if cc, ok := mctx.Module().(*cc.Module); ok && cc.IsVndkOnSystem() {
+		vndkApexList := vndkApexList(mctx.Config())
+		if ab, ok := vndkApexList[cc.VndkVersion()]; ok {
+			targetArch := cc.Target().String()
+			for _, target := range ab.MultiTargets() {
+				if target.String() == targetArch {
+					mctx.AddReverseDependency(mctx.Module(), sharedLibTag, ab.Name())
+					break
+				}
+			}
+		}
+	}
 }
 
 // Mark the direct and transitive dependencies of apex bundles so that they
@@ -231,6 +286,20 @@
 		mctx.CreateVariations(apexBundleName)
 	}
 }
+
+func apexFlattenedMutator(mctx android.BottomUpMutatorContext) {
+	if ab, ok := mctx.Module().(*apexBundle); ok {
+		if !mctx.Config().FlattenApex() || mctx.Config().UnbundledBuild() {
+			modules := mctx.CreateLocalVariations("", "flattened")
+			modules[0].(*apexBundle).SetFlattened(false)
+			modules[1].(*apexBundle).SetFlattened(true)
+		} else {
+			ab.SetFlattened(true)
+			ab.SetFlattenedConfigValue()
+		}
+	}
+}
+
 func apexUsesMutator(mctx android.BottomUpMutatorContext) {
 	if ab, ok := mctx.Module().(*apexBundle); ok {
 		mctx.AddFarVariationDependencies(nil, usesTag, ab.properties.Uses...)
@@ -240,11 +309,14 @@
 type apexNativeDependencies struct {
 	// List of native libraries
 	Native_shared_libs []string
+
 	// List of native executables
 	Binaries []string
+
 	// List of native tests
 	Tests []string
 }
+
 type apexMultilibProperties struct {
 	// Native dependencies whose compile_multilib is "first"
 	First apexNativeDependencies
@@ -271,8 +343,9 @@
 	// If unspecified, a default one is automatically generated.
 	AndroidManifest *string `android:"path"`
 
-	// Canonical name of the APEX bundle in the manifest file.
-	// If unspecified, defaults to the value of name
+	// Canonical name of the APEX bundle. Used to determine the path to the activated APEX on
+	// device (/apex/<apex_name>).
+	// If unspecified, defaults to the value of name.
 	Apex_name *string
 
 	// Determines the file contexts file for setting security context to each file in this APEX bundle.
@@ -337,6 +410,20 @@
 
 	// List of APKs to package inside APEX
 	Apps []string
+
+	// To distinguish between flattened and non-flattened apex.
+	// if set true, then output files are flattened.
+	Flattened bool `blueprint:"mutated"`
+
+	// if true, it means that TARGET_FLATTEN_APEX is true and
+	// TARGET_BUILD_APPS is false
+	FlattenedConfigValue bool `blueprint:"mutated"`
+
+	// List of SDKs that are used to build this APEX. A reference to an SDK should be either
+	// `name#version` or `name` which is an alias for `name#current`. If left empty, `platform#current`
+	// is implied. This value affects all modules included in this APEX. In other words, they are
+	// also built with the SDKs specified here.
+	Uses_sdks []string
 }
 
 type apexTargetBundleProperties struct {
@@ -345,14 +432,17 @@
 		Android struct {
 			Multilib apexMultilibProperties
 		}
+
 		// Multilib properties only for host.
 		Host struct {
 			Multilib apexMultilibProperties
 		}
+
 		// Multilib properties only for host linux_bionic.
 		Linux_bionic struct {
 			Multilib apexMultilibProperties
 		}
+
 		// Multilib properties only for host linux_glibc.
 		Linux_glibc struct {
 			Multilib apexMultilibProperties
@@ -360,6 +450,11 @@
 	}
 }
 
+type apexVndkProperties struct {
+	// Indicates VNDK version of which this VNDK APEX bundles VNDK libs. Default is Platform VNDK Version.
+	Vndk_version *string
+}
+
 type apexFileClass int
 
 const (
@@ -455,9 +550,11 @@
 type apexBundle struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
+	android.SdkBase
 
 	properties       apexBundleProperties
 	targetProperties apexTargetBundleProperties
+	vndkProperties   apexVndkProperties
 
 	apexTypes apexPackaging
 
@@ -480,9 +577,8 @@
 	// list of module names that this APEX is depending on
 	externalDeps []string
 
-	flattened bool
-
 	testApex bool
+	vndkApex bool
 
 	// intermediate path for apex_manifest.json
 	manifestOut android.WritablePath
@@ -654,6 +750,16 @@
 	if cert != "" {
 		ctx.AddDependency(ctx.Module(), certificateTag, cert)
 	}
+
+	// TODO(jiyong): ensure that all apexes are with non-empty uses_sdks
+	if len(a.properties.Uses_sdks) > 0 {
+		sdkRefs := []android.SdkRef{}
+		for _, str := range a.properties.Uses_sdks {
+			parsed := android.ParseSdkRef(ctx, str, "uses_sdks")
+			sdkRefs = append(sdkRefs, parsed)
+		}
+		a.BuildWithSdks(sdkRefs)
+	}
 }
 
 func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string {
@@ -673,7 +779,7 @@
 			return nil, nil
 		}
 	case ".flattened":
-		if a.flattened {
+		if a.properties.Flattened {
 			flattenedApexPath := a.flattenedOutput
 			return android.Paths{flattenedApexPath}, nil
 		} else {
@@ -690,7 +796,7 @@
 
 func (a *apexBundle) getImageVariation(config android.DeviceConfig) string {
 	if config.VndkVersion() != "" && proptools.Bool(a.properties.Use_vendor) {
-		return "vendor"
+		return "vendor." + config.PlatformVndkVersion()
 	} else {
 		return "core"
 	}
@@ -732,38 +838,54 @@
 	a.properties.HideFromMake = true
 }
 
-func getCopyManifestForNativeLibrary(cc *cc.Module, handleSpecialLibs bool) (fileToCopy android.Path, dirInApex string) {
+func (a *apexBundle) SetFlattened(flattened bool) {
+	a.properties.Flattened = flattened
+}
+
+func (a *apexBundle) SetFlattenedConfigValue() {
+	a.properties.FlattenedConfigValue = true
+}
+
+// isFlattenedVariant returns true when the current module is the flattened
+// variant of an apex that has both a flattened and an unflattened variant.
+// It returns false when the current module is flattened but there is no
+// unflattened variant, which occurs when ctx.Config().FlattenedApex() returns
+// true. It can be used to avoid collisions between the install paths of the
+// flattened and unflattened variants.
+func (a *apexBundle) isFlattenedVariant() bool {
+	return a.properties.Flattened && !a.properties.FlattenedConfigValue
+}
+
+func getCopyManifestForNativeLibrary(ccMod *cc.Module, config android.Config, handleSpecialLibs bool) (fileToCopy android.Path, dirInApex string) {
 	// Decide the APEX-local directory by the multilib of the library
 	// In the future, we may query this to the module.
-	switch cc.Arch().ArchType.Multilib {
+	switch ccMod.Arch().ArchType.Multilib {
 	case "lib32":
 		dirInApex = "lib"
 	case "lib64":
 		dirInApex = "lib64"
 	}
-	dirInApex = filepath.Join(dirInApex, cc.RelativeInstallPath())
-	if !cc.Arch().Native {
-		dirInApex = filepath.Join(dirInApex, cc.Arch().ArchType.String())
-	} else if cc.Target().NativeBridge == android.NativeBridgeEnabled {
-		dirInApex = filepath.Join(dirInApex, cc.Target().NativeBridgeRelativePath)
+	dirInApex = filepath.Join(dirInApex, ccMod.RelativeInstallPath())
+	if !ccMod.Arch().Native {
+		dirInApex = filepath.Join(dirInApex, ccMod.Arch().ArchType.String())
+	} else if ccMod.Target().NativeBridge == android.NativeBridgeEnabled {
+		dirInApex = filepath.Join(dirInApex, ccMod.Target().NativeBridgeRelativePath)
 	}
-	if handleSpecialLibs {
-		switch cc.Name() {
-		case "libc", "libm", "libdl":
-			// Special case for bionic libs. This is to prevent the bionic libs
-			// from being included in the search path /apex/com.android.apex/lib.
-			// This exclusion is required because bionic libs in the runtime APEX
-			// are available via the legacy paths /system/lib/libc.so, etc. By the
-			// init process, the bionic libs in the APEX are bind-mounted to the
-			// legacy paths and thus will be loaded into the default linker namespace.
-			// If the bionic libs are directly in /apex/com.android.apex/lib then
-			// the same libs will be again loaded to the runtime linker namespace,
-			// which will result double loading of bionic libs that isn't supported.
-			dirInApex = filepath.Join(dirInApex, "bionic")
-		}
+	if handleSpecialLibs && cc.InstallToBootstrap(ccMod.BaseModuleName(), config) {
+		// Special case for Bionic libs and other libs installed with them. This is
+		// to prevent those libs from being included in the search path
+		// /apex/com.android.runtime/${LIB}. This exclusion is required because
+		// those libs in the Runtime APEX are available via the legacy paths in
+		// /system/lib/. By the init process, the libs in the APEX are bind-mounted
+		// to the legacy paths and thus will be loaded into the default linker
+		// namespace (aka "platform" namespace). If the libs are directly in
+		// /apex/com.android.runtime/${LIB} then the same libs will be loaded again
+		// into the runtime linker namespace, which will result in double loading of
+		// them, which isn't supported.
+		dirInApex = filepath.Join(dirInApex, "bionic")
 	}
 
-	fileToCopy = cc.OutputFile().Path()
+	fileToCopy = ccMod.OutputFile().Path()
 	return
 }
 
@@ -899,7 +1021,7 @@
 					if cc.HasStubsVariants() {
 						provideNativeLibs = append(provideNativeLibs, cc.OutputFile().Path().Base())
 					}
-					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, handleSpecialLibs)
+					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, ctx.Config(), handleSpecialLibs)
 					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeSharedLib, cc, nil})
 					return true
 				} else {
@@ -1030,7 +1152,7 @@
 							// Don't track further
 							return false
 						}
-						fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, handleSpecialLibs)
+						fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, ctx.Config(), handleSpecialLibs)
 						filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeSharedLib, cc, nil})
 						return true
 					}
@@ -1047,6 +1169,8 @@
 					}
 				} 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)
 				}
@@ -1055,7 +1179,6 @@
 		return false
 	})
 
-	a.flattened = ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
 	if a.private_key_file == nil {
 		ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.properties.Key))
 		return
@@ -1063,11 +1186,12 @@
 
 	// remove duplicates in filesInfo
 	removeDup := func(filesInfo []apexFile) []apexFile {
-		encountered := make(map[android.Path]bool)
+		encountered := make(map[string]bool)
 		result := []apexFile{}
 		for _, f := range filesInfo {
-			if !encountered[f.builtFile] {
-				encountered[f.builtFile] = true
+			dest := filepath.Join(f.installDir, f.builtFile.Base())
+			if !encountered[dest] {
+				encountered[dest] = true
 				result = append(result, f)
 			}
 		}
@@ -1393,7 +1517,7 @@
 	})
 
 	// Install to $OUT/soong/{target,host}/.../apex
-	if a.installable() && (!ctx.Config().FlattenApex() || apexType.zip()) {
+	if a.installable() && (!ctx.Config().FlattenApex() || apexType.zip()) && !a.isFlattenedVariant() {
 		ctx.InstallFile(a.installDir, ctx.ModuleName()+suffix, a.outputFiles[apexType])
 	}
 }
@@ -1453,20 +1577,32 @@
 		if cc, ok := fi.module.(*cc.Module); ok && cc.Properties.HideFromMake {
 			continue
 		}
-		if !android.InList(fi.moduleName, moduleNames) {
-			moduleNames = append(moduleNames, fi.moduleName)
+		if a.properties.Flattened && !apexType.image() {
+			continue
 		}
+
+		var suffix string
+		if a.isFlattenedVariant() {
+			suffix = ".flattened"
+		}
+
+		if !android.InList(fi.moduleName, moduleNames) {
+			moduleNames = append(moduleNames, fi.moduleName+suffix)
+		}
+
 		fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
 		fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
-		fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName)
-		// /apex/<name>/{lib|framework|...}
+		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)
-		if a.flattened && apexType.image() {
+		if a.properties.Flattened && apexType.image() {
 			// /system/apex/<name>/{lib|framework|...}
 			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)",
 				a.installDir.RelPathString(), name, fi.installDir))
-			fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated)
+			if !a.isFlattenedVariant() {
+				fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated)
+			}
 			if len(fi.symlinks) > 0 {
 				fmt.Fprintln(w, "LOCAL_MODULE_SYMLINKS :=", strings.Join(fi.symlinks, " "))
 			}
@@ -1518,7 +1654,7 @@
 			fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", fi.builtFile.String())
 			fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false")
 			fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
-		} else if fi.class == nativeSharedLib || fi.class == nativeExecutable {
+		} else if fi.class == nativeSharedLib || fi.class == nativeExecutable || fi.class == nativeTest {
 			fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
 			if cc, ok := fi.module.(*cc.Module); ok {
 				if cc.UnstrippedOutputFile() != nil {
@@ -1546,7 +1682,11 @@
 				moduleNames = a.androidMkForFiles(w, name, moduleDir, apexType)
 			}
 
-			if a.flattened && apexType.image() {
+			if a.isFlattenedVariant() {
+				name = name + ".flattened"
+			}
+
+			if a.properties.Flattened && apexType.image() {
 				// Only image APEXes can be flattened.
 				fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
 				fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
@@ -1557,7 +1697,7 @@
 				fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
 				fmt.Fprintln(w, "$(LOCAL_INSTALLED_MODULE): .KATI_IMPLICIT_OUTPUTS :=", a.flattenedOutput.String())
 
-			} else {
+			} else if !a.isFlattenedVariant() {
 				// zip-apex is the less common type so have the name refer to the image-apex
 				// only and use {name}.zip if you want the zip-apex
 				if apexType == zipApex && a.apexTypes == both {
@@ -1590,18 +1730,9 @@
 		}}
 }
 
-func testApexBundleFactory() android.Module {
-	return ApexBundleFactory(true /*testApex*/)
-}
-
-func apexBundleFactory() android.Module {
-	return ApexBundleFactory(false /*testApex*/)
-}
-
-func ApexBundleFactory(testApex bool) android.Module {
+func newApexBundle() *apexBundle {
 	module := &apexBundle{
 		outputFiles: map[apexPackaging]android.WritablePath{},
-		testApex:    testApex,
 	}
 	module.AddProperties(&module.properties)
 	module.AddProperties(&module.targetProperties)
@@ -1610,9 +1741,43 @@
 	})
 	android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
+	android.InitSdkAwareModule(module)
 	return module
 }
 
+func ApexBundleFactory(testApex bool) android.Module {
+	bundle := newApexBundle()
+	bundle.testApex = testApex
+	return bundle
+}
+
+func testApexBundleFactory() android.Module {
+	bundle := newApexBundle()
+	bundle.testApex = true
+	return bundle
+}
+
+func BundleFactory() android.Module {
+	return newApexBundle()
+}
+
+// apex_vndk creates a special variant of apex modules which contains only VNDK libraries.
+// If `vndk_version` is specified, the VNDK libraries of the specified VNDK version are gathered automatically.
+// If not specified, then the "current" versions are gathered.
+func vndkApexBundleFactory() android.Module {
+	bundle := newApexBundle()
+	bundle.vndkApex = true
+	bundle.AddProperties(&bundle.vndkProperties)
+	android.AddLoadHook(bundle, func(ctx android.LoadHookContext) {
+		ctx.AppendProperties(&struct {
+			Compile_multilib *string
+		}{
+			proptools.StringPtr("both"),
+		})
+	})
+	return bundle
+}
+
 //
 // Defaults
 //
diff --git a/apex/apex_test.go b/apex/apex_test.go
index e2d85ae..91c6426 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -40,8 +40,9 @@
 	return
 }
 
-func testApexError(t *testing.T, pattern, bp string) {
-	ctx, config := testApexContext(t, bp)
+func testApexError(t *testing.T, pattern, bp string, handlers ...testCustomizer) {
+	t.Helper()
+	ctx, config := testApexContext(t, bp, handlers...)
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
 	if len(errs) > 0 {
 		android.FailIfNoMatchingErrors(t, pattern, errs)
@@ -56,8 +57,9 @@
 	t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
 }
 
-func testApex(t *testing.T, bp string) (*android.TestContext, android.Config) {
-	ctx, config := testApexContext(t, bp)
+func testApex(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
+	t.Helper()
+	ctx, config := testApexContext(t, bp, handlers...)
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
 	android.FailIfErrored(t, errs)
 	_, errs = ctx.PrepareBuildActions(config)
@@ -65,37 +67,54 @@
 	return ctx, config
 }
 
-func testApexContext(t *testing.T, bp string) (*android.TestContext, android.Config) {
+type testCustomizer func(fs map[string][]byte, config android.Config)
+
+func withFiles(files map[string][]byte) testCustomizer {
+	return func(fs map[string][]byte, config android.Config) {
+		for k, v := range files {
+			fs[k] = v
+		}
+	}
+}
+
+func withTargets(targets map[android.OsType][]android.Target) testCustomizer {
+	return func(fs map[string][]byte, config android.Config) {
+		for k, v := range targets {
+			config.Targets[k] = v
+		}
+	}
+}
+
+func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
 	config := android.TestArchConfig(buildDir, nil)
 	config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
 	config.TestProductVariables.DefaultAppCertificate = proptools.StringPtr("vendor/foo/devkeys/test")
 	config.TestProductVariables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"}
 	config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Q")
 	config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false)
+	config.TestProductVariables.Platform_vndk_version = proptools.StringPtr("VER")
 
 	ctx := android.NewTestArchContext()
-	ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(apexBundleFactory))
+	ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(BundleFactory))
 	ctx.RegisterModuleType("apex_test", android.ModuleFactoryAdaptor(testApexBundleFactory))
-	ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apexKeyFactory))
+	ctx.RegisterModuleType("apex_vndk", android.ModuleFactoryAdaptor(vndkApexBundleFactory))
+	ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(ApexKeyFactory))
 	ctx.RegisterModuleType("apex_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
 	ctx.RegisterModuleType("prebuilt_apex", android.ModuleFactoryAdaptor(PrebuiltFactory))
-	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
 
-	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
-		ctx.TopDown("apex_deps", apexDepsMutator)
-		ctx.BottomUp("apex", apexMutator)
-		ctx.BottomUp("apex_uses", apexUsesMutator)
-		ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
-		ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
-	})
-
+	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))
+	ctx.RegisterModuleType("cc_prebuilt_library_shared", android.ModuleFactoryAdaptor(cc.PrebuiltSharedLibraryFactory))
+	ctx.RegisterModuleType("cc_prebuilt_library_static", android.ModuleFactoryAdaptor(cc.PrebuiltStaticLibraryFactory))
 	ctx.RegisterModuleType("cc_binary", android.ModuleFactoryAdaptor(cc.BinaryFactory))
 	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
 	ctx.RegisterModuleType("cc_test", android.ModuleFactoryAdaptor(cc.TestFactory))
 	ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory))
+	ctx.RegisterModuleType("vndk_prebuilt_shared", android.ModuleFactoryAdaptor(cc.VndkPrebuiltSharedFactory))
 	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
 	ctx.RegisterModuleType("prebuilt_etc", android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory))
 	ctx.RegisterModuleType("sh_binary", android.ModuleFactoryAdaptor(android.ShBinaryFactory))
@@ -105,6 +124,7 @@
 	ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(java.ImportFactory))
 	ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(java.AndroidAppFactory))
 
+	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
 	ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("prebuilts", android.PrebuiltMutator).Parallel()
 	})
@@ -115,6 +135,15 @@
 		ctx.BottomUp("test_per_src", cc.TestPerSrcMutator).Parallel()
 		ctx.BottomUp("version", cc.VersionMutator).Parallel()
 		ctx.BottomUp("begin", cc.BeginMutator).Parallel()
+		ctx.TopDown("apex_vndk_gather", apexVndkGatherMutator)
+		ctx.BottomUp("apex_vndk_add_deps", apexVndkAddDepsMutator)
+	})
+	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.TopDown("apex_deps", apexDepsMutator)
+		ctx.BottomUp("apex", apexMutator)
+		ctx.BottomUp("apex_uses", apexUsesMutator)
+		ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
+		ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
 	})
 
 	ctx.Register()
@@ -132,6 +161,7 @@
 			src: "",
 			vendor_available: true,
 			recovery_available: true,
+			native_bridge_supported: true,
 		}
 
 		toolchain_library {
@@ -146,6 +176,7 @@
 			src: "",
 			vendor_available: true,
 			recovery_available: true,
+			native_bridge_supported: true,
 		}
 
 		toolchain_library {
@@ -153,6 +184,7 @@
 			src: "",
 			vendor_available: true,
 			recovery_available: true,
+			native_bridge_supported: true,
 		}
 
 		toolchain_library {
@@ -160,6 +192,23 @@
 			src: "",
 			vendor_available: true,
 			recovery_available: true,
+			native_bridge_supported: true,
+		}
+
+		toolchain_library {
+			name: "libclang_rt.builtins-x86_64-android",
+			src: "",
+			vendor_available: true,
+			recovery_available: true,
+			native_bridge_supported: true,
+		}
+
+		toolchain_library {
+			name: "libclang_rt.builtins-i686-android",
+			src: "",
+			vendor_available: true,
+			recovery_available: true,
+			native_bridge_supported: true,
 		}
 
 		cc_object {
@@ -167,6 +216,7 @@
 			stl: "none",
 			vendor_available: true,
 			recovery_available: true,
+			native_bridge_supported: true,
 		}
 
 		cc_object {
@@ -174,6 +224,7 @@
 			stl: "none",
 			vendor_available: true,
 			recovery_available: true,
+			native_bridge_supported: true,
 		}
 
 		cc_object {
@@ -189,20 +240,23 @@
 		llndk_library {
 			name: "libc",
 			symbol_file: "",
+			native_bridge_supported: true,
 		}
 
 		llndk_library {
 			name: "libm",
 			symbol_file: "",
+			native_bridge_supported: true,
 		}
 
 		llndk_library {
 			name: "libdl",
 			symbol_file: "",
+			native_bridge_supported: true,
 		}
 	`
 
-	ctx.MockFileSystem(map[string][]byte{
+	fs := map[string][]byte{
 		"Android.bp":                                        []byte(bp),
 		"build/make/target/product/security":                nil,
 		"apex_manifest.json":                                nil,
@@ -238,7 +292,13 @@
 		"frameworks/base/api/current.txt":            nil,
 		"build/make/core/proguard.flags":             nil,
 		"build/make/core/proguard_basic_keeps.flags": nil,
-	})
+	}
+
+	for _, handler := range handlers {
+		handler(fs, config)
+	}
+
+	ctx.MockFileSystem(fs)
 
 	return ctx, config
 }
@@ -992,8 +1052,8 @@
 	inputsString := strings.Join(inputsList, " ")
 
 	// ensure that the apex includes vendor variants of the direct and indirect deps
-	ensureContains(t, inputsString, "android_arm64_armv8-a_vendor_shared_myapex/mylib.so")
-	ensureContains(t, inputsString, "android_arm64_armv8-a_vendor_shared_myapex/mylib2.so")
+	ensureContains(t, inputsString, "android_arm64_armv8-a_vendor.VER_shared_myapex/mylib.so")
+	ensureContains(t, inputsString, "android_arm64_armv8-a_vendor.VER_shared_myapex/mylib2.so")
 
 	// ensure that the apex does not include core variants
 	ensureNotContains(t, inputsString, "android_arm64_armv8-a_core_shared_myapex/mylib.so")
@@ -1210,6 +1270,252 @@
 	ensureContains(t, cFlags, "-Imy_include")
 }
 
+func TestVndkApexCurrent(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex_vndk {
+			name: "myapex",
+			key: "myapex.key",
+			file_contexts: "myapex",
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "libvndk",
+			srcs: ["mylib.cpp"],
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library {
+			name: "libvndksp",
+			srcs: ["mylib.cpp"],
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+				support_system_process: true,
+			},
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+
+	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+	ensureContains(t, copyCmds, "image.apex/lib/libvndk.so")
+	ensureContains(t, copyCmds, "image.apex/lib/libvndksp.so")
+	ensureContains(t, copyCmds, "image.apex/lib64/libvndk.so")
+	ensureContains(t, copyCmds, "image.apex/lib64/libvndksp.so")
+}
+
+func TestVndkApexWithPrebuilt(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex_vndk {
+			name: "myapex",
+			key: "myapex.key",
+			file_contexts: "myapex",
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_prebuilt_library_shared {
+			name: "libvndkshared",
+			srcs: ["libvndkshared.so"],
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`, withFiles(map[string][]byte{
+		"libvndkshared.so": nil,
+	}))
+
+	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+	ensureContains(t, copyCmds, "image.apex/lib/libvndkshared.so")
+}
+
+func TestVndkApexVersion(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex_vndk {
+			name: "myapex_v27",
+			key: "myapex.key",
+			file_contexts: "myapex",
+			vndk_version: "27",
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "libvndk",
+			srcs: ["mylib.cpp"],
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		vndk_prebuilt_shared {
+			name: "libvndk27",
+			version: "27",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			srcs: ["libvndk27.so"],
+		}
+	`, withFiles(map[string][]byte{
+		"libvndk27.so": nil,
+	}))
+
+	apexRule := ctx.ModuleForTests("myapex_v27", "android_common_myapex_v27").Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+	ensureContains(t, copyCmds, "image.apex/lib/libvndk27.so")
+	ensureContains(t, copyCmds, "image.apex/lib64/libvndk27.so")
+	ensureNotContains(t, copyCmds, "image.apex/lib/libvndk.so")
+}
+
+func TestVndkApexErrorWithDuplicateVersion(t *testing.T) {
+	testApexError(t, `module "myapex_v27.*" .*: vndk_version: 27 is already defined in "myapex_v27.*"`, `
+		apex_vndk {
+			name: "myapex_v27",
+			key: "myapex.key",
+			file_contexts: "myapex",
+			vndk_version: "27",
+		}
+		apex_vndk {
+			name: "myapex_v27_other",
+			key: "myapex.key",
+			file_contexts: "myapex",
+			vndk_version: "27",
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "libvndk",
+			srcs: ["mylib.cpp"],
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		vndk_prebuilt_shared {
+			name: "libvndk",
+			version: "27",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			srcs: ["libvndk.so"],
+		}
+	`, withFiles(map[string][]byte{
+		"libvndk.so": nil,
+	}))
+}
+
+func TestVndkApexSkipsNativeBridgeSupportedModules(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex_vndk {
+			name: "myapex",
+			key: "myapex.key",
+			file_contexts: "myapex",
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "libvndk",
+			srcs: ["mylib.cpp"],
+			vendor_available: true,
+			native_bridge_supported: true,
+			host_supported: true,
+			vndk: {
+				enabled: true,
+			},
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`, withTargets(map[android.OsType][]android.Target{
+		android.Android: []android.Target{
+			{Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+			{Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+			{Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "silvermont", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "arm64", NativeBridgeRelativePath: "x86_64"},
+			{Os: android.Android, Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "arm", NativeBridgeRelativePath: "x86"},
+		},
+	}))
+
+	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+	ensureContains(t, copyCmds, "image.apex/lib/libvndk.so")
+	ensureContains(t, copyCmds, "image.apex/lib64/libvndk.so")
+
+	// apex
+	ensureNotContains(t, copyCmds, "image.apex/lib/x86/libvndk.so")
+	ensureNotContains(t, copyCmds, "image.apex/lib64/x86_64/libvndk.so")
+}
+
+func TestVndkApexDoesntSupportNativeBridgeSupported(t *testing.T) {
+	testApexError(t, `module "myapex" .*: native_bridge_supported: .* doesn't support native bridge binary`, `
+		apex_vndk {
+			name: "myapex",
+			key: "myapex.key",
+			file_contexts: "myapex",
+			native_bridge_supported: true,
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "libvndk",
+			srcs: ["mylib.cpp"],
+			vendor_available: true,
+			native_bridge_supported: true,
+			host_supported: true,
+			vndk: {
+				enabled: true,
+			},
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+}
+
 func TestDependenciesInApexManifest(t *testing.T) {
 	ctx, _ := testApex(t, `
 		apex {
@@ -1824,6 +2130,7 @@
 }
 
 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",
@@ -1854,6 +2161,7 @@
 		}
 	`)
 
+	// respect 'no_apex' even with static link
 	testApexError(t, `tries to include no_apex module mylib2`, `
 		apex {
 			name: "commonapex",
@@ -1884,6 +2192,86 @@
 		}
 	`)
 
+	// '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",
@@ -1916,6 +2304,7 @@
 			},
 		}
 
+		// this won't be included in "myapex", so 'no_apex' is still valid in this case.
 		cc_library {
 			name: "mylib3",
 			srcs: ["mylib.cpp"],
@@ -1932,7 +2321,6 @@
 	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) {
diff --git a/apex/key.go b/apex/key.go
index 08cd45e..ffde315 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -27,7 +27,7 @@
 var String = proptools.String
 
 func init() {
-	android.RegisterModuleType("apex_key", apexKeyFactory)
+	android.RegisterModuleType("apex_key", ApexKeyFactory)
 	android.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
 }
 
@@ -53,7 +53,7 @@
 	Installable *bool
 }
 
-func apexKeyFactory() android.Module {
+func ApexKeyFactory() android.Module {
 	module := &apexKey{}
 	module.AddProperties(&module.properties)
 	android.InitAndroidArchModule(module, android.HostAndDeviceDefault, android.MultilibCommon)
diff --git a/build_kzip.bash b/build_kzip.bash
index 5364e7f..607654b 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -3,16 +3,23 @@
 # Build kzip files (source files for the indexing pipeline) for the given configuration,
 # merge them and place the resulting all.kzip into $DIST_DIR.
 # It is assumed that the current directory is the top of the source tree.
-# The following enviromnet variables affect the result:
-#   TARGET_PRODUCT        target device name, e.g., `aosp_blueline`
+# The following environment variables affect the result:
+#   TARGET_PRODUCT        target device name, e.g., 'aosp_blueline'
 #   TARGET_BUILD_VARIANT  variant, e.g., `userdebug`
-#   OUT_DIR               where the build is happening (./out if not specified)
+#   OUT_DIR               absolute path  where the build is happening ($PWD/out if not specified})
 #   DIST_DIR              where the resulting all.kzip will be placed
-#   XREF_CORPUS           source code repository URI, e.g.,
-#                        `android.googlesource.com/platform/superproject`
+#   XREF_CORPUS           source code repository URI, e.g., 'android.googlesource.com/platform/superproject'
+#   BUILD_NUMBER          build number, used to generate unique ID (will use UUID if not set)
+
+# If OUT_DIR is not set, the build will use out/ as output directory, which is
+# a relative path. Make it absolute, otherwise the indexer will not know that it
+# contains only generated files.
+: ${OUT_DIR:=$PWD/out}
+[[ "$OUT_DIR" =~ ^/ ]] || { echo "$OUT_DIR is not an absolute path"; exit 1; }
+: ${BUILD_NUMBER:=$(uuidgen)}
 
 # The extraction might fail for some source files, so run with -k
-build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k merge_zips xref_cxx xref_java
+OUT_DIR=$OUT_DIR build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k merge_zips xref_cxx xref_java
 
 # We build with -k, so check that we have generated at least 100K files
 # (the actual number is 180K+)
@@ -21,5 +28,6 @@
 
 # Pack
 # TODO(asmundak): this should be done by soong.
-declare -r allkzip=all.kzip
-"${OUT_DIR:-out}/soong/host/linux-x86/bin/merge_zips" "$DIST_DIR/$allkzip" @<(find $OUT_DIR -name '*.kzip')
+declare -r allkzip="$BUILD_NUMBER.kzip"
+"$OUT_DIR/soong/host/linux-x86/bin/merge_zips" "$DIST_DIR/$allkzip" @<(find $OUT_DIR -name '*.kzip')
+
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 4b0cb31..aab4edd 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -37,6 +37,7 @@
 	Os() android.OsType
 	Host() bool
 	useVndk() bool
+	vndkVersion() string
 	static() bool
 	inRecovery() bool
 }
@@ -109,17 +110,7 @@
 	}
 	c.subAndroidMk(&ret, c.installer)
 
-	if c.Target().NativeBridge == android.NativeBridgeEnabled {
-		ret.SubName += nativeBridgeSuffix
-	}
-
-	if c.useVndk() && c.hasVendorVariant() {
-		// .vendor suffix is added only when we will have two variants: core and vendor.
-		// The suffix is not added for vendor-only module.
-		ret.SubName += vendorSuffix
-	} else if c.inRecovery() && !c.onlyInRecovery() {
-		ret.SubName += recoverySuffix
-	}
+	ret.SubName += c.Properties.SubName
 
 	return ret
 }
@@ -207,7 +198,7 @@
 		library.androidMkWriteExportedFlags(w)
 		library.androidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
 
-		_, _, ext := splitFileExt(outputFile.Base())
+		_, _, ext := android.SplitFileExt(outputFile.Base())
 
 		fmt.Fprintln(w, "LOCAL_BUILT_MODULE_STEM := $(LOCAL_MODULE)"+ext)
 
@@ -312,6 +303,33 @@
 	androidMkWriteTestData(test.data, ctx, ret)
 }
 
+func (fuzz *fuzzBinary) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+	ctx.subAndroidMk(ret, fuzz.binaryDecorator)
+
+	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())
+	}
+
+	if fuzz.dictionary != nil {
+		path := strings.TrimSuffix(fuzz.dictionary.String(), fuzz.dictionary.Rel())
+		fuzzFiles = append(fuzzFiles, path+":"+fuzz.dictionary.Base())
+	}
+
+	if len(fuzzFiles) > 0 {
+		ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+			fmt.Fprintln(w, "LOCAL_TEST_DATA := "+strings.Join(fuzzFiles, " "))
+		})
+	}
+
+	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+		fmt.Fprintln(w, "LOCAL_IS_FUZZ_TARGET := true")
+	})
+}
+
 func (test *testLibrary) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
 	ctx.subAndroidMk(ret, test.libraryDecorator)
 }
@@ -319,7 +337,7 @@
 func (library *toolchainLibraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
 	ret.Class = "STATIC_LIBRARIES"
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
-		_, suffix, _ := splitFileExt(outputFile.Base())
+		_, suffix, _ := android.SplitFileExt(outputFile.Base())
 		fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix)
 	})
 }
@@ -334,7 +352,7 @@
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
 		path := installer.path.RelPathString()
 		dir, file := filepath.Split(path)
-		stem, suffix, _ := splitFileExt(file)
+		stem, suffix, _ := android.SplitFileExt(file)
 		fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix)
 		fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(OUT_DIR)/"+filepath.Clean(dir))
 		fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)
@@ -347,7 +365,7 @@
 
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
 		path, file := filepath.Split(c.installPath.String())
-		stem, suffix, _ := splitFileExt(file)
+		stem, suffix, _ := android.SplitFileExt(file)
 		fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix)
 		fmt.Fprintln(w, "LOCAL_MODULE_PATH := "+path)
 		fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)
@@ -357,11 +375,10 @@
 
 func (c *llndkStubDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
 	ret.Class = "SHARED_LIBRARIES"
-	ret.SubName = vendorSuffix
 
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
 		c.libraryDecorator.androidMkWriteExportedFlags(w)
-		_, _, ext := splitFileExt(outputFile.Base())
+		_, _, ext := android.SplitFileExt(outputFile.Base())
 
 		fmt.Fprintln(w, "LOCAL_BUILT_MODULE_STEM := $(LOCAL_MODULE)"+ext)
 		fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
@@ -380,7 +397,7 @@
 
 		path := c.path.RelPathString()
 		dir, file := filepath.Split(path)
-		stem, suffix, ext := splitFileExt(file)
+		stem, suffix, ext := android.SplitFileExt(file)
 		fmt.Fprintln(w, "LOCAL_BUILT_MODULE_STEM := $(LOCAL_MODULE)"+ext)
 		fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix)
 		fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(OUT_DIR)/"+filepath.Clean(dir))
@@ -398,7 +415,7 @@
 
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
 		c.libraryDecorator.androidMkWriteExportedFlags(w)
-		_, _, ext := splitFileExt(outputFile.Base())
+		_, _, ext := android.SplitFileExt(outputFile.Base())
 
 		fmt.Fprintln(w, "LOCAL_BUILT_MODULE_STEM := $(LOCAL_MODULE)"+ext)
 		fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
diff --git a/cc/binary.go b/cc/binary.go
index 17e729c..0d69405 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -454,7 +454,7 @@
 	// The original path becomes a symlink to the corresponding file in the
 	// runtime APEX.
 	translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled || !ctx.Arch().Native
-	if installToBootstrap(ctx.baseModuleName(), ctx.Config()) && !translatedArch && ctx.apexName() == "" && !ctx.inRecovery() {
+	if InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !translatedArch && ctx.apexName() == "" && !ctx.inRecovery() {
 		if ctx.Device() && isBionic(ctx.baseModuleName()) {
 			binary.installSymlinkToRuntimeApex(ctx, file)
 		}
diff --git a/cc/builder.go b/cc/builder.go
index 42d809a..b353814 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -764,7 +764,7 @@
 
 // Generate a rule for compiling multiple .o files to a .o using ld partial linking
 func TransformObjsToObj(ctx android.ModuleContext, objFiles android.Paths,
-	flags builderFlags, outputFile android.WritablePath) {
+	flags builderFlags, outputFile android.WritablePath, deps android.Paths) {
 
 	ldCmd := "${config.ClangBin}/clang++"
 
@@ -773,6 +773,7 @@
 		Description: "link " + outputFile.Base(),
 		Output:      outputFile,
 		Inputs:      objFiles,
+		Implicits:   deps,
 		Args: map[string]string{
 			"ldCmd":   ldCmd,
 			"ldFlags": flags.ldFlags,
diff --git a/cc/cc.go b/cc/cc.go
index f97ef5a..744e0cb 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -36,9 +36,9 @@
 	android.RegisterModuleType("cc_defaults", defaultsFactory)
 
 	android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.BottomUp("vndk", VndkMutator).Parallel()
 		ctx.BottomUp("image", ImageMutator).Parallel()
 		ctx.BottomUp("link", LinkageMutator).Parallel()
-		ctx.BottomUp("vndk", VndkMutator).Parallel()
 		ctx.BottomUp("ndk_api", ndkApiMutator).Parallel()
 		ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
 		ctx.BottomUp("version", VersionMutator).Parallel()
@@ -200,7 +200,8 @@
 	PreventInstall            bool     `blueprint:"mutated"`
 	ApexesProvidingSharedLibs []string `blueprint:"mutated"`
 
-	UseVndk bool `blueprint:"mutated"`
+	VndkVersion string `blueprint:"mutated"`
+	SubName     string `blueprint:"mutated"`
 
 	// *.logtags files, to combine together in order to generate the /system/etc/event-log-tags
 	// file
@@ -400,6 +401,14 @@
 	return staticDepTag
 }
 
+func CrtBeginDepTag() dependencyTag {
+	return crtBeginDepTag
+}
+
+func CrtEndDepTag() dependencyTag {
+	return crtEndDepTag
+}
+
 // Module contains the properties and members used by all C/C++ module types, and implements
 // the blueprint.Module interface.  It delegates to compiler, linker, and installer interfaces
 // to construct the output file.  Behavior can be customized with a Customizer interface
@@ -407,6 +416,7 @@
 	android.ModuleBase
 	android.DefaultableModuleBase
 	android.ApexModuleBase
+	android.SdkBase
 
 	Properties       BaseProperties
 	VendorProperties VendorProperties
@@ -478,6 +488,19 @@
 	return ""
 }
 
+// IsVndkOnSystem returns true if a module is supposed to be a vndk library provided by system to vendor
+func (c *Module) IsVndkOnSystem() bool {
+	if linker, ok := c.linker.(libraryInterface); ok {
+		return linker.shared() && c.isVndk() && c.useVndk() && !c.isVndkExt()
+	}
+
+	return false
+}
+
+func (c *Module) VndkVersion() string {
+	return c.vndkVersion()
+}
+
 func (c *Module) Init() android.Module {
 	c.AddProperties(&c.Properties, &c.VendorProperties)
 	if c.compiler != nil {
@@ -529,10 +552,9 @@
 		}
 	})
 	android.InitAndroidArchModule(c, c.hod, c.multilib)
-
-	android.InitDefaultableModule(c)
-
 	android.InitApexModule(c)
+	android.InitDefaultableModule(c)
+	android.InitSdkAwareModule(c)
 
 	return c
 }
@@ -549,7 +571,7 @@
 }
 
 func (c *Module) useVndk() bool {
-	return c.Properties.UseVndk
+	return c.Properties.VndkVersion != ""
 }
 
 func (c *Module) isCoverageVariant() bool {
@@ -583,10 +605,7 @@
 }
 
 func (c *Module) vndkVersion() string {
-	if vndkdep := c.vndkdep; vndkdep != nil {
-		return vndkdep.Properties.Vndk.Version
-	}
-	return ""
+	return c.Properties.VndkVersion
 }
 
 func (c *Module) isPgoCompile() bool {
@@ -666,6 +685,10 @@
 }
 
 func (c *Module) nativeCoverage() bool {
+	// Bug: http://b/137883967 - native-bridge modules do not currently work with coverage
+	if c.Target().NativeBridge == android.NativeBridgeEnabled {
+		return false
+	}
 	return c.linker != nil && c.linker.nativeCoverage()
 }
 
@@ -677,7 +700,7 @@
 	return false
 }
 
-func installToBootstrap(name string, config android.Config) bool {
+func InstallToBootstrap(name string, config android.Config) bool {
 	if name == "libclang_rt.hwasan-aarch64-android" {
 		return inList("hwaddress", config.SanitizeDevice())
 	}
@@ -992,6 +1015,31 @@
 
 	c.makeLinkType = c.getMakeLinkType(actx)
 
+	c.Properties.SubName = ""
+
+	if c.Target().NativeBridge == android.NativeBridgeEnabled {
+		c.Properties.SubName += nativeBridgeSuffix
+	}
+
+	if _, ok := c.linker.(*vndkPrebuiltLibraryDecorator); ok {
+		// .vendor suffix is added for backward compatibility with VNDK snapshot whose names with
+		// such suffixes are already hard-coded in prebuilts/vndk/.../Android.bp.
+		c.Properties.SubName += vendorSuffix
+	} else if _, ok := c.linker.(*llndkStubDecorator); ok || (c.useVndk() && c.hasVendorVariant()) {
+		// .vendor.{version} suffix is added only when we will have two variants: core and vendor.
+		// The suffix is not added for vendor-only module.
+		c.Properties.SubName += vendorSuffix
+		vendorVersion := actx.DeviceConfig().VndkVersion()
+		if vendorVersion == "current" {
+			vendorVersion = actx.DeviceConfig().PlatformVndkVersion()
+		}
+		if c.Properties.VndkVersion != vendorVersion {
+			c.Properties.SubName += "." + c.Properties.VndkVersion
+		}
+	} else if c.inRecovery() && !c.onlyInRecovery() {
+		c.Properties.SubName += recoverySuffix
+	}
+
 	ctx := &moduleContext{
 		ModuleContext: actx,
 		moduleContextImpl: moduleContextImpl{
@@ -1479,9 +1527,11 @@
 
 	if vndkdep := c.vndkdep; vndkdep != nil {
 		if vndkdep.isVndkExt() {
-			baseModuleMode := vendorMode
+			var baseModuleMode string
 			if actx.DeviceConfig().VndkVersion() == "" {
 				baseModuleMode = coreMode
+			} else {
+				baseModuleMode = c.imageVariation()
 			}
 			actx.AddVariationDependencies([]blueprint.Variation{
 				{Mutator: "image", Variation: baseModuleMode},
@@ -1504,7 +1554,7 @@
 		// Host code is not restricted
 		return
 	}
-	if from.Properties.UseVndk {
+	if from.useVndk() {
 		// Though vendor code is limited by the vendor mutator,
 		// each vendor-available module needs to check
 		// link-type for VNDK.
@@ -1911,7 +1961,15 @@
 			} else if c.useVndk() && bothVendorAndCoreVariantsExist {
 				// The vendor module in Make will have been renamed to not conflict with the core
 				// module, so update the dependency name here accordingly.
-				return libName + vendorSuffix
+				ret := libName + vendorSuffix
+				vendorVersion := ctx.DeviceConfig().VndkVersion()
+				if vendorVersion == "current" {
+					vendorVersion = ctx.DeviceConfig().PlatformVndkVersion()
+				}
+				if c.Properties.VndkVersion != vendorVersion {
+					ret += "." + c.Properties.VndkVersion
+				}
+				return ret
 			} else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib {
 				return libName + vendorPublicLibrarySuffix
 			} else if ccDep.inRecovery() && !ccDep.onlyInRecovery() {
@@ -2097,13 +2155,12 @@
 }
 
 func (c *Module) imageVariation() string {
-	variation := "core"
 	if c.useVndk() {
-		variation = "vendor"
+		return vendorMode + "." + c.Properties.VndkVersion
 	} else if c.inRecovery() {
-		variation = "recovery"
+		return recoveryMode
 	}
-	return variation
+	return coreMode
 }
 
 func (c *Module) IDEInfo(dpInfo *android.IdeInfo) {
@@ -2155,6 +2212,7 @@
 		&BinaryLinkerProperties{},
 		&TestProperties{},
 		&TestBinaryProperties{},
+		&FuzzProperties{},
 		&StlProperties{},
 		&SanitizeProperties{},
 		&StripProperties{},
@@ -2169,8 +2227,8 @@
 		&android.ProtoProperties{},
 	)
 
-	android.InitDefaultsModule(module)
 	android.InitApexModule(module)
+	android.InitDefaultsModule(module)
 
 	return module
 }
@@ -2180,7 +2238,7 @@
 	// SDK libraries. (which framework-private libraries can use)
 	coreMode = "core"
 
-	// vendorMode is the variant used for /vendor code that compiles
+	// vendorMode is the variant prefix used for /vendor code that compiles
 	// against the VNDK.
 	vendorMode = "vendor"
 
@@ -2244,7 +2302,10 @@
 				variants = append(variants, coreMode)
 			}
 			if vendorVariantNeeded {
-				variants = append(variants, vendorMode)
+				variants = append(variants, vendorMode+"."+mctx.DeviceConfig().PlatformVndkVersion())
+				if vndkVersion := mctx.DeviceConfig().VndkVersion(); vndkVersion != "current" {
+					variants = append(variants, vendorMode+"."+vndkVersion)
+				}
 			}
 			if recoveryVariantNeeded {
 				variants = append(variants, recoveryMode)
@@ -2316,9 +2377,16 @@
 	}
 
 	var coreVariantNeeded bool = false
-	var vendorVariantNeeded bool = false
 	var recoveryVariantNeeded bool = false
 
+	var vendorVariants []string
+
+	platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
+	deviceVndkVersion := mctx.DeviceConfig().VndkVersion()
+	if deviceVndkVersion == "current" {
+		deviceVndkVersion = platformVndkVersion
+	}
+
 	if mctx.DeviceConfig().VndkVersion() == "" {
 		// If the device isn't compiling against the VNDK, we always
 		// use the core mode.
@@ -2329,22 +2397,31 @@
 	} else if _, ok := m.linker.(*llndkStubDecorator); ok {
 		// LL-NDK stubs only exist in the vendor variant, since the
 		// real libraries will be used in the core variant.
-		vendorVariantNeeded = true
+		vendorVariants = append(vendorVariants,
+			platformVndkVersion,
+			deviceVndkVersion,
+		)
 	} else if _, ok := m.linker.(*llndkHeadersDecorator); ok {
 		// ... and LL-NDK headers as well
-		vendorVariantNeeded = true
-	} else if _, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
+		vendorVariants = append(vendorVariants,
+			platformVndkVersion,
+			deviceVndkVersion,
+		)
+	} else if lib, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
 		// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
 		// PRODUCT_EXTRA_VNDK_VERSIONS.
-		vendorVariantNeeded = true
+		vendorVariants = append(vendorVariants, lib.version())
 	} else if m.hasVendorVariant() && !vendorSpecific {
 		// This will be available in both /system and /vendor
 		// or a /system directory that is available to vendor.
 		coreVariantNeeded = true
-		vendorVariantNeeded = true
+		vendorVariants = append(vendorVariants, platformVndkVersion)
+		if m.isVndk() {
+			vendorVariants = append(vendorVariants, deviceVndkVersion)
+		}
 	} else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
 		// This will be available in /vendor (or /odm) only
-		vendorVariantNeeded = true
+		vendorVariants = append(vendorVariants, deviceVndkVersion)
 	} else {
 		// This is either in /system (or similar: /data), or is a
 		// modules built with the NDK. Modules built with the NDK
@@ -2373,17 +2450,17 @@
 	if coreVariantNeeded {
 		variants = append(variants, coreMode)
 	}
-	if vendorVariantNeeded {
-		variants = append(variants, vendorMode)
+	for _, variant := range android.FirstUniqueStrings(vendorVariants) {
+		variants = append(variants, vendorMode+"."+variant)
 	}
 	if recoveryVariantNeeded {
 		variants = append(variants, recoveryMode)
 	}
 	mod := mctx.CreateVariations(variants...)
 	for i, v := range variants {
-		if v == vendorMode {
+		if strings.HasPrefix(v, vendorMode+".") {
 			m := mod[i].(*Module)
-			m.Properties.UseVndk = true
+			m.Properties.VndkVersion = strings.TrimPrefix(v, vendorMode+".")
 			squashVendorSrcs(m)
 		} else if v == recoveryMode {
 			m := mod[i].(*Module)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index c9eb421..6275822 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -112,7 +112,7 @@
 
 const (
 	coreVariant     = "android_arm64_armv8-a_core_shared"
-	vendorVariant   = "android_arm64_armv8-a_vendor_shared"
+	vendorVariant   = "android_arm64_armv8-a_vendor.VER_shared"
 	recoveryVariant = "android_arm64_armv8-a_recovery_shared"
 )
 
@@ -328,8 +328,8 @@
 	vndkCoreLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-core")
 	vndkSpLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-sp")
 
-	variant := "android_arm64_armv8-a_vendor_shared"
-	variant2nd := "android_arm_armv7-a-neon_vendor_shared"
+	variant := "android_arm64_armv8-a_vendor.VER_shared"
+	variant2nd := "android_arm_armv7-a-neon_vendor.VER_shared"
 
 	checkVndkSnapshot(t, ctx, "libvndk", vndkCoreLibPath, variant)
 	checkVndkSnapshot(t, ctx, "libvndk", vndkCoreLib2ndPath, variant2nd)
@@ -1343,6 +1343,8 @@
 	assertArrayString(t, *vndkPrivateLibraries(config),
 		[]string{"libllndkprivate", "libvndkprivate"})
 
+	vendorVariant27 := "android_arm64_armv8-a_vendor.27_shared"
+
 	tests := []struct {
 		variant  string
 		name     string
@@ -1353,8 +1355,8 @@
 		{vendorVariant, "libvndkprivate", "native:vndk_private"},
 		{vendorVariant, "libvendor", "native:vendor"},
 		{vendorVariant, "libvndkext", "native:vendor"},
-		{vendorVariant, "prevndk.vndk.27.arm.binder32", "native:vndk"},
 		{vendorVariant, "libllndk.llndk", "native:vndk"},
+		{vendorVariant27, "prevndk.vndk.27.arm.binder32", "native:vndk"},
 		{coreVariant, "libvndk", "native:platform"},
 		{coreVariant, "libvndkprivate", "native:platform"},
 		{coreVariant, "libllndk", "native:platform"},
@@ -1792,7 +1794,7 @@
 	`)
 
 	// _static variant is used since _shared reuses *.o from the static variant
-	cc := ctx.ModuleForTests("libvendor", "android_arm_armv7-a-neon_vendor_static").Rule("cc")
+	cc := ctx.ModuleForTests("libvendor", "android_arm_armv7-a-neon_vendor.VER_static").Rule("cc")
 	cflags := cc.Args["cFlags"]
 	if !strings.Contains(cflags, "-Imy_include") {
 		t.Errorf("cflags for libvendor must contain -Imy_include, but was %#v.", cflags)
@@ -1878,7 +1880,7 @@
 
 	// runtime_libs for vendor variants have '.vendor' suffixes if the modules have both core
 	// and vendor variants.
-	variant = "android_arm64_armv8-a_vendor_shared"
+	variant = "android_arm64_armv8-a_vendor.VER_shared"
 
 	module = ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
 	checkRuntimeLibs(t, []string{"libvendor_available1.vendor"}, module)
@@ -1894,7 +1896,7 @@
 	module := ctx.ModuleForTests("libvendor_available3", variant).Module().(*Module)
 	checkRuntimeLibs(t, []string{"libvendor_available1"}, module)
 
-	variant = "android_arm64_armv8-a_vendor_shared"
+	variant = "android_arm64_armv8-a_vendor.VER_shared"
 	module = ctx.ModuleForTests("libvendor_available3", variant).Module().(*Module)
 	checkRuntimeLibs(t, nil, module)
 }
@@ -2091,9 +2093,9 @@
 	}
 
 	// test if libvendor is linked to the real shared lib
-	ld = ctx.ModuleForTests("libvendor", strings.Replace(variant, "_core", "_vendor", 1)).Rule("ld")
+	ld = ctx.ModuleForTests("libvendor", strings.Replace(variant, "_core", "_vendor.VER", 1)).Rule("ld")
 	libflags = ld.Args["libFlags"]
-	stubPaths = getOutputPaths(ctx, strings.Replace(variant, "_core", "_vendor", 1), []string{"libvendorpublic"})
+	stubPaths = getOutputPaths(ctx, strings.Replace(variant, "_core", "_vendor.VER", 1), []string{"libvendorpublic"})
 	if !strings.Contains(libflags, stubPaths[0].String()) {
 		t.Errorf("libflags for libvendor must contain %#v, but was %#v", stubPaths[0], libflags)
 	}
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index cd7c410..d37e486 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -236,6 +236,7 @@
 		"cortex-a72":     "${config.ArmClangCortexA53Cflags}",
 		"cortex-a73":     "${config.ArmClangCortexA53Cflags}",
 		"cortex-a75":     "${config.ArmClangCortexA55Cflags}",
+		"cortex-a76":     "${config.ArmClangCortexA55Cflags}",
 		"krait":          "${config.ArmClangKraitCflags}",
 		"kryo":           "${config.ArmClangKryoCflags}",
 		"kryo385":        "${config.ArmClangCortexA53Cflags}",
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 3636ae9..e59aa37 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -115,10 +115,6 @@
 		// TODO: can we remove this now?
 		"-Wno-reserved-id-macro",
 
-		// Disable overly aggressive warning for format strings.
-		// Bug: 20148343
-		"-Wno-format-pedantic",
-
 		// Workaround for ccache with clang.
 		// See http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html.
 		"-Wno-unused-command-line-argument",
diff --git a/cc/config/global.go b/cc/config/global.go
index d873494..0943126 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -108,6 +108,7 @@
 	noOverrideGlobalCflags = []string{
 		"-Werror=int-to-pointer-cast",
 		"-Werror=pointer-to-int-cast",
+		"-Werror=fortify-source",
 	}
 
 	IllegalFlags = []string{
@@ -123,8 +124,8 @@
 
 	// prebuilts/clang default settings.
 	ClangDefaultBase         = "prebuilts/clang/host"
-	ClangDefaultVersion      = "clang-r365631"
-	ClangDefaultShortVersion = "9.0.6"
+	ClangDefaultVersion      = "clang-r365631b"
+	ClangDefaultShortVersion = "9.0.7"
 
 	// Directories with warnings from Android.bp files.
 	WarningAllowedProjects = []string{
diff --git a/cc/fuzz.go b/cc/fuzz.go
index d44c02d..7806e83 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -15,13 +15,26 @@
 package cc
 
 import (
+	"path/filepath"
+
+	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
+
 	"android/soong/android"
 	"android/soong/cc/config"
-	"github.com/google/blueprint/proptools"
 )
 
+type FuzzProperties struct {
+	// Optional list of seed files to be installed to the fuzz target's output
+	// directory.
+	Corpus []string `android:"path"`
+	// Optional dictionary to be installed to the fuzz target's output directory.
+	Dictionary *string `android:"path"`
+}
+
 func init() {
 	android.RegisterModuleType("cc_fuzz", FuzzFactory)
+	android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory)
 }
 
 // cc_fuzz creates a host/device fuzzer binary. Host binaries can be found at
@@ -39,10 +52,15 @@
 type fuzzBinary struct {
 	*binaryDecorator
 	*baseCompiler
+
+	Properties FuzzProperties
+	corpus     android.Paths
+	dictionary android.Path
 }
 
 func (fuzz *fuzzBinary) linkerProps() []interface{} {
 	props := fuzz.binaryDecorator.linkerProps()
+	props = append(props, &fuzz.Properties)
 	return props
 }
 
@@ -78,21 +96,26 @@
 }
 
 func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) {
-	fuzz.binaryDecorator.baseInstaller.dir = "fuzz"
-	fuzz.binaryDecorator.baseInstaller.dir64 = "fuzz"
+	fuzz.binaryDecorator.baseInstaller.dir = filepath.Join(
+		"fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
+	fuzz.binaryDecorator.baseInstaller.dir64 = filepath.Join(
+		"fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
 	fuzz.binaryDecorator.baseInstaller.install(ctx, file)
+
+	fuzz.corpus = android.PathsForModuleSrc(ctx, fuzz.Properties.Corpus)
+	if fuzz.Properties.Dictionary != nil {
+		fuzz.dictionary = android.PathForModuleSrc(ctx, *fuzz.Properties.Dictionary)
+		if fuzz.dictionary.Ext() != ".dict" {
+			ctx.PropertyErrorf("dictionary",
+				"Fuzzer dictionary %q does not have '.dict' extension",
+				fuzz.dictionary.String())
+		}
+	}
 }
 
 func NewFuzz(hod android.HostOrDeviceSupported) *Module {
 	module, binary := NewBinary(hod)
 
-	// TODO(mitchp): The toolchain does not currently export the x86 (32-bit)
-	// variant of libFuzzer for host. There is no way to only disable the host
-	// 32-bit variant, so we specify cc_fuzz targets as 64-bit only. This doesn't
-	// hurt anyone, as cc_fuzz is mostly for experimental targets as of this
-	// moment.
-	module.multilib = "64"
-
 	binary.baseInstaller = NewFuzzInstaller()
 	module.sanitize.SetSanitizer(fuzzer, true)
 
@@ -134,3 +157,96 @@
 
 	return module
 }
+
+// Responsible for generating GNU Make rules that package fuzz targets into
+// their architecture & target/host specific zip file.
+type fuzzPackager struct {
+}
+
+func fuzzPackagingFactory() android.Singleton {
+	return &fuzzPackager{}
+}
+
+type fileToZip struct {
+	SourceFilePath        android.Path
+	DestinationPathPrefix string
+}
+
+func (s *fuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
+	// Map between each architecture + host/device combination, and the files that
+	// need to be packaged (in the tuple of {source file, destination folder in
+	// archive}).
+	archDirs := make(map[android.OutputPath][]fileToZip)
+
+	ctx.VisitAllModules(func(module android.Module) {
+		// Discard non-fuzz targets.
+		ccModule, ok := module.(*Module)
+		if !ok {
+			return
+		}
+		fuzzModule, ok := ccModule.compiler.(*fuzzBinary)
+		if !ok {
+			return
+		}
+
+		// Discard vendor-NDK-linked modules, they're duplicates of fuzz targets
+		// we're going to package anyway.
+		if ccModule.useVndk() || !ccModule.Enabled() {
+			return
+		}
+
+		hostOrTargetString := "target"
+		if ccModule.Host() {
+			hostOrTargetString = "host"
+		}
+
+		archString := ccModule.Arch().ArchType.String()
+		archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
+
+		// The executable.
+		archDirs[archDir] = append(archDirs[archDir],
+			fileToZip{ccModule.outputFile.Path(), ccModule.Name()})
+
+		// The corpora.
+		for _, corpusEntry := range fuzzModule.corpus {
+			archDirs[archDir] = append(archDirs[archDir],
+				fileToZip{corpusEntry, ccModule.Name() + "/corpus/" + corpusEntry.Base()})
+		}
+
+		// The dictionary.
+		if fuzzModule.dictionary != nil {
+			archDirs[archDir] = append(archDirs[archDir],
+				fileToZip{fuzzModule.dictionary, ccModule.Name()})
+		}
+	})
+
+	// List of architecture + host/device specific packages to build via. 'make fuzz'.
+	var archDirTargets android.Paths
+
+	for archDir, filesToZip := range archDirs {
+		arch := archDir.Base()
+		hostOrTarget := filepath.Base(filepath.Dir(archDir.String()))
+		builder := android.NewRuleBuilder()
+		outputFile := android.PathForOutput(ctx, "fuzz-"+hostOrTarget+"-"+arch+".zip")
+		archDirTargets = append(archDirTargets, outputFile)
+
+		command := builder.Command().BuiltTool(ctx, "soong_zip").
+			Flag("-j").
+			FlagWithOutput("-o ", outputFile)
+
+		for _, fileToZip := range filesToZip {
+			command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix).
+				FlagWithInput("-f ", fileToZip.SourceFilePath)
+		}
+
+		builder.Build(pctx, ctx, "create-fuzz-package-"+arch+"-"+hostOrTarget,
+			"Create fuzz target packages for "+arch+"-"+hostOrTarget)
+	}
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        blueprint.Phony,
+		Output:      android.PathForPhony(ctx, "fuzz"),
+		Implicits:   archDirTargets,
+		Description: "Build all Android fuzz targets, and create packages.",
+	})
+}
diff --git a/cc/gen.go b/cc/gen.go
index 42b0cbe..17ab45f 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -113,7 +113,14 @@
 
 	aidlPackage := strings.TrimSuffix(aidlFile.Rel(), aidlFile.Base())
 	baseName := strings.TrimSuffix(aidlFile.Base(), aidlFile.Ext())
-	shortName := strings.TrimPrefix(baseName, "I")
+	shortName := baseName
+	// TODO(b/111362593): aidl_to_cpp_common.cpp uses heuristics to figure out if
+	//   an interface name has a leading I. Those same heuristics have been
+	//   moved here.
+	if len(baseName) >= 2 && baseName[0] == 'I' &&
+		strings.ToUpper(baseName)[1] == baseName[1] {
+		shortName = strings.TrimPrefix(baseName, "I")
+	}
 
 	outDir := android.PathForModuleGen(ctx, "aidl")
 	headerI := outDir.Join(ctx, aidlPackage, baseName+".h")
diff --git a/cc/library.go b/cc/library.go
index 9178a52..c402ea0 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -88,6 +88,16 @@
 	// set the name of the output
 	Stem *string `android:"arch_variant"`
 
+	// set suffix of the name of the output
+	Suffix *string `android:"arch_variant"`
+
+	Target struct {
+		Vendor struct {
+			// set suffix of the name of the output
+			Suffix *string `android:"arch_variant"`
+		}
+	}
+
 	// Names of modules to be overridden. Listed modules can only be other shared libraries
 	// (in Make or Soong).
 	// This does not completely prevent installation of the overridden libraries, but if both
@@ -549,7 +559,7 @@
 	androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer)
 }
 
-func (library *libraryDecorator) getLibName(ctx ModuleContext) string {
+func (library *libraryDecorator) getLibName(ctx BaseModuleContext) string {
 	name := library.libName
 	if name == "" {
 		name = String(library.Properties.Stem)
@@ -558,6 +568,16 @@
 		}
 	}
 
+	suffix := ""
+	if ctx.useVndk() {
+		suffix = String(library.Properties.Target.Vendor.Suffix)
+	}
+	if suffix == "" {
+		suffix = String(library.Properties.Suffix)
+	}
+
+	name += suffix
+
 	if ctx.isVndkExt() {
 		name = ctx.getVndkExtendsModuleName()
 	}
@@ -1013,8 +1033,8 @@
 			// The original path becomes a symlink to the corresponding file in the
 			// runtime APEX.
 			translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled || !ctx.Arch().Native
-			if installToBootstrap(ctx.baseModuleName(), ctx.Config()) && !library.buildStubs() && !translatedArch && !ctx.inRecovery() {
-				if ctx.Device() && isBionic(ctx.baseModuleName()) {
+			if InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !library.buildStubs() && !translatedArch && !ctx.inRecovery() {
+				if ctx.Device() {
 					library.installSymlinkToRuntimeApex(ctx, file)
 				}
 				library.baseInstaller.subDir = "bootstrap"
diff --git a/cc/linker.go b/cc/linker.go
index 563ad04..e5e1486 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -491,7 +491,7 @@
 	gen_sorted_bss_symbols = pctx.AndroidStaticRule("gen_sorted_bss_symbols",
 		blueprint.RuleParams{
 			Command:     "CROSS_COMPILE=$crossCompile $genSortedBssSymbolsPath ${in} ${out}",
-			CommandDeps: []string{"$genSortedBssSymbolsPath"},
+			CommandDeps: []string{"$genSortedBssSymbolsPath", "${crossCompile}nm"},
 		},
 		"crossCompile")
 )
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 4d59975..9cbe800 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -76,7 +76,7 @@
 }
 
 func (stub *llndkStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
-	vndk_ver := ctx.DeviceConfig().VndkVersion()
+	vndk_ver := ctx.Module().(*Module).Properties.VndkVersion
 	if vndk_ver == "current" {
 		platform_vndk_ver := ctx.DeviceConfig().PlatformVndkVersion()
 		if !inList(platform_vndk_ver, ctx.Config().PlatformVersionCombinedCodenames()) {
@@ -177,7 +177,6 @@
 		libraryDecorator: library,
 	}
 	stub.Properties.Vendor_available = BoolPtr(true)
-	module.Properties.UseVndk = true
 	module.compiler = stub
 	module.linker = stub
 	module.installer = nil
diff --git a/cc/object.go b/cc/object.go
index 1a2711d..f619c79 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -123,7 +123,7 @@
 			output = input
 		}
 
-		TransformObjsToObj(ctx, objs.objFiles, builderFlags, output)
+		TransformObjsToObj(ctx, objs.objFiles, builderFlags, output, flags.LdFlagsDeps)
 	}
 
 	ctx.CheckbuildFile(outputFile)
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index dc6c43a..4e6cdd7 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -19,8 +19,8 @@
 )
 
 func init() {
-	android.RegisterModuleType("cc_prebuilt_library_shared", prebuiltSharedLibraryFactory)
-	android.RegisterModuleType("cc_prebuilt_library_static", prebuiltStaticLibraryFactory)
+	android.RegisterModuleType("cc_prebuilt_library_shared", PrebuiltSharedLibraryFactory)
+	android.RegisterModuleType("cc_prebuilt_library_static", PrebuiltStaticLibraryFactory)
 	android.RegisterModuleType("cc_prebuilt_binary", prebuiltBinaryFactory)
 }
 
@@ -97,7 +97,7 @@
 
 		if p.shared() {
 			p.unstrippedOutputFile = in
-			libName := ctx.baseModuleName() + flags.Toolchain.ShlibSuffix()
+			libName := p.libraryDecorator.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
 			if p.needsStrip(ctx) {
 				stripped := android.PathForModuleOut(ctx, "stripped", libName)
 				p.stripExecutableOrSharedLib(ctx, in, stripped, builderFlags)
@@ -131,7 +131,7 @@
 
 // cc_prebuilt_library_shared installs a precompiled shared library that are
 // listed in the srcs property in the device's directory.
-func prebuiltSharedLibraryFactory() android.Module {
+func PrebuiltSharedLibraryFactory() android.Module {
 	module, _ := NewPrebuiltSharedLibrary(android.HostAndDeviceSupported)
 	return module.Init()
 }
@@ -152,13 +152,14 @@
 
 	// Prebuilt libraries can be included in APEXes
 	android.InitApexModule(module)
+	android.InitSdkAwareModule(module)
 
 	return module, library
 }
 
 // cc_prebuilt_library_static installs a precompiled static library that are
 // listed in the srcs property in the device's directory.
-func prebuiltStaticLibraryFactory() android.Module {
+func PrebuiltStaticLibraryFactory() android.Module {
 	module, _ := NewPrebuiltStaticLibrary(android.HostAndDeviceSupported)
 	return module.Init()
 }
@@ -176,6 +177,7 @@
 	module.AddProperties(&prebuilt.properties)
 
 	android.InitPrebuiltModule(module, &prebuilt.properties.Srcs)
+	android.InitSdkAwareModule(module)
 	return module, library
 }
 
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 98d78e8..edcd26e 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -72,8 +72,8 @@
 
 	ctx := CreateTestContext(bp, fs, android.Android)
 
-	ctx.RegisterModuleType("cc_prebuilt_library_shared", android.ModuleFactoryAdaptor(prebuiltSharedLibraryFactory))
-	ctx.RegisterModuleType("cc_prebuilt_library_static", android.ModuleFactoryAdaptor(prebuiltStaticLibraryFactory))
+	ctx.RegisterModuleType("cc_prebuilt_library_shared", android.ModuleFactoryAdaptor(PrebuiltSharedLibraryFactory))
+	ctx.RegisterModuleType("cc_prebuilt_library_static", android.ModuleFactoryAdaptor(PrebuiltStaticLibraryFactory))
 	ctx.RegisterModuleType("cc_prebuilt_binary", android.ModuleFactoryAdaptor(prebuiltBinaryFactory))
 
 	ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
diff --git a/cc/strip.go b/cc/strip.go
index f3e3374..7e560ec 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -27,7 +27,6 @@
 		Keep_symbols                 *bool    `android:"arch_variant"`
 		Keep_symbols_list            []string `android:"arch_variant"`
 		Keep_symbols_and_debug_frame *bool    `android:"arch_variant"`
-		Use_gnu_strip                *bool    `android:"arch_variant"`
 	} `android:"arch_variant"`
 }
 
@@ -54,9 +53,6 @@
 		} else if !Bool(stripper.StripProperties.Strip.All) {
 			flags.stripKeepMiniDebugInfo = true
 		}
-		if Bool(stripper.StripProperties.Strip.Use_gnu_strip) {
-			flags.stripUseGnuStrip = true
-		}
 		if ctx.Config().Debuggable() && !flags.stripKeepMiniDebugInfo && !isStaticLib {
 			flags.stripAddGnuDebuglink = true
 		}
diff --git a/cc/test.go b/cc/test.go
index 1a0d44f..0e66e28 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -16,6 +16,7 @@
 
 import (
 	"path/filepath"
+	"strconv"
 	"strings"
 
 	"android/soong/android"
@@ -71,6 +72,19 @@
 
 	// Add RunCommandTargetPreparer to stop framework before the test and start it after the test.
 	Disable_framework *bool
+
+	// Add MinApiLevelModuleController to auto generated test config. If the device property of
+	// "ro.product.first_api_level" < Test_min_api_level, then skip this module.
+	Test_min_api_level *int64
+
+	// Add MinApiLevelModuleController to auto generated test config. If the device property of
+	// "ro.build.version.sdk" < Test_min_sdk_version, then skip this module.
+	Test_min_sdk_version *int64
+
+	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
+	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
+	// explicitly.
+	Auto_gen_config *bool
 }
 
 func init() {
@@ -314,15 +328,21 @@
 
 func (test *testBinary) install(ctx ModuleContext, file android.Path) {
 	test.data = android.PathsForModuleSrc(ctx, test.Properties.Data)
+	var api_level_prop string
 	var configs []tradefed.Config
+	var min_level string
 	if Bool(test.Properties.Require_root) {
-		configs = append(configs, tradefed.Preparer{"com.android.tradefed.targetprep.RootTargetPreparer", nil})
+		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
+	} else {
+		var options []tradefed.Option
+		options = append(options, tradefed.Option{"force-root", "false"})
+		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
 	}
 	if Bool(test.Properties.Disable_framework) {
 		var options []tradefed.Option
 		options = append(options, tradefed.Option{"run-command", "stop"})
 		options = append(options, tradefed.Option{"teardown-command", "start"})
-		configs = append(configs, tradefed.Preparer{"com.android.tradefed.targetprep.RunCommandTargetPreparer", options})
+		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RunCommandTargetPreparer", options})
 	}
 	if Bool(test.testDecorator.Properties.Isolated) {
 		configs = append(configs, tradefed.Option{"not-shardable", "true"})
@@ -330,9 +350,24 @@
 	if test.Properties.Test_options.Run_test_as != nil {
 		configs = append(configs, tradefed.Option{"run-test-as", String(test.Properties.Test_options.Run_test_as)})
 	}
+	if test.Properties.Test_min_api_level != nil && test.Properties.Test_min_sdk_version != nil {
+		ctx.PropertyErrorf("test_min_api_level", "'test_min_api_level' and 'test_min_sdk_version' should not be set at the same time.")
+	} else if test.Properties.Test_min_api_level != nil {
+		api_level_prop = "ro.product.first_api_level"
+		min_level = strconv.FormatInt(int64(*test.Properties.Test_min_api_level), 10)
+	} else if test.Properties.Test_min_sdk_version != nil {
+		api_level_prop = "ro.build.version.sdk"
+		min_level = strconv.FormatInt(int64(*test.Properties.Test_min_sdk_version), 10)
+	}
+	if api_level_prop != "" {
+		var options []tradefed.Option
+		options = append(options, tradefed.Option{"min-api-level", min_level})
+		options = append(options, tradefed.Option{"api-level-prop", api_level_prop})
+		configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.MinApiLevelModuleController", options})
+	}
 
 	test.testConfig = tradefed.AutoGenNativeTestConfig(ctx, test.Properties.Test_config,
-		test.Properties.Test_config_template, test.Properties.Test_suites, configs)
+		test.Properties.Test_config_template, test.Properties.Test_suites, configs, test.Properties.Auto_gen_config)
 
 	test.binaryDecorator.baseInstaller.dir = "nativetest"
 	test.binaryDecorator.baseInstaller.dir64 = "nativetest64"
@@ -423,6 +458,11 @@
 	// Add RootTargetPreparer to auto generated test config. This guarantees the test to run
 	// with root permission.
 	Require_root *bool
+
+	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
+	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
+	// explicitly.
+	Auto_gen_config *bool
 }
 
 type benchmarkDecorator struct {
@@ -457,10 +497,10 @@
 	benchmark.data = android.PathsForModuleSrc(ctx, benchmark.Properties.Data)
 	var configs []tradefed.Config
 	if Bool(benchmark.Properties.Require_root) {
-		configs = append(configs, tradefed.Preparer{"com.android.tradefed.targetprep.RootTargetPreparer", nil})
+		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
 	}
 	benchmark.testConfig = tradefed.AutoGenNativeBenchmarkTestConfig(ctx, benchmark.Properties.Test_config,
-		benchmark.Properties.Test_config_template, benchmark.Properties.Test_suites, configs)
+		benchmark.Properties.Test_config_template, benchmark.Properties.Test_suites, configs, benchmark.Properties.Auto_gen_config)
 
 	benchmark.binaryDecorator.baseInstaller.dir = filepath.Join("benchmarktest", ctx.ModuleName())
 	benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("benchmarktest64", ctx.ModuleName())
diff --git a/cc/testing.go b/cc/testing.go
index 5a3993c..a0b1634 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -253,7 +253,7 @@
 	ctx.RegisterModuleType("vendor_public_library", android.ModuleFactoryAdaptor(vendorPublicLibraryFactory))
 	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(ObjectFactory))
 	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
-	ctx.RegisterModuleType("vndk_prebuilt_shared", android.ModuleFactoryAdaptor(vndkPrebuiltSharedFactory))
+	ctx.RegisterModuleType("vndk_prebuilt_shared", android.ModuleFactoryAdaptor(VndkPrebuiltSharedFactory))
 	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("image", ImageMutator).Parallel()
 		ctx.BottomUp("link", LinkageMutator).Parallel()
diff --git a/cc/util.go b/cc/util.go
index 7b8ad18..2f7bec2 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -104,32 +104,6 @@
 	return list
 }
 
-var shlibVersionPattern = regexp.MustCompile("(?:\\.\\d+(?:svn)?)+")
-
-// splitFileExt splits a file name into root, suffix and ext. root stands for the file name without
-// the file extension and the version number (e.g. "libexample"). suffix stands for the
-// concatenation of the file extension and the version number (e.g. ".so.1.0"). ext stands for the
-// file extension after the version numbers are trimmed (e.g. ".so").
-func splitFileExt(name string) (string, string, string) {
-	// Extract and trim the shared lib version number if the file name ends with dot digits.
-	suffix := ""
-	matches := shlibVersionPattern.FindAllStringIndex(name, -1)
-	if len(matches) > 0 {
-		lastMatch := matches[len(matches)-1]
-		if lastMatch[1] == len(name) {
-			suffix = name[lastMatch[0]:lastMatch[1]]
-			name = name[0:lastMatch[0]]
-		}
-	}
-
-	// Extract the file name root and the file extension.
-	ext := filepath.Ext(name)
-	root := strings.TrimSuffix(name, ext)
-	suffix = ext + suffix
-
-	return root, suffix, ext
-}
-
 // linkDirOnDevice/linkName -> target
 func makeSymlinkCmd(linkDirOnDevice string, linkName string, target string) string {
 	dir := filepath.Join("$(PRODUCT_OUT)", linkDirOnDevice)
diff --git a/cc/util_test.go b/cc/util_test.go
deleted file mode 100644
index 7c718ea..0000000
--- a/cc/util_test.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2018 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package cc
-
-import (
-	"testing"
-)
-
-func TestSplitFileExt(t *testing.T) {
-	t.Run("soname with version", func(t *testing.T) {
-		root, suffix, ext := splitFileExt("libtest.so.1.0.30")
-		expected := "libtest"
-		if root != expected {
-			t.Errorf("root should be %q but got %q", expected, root)
-		}
-		expected = ".so.1.0.30"
-		if suffix != expected {
-			t.Errorf("suffix should be %q but got %q", expected, suffix)
-		}
-		expected = ".so"
-		if ext != expected {
-			t.Errorf("ext should be %q but got %q", expected, ext)
-		}
-	})
-
-	t.Run("soname with svn version", func(t *testing.T) {
-		root, suffix, ext := splitFileExt("libtest.so.1svn")
-		expected := "libtest"
-		if root != expected {
-			t.Errorf("root should be %q but got %q", expected, root)
-		}
-		expected = ".so.1svn"
-		if suffix != expected {
-			t.Errorf("suffix should be %q but got %q", expected, suffix)
-		}
-		expected = ".so"
-		if ext != expected {
-			t.Errorf("ext should be %q but got %q", expected, ext)
-		}
-	})
-
-	t.Run("version numbers in the middle should be ignored", func(t *testing.T) {
-		root, suffix, ext := splitFileExt("libtest.1.0.30.so")
-		expected := "libtest.1.0.30"
-		if root != expected {
-			t.Errorf("root should be %q but got %q", expected, root)
-		}
-		expected = ".so"
-		if suffix != expected {
-			t.Errorf("suffix should be %q but got %q", expected, suffix)
-		}
-		expected = ".so"
-		if ext != expected {
-			t.Errorf("ext should be %q but got %q", expected, ext)
-		}
-	})
-
-	t.Run("no known file extension", func(t *testing.T) {
-		root, suffix, ext := splitFileExt("test.exe")
-		expected := "test"
-		if root != expected {
-			t.Errorf("root should be %q but got %q", expected, root)
-		}
-		expected = ".exe"
-		if suffix != expected {
-			t.Errorf("suffix should be %q but got %q", expected, suffix)
-		}
-		if ext != expected {
-			t.Errorf("ext should be %q but got %q", expected, ext)
-		}
-	})
-}
diff --git a/cc/vndk.go b/cc/vndk.go
index 698fab5..14bbf11 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -49,10 +49,6 @@
 
 		// Extending another module
 		Extends *string
-
-		// for vndk_prebuilt_shared, this is set by "version" property.
-		// Otherwise, this is set as PLATFORM_VNDK_VERSION.
-		Version string `blueprint:"mutated"`
 	}
 }
 
@@ -129,7 +125,7 @@
 		// Other (static and LL-NDK) libraries are allowed to link.
 		return
 	}
-	if !to.Properties.UseVndk {
+	if !to.useVndk() {
 		ctx.ModuleErrorf("(%s) should not link to %q which is not a vendor-available library",
 			vndk.typeName(), to.Name())
 		return
@@ -325,14 +321,6 @@
 		return
 	}
 
-	if m.isVndk() {
-		if lib, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
-			m.vndkdep.Properties.Vndk.Version = lib.version()
-		} else {
-			m.vndkdep.Properties.Vndk.Version = mctx.DeviceConfig().PlatformVndkVersion()
-		}
-	}
-
 	if _, ok := m.linker.(*llndkStubDecorator); ok {
 		processLlndkLibrary(mctx, m)
 		return
@@ -341,8 +329,8 @@
 	lib, is_lib := m.linker.(*libraryDecorator)
 	prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker)
 
-	if (is_lib && lib.shared()) || (is_prebuilt_lib && prebuilt_lib.shared()) {
-		if m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
+	if (is_lib && lib.buildShared()) || (is_prebuilt_lib && prebuilt_lib.buildShared()) {
+		if m.vndkdep != nil && m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
 			processVndkLibrary(mctx, m)
 			return
 		}
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index da357ed..8126e4a 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -167,13 +167,19 @@
 	module.stl = nil
 	module.sanitize = nil
 	library.StripProperties.Strip.None = BoolPtr(true)
-	module.Properties.UseVndk = true
 
 	prebuilt := &vndkPrebuiltLibraryDecorator{
 		libraryDecorator: library,
 	}
 
 	prebuilt.properties.Check_elf_files = BoolPtr(false)
+	prebuilt.baseLinker.Properties.No_libcrt = BoolPtr(true)
+	prebuilt.baseLinker.Properties.Nocrt = BoolPtr(true)
+
+	// Prevent default system libs (libc, libm, and libdl) from being linked
+	if prebuilt.baseLinker.Properties.System_shared_libs == nil {
+		prebuilt.baseLinker.Properties.System_shared_libs = []string{}
+	}
 
 	module.compiler = nil
 	module.linker = prebuilt
@@ -206,11 +212,11 @@
 //            },
 //        },
 //    }
-func vndkPrebuiltSharedFactory() android.Module {
+func VndkPrebuiltSharedFactory() android.Module {
 	module := vndkPrebuiltSharedLibrary()
 	return module.Init()
 }
 
 func init() {
-	android.RegisterModuleType("vndk_prebuilt_shared", vndkPrebuiltSharedFactory)
+	android.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
 }
diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go
index 27179cb..a9be612 100644
--- a/cmd/merge_zips/merge_zips.go
+++ b/cmd/merge_zips/merge_zips.go
@@ -417,7 +417,7 @@
 	}
 	oldOlderMiz := miz.older
 	if oldOlderMiz.newer != miz {
-		panic(fmt.Errorf("broken list between %p:%#v and %p:%#v", miz, oldOlderMiz))
+		panic(fmt.Errorf("broken list between %p:%#v and %p:%#v", miz, miz, oldOlderMiz, oldOlderMiz))
 	}
 	miz.older = olderMiz
 	olderMiz.older = oldOlderMiz
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 1171a65..2800ade 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -158,7 +158,7 @@
 func main() {
 	stdio := terminal.StdioImpl{}
 
-	output := terminal.NewStatusOutput(stdio.Stdout(), "",
+	output := terminal.NewStatusOutput(stdio.Stdout(), "", false,
 		build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
 
 	log := logger.New(output)
@@ -391,7 +391,7 @@
 		Thread:  mpctx.Tracer.NewThread(product),
 		Status:  &status.Status{},
 	}}
-	ctx.Status.AddOutput(terminal.NewStatusOutput(ctx.Writer, "",
+	ctx.Status.AddOutput(terminal.NewStatusOutput(ctx.Writer, "", false,
 		build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD")))
 
 	config := build.NewConfig(ctx, flag.Args()...)
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index ec4f90e..974c644 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -41,6 +41,12 @@
 	// description for the flag (to display when running help)
 	description string
 
+	// Forces the status output into dumb terminal mode.
+	forceDumbOutput bool
+
+	// Sets a prefix string to use for filenames of log files.
+	logsPrefix string
+
 	// Creates the build configuration based on the args and build context.
 	config func(ctx build.Context, args ...string) build.Config
 
@@ -64,17 +70,21 @@
 		stdio: stdio,
 		run:   make,
 	}, {
-		flag:        "--dumpvar-mode",
-		description: "print the value of the legacy make variable VAR to stdout",
-		config:      dumpVarConfig,
-		stdio:       customStdio,
-		run:         dumpVar,
+		flag:            "--dumpvar-mode",
+		description:     "print the value of the legacy make variable VAR to stdout",
+		forceDumbOutput: true,
+		logsPrefix:      "dumpvars-",
+		config:          dumpVarConfig,
+		stdio:           customStdio,
+		run:             dumpVar,
 	}, {
-		flag:        "--dumpvars-mode",
-		description: "dump the values of one or more legacy make variables, in shell syntax",
-		config:      dumpVarConfig,
-		stdio:       customStdio,
-		run:         dumpVars,
+		flag:            "--dumpvars-mode",
+		description:     "dump the values of one or more legacy make variables, in shell syntax",
+		forceDumbOutput: true,
+		logsPrefix:      "dumpvars-",
+		config:          dumpVarConfig,
+		stdio:           customStdio,
+		run:             dumpVars,
 	}, {
 		flag:        "--build-mode",
 		description: "build modules based on the specified build action",
@@ -113,7 +123,7 @@
 		os.Exit(1)
 	}
 
-	output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"),
+	output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.forceDumbOutput,
 		build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
 
 	log := logger.New(output)
@@ -157,14 +167,14 @@
 	}
 
 	os.MkdirAll(logsDir, 0777)
-	log.SetOutput(filepath.Join(logsDir, "soong.log"))
-	trace.SetOutput(filepath.Join(logsDir, "build.trace"))
-	stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, "verbose.log")))
-	stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, "error.log")))
-	stat.AddOutput(status.NewProtoErrorLog(log, filepath.Join(logsDir, "build_error")))
+	log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
+	trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
+	stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, c.logsPrefix+"verbose.log")))
+	stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"error.log")))
+	stat.AddOutput(status.NewProtoErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"build_error")))
 	stat.AddOutput(status.NewCriticalPath(log))
 
-	defer met.Dump(filepath.Join(logsDir, "soong_metrics"))
+	defer met.Dump(filepath.Join(logsDir, c.logsPrefix+"soong_metrics"))
 
 	if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
 		if !strings.HasSuffix(start, "N") {
diff --git a/genrule/genrule.go b/genrule/genrule.go
index cf0b484..b8b0e01 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -437,7 +437,7 @@
 		phonyFile := android.PathForModuleGen(ctx, "genrule-phony")
 
 		ctx.Build(pctx, android.BuildParams{
-			Rule:   android.Phony,
+			Rule:   blueprint.Phony,
 			Output: phonyFile,
 			Inputs: g.outputFiles,
 		})
diff --git a/java/aar.go b/java/aar.go
index f5d7e97..6a883d3 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -220,14 +220,13 @@
 	manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext, sdkLibraries,
 		a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex, a.hasNoCode)
 
-	a.transitiveManifestPaths = append(android.Paths{manifestPath}, transitiveStaticLibManifests...)
+	// Add additional manifest files to transitive manifests.
+	additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests)
+	a.transitiveManifestPaths = append(android.Paths{manifestPath}, additionalManifests...)
+	a.transitiveManifestPaths = append(a.transitiveManifestPaths, transitiveStaticLibManifests...)
 
-	if len(transitiveStaticLibManifests) > 0 {
-		// Merge additional manifest files with app manifest.
-		additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests)
-		additionalManifests = append(additionalManifests, transitiveStaticLibManifests...)
-
-		a.mergedManifestFile = manifestMerger(ctx, manifestPath, additionalManifests, a.isLibrary)
+	if len(a.transitiveManifestPaths) > 1 {
+		a.mergedManifestFile = manifestMerger(ctx, a.transitiveManifestPaths[0], a.transitiveManifestPaths[1:], a.isLibrary)
 		if !a.isLibrary {
 			// Only use the merged manifest for applications.  For libraries, the transitive closure of manifests
 			// will be propagated to the final application and merged there.  The merged manifest for libraries is
diff --git a/java/androidmk.go b/java/androidmk.go
index 5938d0f..246de58 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -145,7 +145,7 @@
 }
 
 func (prebuilt *Import) AndroidMk() android.AndroidMkData {
-	if !prebuilt.IsForPlatform() {
+	if !prebuilt.IsForPlatform() || !prebuilt.ContainingSdk().IsCurrentVersion() {
 		return android.AndroidMkData{
 			Disabled: true,
 		}
diff --git a/java/app.go b/java/app.go
index d00c4c0..afddb6a 100644
--- a/java/app.go
+++ b/java/app.go
@@ -608,7 +608,8 @@
 	}
 	a.generateAndroidBuildActions(ctx)
 
-	a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites)
+	a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config,
+		a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites, a.testProperties.Auto_gen_config)
 	a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
 }
 
@@ -656,6 +657,11 @@
 	// list of compatibility suites (for example "cts", "vts") that the module should be
 	// installed into.
 	Test_suites []string `android:"arch_variant"`
+
+	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
+	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
+	// explicitly.
+	Auto_gen_config *bool
 }
 
 type AndroidTestHelperApp struct {
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 9eaa1b6..1d5331e 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -17,7 +17,6 @@
 import (
 	"fmt"
 	"path/filepath"
-	"runtime"
 	"strings"
 
 	"github.com/google/blueprint/proptools"
@@ -58,6 +57,10 @@
 	// filegroup or genrule can be included within this property.
 	Exclude_srcs []string `android:"path,arch_variant"`
 
+	// list of package names that should actually be used. If this property is left unspecified,
+	// all the sources from the srcs property is used.
+	Filter_packages []string
+
 	// list of java libraries that will be in the classpath.
 	Libs []string `android:"arch_variant"`
 
@@ -525,6 +528,34 @@
 	// do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
 	// may contain filegroup or genrule.
 	srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
+
+	filterByPackage := func(srcs []android.Path, filterPackages []string) []android.Path {
+		if filterPackages == nil {
+			return srcs
+		}
+		filtered := []android.Path{}
+		for _, src := range srcs {
+			if src.Ext() != ".java" {
+				// Don't filter-out non-Java (=generated sources) by package names. This is not ideal,
+				// but otherwise metalava emits stub sources having references to the generated AIDL classes
+				// in filtered-out pacages (e.g. com.android.internal.*).
+				// TODO(b/141149570) We need to fix this by introducing default private constructors or
+				// fixing metalava to not emit constructors having references to unknown classes.
+				filtered = append(filtered, src)
+				continue
+			}
+			packageName := strings.ReplaceAll(filepath.Dir(src.Rel()), "/", ".")
+			for _, pkg := range filterPackages {
+				if strings.HasPrefix(packageName, pkg) {
+					filtered = append(filtered, src)
+					break
+				}
+			}
+		}
+		return filtered
+	}
+	srcFiles = filterByPackage(srcFiles, j.properties.Filter_packages)
+
 	flags := j.collectAidlFlags(ctx, deps)
 	srcFiles = j.genSources(ctx, srcFiles, flags)
 
@@ -687,13 +718,6 @@
 }
 
 func (d *Droiddoc) doclavaDocsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, docletPath classpath) {
-	var date string
-	if runtime.GOOS == "darwin" {
-		date = `date -r`
-	} else {
-		date = `date -d @`
-	}
-
 	// Droiddoc always gets "-source 1.8" because it doesn't support 1.9 sources.  For modules with 1.9
 	// sources, droiddoc will get sources produced by metalava which will have already stripped out the
 	// 1.9 language features.
@@ -704,7 +728,7 @@
 		FlagWithArg("-doclet ", "com.google.doclava.Doclava").
 		FlagWithInputList("-docletpath ", docletPath.Paths(), ":").
 		FlagWithArg("-hdf page.build ", ctx.Config().BuildId()+"-"+ctx.Config().BuildNumberFromFile()).
-		FlagWithArg("-hdf page.now ", `"$(`+date+`$(cat `+ctx.Config().Getenv("BUILD_DATETIME_FILE")+`) "+%d %b %Y %k:%M")" `)
+		FlagWithArg("-hdf page.now ", `"$(date -d @$(cat `+ctx.Config().Getenv("BUILD_DATETIME_FILE")+`) "+%d %b %Y %k:%M")" `)
 
 	if String(d.properties.Custom_template) == "" {
 		// TODO: This is almost always droiddoc-templates-sdk
diff --git a/java/gen.go b/java/gen.go
index a69e9a2..b840b60 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -23,7 +23,6 @@
 )
 
 func init() {
-	pctx.HostBinToolVariable("syspropCmd", "sysprop_java")
 	pctx.SourcePathVariable("logtagsCmd", "build/make/tools/java-event-log-tags.py")
 	pctx.SourcePathVariable("mergeLogtagsCmd", "build/make/tools/merge-event-log-tags.py")
 	pctx.SourcePathVariable("logtagsLib", "build/make/tools/event_log_tags.py")
@@ -48,17 +47,6 @@
 			Command:     "$mergeLogtagsCmd -o $out $in",
 			CommandDeps: []string{"$mergeLogtagsCmd", "$logtagsLib"},
 		})
-
-	sysprop = pctx.AndroidStaticRule("sysprop",
-		blueprint.RuleParams{
-			Command: `rm -rf $out.tmp && mkdir -p $out.tmp && ` +
-				`$syspropCmd --scope $scope --java-output-dir $out.tmp $in && ` +
-				`${config.SoongZipCmd} -jar -o $out -C $out.tmp -D $out.tmp && rm -rf $out.tmp`,
-			CommandDeps: []string{
-				"$syspropCmd",
-				"${config.SoongZipCmd}",
-			},
-		}, "scope")
 )
 
 func genAidl(ctx android.ModuleContext, aidlFile android.Path, aidlFlags string, deps android.Paths) android.Path {
@@ -93,22 +81,6 @@
 	return javaFile
 }
 
-func genSysprop(ctx android.ModuleContext, syspropFile android.Path, scope string) android.Path {
-	srcJarFile := android.GenPathWithExt(ctx, "sysprop", syspropFile, "srcjar")
-
-	ctx.Build(pctx, android.BuildParams{
-		Rule:        sysprop,
-		Description: "sysprop_java " + syspropFile.Rel(),
-		Output:      srcJarFile,
-		Input:       syspropFile,
-		Args: map[string]string{
-			"scope": scope,
-		},
-	})
-
-	return srcJarFile
-}
-
 func genAidlIncludeFlags(srcFiles android.Paths) string {
 	var baseDirs []string
 	for _, srcFile := range srcFiles {
@@ -141,29 +113,6 @@
 		case ".proto":
 			srcJarFile := genProto(ctx, srcFile, flags.proto)
 			outSrcFiles = append(outSrcFiles, srcJarFile)
-		case ".sysprop":
-			// internal scope contains all properties
-			// public scope only contains public properties
-			// use public if the owner is different from client
-			scope := "internal"
-			if j.properties.Sysprop.Platform != nil {
-				isProduct := ctx.ProductSpecific()
-				isVendor := ctx.SocSpecific()
-				isOwnerPlatform := Bool(j.properties.Sysprop.Platform)
-
-				if isProduct {
-					// product can't own any sysprop_library now, so product must use public scope
-					scope = "public"
-				} else if isVendor && !isOwnerPlatform {
-					// vendor and odm can't use system's internal property.
-					scope = "public"
-				}
-
-				// We don't care about clients under system.
-				// They can't use sysprop_library owned by other partitions.
-			}
-			srcJarFile := genSysprop(ctx, srcFile, scope)
-			outSrcFiles = append(outSrcFiles, srcJarFile)
 		default:
 			outSrcFiles = append(outSrcFiles, srcFile)
 		}
diff --git a/java/java.go b/java/java.go
index b05d7bb..ce72c27 100644
--- a/java/java.go
+++ b/java/java.go
@@ -184,10 +184,6 @@
 		Output_params []string
 	}
 
-	Sysprop struct {
-		Platform *bool
-	} `blueprint:"mutated"`
-
 	Instrument bool `blueprint:"mutated"`
 
 	// List of files to include in the META-INF/services folder of the resulting jar.
@@ -290,6 +286,7 @@
 	android.ModuleBase
 	android.DefaultableModuleBase
 	android.ApexModuleBase
+	android.SdkBase
 
 	properties       CompilerProperties
 	protoProperties  android.ProtoProperties
@@ -398,6 +395,7 @@
 	AidlIncludeDirs() android.Paths
 	ExportedSdkLibs() []string
 	SrcJarArgs() ([]string, android.Paths)
+	BaseModuleName() string
 }
 
 type SdkLibraryDependency interface {
@@ -534,7 +532,9 @@
 			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" {
+			// 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)
 		}
 		if ctx.ModuleName() == "android_stubs_current" ||
 			ctx.ModuleName() == "android_system_stubs_current" ||
@@ -847,6 +847,12 @@
 			}
 		default:
 			switch tag {
+			case bootClasspathTag:
+				// If a system modules dependency has been added to the bootclasspath
+				// then add its libs to the bootclasspath.
+				sm := module.(*SystemModules)
+				deps.bootClasspath = append(deps.bootClasspath, sm.headerJars...)
+
 			case systemModulesTag:
 				if deps.systemModules != nil {
 					panic("Found two system module dependencies")
@@ -1632,6 +1638,7 @@
 
 	InitJavaModule(module, android.HostAndDeviceSupported)
 	android.InitApexModule(module)
+	android.InitSdkAwareModule(module)
 	return module
 }
 
@@ -1678,6 +1685,11 @@
 	// list of files or filegroup modules that provide data that should be installed alongside
 	// the test
 	Data []string `android:"path"`
+
+	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
+	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
+	// explicitly.
+	Auto_gen_config *bool
 }
 
 type testHelperLibraryProperties struct {
@@ -1702,7 +1714,8 @@
 }
 
 func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template, j.testProperties.Test_suites)
+	j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
+		j.testProperties.Test_suites, j.testProperties.Auto_gen_config)
 	j.data = android.PathsForModuleSrc(ctx, j.testProperties.Data)
 
 	j.Library.GenerateAndroidBuildActions(ctx)
@@ -1912,6 +1925,7 @@
 	android.DefaultableModuleBase
 	android.ApexModuleBase
 	prebuilt android.Prebuilt
+	android.SdkBase
 
 	properties ImportProperties
 
@@ -2068,6 +2082,7 @@
 	android.InitPrebuiltModule(module, &module.properties.Jars)
 	InitJavaModule(module, android.HostAndDeviceSupported)
 	android.InitApexModule(module)
+	android.InitSdkAwareModule(module)
 	return module
 }
 
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index c370811..0d5e31f 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -82,7 +82,7 @@
 	props.Sdk_version = proptools.StringPtr("current")
 	props.Installable = proptools.BoolPtr(false)
 
-	mctx.CreateModule(android.ModuleFactoryAdaptor(ImportFactory), &props)
+	mctx.CreateModule(ImportFactory, &props)
 }
 
 func createFilegroup(mctx android.TopDownMutatorContext, module string, scope string, apiver string, path string) {
@@ -93,7 +93,7 @@
 	}{}
 	filegroupProps.Name = proptools.StringPtr(fgName)
 	filegroupProps.Srcs = []string{path}
-	mctx.CreateModule(android.ModuleFactoryAdaptor(android.FileGroupFactory), &filegroupProps)
+	mctx.CreateModule(android.FileGroupFactory, &filegroupProps)
 }
 
 func getPrebuiltFiles(mctx android.TopDownMutatorContext, name string) []string {
diff --git a/java/proto.go b/java/proto.go
index 22a3eed..f5c233c 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -82,6 +82,7 @@
 			typeToPlugin = "javamicro"
 		case "nano":
 			flags.proto.OutTypeFlag = "--javanano_out"
+			typeToPlugin = "javanano"
 		case "lite":
 			flags.proto.OutTypeFlag = "--java_out"
 			flags.proto.OutParams = append(flags.proto.OutParams, "lite")
diff --git a/java/robolectric.go b/java/robolectric.go
index a5d18e0..dbf54c9 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -105,7 +105,7 @@
 	r.roboSrcJar = roboSrcJar
 
 	for _, dep := range ctx.GetDirectDepsWithTag(libTag) {
-		r.libs = append(r.libs, ctx.OtherModuleName(dep))
+		r.libs = append(r.libs, dep.(Dependency).BaseModuleName())
 	}
 
 	// TODO: this could all be removed if tradefed was used as the test runner, it will find everything
@@ -233,6 +233,7 @@
 
 	module.AddProperties(
 		&module.Module.properties,
+		&module.Module.deviceProperties,
 		&module.Module.protoProperties,
 		&module.robolectricProperties)
 
diff --git a/java/sdk_library.go b/java/sdk_library.go
index be65859..476e549 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -422,7 +422,7 @@
 		props.Product_specific = proptools.BoolPtr(true)
 	}
 
-	mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory), &props)
+	mctx.CreateModule(LibraryFactory, &props)
 }
 
 // Creates a droiddoc module that creates stubs source files from the given full source
@@ -522,7 +522,7 @@
 		module.latestRemovedApiFilegroupName(apiScope))
 	props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(true)
 
-	mctx.CreateModule(android.ModuleFactoryAdaptor(DroidstubsFactory), &props)
+	mctx.CreateModule(DroidstubsFactory, &props)
 }
 
 // Creates the xml file that publicizes the runtime library
@@ -560,7 +560,7 @@
 	genruleProps.Name = proptools.StringPtr(module.xmlFileName() + "-gen")
 	genruleProps.Cmd = proptools.StringPtr("echo '" + xmlContent + "' > $(out)")
 	genruleProps.Out = []string{module.xmlFileName()}
-	mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProps)
+	mctx.CreateModule(genrule.GenRuleFactory, &genruleProps)
 
 	// creates a prebuilt_etc module to actually place the xml file under
 	// <partition>/etc/permissions
@@ -582,7 +582,7 @@
 	} else if module.ProductSpecific() {
 		etcProps.Product_specific = proptools.BoolPtr(true)
 	}
-	mctx.CreateModule(android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory), &etcProps)
+	mctx.CreateModule(android.PrebuiltEtcFactory, &etcProps)
 }
 
 func (module *SdkLibrary) PrebuiltJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths {
@@ -815,7 +815,7 @@
 		props.Product_specific = proptools.BoolPtr(true)
 	}
 
-	mctx.CreateModule(android.ModuleFactoryAdaptor(ImportFactory), &props, &module.properties)
+	mctx.CreateModule(ImportFactory, &props, &module.properties)
 
 	javaSdkLibraries := javaSdkLibraries(mctx.Config())
 	javaSdkLibrariesLock.Lock()
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 6be17eb..88e21d7 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -124,7 +124,7 @@
 			name:          "nostdlib system_modules",
 			properties:    `sdk_version: "none", system_modules: "core-platform-api-stubs-system-modules"`,
 			system:        "core-platform-api-stubs-system-modules",
-			bootclasspath: []string{`""`},
+			bootclasspath: []string{"core-platform-api-stubs-system-modules-lib"},
 			classpath:     []string{},
 		},
 		{
diff --git a/java/system_modules.go b/java/system_modules.go
index c616249..43e4e11 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -101,6 +101,9 @@
 
 	properties SystemModulesProperties
 
+	// The aggregated header jars from all jars specified in the libs property.
+	// Used when system module is added as a dependency to bootclasspath.
+	headerJars android.Paths
 	outputDir  android.Path
 	outputDeps android.Paths
 }
@@ -118,6 +121,8 @@
 		jars = append(jars, dep.HeaderJars()...)
 	})
 
+	system.headerJars = jars
+
 	system.outputDir, system.outputDeps = TransformJarsToSystemModules(ctx, "java.base", jars)
 }
 
diff --git a/java/testing.go b/java/testing.go
index a37c0a9..acbefb9 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -103,7 +103,6 @@
 	`
 
 	systemModules := []string{
-		"core-system-modules",
 		"core-current-stubs-system-modules",
 		"core-platform-api-stubs-system-modules",
 		"android_stubs_current_system_modules",
@@ -114,7 +113,13 @@
 	for _, extra := range systemModules {
 		bp += fmt.Sprintf(`
 			java_system_modules {
-				name: "%s",
+				name: "%[1]s",
+				libs: ["%[1]s-lib"],
+			}
+			java_library {
+				name: "%[1]s-lib",
+				sdk_version: "none",
+				system_modules: "none",
 			}
 		`, extra)
 	}
diff --git a/python/binary.go b/python/binary.go
index 140f07a..695fa12 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -47,6 +47,11 @@
 	// false it will act much like the normal `python` executable, but with the sources and
 	// libraries automatically included in the PYTHONPATH.
 	Autorun *bool `android:"arch_variant"`
+
+	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
+	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
+	// explicitly.
+	Auto_gen_config *bool
 }
 
 type binaryDecorator struct {
diff --git a/python/test.go b/python/test.go
index 55b0ab5..f684fd5 100644
--- a/python/test.go
+++ b/python/test.go
@@ -50,7 +50,8 @@
 
 func (test *testDecorator) install(ctx android.ModuleContext, file android.Path) {
 	test.testConfig = tradefed.AutoGenPythonBinaryHostTestConfig(ctx, test.testProperties.Test_config,
-		test.testProperties.Test_config_template, test.binaryDecorator.binaryProperties.Test_suites)
+		test.testProperties.Test_config_template, test.binaryDecorator.binaryProperties.Test_suites,
+		test.binaryDecorator.binaryProperties.Auto_gen_config)
 
 	test.binaryDecorator.pythonInstaller.dir = "nativetest"
 	test.binaryDecorator.pythonInstaller.dir64 = "nativetest64"
diff --git a/rust/androidmk.go b/rust/androidmk.go
index c9056e1..107959f 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -18,7 +18,6 @@
 	"fmt"
 	"io"
 	"path/filepath"
-	"regexp"
 	"strings"
 
 	"android/soong/android"
@@ -119,37 +118,9 @@
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
 		path := compiler.path.RelPathString()
 		dir, file := filepath.Split(path)
-		stem, suffix, _ := splitFileExt(file)
+		stem, suffix, _ := android.SplitFileExt(file)
 		fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix)
 		fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(OUT_DIR)/"+filepath.Clean(dir))
 		fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)
 	})
 }
-
-//TODO: splitFileExt copied from cc/util.go; move this to android/util.go and refactor usages.
-
-// splitFileExt splits a file name into root, suffix and ext. root stands for the file name without
-// the file extension and the version number (e.g. "libexample"). suffix stands for the
-// concatenation of the file extension and the version number (e.g. ".so.1.0"). ext stands for the
-// file extension after the version numbers are trimmed (e.g. ".so").
-var shlibVersionPattern = regexp.MustCompile("(?:\\.\\d+(?:svn)?)+")
-
-func splitFileExt(name string) (string, string, string) {
-	// Extract and trim the shared lib version number if the file name ends with dot digits.
-	suffix := ""
-	matches := shlibVersionPattern.FindAllStringIndex(name, -1)
-	if len(matches) > 0 {
-		lastMatch := matches[len(matches)-1]
-		if lastMatch[1] == len(name) {
-			suffix = name[lastMatch[0]:lastMatch[1]]
-			name = name[0:lastMatch[0]]
-		}
-	}
-
-	// Extract the file name root and the file extension.
-	ext := filepath.Ext(name)
-	root := strings.TrimSuffix(name, ext)
-	suffix = ext + suffix
-
-	return root, suffix, ext
-}
diff --git a/rust/binary.go b/rust/binary.go
index 279c6f5..52f840e 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -71,6 +71,15 @@
 
 func (binary *binaryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
 	flags = binary.baseCompiler.compilerFlags(ctx, flags)
+
+	if ctx.toolchain().Bionic() {
+		// no-undefined-version breaks dylib compilation since __rust_*alloc* functions aren't defined, but we can apply this to binaries.
+		flags.LinkFlags = append(flags.LinkFlags,
+			"-Wl,--gc-sections",
+			"-Wl,-z,nocopyreloc",
+			"-Wl,--no-undefined-version")
+	}
+
 	if binary.preferDynamic() {
 		flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic")
 	}
@@ -86,6 +95,12 @@
 		}
 	}
 
+	if ctx.toolchain().Bionic() {
+		deps = binary.baseCompiler.bionicDeps(ctx, deps)
+		deps.CrtBegin = "crtbegin_dynamic"
+		deps.CrtEnd = "crtend_android"
+	}
+
 	return deps
 }
 
diff --git a/rust/builder.go b/rust/builder.go
index 64e387b..6611492 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -28,14 +28,14 @@
 		blueprint.RuleParams{
 			Command: "$rustcCmd " +
 				"-C linker=${config.RustLinker} " +
-				"-C link-args=\"${config.RustLinkerArgs} ${linkFlags}\" " +
+				"-C link-args=\"${crtBegin} ${config.RustLinkerArgs} ${linkFlags} ${crtEnd}\" " +
 				"-o $out $in ${libFlags} $rustcFlags " +
 				"&& $rustcCmd --emit=dep-info -o $out.d $in ${libFlags} $rustcFlags",
 			CommandDeps: []string{"$rustcCmd"},
 			Depfile:     "$out.d",
 			Deps:        blueprint.DepsGCC, // Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
 		},
-		"rustcFlags", "linkFlags", "libFlags")
+		"rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd")
 )
 
 func init() {
@@ -43,28 +43,19 @@
 }
 
 func TransformSrcToBinary(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	targetTriple := ctx.(ModuleContext).toolchain().RustTriple()
-
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "bin", includeDirs, targetTriple)
+	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "bin", includeDirs)
 }
 
 func TransformSrctoRlib(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	targetTriple := ctx.(ModuleContext).toolchain().RustTriple()
-
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "rlib", includeDirs, targetTriple)
+	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "rlib", includeDirs)
 }
 
 func TransformSrctoDylib(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	targetTriple := ctx.(ModuleContext).toolchain().RustTriple()
-
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "dylib", includeDirs, targetTriple)
+	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "dylib", includeDirs)
 }
 
 func TransformSrctoProcMacro(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	// Proc macros are compiler plugins, and thus should target the host compiler
-	targetTriple := ""
-
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "proc-macro", includeDirs, targetTriple)
+	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "proc-macro", includeDirs)
 }
 
 func rustLibsToPaths(libs RustLibraries) android.Paths {
@@ -76,23 +67,28 @@
 }
 
 func transformSrctoCrate(ctx android.ModuleContext, main android.Path,
-	rlibs, dylibs, proc_macros RustLibraries, static_libs, shared_libs android.Paths, flags Flags, outputFile android.WritablePath, crate_type string, includeDirs []string, targetTriple string) {
+	rlibs, dylibs, proc_macros RustLibraries, static_libs, shared_libs android.Paths, crtBegin, crtEnd android.OptionalPath, flags Flags, outputFile android.WritablePath, crate_type string, includeDirs []string) {
 
 	var inputs android.Paths
 	var deps android.Paths
-	var libFlags, rustcFlags []string
+	var libFlags, rustcFlags, linkFlags []string
 	crate_name := ctx.(ModuleContext).CrateName()
+	targetTriple := ctx.(ModuleContext).toolchain().RustTriple()
 
 	inputs = append(inputs, main)
 
 	// Collect rustc flags
-	rustcFlags = append(rustcFlags, flags.GlobalFlags...)
+	rustcFlags = append(rustcFlags, flags.GlobalRustFlags...)
 	rustcFlags = append(rustcFlags, flags.RustFlags...)
 	rustcFlags = append(rustcFlags, "--crate-type="+crate_type)
 	rustcFlags = append(rustcFlags, "--crate-name="+crate_name)
 	if targetTriple != "" {
 		rustcFlags = append(rustcFlags, "--target="+targetTriple)
+		linkFlags = append(linkFlags, "-target "+targetTriple)
 	}
+	// Collect linker flags
+	linkFlags = append(linkFlags, flags.GlobalLinkFlags...)
+	linkFlags = append(linkFlags, flags.LinkFlags...)
 
 	// Collect library/crate flags
 	for _, lib := range rlibs {
@@ -115,6 +111,9 @@
 	deps = append(deps, rustLibsToPaths(proc_macros)...)
 	deps = append(deps, static_libs...)
 	deps = append(deps, shared_libs...)
+	if crtBegin.Valid() {
+		deps = append(deps, crtBegin.Path(), crtEnd.Path())
+	}
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        rustc,
@@ -124,8 +123,10 @@
 		Implicits:   deps,
 		Args: map[string]string{
 			"rustcFlags": strings.Join(rustcFlags, " "),
-			"linkFlags":  strings.Join(flags.LinkFlags, " "),
+			"linkFlags":  strings.Join(linkFlags, " "),
 			"libFlags":   strings.Join(libFlags, " "),
+			"crtBegin":   crtBegin.String(),
+			"crtEnd":     crtEnd.String(),
 		},
 	})
 
diff --git a/rust/compiler.go b/rust/compiler.go
index 87cf08b..f45744b 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -113,7 +113,8 @@
 	flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(compiler.Properties.Features)...)
 	flags.RustFlags = append(flags.RustFlags, "--edition="+*compiler.Properties.Edition)
 	flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...)
-	flags.GlobalFlags = append(flags.GlobalFlags, ctx.toolchain().ToolchainRustFlags())
+	flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags())
+	flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, ctx.toolchain().ToolchainLinkFlags())
 
 	if ctx.Host() && !ctx.Windows() {
 		rpath_prefix := `\$$ORIGIN/`
@@ -148,6 +149,18 @@
 	return deps
 }
 
+func (compiler *baseCompiler) bionicDeps(ctx DepsContext, deps Deps) Deps {
+	deps.SharedLibs = append(deps.SharedLibs, "liblog")
+	deps.SharedLibs = append(deps.SharedLibs, "libc")
+	deps.SharedLibs = append(deps.SharedLibs, "libm")
+	deps.SharedLibs = append(deps.SharedLibs, "libdl")
+
+	//TODO(b/141331117) libstd requires libgcc on Android
+	deps.StaticLibs = append(deps.StaticLibs, "libgcc")
+
+	return deps
+}
+
 func (compiler *baseCompiler) crateName() string {
 	return compiler.Properties.Crate_name
 }
diff --git a/rust/compiler_test.go b/rust/compiler_test.go
index 5369096..bbf9f8d 100644
--- a/rust/compiler_test.go
+++ b/rust/compiler_test.go
@@ -64,7 +64,6 @@
 		rust_proc_macro {
 			name: "foo-bar-proc-macro",
 			srcs: ["foo.rs", "src/bar.rs"],
-			host_supported: true,
 		}`)
 
 	// Test prebuilts
diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go
new file mode 100644
index 0000000..0264052
--- /dev/null
+++ b/rust/config/arm64_device.go
@@ -0,0 +1,92 @@
+// 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 (
+	Arm64RustFlags            = []string{}
+	Arm64ArchFeatureRustFlags = map[string][]string{}
+	Arm64LinkFlags            = []string{
+		"-Wl,--icf=safe",
+		"-Wl,-z,max-page-size=4096",
+
+		"-Wl,-execute-only",
+	}
+
+	Arm64ArchVariantRustFlags = map[string][]string{
+		"armv8-a":  []string{},
+		"armv8-2a": []string{},
+	}
+)
+
+func init() {
+	registerToolchainFactory(android.Android, android.Arm64, Arm64ToolchainFactory)
+
+	pctx.StaticVariable("Arm64ToolchainRustFlags", strings.Join(Arm64RustFlags, " "))
+	pctx.StaticVariable("Arm64ToolchainLinkFlags", strings.Join(Arm64LinkFlags, " "))
+
+	for variant, rustFlags := range Arm64ArchVariantRustFlags {
+		pctx.StaticVariable("Arm64"+variant+"VariantRustFlags",
+			strings.Join(rustFlags, " "))
+	}
+
+}
+
+type toolchainArm64 struct {
+	toolchain64Bit
+	toolchainRustFlags string
+}
+
+func (t *toolchainArm64) RustTriple() string {
+	return "aarch64-linux-android"
+}
+
+func (t *toolchainArm64) ToolchainLinkFlags() string {
+	return "${config.DeviceGlobalLinkFlags} ${config.Arm64ToolchainLinkFlags}"
+}
+
+func (t *toolchainArm64) ToolchainRustFlags() string {
+	return t.toolchainRustFlags
+}
+
+func (t *toolchainArm64) RustFlags() string {
+	return "${config.Arm64ToolchainRustFlags}"
+}
+
+func (t *toolchainArm64) Supported() bool {
+	return true
+}
+
+func Arm64ToolchainFactory(arch android.Arch) Toolchain {
+	toolchainRustFlags := []string{
+		"${config.Arm64ToolchainRustFlags}",
+		"${config.Arm64" + arch.ArchVariant + "VariantRustFlags}",
+	}
+
+	toolchainRustFlags = append(toolchainRustFlags, deviceGlobalRustFlags...)
+
+	for _, feature := range arch.ArchFeatures {
+		toolchainRustFlags = append(toolchainRustFlags, Arm64ArchFeatureRustFlags[feature]...)
+	}
+
+	return &toolchainArm64{
+		toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
+	}
+}
diff --git a/rust/config/arm_device.go b/rust/config/arm_device.go
new file mode 100644
index 0000000..aedb42b
--- /dev/null
+++ b/rust/config/arm_device.go
@@ -0,0 +1,92 @@
+// 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 (
+	ArmRustFlags            = []string{}
+	ArmArchFeatureRustFlags = map[string][]string{}
+	ArmLinkFlags            = []string{
+		"-Wl,--icf=safe",
+		"-Wl,-m,armelf",
+	}
+
+	ArmArchVariantRustFlags = map[string][]string{
+		"armv7-a":      []string{},
+		"armv7-a-neon": []string{},
+		"armv8-a":      []string{},
+		"armv8-2a":     []string{},
+	}
+)
+
+func init() {
+	registerToolchainFactory(android.Android, android.Arm, ArmToolchainFactory)
+
+	pctx.StaticVariable("ArmToolchainRustFlags", strings.Join(ArmRustFlags, " "))
+	pctx.StaticVariable("ArmToolchainLinkFlags", strings.Join(ArmLinkFlags, " "))
+
+	for variant, rustFlags := range ArmArchVariantRustFlags {
+		pctx.StaticVariable("Arm"+variant+"VariantRustFlags",
+			strings.Join(rustFlags, " "))
+	}
+
+}
+
+type toolchainArm struct {
+	toolchain64Bit
+	toolchainRustFlags string
+}
+
+func (t *toolchainArm) RustTriple() string {
+	return "arm-linux-androideabi"
+}
+
+func (t *toolchainArm) ToolchainLinkFlags() string {
+	return "${config.DeviceGlobalLinkFlags} ${config.ArmToolchainLinkFlags}"
+}
+
+func (t *toolchainArm) ToolchainRustFlags() string {
+	return t.toolchainRustFlags
+}
+
+func (t *toolchainArm) RustFlags() string {
+	return "${config.ArmToolchainRustFlags}"
+}
+
+func (t *toolchainArm) Supported() bool {
+	return true
+}
+
+func ArmToolchainFactory(arch android.Arch) Toolchain {
+	toolchainRustFlags := []string{
+		"${config.ArmToolchainRustFlags}",
+		"${config.Arm" + arch.ArchVariant + "VariantRustFlags}",
+	}
+
+	toolchainRustFlags = append(toolchainRustFlags, deviceGlobalRustFlags...)
+
+	for _, feature := range arch.ArchFeatures {
+		toolchainRustFlags = append(toolchainRustFlags, ArmArchFeatureRustFlags[feature]...)
+	}
+
+	return &toolchainArm{
+		toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
+	}
+}
diff --git a/rust/config/global.go b/rust/config/global.go
index 2e08a8c..cec5a74 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -15,6 +15,8 @@
 package config
 
 import (
+	"strings"
+
 	"android/soong/android"
 	_ "android/soong/cc/config"
 )
@@ -22,19 +24,31 @@
 var pctx = android.NewPackageContext("android/soong/rust/config")
 
 var (
-	RustDefaultVersion = "1.35.0"
+	RustDefaultVersion = "1.37.0"
 	RustDefaultBase    = "prebuilts/rust/"
 	DefaultEdition     = "2018"
 	Stdlibs            = []string{
-		"libarena",
-		"libfmt_macros",
-		"libgraphviz",
-		"libserialize",
 		"libstd",
-		"libsyntax",
-		"libsyntax_ext",
-		"libsyntax_pos",
 		"libterm",
+		"libtest",
+	}
+
+	deviceGlobalRustFlags = []string{}
+
+	deviceGlobalLinkFlags = []string{
+		"-Bdynamic",
+		"-nostdlib",
+		"-Wl,-z,noexecstack",
+		"-Wl,-z,relro",
+		"-Wl,-z,now",
+		"-Wl,--build-id=md5",
+		"-Wl,--warn-shared-textrel",
+		"-Wl,--fatal-warnings",
+
+		"-Wl,--pack-dyn-relocs=android+relr",
+		"-Wl,--use-android-relr-tags",
+		"-Wl,--no-undefined",
+		"-Wl,--hash-style=gnu",
 	}
 )
 
@@ -62,4 +76,7 @@
 	pctx.ImportAs("ccConfig", "android/soong/cc/config")
 	pctx.StaticVariable("RustLinker", "${ccConfig.ClangBin}/clang++")
 	pctx.StaticVariable("RustLinkerArgs", "-B ${ccConfig.ClangBin} -fuse-ld=lld")
+
+	pctx.StaticVariable("DeviceGlobalLinkFlags", strings.Join(deviceGlobalLinkFlags, " "))
+
 }
diff --git a/rust/config/toolchain.go b/rust/config/toolchain.go
index a36d61b..328bca3 100644
--- a/rust/config/toolchain.go
+++ b/rust/config/toolchain.go
@@ -32,6 +32,8 @@
 
 	Is64Bit() bool
 	Supported() bool
+
+	Bionic() bool
 }
 
 type toolchainBase struct {
@@ -53,6 +55,10 @@
 	panic("toolchainBase cannot determine datapath width.")
 }
 
+func (toolchainBase) Bionic() bool {
+	return true
+}
+
 type toolchain64Bit struct {
 	toolchainBase
 }
diff --git a/rust/config/whitelist.go b/rust/config/whitelist.go
new file mode 100644
index 0000000..4646264
--- /dev/null
+++ b/rust/config/whitelist.go
@@ -0,0 +1,21 @@
+package config
+
+var (
+	RustAllowedPaths = []string{
+		"external/rust/crates",
+		"external/crosvm",
+		"external/adhd",
+	}
+
+	RustModuleTypes = []string{
+		"rust_binary",
+		"rust_binary_host",
+		"rust_library",
+		"rust_library_dylib",
+		"rust_library_rlib",
+		"rust_library_host",
+		"rust_library_host_dylib",
+		"rust_library_host_rlib",
+		"rust_proc_macro",
+	}
+)
diff --git a/rust/config/x86_linux_host.go b/rust/config/x86_linux_host.go
index cb6bf1a..5376e5b 100644
--- a/rust/config/x86_linux_host.go
+++ b/rust/config/x86_linux_host.go
@@ -61,6 +61,10 @@
 	return true
 }
 
+func (toolchainLinuxX8664) Bionic() bool {
+	return false
+}
+
 func (t *toolchainLinuxX8664) Name() string {
 	return "x86_64"
 }
@@ -85,6 +89,10 @@
 	return true
 }
 
+func (toolchainLinuxX86) Bionic() bool {
+	return false
+}
+
 func (t *toolchainLinuxX86) Name() string {
 	return "x86"
 }
diff --git a/rust/library.go b/rust/library.go
index 5cf8ac7..c831727 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -191,6 +191,16 @@
 		&library.MutatedProperties)
 }
 
+func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
+	deps = library.baseCompiler.compilerDeps(ctx, deps)
+
+	if ctx.toolchain().Bionic() && library.dylib() {
+		deps = library.baseCompiler.bionicDeps(ctx, deps)
+	}
+
+	return deps
+}
+
 func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
 	var outputFile android.WritablePath
 
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index d4e631b..fa69fbb 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -63,3 +63,8 @@
 
 	return srcPath
 }
+
+func (prebuilt *prebuiltLibraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
+	deps = prebuilt.baseCompiler.compilerDeps(ctx, deps)
+	return deps
+}
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 4acb06f..1a247d9 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -45,7 +45,7 @@
 var _ compiler = (*procMacroDecorator)(nil)
 
 func ProcMacroFactory() android.Module {
-	module, _ := NewProcMacro(android.HostAndDeviceSupported)
+	module, _ := NewProcMacro(android.HostSupportedNoCross)
 	return module.Init()
 }
 
diff --git a/rust/rust.go b/rust/rust.go
index 62ccfc7..61b51e5 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -29,28 +29,11 @@
 
 func init() {
 	// Only allow rust modules to be defined for certain projects
-	rustModuleTypes := []string{
-		"rust_binary",
-		"rust_binary_host",
-		"rust_library",
-		"rust_library_dylib",
-		"rust_library_rlib",
-		"rust_library_host",
-		"rust_library_host_dylib",
-		"rust_library_host_rlib",
-		"rust_proc_macro",
-	}
-
-	rustAllowedPaths := []string{
-		"external/rust/crates",
-		"external/crosvm",
-		"external/adhd",
-	}
 
 	android.AddNeverAllowRules(
 		android.NeverAllow().
-			NotIn(rustAllowedPaths...).
-			ModuleType(rustModuleTypes...))
+			NotIn(config.RustAllowedPaths...).
+			ModuleType(config.RustModuleTypes...))
 
 	android.RegisterModuleType("rust_defaults", defaultsFactory)
 	android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -60,11 +43,12 @@
 }
 
 type Flags struct {
-	GlobalFlags   []string      // Flags that apply globally
-	RustFlags     []string      // Flags that apply to rust
-	LinkFlags     []string      // Flags that apply to linker
-	RustFlagsDeps android.Paths // Files depended on by compiler flags
-	Toolchain     config.Toolchain
+	GlobalRustFlags []string      // Flags that apply globally to rust
+	GlobalLinkFlags []string      // Flags that apply globally to linker
+	RustFlags       []string      // Flags that apply to rust
+	LinkFlags       []string      // Flags that apply to linker
+	RustFlagsDeps   android.Paths // Files depended on by compiler flags
+	Toolchain       config.Toolchain
 }
 
 type BaseProperties struct {
@@ -109,6 +93,9 @@
 	linkDirs   []string
 	depFlags   []string
 	//ReexportedDeps android.Paths
+
+	CrtBegin android.OptionalPath
+	CrtEnd   android.OptionalPath
 }
 
 type RustLibraries []RustLibrary
@@ -334,17 +321,10 @@
 	ctx.VisitDirectDeps(func(dep android.Module) {
 		depName := ctx.OtherModuleName(dep)
 		depTag := ctx.OtherModuleDependencyTag(dep)
-		if dep.Target().Os != ctx.Os() {
-			ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
-			return
-		}
-		if dep.Target().Arch.ArchType != ctx.Arch().ArchType {
-			ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
-			return
-		}
 
 		if rustDep, ok := dep.(*Module); ok {
 			//Handle Rust Modules
+
 			linkFile := rustDep.outputFile
 			if !linkFile.Valid() {
 				ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
@@ -376,9 +356,6 @@
 			if lib, ok := rustDep.compiler.(*libraryDecorator); ok {
 				depPaths.linkDirs = append(depPaths.linkDirs, lib.exportedDirs()...)
 				depPaths.depFlags = append(depPaths.depFlags, lib.exportedDepFlags()...)
-			} else if procMacro, ok := rustDep.compiler.(*libraryDecorator); ok {
-				depPaths.linkDirs = append(depPaths.linkDirs, procMacro.exportedDirs()...)
-				depPaths.depFlags = append(depPaths.depFlags, procMacro.exportedDepFlags()...)
 			}
 
 			// Append this dependencies output to this mod's linkDirs so they can be exported to dependencies
@@ -393,8 +370,17 @@
 			}
 
 		} else if ccDep, ok := dep.(*cc.Module); ok {
-
 			//Handle C dependencies
+
+			if ccDep.Target().Os != ctx.Os() {
+				ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
+				return
+			}
+			if ccDep.Target().Arch.ArchType != ctx.Arch().ArchType {
+				ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
+				return
+			}
+
 			linkFile := ccDep.OutputFile()
 			linkPath := linkPathFromFilePath(linkFile.Path())
 			libName := libNameFromFilePath(linkFile.Path())
@@ -416,6 +402,10 @@
 				directSharedLibDeps = append(directSharedLibDeps, ccDep)
 				mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName)
 				exportDep = true
+			case cc.CrtBeginDepTag():
+				depPaths.CrtBegin = linkFile
+			case cc.CrtEndDepTag():
+				depPaths.CrtEnd = linkFile
 			}
 
 			// Make sure these dependencies are propagated
@@ -497,7 +487,16 @@
 	}
 	actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "shared"}), cc.SharedDepTag(), deps.SharedLibs...)
 	actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "static"}), cc.StaticDepTag(), deps.StaticLibs...)
-	actx.AddDependency(mod, procMacroDepTag, deps.ProcMacros...)
+
+	if deps.CrtBegin != "" {
+		actx.AddVariationDependencies(ccDepVariations, cc.CrtBeginDepTag(), deps.CrtBegin)
+	}
+	if deps.CrtEnd != "" {
+		actx.AddVariationDependencies(ccDepVariations, cc.CrtEndDepTag(), deps.CrtEnd)
+	}
+
+	// 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...)
 }
 
 func (mod *Module) Name() string {
diff --git a/rust/rust_test.go b/rust/rust_test.go
index f7c96dd..0c8d355 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -18,6 +18,7 @@
 	"io/ioutil"
 	"os"
 	"runtime"
+	"strings"
 	"testing"
 
 	"android/soong/android"
@@ -150,7 +151,6 @@
 		rust_proc_macro {
 			name: "libpm",
 			srcs: ["foo.rs"],
-			host_supported: true,
 		}
 		rust_binary_host {
 			name: "fizz-buzz",
@@ -176,3 +176,28 @@
 	}
 
 }
+
+// Test to make sure proc_macros use host variants when building device modules.
+func TestProcMacroDeviceDeps(t *testing.T) {
+	ctx := testRust(t, `
+		rust_library_host_rlib {
+			name: "libbar",
+			srcs: ["foo.rs"],
+		}
+		rust_proc_macro {
+			name: "libpm",
+			rlibs: ["libbar"],
+			srcs: ["foo.rs"],
+		}
+		rust_binary {
+			name: "fizz-buzz",
+			proc_macros: ["libpm"],
+			srcs: ["foo.rs"],
+		}
+	`)
+	rustc := ctx.ModuleForTests("libpm", "linux_glibc_x86_64").Rule("rustc")
+
+	if !strings.Contains(rustc.Args["libFlags"], "libbar/linux_glibc_x86_64") {
+		t.Errorf("Proc_macro is not using host variant of dependent modules.")
+	}
+}
diff --git a/rust/testing.go b/rust/testing.go
index a38697f..92347f1 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/cc"
 )
 
 func GatherRequiredDepsForTest() string {
@@ -70,12 +71,101 @@
 				srcs: [""],
 				host_supported: true,
 		}
+
+		//////////////////////////////
+		// Device module requirements
+
+		toolchain_library {
+			name: "libgcc",
+			no_libcrt: true,
+			nocrt: true,
+			src: "",
+			system_shared_libs: [],
+		}
+		cc_library {
+			name: "libc",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+		}
+		cc_library {
+			name: "libm",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+		}
+		cc_library {
+			name: "libdl",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+		}
+		cc_object {
+			name: "crtbegin_dynamic",
+		}
+
+		cc_object {
+			name: "crtend_android",
+		}
+		cc_library {
+			name: "liblog",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+		}
+
+		//////////////////////////////
+		// cc module requirements
+
+		toolchain_library {
+			name: "libatomic",
+			src: "",
+		}
+		toolchain_library {
+			name: "libclang_rt.builtins-aarch64-android",
+			src: "",
+		}
+		toolchain_library {
+			name: "libgcc_stripped",
+			src: "",
+		}
+		cc_library {
+			name: "libc++_static",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+		}
+		cc_library {
+			name: "libc++demangle",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+			host_supported: false,
+		}
+		cc_library {
+			name: "libc++",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+		}
+		cc_library {
+			name: "libunwind_llvm",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+		}
 		`
 	return bp
 }
 
 func CreateTestContext(bp string) *android.TestContext {
 	ctx := android.NewTestArchContext()
+	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
+	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
 	ctx.RegisterModuleType("rust_binary", android.ModuleFactoryAdaptor(RustBinaryFactory))
 	ctx.RegisterModuleType("rust_binary_host", android.ModuleFactoryAdaptor(RustBinaryHostFactory))
 	ctx.RegisterModuleType("rust_library", android.ModuleFactoryAdaptor(RustLibraryFactory))
@@ -86,9 +176,16 @@
 	ctx.RegisterModuleType("rust_library_dylib", android.ModuleFactoryAdaptor(RustLibraryDylibFactory))
 	ctx.RegisterModuleType("rust_proc_macro", android.ModuleFactoryAdaptor(ProcMacroFactory))
 	ctx.RegisterModuleType("rust_prebuilt_dylib", android.ModuleFactoryAdaptor(PrebuiltDylibFactory))
+	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
 	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
+
+		ctx.BottomUp("image", cc.ImageMutator).Parallel()
+		ctx.BottomUp("link", cc.LinkageMutator).Parallel()
+		ctx.BottomUp("version", cc.VersionMutator).Parallel()
+		ctx.BottomUp("begin", cc.BeginMutator).Parallel()
 	})
+
 	bp = bp + GatherRequiredDepsForTest()
 
 	mockFS := map[string][]byte{
diff --git a/scripts/strip.sh b/scripts/strip.sh
index 52f9366..f987d98 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -29,7 +29,6 @@
 #   --keep-mini-debug-info
 #   --keep-symbols
 #   --keep-symbols-and-debug-frame
-#   --use-gnu-strip
 #   --remove-build-id
 
 set -o pipefail
@@ -44,86 +43,55 @@
         --keep-mini-debug-info          Keep compressed debug info in out-file
         --keep-symbols                  Keep symbols in out-file
         --keep-symbols-and-debug-frame  Keep symbols and .debug_frame in out-file
-        --use-gnu-strip                 Use strip/objcopy instead of llvm-{strip,objcopy}
         --remove-build-id               Remove the gnu build-id section in out-file
 EOF
     exit 1
 }
 
-# Without --use-gnu-strip, GNU strip is replaced with llvm-strip to work around
-# old GNU strip bug on lld output files, b/80093681.
-# Similary, calls to objcopy are replaced with llvm-objcopy,
-# with some exceptions.
-
 do_strip() {
-    # ${CROSS_COMPILE}strip --strip-all does not strip .ARM.attributes,
+    # GNU strip --strip-all does not strip .ARM.attributes,
     # so we tell llvm-strip to keep it too.
-    if [ -z "${use_gnu_strip}" ]; then
-        "${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes "${infile}" -o "${outfile}.tmp"
-    else
-        "${CROSS_COMPILE}strip" --strip-all "${infile}" -o "${outfile}.tmp"
-    fi
+    "${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes "${infile}" -o "${outfile}.tmp"
 }
 
 do_strip_keep_symbols_and_debug_frame() {
-    REMOVE_SECTIONS=`"${CROSS_COMPILE}readelf" -S "${infile}" | awk '/.debug_/ {if ($2 != ".debug_frame") {print "--remove-section " $2}}' | xargs`
-    if [ -z "${use_gnu_strip}" ]; then
-        "${CLANG_BIN}/llvm-objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
-    else
-        "${CROSS_COMPILE}objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
-    fi
+    REMOVE_SECTIONS=`"${CLANG_BIN}/llvm-readelf" -S "${infile}" | awk '/.debug_/ {if ($2 != ".debug_frame") {print "--remove-section " $2}}' | xargs`
+    "${CLANG_BIN}/llvm-objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
 }
 
 do_strip_keep_symbols() {
-    REMOVE_SECTIONS=`"${CROSS_COMPILE}readelf" -S "${infile}" | awk '/.debug_/ {print "--remove-section " $2}' | xargs`
-    if [ -z "${use_gnu_strip}" ]; then
-        "${CLANG_BIN}/llvm-objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
-    else
-        "${CROSS_COMPILE}objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
-    fi
+    REMOVE_SECTIONS=`"${CLANG_BIN}/llvm-readelf" -S "${infile}" | awk '/.debug_/ {print "--remove-section " $2}' | xargs`
+    "${CLANG_BIN}/llvm-objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
 }
 
 do_strip_keep_symbol_list() {
     echo "${symbols_to_keep}" | tr ',' '\n' > "${outfile}.symbolList"
 
-    if [ -z "${use_gnu_strip}" ]; then
-        KEEP_SYMBOLS="--strip-unneeded-symbol=.* --keep-symbols="
-        KEEP_SYMBOLS+="${outfile}.symbolList"
-        "${CLANG_BIN}/llvm-objcopy" --regex "${infile}" "${outfile}.tmp" ${KEEP_SYMBOLS}
-    else
-        KEEP_SYMBOLS="--strip-unneeded-symbol=* --keep-symbols="
-        KEEP_SYMBOLS+="${outfile}.symbolList"
-        "${CROSS_COMPILE}objcopy" -w "${infile}" "${outfile}.tmp" ${KEEP_SYMBOLS}
-    fi
+    KEEP_SYMBOLS="--strip-unneeded-symbol=.* --keep-symbols="
+    KEEP_SYMBOLS+="${outfile}.symbolList"
+    "${CLANG_BIN}/llvm-objcopy" --regex "${infile}" "${outfile}.tmp" ${KEEP_SYMBOLS}
 }
 
 do_strip_keep_mini_debug_info() {
     rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo" "${outfile}.mini_debuginfo.xz"
     local fail=
-    if [ -z "${use_gnu_strip}" ]; then
-        "${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes --remove-section=.comment "${infile}" -o "${outfile}.tmp" || fail=true
-    else
-        "${CROSS_COMPILE}strip" --strip-all -R .comment "${infile}" -o "${outfile}.tmp" || fail=true
-    fi
+    "${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes --remove-section=.comment "${infile}" -o "${outfile}.tmp" || fail=true
+
     if [ -z $fail ]; then
-        # Current prebult llvm-objcopy does not support the following flags:
-        #    --only-keep-debug --rename-section --keep-symbols
-        # For the following use cases, ${CROSS_COMPILE}objcopy does fine with lld linked files,
-        # except the --add-section flag.
+        # Current prebult llvm-objcopy does not support --only-keep-debug flag,
+        # and cannot process object files that are produced with the flag. Use
+        # GNU objcopy instead for now. (b/141010852)
         "${CROSS_COMPILE}objcopy" --only-keep-debug "${infile}" "${outfile}.debug"
-        "${CROSS_COMPILE}nm" -D "${infile}" --format=posix --defined-only 2> /dev/null | awk '{ print $1 }' | sort >"${outfile}.dynsyms"
-        "${CROSS_COMPILE}nm" "${infile}" --format=posix --defined-only | awk '{ if ($2 == "T" || $2 == "t" || $2 == "D") print $1 }' | sort > "${outfile}.funcsyms"
+        "${CLANG_BIN}/llvm-nm" -D "${infile}" --format=posix --defined-only 2> /dev/null | awk '{ print $1 }' | sort >"${outfile}.dynsyms"
+        "${CLANG_BIN}/llvm-nm" "${infile}" --format=posix --defined-only | awk '{ if ($2 == "T" || $2 == "t" || $2 == "D") print $1 }' | sort > "${outfile}.funcsyms"
         comm -13 "${outfile}.dynsyms" "${outfile}.funcsyms" > "${outfile}.keep_symbols"
         echo >> "${outfile}.keep_symbols" # Ensure that the keep_symbols file is not empty.
         "${CROSS_COMPILE}objcopy" --rename-section .debug_frame=saved_debug_frame "${outfile}.debug" "${outfile}.mini_debuginfo"
         "${CROSS_COMPILE}objcopy" -S --remove-section .gdb_index --remove-section .comment --keep-symbols="${outfile}.keep_symbols" "${outfile}.mini_debuginfo"
         "${CROSS_COMPILE}objcopy" --rename-section saved_debug_frame=.debug_frame "${outfile}.mini_debuginfo"
         "${XZ}" "${outfile}.mini_debuginfo"
-        if [ -z "${use_gnu_strip}" ]; then
-            "${CLANG_BIN}/llvm-objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp"
-        else
-            "${CROSS_COMPILE}objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp"
-        fi
+
+        "${CLANG_BIN}/llvm-objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp"
         rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo" "${outfile}.mini_debuginfo.xz"
     else
         cp -f "${infile}" "${outfile}.tmp"
@@ -131,19 +99,11 @@
 }
 
 do_add_gnu_debuglink() {
-    if [ -z "${use_gnu_strip}" ]; then
-        "${CLANG_BIN}/llvm-objcopy" --add-gnu-debuglink="${infile}" "${outfile}.tmp"
-    else
-        "${CROSS_COMPILE}objcopy" --add-gnu-debuglink="${infile}" "${outfile}.tmp"
-    fi
+    "${CLANG_BIN}/llvm-objcopy" --add-gnu-debuglink="${infile}" "${outfile}.tmp"
 }
 
 do_remove_build_id() {
-    if [ -z "${use_gnu_strip}" ]; then
-        "${CLANG_BIN}/llvm-strip" --remove-section=.note.gnu.build-id "${outfile}.tmp" -o "${outfile}.tmp.no-build-id"
-    else
-        "${CROSS_COMPILE}strip" --remove-section=.note.gnu.build-id "${outfile}.tmp" -o "${outfile}.tmp.no-build-id"
-    fi
+    "${CLANG_BIN}/llvm-strip" --remove-section=.note.gnu.build-id "${outfile}.tmp" -o "${outfile}.tmp.no-build-id"
     rm -f "${outfile}.tmp"
     mv "${outfile}.tmp.no-build-id" "${outfile}.tmp"
 }
@@ -161,7 +121,6 @@
                 keep-symbols) keep_symbols=true ;;
                 keep-symbols-and-debug-frame) keep_symbols_and_debug_frame=true ;;
                 remove-build-id) remove_build_id=true ;;
-                use-gnu-strip) use_gnu_strip=true ;;
                 *) echo "Unknown option --${OPTARG}"; usage ;;
             esac;;
         ?) usage ;;
@@ -234,18 +193,13 @@
 rm -f "${outfile}"
 mv "${outfile}.tmp" "${outfile}"
 
-if [ -z "${use_gnu_strip}" ]; then
-  USED_STRIP_OBJCOPY="${CLANG_BIN}/llvm-strip ${CLANG_BIN}/llvm-objcopy"
-else
-  USED_STRIP_OBJCOPY="${CROSS_COMPILE}strip"
-fi
-
 cat <<EOF > "${depsfile}"
 ${outfile}: \
   ${infile} \
-  ${CROSS_COMPILE}nm \
   ${CROSS_COMPILE}objcopy \
-  ${CROSS_COMPILE}readelf \
-  ${USED_STRIP_OBJCOPY}
+  ${CLANG_BIN}/llvm-nm \
+  ${CLANG_BIN}/llvm-objcopy \
+  ${CLANG_BIN}/llvm-readelf \
+  ${CLANG_BIN}/llvm-strip
 
 EOF
diff --git a/sdk/sdk.go b/sdk/sdk.go
new file mode 100644
index 0000000..fcb3fb7
--- /dev/null
+++ b/sdk/sdk.go
@@ -0,0 +1,172 @@
+// 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 (
+	"github.com/google/blueprint"
+
+	"android/soong/android"
+	// This package doesn't depend on the apex package, but import it to make its mutators to be
+	// registered before mutators in this package. See RegisterPostDepsMutators for more details.
+	_ "android/soong/apex"
+)
+
+func init() {
+	android.RegisterModuleType("sdk", ModuleFactory)
+	android.PreDepsMutators(RegisterPreDepsMutators)
+	android.PostDepsMutators(RegisterPostDepsMutators)
+}
+
+type sdk struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	properties sdkProperties
+}
+
+type sdkProperties struct {
+	// The list of java_import modules that provide Java stubs for this SDK
+	Java_libs          []string
+	Native_shared_libs []string
+}
+
+// sdk defines an SDK which is a logical group of modules (e.g. native libs, headers, java libs, etc.)
+// which Mainline modules like APEX can choose to build with.
+func ModuleFactory() android.Module {
+	s := &sdk{}
+	s.AddProperties(&s.properties)
+	android.InitAndroidMultiTargetsArchModule(s, android.HostAndDeviceSupported, android.MultilibCommon)
+	android.InitDefaultableModule(s)
+	return s
+}
+
+func (s *sdk) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	// TODO(jiyong): add build rules for creating stubs from members of this SDK
+}
+
+// RegisterPreDepsMutators registers pre-deps mutators to support modules implementing SdkAware
+// interface and the sdk module type. This function has been made public to be called by tests
+// outside of the sdk package
+func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
+	ctx.BottomUp("SdkMember", memberMutator).Parallel()
+	ctx.TopDown("SdkMember_deps", memberDepsMutator).Parallel()
+	ctx.BottomUp("SdkMemberInterVersion", memberInterVersionMutator).Parallel()
+}
+
+// RegisterPostDepshMutators registers post-deps mutators to support modules implementing SdkAware
+// interface and the sdk module type. This function has been made public to be called by tests
+// outside of the sdk package
+func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
+	// These must run AFTER apexMutator. Note that the apex package is imported even though there is
+	// no direct dependency to the package here. sdkDepsMutator sets the SDK requirements from an
+	// APEX to its dependents. Since different versions of the same SDK can be used by different
+	// APEXes, the apex and its dependents (which includes the dependencies to the sdk members)
+	// should have been mutated for the apex before the SDK requirements are set.
+	ctx.TopDown("SdkDepsMutator", sdkDepsMutator).Parallel()
+	ctx.BottomUp("SdkDepsReplaceMutator", sdkDepsReplaceMutator).Parallel()
+}
+
+type dependencyTag struct {
+	blueprint.BaseDependencyTag
+}
+
+// For dependencies from an SDK module to its members
+// e.g. mysdk -> libfoo and libbar
+var sdkMemberDepTag dependencyTag
+
+// For dependencies from an in-development version of an SDK member to frozen versions of the same member
+// e.g. libfoo -> libfoo.mysdk.11 and libfoo.mysdk.12
+type sdkMemberVesionedDepTag struct {
+	dependencyTag
+	member  string
+	version string
+}
+
+// Step 1: create dependencies from an SDK module to its members.
+func memberMutator(mctx android.BottomUpMutatorContext) {
+	if m, ok := mctx.Module().(*sdk); ok {
+		mctx.AddVariationDependencies(nil, sdkMemberDepTag, m.properties.Java_libs...)
+
+		targets := mctx.MultiTargets()
+		for _, target := range targets {
+			mctx.AddFarVariationDependencies([]blueprint.Variation{
+				{Mutator: "arch", Variation: target.String()},
+				{Mutator: "image", Variation: "core"},
+				{Mutator: "link", Variation: "shared"},
+			}, 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 {
+		mySdkRef := android.ParseSdkRef(mctx, mctx.ModuleName(), "name")
+		mctx.VisitDirectDeps(func(child android.Module) {
+			if member, ok := child.(android.SdkAware); ok {
+				member.MakeMemberOf(mySdkRef)
+			}
+		})
+	}
+}
+
+// Step 3: create dependencies from the in-development version of an SDK member to frozen 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
+// built with libfoo.mysdk.11 and libfoo.mysdk.12, respectively depending on which sdk they are
+// using.
+func memberInterVersionMutator(mctx android.BottomUpMutatorContext) {
+	if m, ok := mctx.Module().(android.SdkAware); ok && m.IsInAnySdk() {
+		if !m.ContainingSdk().IsCurrentVersion() {
+			memberName := m.MemberName()
+			tag := sdkMemberVesionedDepTag{member: memberName, version: m.ContainingSdk().Version}
+			mctx.AddReverseDependency(mctx.Module(), tag, memberName)
+		}
+	}
+}
+
+// Step 4: transitively ripple down the SDK requirements from the root modules like APEX to its
+// descendants
+func sdkDepsMutator(mctx android.TopDownMutatorContext) {
+	if m, ok := mctx.Module().(android.SdkAware); ok {
+		// Module types for Mainline modules (e.g. APEX) are expected to implement RequiredSdks()
+		// by reading its own properties like `uses_sdks`.
+		requiredSdks := m.RequiredSdks()
+		if len(requiredSdks) > 0 {
+			mctx.VisitDirectDeps(func(m android.Module) {
+				if dep, ok := m.(android.SdkAware); ok {
+					dep.BuildWithSdks(requiredSdks)
+				}
+			})
+		}
+	}
+}
+
+// Step 5: if libfoo.mysdk.11 is in the context where version 11 of mysdk is requested, the
+// 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 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
+				// apex references in other APEXes are not affected by this replacement.
+				memberName := m.MemberName()
+				mctx.ReplaceDependencies(memberName)
+			}
+		}
+	}
+}
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
new file mode 100644
index 0000000..9eca72f
--- /dev/null
+++ b/sdk/sdk_test.go
@@ -0,0 +1,318 @@
+// 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 sdk
+
+import (
+	"io/ioutil"
+	"os"
+	"strings"
+	"testing"
+
+	"android/soong/android"
+	"android/soong/apex"
+	"android/soong/cc"
+	"android/soong/java"
+)
+
+func testSdkContext(t *testing.T, bp string) (*android.TestContext, android.Config) {
+	config := android.TestArchConfig(buildDir, nil)
+	ctx := android.NewTestArchContext()
+
+	// from android package
+	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+	ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.BottomUp("prebuilts", android.PrebuiltMutator).Parallel()
+	})
+	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
+		ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
+	})
+
+	// from java package
+	ctx.RegisterModuleType("android_app_certificate", android.ModuleFactoryAdaptor(java.AndroidAppCertificateFactory))
+	ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(java.LibraryFactory))
+	ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(java.ImportFactory))
+
+	// from cc package
+	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
+	ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(cc.LibrarySharedFactory))
+	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
+	ctx.RegisterModuleType("cc_prebuilt_library_shared", android.ModuleFactoryAdaptor(cc.PrebuiltSharedLibraryFactory))
+	ctx.RegisterModuleType("cc_prebuilt_library_static", android.ModuleFactoryAdaptor(cc.PrebuiltStaticLibraryFactory))
+	ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory))
+	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
+	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.BottomUp("image", cc.ImageMutator).Parallel()
+		ctx.BottomUp("link", cc.LinkageMutator).Parallel()
+		ctx.BottomUp("vndk", cc.VndkMutator).Parallel()
+		ctx.BottomUp("test_per_src", cc.TestPerSrcMutator).Parallel()
+		ctx.BottomUp("version", cc.VersionMutator).Parallel()
+		ctx.BottomUp("begin", cc.BeginMutator).Parallel()
+	})
+
+	// from apex package
+	ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(apex.BundleFactory))
+	ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apex.ApexKeyFactory))
+	ctx.PostDepsMutators(apex.RegisterPostDepsMutators)
+
+	// from this package
+	ctx.RegisterModuleType("sdk", android.ModuleFactoryAdaptor(ModuleFactory))
+	ctx.PreDepsMutators(RegisterPreDepsMutators)
+	ctx.PostDepsMutators(RegisterPostDepsMutators)
+
+	ctx.Register()
+
+	bp = bp + `
+		apex_key {
+			name: "myapex.key",
+			public_key: "myapex.avbpubkey",
+			private_key: "myapex.pem",
+		}
+
+		android_app_certificate {
+			name: "myapex.cert",
+			certificate: "myapex",
+		}
+	` + cc.GatherRequiredDepsForTest(android.Android)
+
+	ctx.MockFileSystem(map[string][]byte{
+		"Android.bp":                                 []byte(bp),
+		"build/make/target/product/security":         nil,
+		"apex_manifest.json":                         nil,
+		"system/sepolicy/apex/myapex-file_contexts":  nil,
+		"system/sepolicy/apex/myapex2-file_contexts": nil,
+		"myapex.avbpubkey":                           nil,
+		"myapex.pem":                                 nil,
+		"myapex.x509.pem":                            nil,
+		"myapex.pk8":                                 nil,
+		"Test.java":                                  nil,
+		"Test.cpp":                                   nil,
+		"libfoo.so":                                  nil,
+	})
+
+	return ctx, config
+}
+
+func testSdk(t *testing.T, bp string) (*android.TestContext, android.Config) {
+	ctx, config := testSdkContext(t, bp)
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	android.FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	android.FailIfErrored(t, errs)
+	return ctx, config
+}
+
+// ensure that 'result' contains 'expected'
+func ensureContains(t *testing.T, result string, expected string) {
+	t.Helper()
+	if !strings.Contains(result, expected) {
+		t.Errorf("%q is not found in %q", expected, result)
+	}
+}
+
+// ensures that 'result' does not contain 'notExpected'
+func ensureNotContains(t *testing.T, result string, notExpected string) {
+	t.Helper()
+	if strings.Contains(result, notExpected) {
+		t.Errorf("%q is found in %q", notExpected, result)
+	}
+}
+
+func ensureListContains(t *testing.T, result []string, expected string) {
+	t.Helper()
+	if !android.InList(expected, result) {
+		t.Errorf("%q is not found in %v", expected, result)
+	}
+}
+
+func ensureListNotContains(t *testing.T, result []string, notExpected string) {
+	t.Helper()
+	if android.InList(notExpected, result) {
+		t.Errorf("%q is found in %v", notExpected, result)
+	}
+}
+
+func pathsToStrings(paths android.Paths) []string {
+	ret := []string{}
+	for _, p := range paths {
+		ret = append(ret, p.String())
+	}
+	return ret
+}
+
+func TestBasicSdkWithJava(t *testing.T) {
+	ctx, _ := testSdk(t, `
+		sdk {
+			name: "mysdk#1",
+			java_libs: ["sdkmember_mysdk_1"],
+		}
+
+		sdk {
+			name: "mysdk#2",
+			java_libs: ["sdkmember_mysdk_2"],
+		}
+
+		java_import {
+			name: "sdkmember",
+			prefer: false,
+			host_supported: true,
+		}
+
+		java_import {
+			name: "sdkmember_mysdk_1",
+			sdk_member_name: "sdkmember",
+			host_supported: true,
+		}
+
+		java_import {
+			name: "sdkmember_mysdk_2",
+			sdk_member_name: "sdkmember",
+			host_supported: true,
+		}
+
+		java_library {
+			name: "myjavalib",
+			srcs: ["Test.java"],
+			libs: ["sdkmember"],
+			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",
+		}
+
+		apex {
+			name: "myapex2",
+			java_libs: ["myjavalib"],
+			uses_sdks: ["mysdk#2"],
+			key: "myapex.key",
+			certificate: ":myapex.cert",
+		}
+	`)
+
+	sdkMemberV1 := ctx.ModuleForTests("sdkmember_mysdk_1", "android_common_myapex").Rule("combineJar").Output
+	sdkMemberV2 := ctx.ModuleForTests("sdkmember_mysdk_2", "android_common_myapex2").Rule("combineJar").Output
+
+	javalibForMyApex := ctx.ModuleForTests("myjavalib", "android_common_myapex")
+	javalibForMyApex2 := ctx.ModuleForTests("myjavalib", "android_common_myapex2")
+
+	// Depending on the uses_sdks value, different libs are linked
+	ensureListContains(t, pathsToStrings(javalibForMyApex.Rule("javac").Implicits), sdkMemberV1.String())
+	ensureListContains(t, pathsToStrings(javalibForMyApex2.Rule("javac").Implicits), sdkMemberV2.String())
+}
+
+func TestBasicSdkWithCc(t *testing.T) {
+	ctx, _ := testSdk(t, `
+		sdk {
+			name: "mysdk#1",
+			native_shared_libs: ["sdkmember_mysdk_1"],
+		}
+
+		sdk {
+			name: "mysdk#2",
+			native_shared_libs: ["sdkmember_mysdk_2"],
+		}
+
+		cc_prebuilt_library_shared {
+			name: "sdkmember",
+			srcs: ["libfoo.so"],
+			prefer: false,
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_prebuilt_library_shared {
+			name: "sdkmember_mysdk_1",
+			sdk_member_name: "sdkmember",
+			srcs: ["libfoo.so"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_prebuilt_library_shared {
+			name: "sdkmember_mysdk_2",
+			sdk_member_name: "sdkmember",
+			srcs: ["libfoo.so"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library_shared {
+			name: "mycpplib",
+			srcs: ["Test.cpp"],
+			shared_libs: ["sdkmember"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		apex {
+			name: "myapex",
+			native_shared_libs: ["mycpplib"],
+			uses_sdks: ["mysdk#1"],
+			key: "myapex.key",
+			certificate: ":myapex.cert",
+		}
+
+		apex {
+			name: "myapex2",
+			native_shared_libs: ["mycpplib"],
+			uses_sdks: ["mysdk#2"],
+			key: "myapex.key",
+			certificate: ":myapex.cert",
+		}
+	`)
+
+	sdkMemberV1 := ctx.ModuleForTests("sdkmember_mysdk_1", "android_arm64_armv8-a_core_shared_myapex").Rule("toc").Output
+	sdkMemberV2 := ctx.ModuleForTests("sdkmember_mysdk_2", "android_arm64_armv8-a_core_shared_myapex2").Rule("toc").Output
+
+	cpplibForMyApex := ctx.ModuleForTests("mycpplib", "android_arm64_armv8-a_core_shared_myapex")
+	cpplibForMyApex2 := ctx.ModuleForTests("mycpplib", "android_arm64_armv8-a_core_shared_myapex2")
+
+	// Depending on the uses_sdks value, different libs are linked
+	ensureListContains(t, pathsToStrings(cpplibForMyApex.Rule("ld").Implicits), sdkMemberV1.String())
+	ensureListContains(t, pathsToStrings(cpplibForMyApex2.Rule("ld").Implicits), sdkMemberV2.String())
+}
+
+var buildDir string
+
+func setUp() {
+	var err error
+	buildDir, err = ioutil.TempDir("", "soong_sdk_test")
+	if err != nil {
+		panic(err)
+	}
+}
+
+func tearDown() {
+	os.RemoveAll(buildDir)
+}
+
+func TestMain(m *testing.M) {
+	run := func() int {
+		setUp()
+		defer tearDown()
+
+		return m.Run()
+	}
+
+	os.Exit(run())
+}
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index c7669bd..a876341 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -32,6 +32,86 @@
 	name string
 }
 
+type syspropGenProperties struct {
+	Srcs  []string `android:"path"`
+	Scope string
+}
+
+type syspropJavaGenRule struct {
+	android.ModuleBase
+
+	properties syspropGenProperties
+
+	genSrcjars android.Paths
+}
+
+var _ android.OutputFileProducer = (*syspropJavaGenRule)(nil)
+
+var (
+	syspropJava = pctx.AndroidStaticRule("syspropJava",
+		blueprint.RuleParams{
+			Command: `rm -rf $out.tmp && mkdir -p $out.tmp && ` +
+				`$syspropJavaCmd --scope $scope --java-output-dir $out.tmp $in && ` +
+				`$soongZipCmd -jar -o $out -C $out.tmp -D $out.tmp && rm -rf $out.tmp`,
+			CommandDeps: []string{
+				"$syspropJavaCmd",
+				"$soongZipCmd",
+			},
+		}, "scope")
+)
+
+func init() {
+	pctx.HostBinToolVariable("soongZipCmd", "soong_zip")
+	pctx.HostBinToolVariable("syspropJavaCmd", "sysprop_java")
+
+	android.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.BottomUp("sysprop_deps", syspropDepsMutator).Parallel()
+	})
+}
+
+func (g *syspropJavaGenRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	var checkApiFileTimeStamp android.WritablePath
+
+	ctx.VisitDirectDeps(func(dep android.Module) {
+		if m, ok := dep.(*syspropLibrary); ok {
+			checkApiFileTimeStamp = m.checkApiFileTimeStamp
+		}
+	})
+
+	for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Srcs) {
+		srcJarFile := android.GenPathWithExt(ctx, "sysprop", syspropFile, "srcjar")
+
+		ctx.Build(pctx, android.BuildParams{
+			Rule:        syspropJava,
+			Description: "sysprop_java " + syspropFile.Rel(),
+			Output:      srcJarFile,
+			Input:       syspropFile,
+			Implicit:    checkApiFileTimeStamp,
+			Args: map[string]string{
+				"scope": g.properties.Scope,
+			},
+		})
+
+		g.genSrcjars = append(g.genSrcjars, srcJarFile)
+	}
+}
+
+func (g *syspropJavaGenRule) OutputFiles(tag string) (android.Paths, error) {
+	switch tag {
+	case "":
+		return g.genSrcjars, nil
+	default:
+		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+	}
+}
+
+func syspropJavaGenFactory() android.Module {
+	g := &syspropJavaGenRule{}
+	g.AddProperties(&g.properties)
+	android.InitAndroidModule(g)
+	return g
+}
+
 type syspropLibrary struct {
 	android.ModuleBase
 
@@ -81,13 +161,29 @@
 	return "lib" + m.BaseModuleName()
 }
 
+func (m *syspropLibrary) javaGenModuleName() string {
+	return m.BaseModuleName() + "_java_gen"
+}
+
 func (m *syspropLibrary) BaseModuleName() string {
 	return m.ModuleBase.Name()
 }
 
 func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	m.currentApiFile = android.PathForSource(ctx, ctx.ModuleDir(), "api", m.BaseModuleName()+"-current.txt")
-	m.latestApiFile = android.PathForSource(ctx, ctx.ModuleDir(), "api", m.BaseModuleName()+"-latest.txt")
+	baseModuleName := m.BaseModuleName()
+
+	for _, syspropFile := range android.PathsForModuleSrc(ctx, m.properties.Srcs) {
+		if syspropFile.Ext() != ".sysprop" {
+			ctx.PropertyErrorf("srcs", "srcs contains non-sysprop file %q", syspropFile.String())
+		}
+	}
+
+	if ctx.Failed() {
+		return
+	}
+
+	m.currentApiFile = android.PathForSource(ctx, ctx.ModuleDir(), "api", baseModuleName+"-current.txt")
+	m.latestApiFile = android.PathForSource(ctx, ctx.ModuleDir(), "api", baseModuleName+"-latest.txt")
 
 	// dump API rule
 	rule := android.NewRuleBuilder()
@@ -96,7 +192,7 @@
 		BuiltTool(ctx, "sysprop_api_dump").
 		Output(m.dumpedApiFile).
 		Inputs(android.PathsForModuleSrc(ctx, m.properties.Srcs))
-	rule.Build(pctx, ctx, m.BaseModuleName()+"_api_dump", m.BaseModuleName()+" api dump")
+	rule.Build(pctx, ctx, baseModuleName+"_api_dump", baseModuleName+" api dump")
 
 	// check API rule
 	rule = android.NewRuleBuilder()
@@ -105,8 +201,8 @@
 	msg := fmt.Sprintf(`\n******************************\n`+
 		`API of sysprop_library %s doesn't match with current.txt\n`+
 		`Please update current.txt by:\n`+
-		`rm -rf %q && cp -f %q %q\n`+
-		`******************************\n`, m.BaseModuleName(),
+		`m %s-dump-api && rm -rf %q && cp -f %q %q\n`+
+		`******************************\n`, baseModuleName, baseModuleName,
 		m.currentApiFile.String(), m.dumpedApiFile.String(), m.currentApiFile.String())
 
 	rule.Command().
@@ -121,7 +217,7 @@
 	msg = fmt.Sprintf(`\n******************************\n`+
 		`API of sysprop_library %s doesn't match with latest version\n`+
 		`Please fix the breakage and rebuild.\n`+
-		`******************************\n`, m.BaseModuleName())
+		`******************************\n`, baseModuleName)
 
 	rule.Command().
 		Text("( ").
@@ -138,7 +234,7 @@
 		Text("touch").
 		Output(m.checkApiFileTimeStamp)
 
-	rule.Build(pctx, ctx, m.BaseModuleName()+"_check_api", m.BaseModuleName()+" check api")
+	rule.Build(pctx, ctx, baseModuleName+"_check_api", baseModuleName+" check api")
 }
 
 func (m *syspropLibrary) AndroidMk() android.AndroidMkData {
@@ -153,13 +249,13 @@
 			fmt.Fprintf(w, "include $(BUILD_SYSTEM)/base_rules.mk\n\n")
 			fmt.Fprintf(w, "$(LOCAL_BUILT_MODULE): %s\n", m.checkApiFileTimeStamp.String())
 			fmt.Fprintf(w, "\ttouch $@\n\n")
-			fmt.Fprintf(w, ".PHONY: %s-check-api\n\n", name)
+			fmt.Fprintf(w, ".PHONY: %s-check-api %s-dump-api\n\n", name, name)
+
+			// dump API rule
+			fmt.Fprintf(w, "%s-dump-api: %s\n\n", name, m.dumpedApiFile.String())
 
 			// check API rule
 			fmt.Fprintf(w, "%s-check-api: %s\n\n", name, m.checkApiFileTimeStamp.String())
-
-			// "make {sysprop_library}" should also build the C++ library
-			fmt.Fprintf(w, "%s: %s\n\n", name, m.CcModuleName())
 		}}
 }
 
@@ -263,14 +359,38 @@
 	ccProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
 	ccProps.Header_libs = []string{"libbase_headers"}
 	ccProps.Shared_libs = []string{"liblog"}
-
-	// add sysprop_library module to perform check API
-	ccProps.Required = []string{m.Name()}
-	ccProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
 	ccProps.Recovery_available = m.properties.Recovery_available
 	ccProps.Vendor_available = m.properties.Vendor_available
 
-	ctx.CreateModule(android.ModuleFactoryAdaptor(cc.LibraryFactory), &ccProps)
+	ctx.CreateModule(cc.LibraryFactory, &ccProps)
+
+	// internal scope contains all properties
+	// public scope only contains public properties
+	// use public if the owner is different from client
+	scope := "internal"
+	isProduct := ctx.ProductSpecific()
+	isVendor := ctx.SocSpecific()
+	isOwnerPlatform := owner == "Platform"
+
+	if isProduct {
+		// product can't own any sysprop_library now, so product must use public scope
+		scope = "public"
+	} else if isVendor && !isOwnerPlatform {
+		// vendor and odm can't use system's internal property.
+		scope = "public"
+	}
+
+	javaGenProps := struct {
+		Srcs  []string
+		Scope string
+		Name  *string
+	}{
+		Srcs:  m.properties.Srcs,
+		Scope: scope,
+		Name:  proptools.StringPtr(m.javaGenModuleName()),
+	}
+
+	ctx.CreateModule(syspropJavaGenFactory, &javaGenProps)
 
 	javaProps := struct {
 		Name             *string
@@ -278,27 +398,26 @@
 		Soc_specific     *bool
 		Device_specific  *bool
 		Product_specific *bool
-		Sysprop          struct {
-			Platform *bool
-		}
-		Required    []string
-		Sdk_version *string
-		Installable *bool
-		Libs        []string
+		Required         []string
+		Sdk_version      *string
+		Installable      *bool
+		Libs             []string
 	}{}
 
 	javaProps.Name = proptools.StringPtr(m.BaseModuleName())
-	javaProps.Srcs = m.properties.Srcs
+	javaProps.Srcs = []string{":" + *javaGenProps.Name}
 	javaProps.Soc_specific = proptools.BoolPtr(socSpecific)
 	javaProps.Device_specific = proptools.BoolPtr(deviceSpecific)
 	javaProps.Product_specific = proptools.BoolPtr(productSpecific)
 	javaProps.Installable = m.properties.Installable
-
-	// add sysprop_library module to perform check API
-	javaProps.Required = []string{m.Name()}
 	javaProps.Sdk_version = proptools.StringPtr("core_current")
-	javaProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
 	javaProps.Libs = []string{stub}
 
-	ctx.CreateModule(android.ModuleFactoryAdaptor(java.LibraryFactory), &javaProps)
+	ctx.CreateModule(java.LibraryFactory, &javaProps)
+}
+
+func syspropDepsMutator(ctx android.BottomUpMutatorContext) {
+	if m, ok := ctx.Module().(*syspropLibrary); ok {
+		ctx.AddReverseDependency(m, nil, m.javaGenModuleName())
+	}
 }
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 5345770..6b4337a 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -62,6 +62,9 @@
 	ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
 	ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+	ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.BottomUp("sysprop_deps", syspropDepsMutator).Parallel()
+	})
 
 	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
 	ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(cc.LibraryHeaderFactory))
@@ -282,10 +285,10 @@
 
 	// Check for generated cc_library
 	for _, variant := range []string{
-		"android_arm_armv7-a-neon_vendor_shared",
-		"android_arm_armv7-a-neon_vendor_static",
-		"android_arm64_armv8-a_vendor_shared",
-		"android_arm64_armv8-a_vendor_static",
+		"android_arm_armv7-a-neon_vendor.VER_shared",
+		"android_arm_armv7-a-neon_vendor.VER_static",
+		"android_arm64_armv8-a_vendor.VER_shared",
+		"android_arm64_armv8-a_vendor.VER_static",
 	} {
 		ctx.ModuleForTests("libsysprop-platform", variant)
 		ctx.ModuleForTests("libsysprop-vendor", variant)
@@ -309,15 +312,15 @@
 
 	// Check for exported includes
 	coreVariant := "android_arm64_armv8-a_core_static"
-	vendorVariant := "android_arm64_armv8-a_vendor_static"
+	vendorVariant := "android_arm64_armv8-a_vendor.VER_static"
 
 	platformInternalPath := "libsysprop-platform/android_arm64_armv8-a_core_static/gen/sysprop/include"
 	platformPublicCorePath := "libsysprop-platform/android_arm64_armv8-a_core_static/gen/sysprop/public/include"
-	platformPublicVendorPath := "libsysprop-platform/android_arm64_armv8-a_vendor_static/gen/sysprop/public/include"
+	platformPublicVendorPath := "libsysprop-platform/android_arm64_armv8-a_vendor.VER_static/gen/sysprop/public/include"
 
 	platformOnProductPath := "libsysprop-platform-on-product/android_arm64_armv8-a_core_static/gen/sysprop/public/include"
 
-	vendorInternalPath := "libsysprop-vendor/android_arm64_armv8-a_vendor_static/gen/sysprop/include"
+	vendorInternalPath := "libsysprop-vendor/android_arm64_armv8-a_vendor.VER_static/gen/sysprop/include"
 	vendorPublicPath := "libsysprop-vendor/android_arm64_armv8-a_core_static/gen/sysprop/public/include"
 
 	platformClient := ctx.ModuleForTests("cc-client-platform", coreVariant)
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index 7cd7c5a..3d30cfa 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -44,10 +44,11 @@
 	CommandDeps: []string{"$template"},
 }, "name", "template", "extraConfigs")
 
-func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string) (path android.Path, autogenPath android.WritablePath) {
-	if p := getTestConfig(ctx, prop); p != nil {
+func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string, autoGenConfig *bool) (path android.Path, autogenPath android.WritablePath) {
+	p := getTestConfig(ctx, prop)
+	if !Bool(autoGenConfig) && p != nil {
 		return p, nil
-	} else if !android.InList("cts", testSuites) {
+	} else if !android.InList("cts", testSuites) && BoolDefault(autoGenConfig, true) {
 		outputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".config")
 		return nil, outputFile
 	} else {
@@ -73,26 +74,34 @@
 	return fmt.Sprintf(`<option name="%s" value="%s" />`, o.Name, o.Value)
 }
 
-type Preparer struct {
+// It can be a template of object or target_preparer.
+type Object struct {
+	// Set it as a target_preparer if object type == "target_preparer".
+	Type    string
 	Class   string
 	Options []Option
 }
 
-var _ Config = Preparer{}
+var _ Config = Object{}
 
-func (p Preparer) Config() string {
+func (ob Object) Config() string {
 	var optionStrings []string
-	for _, option := range p.Options {
+	for _, option := range ob.Options {
 		optionStrings = append(optionStrings, option.Config())
 	}
 	var options string
-	if len(p.Options) == 0 {
+	if len(ob.Options) == 0 {
 		options = ""
 	} else {
 		optionDelimiter := fmt.Sprintf("\\n%s%s", test_xml_indent, test_xml_indent)
 		options = optionDelimiter + strings.Join(optionStrings, optionDelimiter)
 	}
-	return fmt.Sprintf(`<target_preparer class="%s">%s\n%s</target_preparer>`, p.Class, options, test_xml_indent)
+	if ob.Type == "target_preparer" {
+		return fmt.Sprintf(`<target_preparer class="%s">%s\n%s</target_preparer>`, ob.Class, options, test_xml_indent)
+	} else {
+		return fmt.Sprintf(`<object type="%s" class="%s">%s\n%s</object>`, ob.Type, ob.Class, options, test_xml_indent)
+	}
+
 }
 
 func autogenTemplate(ctx android.ModuleContext, output android.WritablePath, template string, configs []Config) {
@@ -116,8 +125,8 @@
 }
 
 func AutoGenNativeTestConfig(ctx android.ModuleContext, testConfigProp *string,
-	testConfigTemplateProp *string, testSuites []string, config []Config) android.Path {
-	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
+	testConfigTemplateProp *string, testSuites []string, config []Config, autoGenConfig *bool) android.Path {
+	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
 	if autogenPath != nil {
 		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
 		if templatePath.Valid() {
@@ -135,8 +144,8 @@
 }
 
 func AutoGenNativeBenchmarkTestConfig(ctx android.ModuleContext, testConfigProp *string,
-	testConfigTemplateProp *string, testSuites []string, configs []Config) android.Path {
-	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
+	testConfigTemplateProp *string, testSuites []string, configs []Config, autoGenConfig *bool) android.Path {
+	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
 	if autogenPath != nil {
 		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
 		if templatePath.Valid() {
@@ -149,8 +158,9 @@
 	return path
 }
 
-func AutoGenJavaTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string, testSuites []string) android.Path {
-	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
+func AutoGenJavaTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string,
+	testSuites []string, autoGenConfig *bool) android.Path {
+	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
 	if autogenPath != nil {
 		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
 		if templatePath.Valid() {
@@ -168,9 +178,9 @@
 }
 
 func AutoGenPythonBinaryHostTestConfig(ctx android.ModuleContext, testConfigProp *string,
-	testConfigTemplateProp *string, testSuites []string) android.Path {
+	testConfigTemplateProp *string, testSuites []string, autoGenConfig *bool) android.Path {
 
-	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
+	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
 	if autogenPath != nil {
 		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
 		if templatePath.Valid() {
@@ -192,8 +202,9 @@
 	},
 }, "name", "template")
 
-func AutoGenInstrumentationTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string, manifest android.Path, testSuites []string) android.Path {
-	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
+func AutoGenInstrumentationTestConfig(ctx android.ModuleContext, testConfigProp *string,
+	testConfigTemplateProp *string, manifest android.Path, testSuites []string, autoGenConfig *bool) android.Path {
+	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig)
 	if autogenPath != nil {
 		template := "${InstrumentationTestConfigTemplate}"
 		moduleTemplate := getTestConfigTemplate(ctx, testConfigTemplateProp)
@@ -214,3 +225,6 @@
 	}
 	return path
 }
+
+var Bool = proptools.Bool
+var BoolDefault = proptools.BoolDefault
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index bfe2c36..0a2b510 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -87,6 +87,7 @@
 	// otherwise we'd have to rebuild any generated files created with
 	// those tools.
 	removeGlobs(ctx,
+		hostOut("apex"),
 		hostOut("obj/NOTICE_FILES"),
 		hostOut("obj/PACKAGING"),
 		hostOut("coverage"),
diff --git a/ui/build/config.go b/ui/build/config.go
index 665d2f0..def3345 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -16,7 +16,6 @@
 
 import (
 	"io/ioutil"
-	"log"
 	"os"
 	"path/filepath"
 	"runtime"
@@ -189,27 +188,27 @@
 	checkTopDir(ctx)
 
 	if srcDir := absPath(ctx, "."); strings.ContainsRune(srcDir, ' ') {
-		log.Println("You are building in a directory whose absolute path contains a space character:")
-		log.Println()
-		log.Printf("%q\n", srcDir)
-		log.Println()
-		log.Fatalln("Directory names containing spaces are not supported")
+		ctx.Println("You are building in a directory whose absolute path contains a space character:")
+		ctx.Println()
+		ctx.Printf("%q\n", srcDir)
+		ctx.Println()
+		ctx.Fatalln("Directory names containing spaces are not supported")
 	}
 
 	if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') {
-		log.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
-		log.Println()
-		log.Printf("%q\n", outDir)
-		log.Println()
-		log.Fatalln("Directory names containing spaces are not supported")
+		ctx.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
+		ctx.Println()
+		ctx.Printf("%q\n", outDir)
+		ctx.Println()
+		ctx.Fatalln("Directory names containing spaces are not supported")
 	}
 
 	if distDir := ret.DistDir(); strings.ContainsRune(distDir, ' ') {
-		log.Println("The absolute path of your dist directory ($DIST_DIR) contains a space character:")
-		log.Println()
-		log.Printf("%q\n", distDir)
-		log.Println()
-		log.Fatalln("Directory names containing spaces are not supported")
+		ctx.Println("The absolute path of your dist directory ($DIST_DIR) contains a space character:")
+		ctx.Println()
+		ctx.Printf("%q\n", distDir)
+		ctx.Println()
+		ctx.Fatalln("Directory names containing spaces are not supported")
 	}
 
 	// Configure Java-related variables, including adding it to $PATH
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 786e7d3..e44600e 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -118,9 +118,6 @@
 	"ld.gold":    Forbidden,
 	"pkg-config": Forbidden,
 
-	// These are currently Linux-only toybox tools (but can be switched now).
-	"date": LinuxOnlyPrebuilt,
-
 	// These are toybox tools that only work on Linux.
 	"pgrep": LinuxOnlyPrebuilt,
 	"pkill": LinuxOnlyPrebuilt,
diff --git a/ui/terminal/smart_status.go b/ui/terminal/smart_status.go
index 57f71ab..efcfd43 100644
--- a/ui/terminal/smart_status.go
+++ b/ui/terminal/smart_status.go
@@ -189,7 +189,7 @@
 		fmt.Fprintf(s.writer, ansi.resetScrollingMargins())
 		_, height, _ := termSize(s.writer)
 		// Move the cursor to the top of the now-blank, previously non-scrolling region
-		fmt.Fprintf(s.writer, ansi.setCursor(height-s.tableHeight, 0))
+		fmt.Fprintf(s.writer, ansi.setCursor(height-s.tableHeight, 1))
 		// Turn the cursor back on
 		fmt.Fprintf(s.writer, ansi.showCursor())
 	}
@@ -334,52 +334,44 @@
 	scrollingHeight := s.termHeight - s.tableHeight
 
 	// Update the scrolling region in case the height of the terminal changed
-	fmt.Fprint(s.writer, ansi.setScrollingMargins(0, scrollingHeight))
-	// Move the cursor to the first line of the non-scrolling region
-	fmt.Fprint(s.writer, ansi.setCursor(scrollingHeight+1, 0))
+
+	fmt.Fprint(s.writer, ansi.setScrollingMargins(1, scrollingHeight))
 
 	// Write as many status lines as fit in the table
-	var tableLine int
-	var runningAction actionTableEntry
-	for tableLine, runningAction = range s.runningActions {
+	for tableLine := 0; tableLine < s.tableHeight; tableLine++ {
 		if tableLine >= s.tableHeight {
 			break
 		}
+		// Move the cursor to the correct line of the non-scrolling region
+		fmt.Fprint(s.writer, ansi.setCursor(scrollingHeight+1+tableLine, 1))
 
-		seconds := int(time.Since(runningAction.startTime).Round(time.Second).Seconds())
+		if tableLine < len(s.runningActions) {
+			runningAction := s.runningActions[tableLine]
 
-		desc := runningAction.action.Description
-		if desc == "" {
-			desc = runningAction.action.Command
+			seconds := int(time.Since(runningAction.startTime).Round(time.Second).Seconds())
+
+			desc := runningAction.action.Description
+			if desc == "" {
+				desc = runningAction.action.Command
+			}
+
+			color := ""
+			if seconds >= 60 {
+				color = ansi.red() + ansi.bold()
+			} else if seconds >= 30 {
+				color = ansi.yellow() + ansi.bold()
+			}
+
+			durationStr := fmt.Sprintf("   %2d:%02d ", seconds/60, seconds%60)
+			desc = elide(desc, s.termWidth-len(durationStr))
+			durationStr = color + durationStr + ansi.regular()
+			fmt.Fprint(s.writer, durationStr, desc)
 		}
-
-		color := ""
-		if seconds >= 60 {
-			color = ansi.red() + ansi.bold()
-		} else if seconds >= 30 {
-			color = ansi.yellow() + ansi.bold()
-		}
-
-		durationStr := fmt.Sprintf("   %2d:%02d ", seconds/60, seconds%60)
-		desc = elide(desc, s.termWidth-len(durationStr))
-		durationStr = color + durationStr + ansi.regular()
-
-		fmt.Fprint(s.writer, durationStr, desc, ansi.clearToEndOfLine())
-		if tableLine < s.tableHeight-1 {
-			fmt.Fprint(s.writer, "\n")
-		}
-	}
-
-	// Clear any remaining lines in the table
-	for ; tableLine < s.tableHeight; tableLine++ {
 		fmt.Fprint(s.writer, ansi.clearToEndOfLine())
-		if tableLine < s.tableHeight-1 {
-			fmt.Fprint(s.writer, "\n")
-		}
 	}
 
 	// Move the cursor back to the last line of the scrolling region
-	fmt.Fprint(s.writer, ansi.setCursor(scrollingHeight, 0))
+	fmt.Fprint(s.writer, ansi.setCursor(scrollingHeight, 1))
 }
 
 var ansi = ansiImpl{}
diff --git a/ui/terminal/status.go b/ui/terminal/status.go
index 69a2a09..60dfc70 100644
--- a/ui/terminal/status.go
+++ b/ui/terminal/status.go
@@ -26,10 +26,10 @@
 //
 // statusFormat takes nearly all the same options as NINJA_STATUS.
 // %c is currently unsupported.
-func NewStatusOutput(w io.Writer, statusFormat string, quietBuild bool) status.StatusOutput {
+func NewStatusOutput(w io.Writer, statusFormat string, forceDumbOutput, quietBuild bool) status.StatusOutput {
 	formatter := newFormatter(statusFormat, quietBuild)
 
-	if isSmartTerminal(w) {
+	if !forceDumbOutput && isSmartTerminal(w) {
 		return NewSmartStatusOutput(w, formatter)
 	} else {
 		return NewDumbStatusOutput(w, formatter)
diff --git a/ui/terminal/status_test.go b/ui/terminal/status_test.go
index 81aa238..9f60829 100644
--- a/ui/terminal/status_test.go
+++ b/ui/terminal/status_test.go
@@ -94,7 +94,7 @@
 
 			t.Run("smart", func(t *testing.T) {
 				smart := &fakeSmartTerminal{termWidth: 40}
-				stat := NewStatusOutput(smart, "", false)
+				stat := NewStatusOutput(smart, "", false, false)
 				tt.calls(stat)
 				stat.Flush()
 
@@ -105,7 +105,7 @@
 
 			t.Run("dumb", func(t *testing.T) {
 				dumb := &bytes.Buffer{}
-				stat := NewStatusOutput(dumb, "", false)
+				stat := NewStatusOutput(dumb, "", false, false)
 				tt.calls(stat)
 				stat.Flush()
 
@@ -113,6 +113,17 @@
 					t.Errorf("want:\n%q\ngot:\n%q", w, g)
 				}
 			})
+
+			t.Run("force dumb", func(t *testing.T) {
+				smart := &fakeSmartTerminal{termWidth: 40}
+				stat := NewStatusOutput(smart, "", true, false)
+				tt.calls(stat)
+				stat.Flush()
+
+				if g, w := smart.String(), tt.dumb; g != w {
+					t.Errorf("want:\n%q\ngot:\n%q", w, g)
+				}
+			})
 		})
 	}
 }
@@ -258,7 +269,7 @@
 	os.Setenv(tableHeightEnVar, "")
 
 	smart := &fakeSmartTerminal{termWidth: 40}
-	stat := NewStatusOutput(smart, "", false)
+	stat := NewStatusOutput(smart, "", false, false)
 	smartStat := stat.(*smartStatusOutput)
 	smartStat.sigwinchHandled = make(chan bool)