Merge "Add Symbol_ordering_file property"
diff --git a/Android.bp b/Android.bp
index d5f052e..b4a9d30 100644
--- a/Android.bp
+++ b/Android.bp
@@ -285,6 +285,7 @@
     deps: [
         "blueprint",
         "soong-android",
+        "soong-tradefed",
     ],
     srcs: [
         "python/androidmk.go",
diff --git a/OWNERS b/OWNERS
index d56644b..892beb7 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,4 @@
-per-file * = ccross@android.com,dwillemsen@google.com,nanzhang@google.com,jungjw@google.com
+per-file * = ccross@android.com,dwillemsen@google.com,jungjw@google.com
 per-file ndk_*.go, *gen_stub_libs.py = danalbert@google.com
 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
diff --git a/android/androidmk.go b/android/androidmk.go
index 18b26d9..fc34471 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -72,7 +72,9 @@
 		androidMkModulesList = append(androidMkModulesList, module)
 	})
 
-	sort.Sort(ModulesByName{androidMkModulesList, ctx})
+	sort.SliceStable(androidMkModulesList, func(i, j int) bool {
+		return ctx.ModuleName(androidMkModulesList[i]) < ctx.ModuleName(androidMkModulesList[j])
+	})
 
 	transMk := PathForOutput(ctx, "Android"+String(ctx.Config().productVariables.Make_suffix)+".mk")
 	if ctx.Failed() {
diff --git a/android/arch.go b/android/arch.go
index bee09b0..e8d9c6e 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -106,6 +106,7 @@
 var archVariants = map[ArchType][]string{}
 var archFeatures = map[ArchType][]string{}
 var archFeatureMap = map[ArchType]map[string][]string{}
+var defaultArchFeatureMap = map[OsType]map[ArchType][]string{}
 
 func RegisterArchVariants(arch ArchType, variants ...string) {
 	checkCalledFromInit()
@@ -117,9 +118,24 @@
 	archFeatures[arch] = append(archFeatures[arch], features...)
 }
 
+func RegisterDefaultArchVariantFeatures(os OsType, arch ArchType, features ...string) {
+	checkCalledFromInit()
+
+	for _, feature := range features {
+		if !InList(feature, archFeatures[arch]) {
+			panic(fmt.Errorf("Invalid feature %q for arch %q variant \"\"", feature, arch))
+		}
+	}
+
+	if defaultArchFeatureMap[os] == nil {
+		defaultArchFeatureMap[os] = make(map[ArchType][]string)
+	}
+	defaultArchFeatureMap[os][arch] = features
+}
+
 func RegisterArchVariantFeatures(arch ArchType, variant string, features ...string) {
 	checkCalledFromInit()
-	if variant != "" && !InList(variant, archVariants[arch]) {
+	if !InList(variant, archVariants[arch]) {
 		panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch))
 	}
 
@@ -952,7 +968,7 @@
 			return
 		}
 
-		arch, err := decodeArch(archName, archVariant, cpuVariant, abi)
+		arch, err := decodeArch(os, archName, archVariant, cpuVariant, abi)
 		if err != nil {
 			targetErr = err
 			return
@@ -1127,11 +1143,11 @@
 	}
 }
 
-func decodeArchSettings(archConfigs []archConfig) ([]Target, error) {
+func decodeArchSettings(os OsType, archConfigs []archConfig) ([]Target, error) {
 	var ret []Target
 
 	for _, config := range archConfigs {
-		arch, err := decodeArch(config.arch, &config.archVariant,
+		arch, err := decodeArch(os, config.arch, &config.archVariant,
 			&config.cpuVariant, &config.abi)
 		if err != nil {
 			return nil, err
@@ -1147,7 +1163,7 @@
 }
 
 // Convert a set of strings from product variables into a single Arch struct
-func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
+func decodeArch(os OsType, arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
 	stringPtr := func(p *string) string {
 		if p != nil {
 			return *p
@@ -1190,8 +1206,14 @@
 		}
 	}
 
-	if featureMap, ok := archFeatureMap[archType]; ok {
-		a.ArchFeatures = featureMap[a.ArchVariant]
+	if a.ArchVariant == "" {
+		if featureMap, ok := defaultArchFeatureMap[os]; ok {
+			a.ArchFeatures = featureMap[archType]
+		}
+	} else {
+		if featureMap, ok := archFeatureMap[archType]; ok {
+			a.ArchFeatures = featureMap[a.ArchVariant]
+		}
 	}
 
 	return a, nil
diff --git a/android/config.go b/android/config.go
index f5ea381..7c1278e 100644
--- a/android/config.go
+++ b/android/config.go
@@ -303,7 +303,7 @@
 	}
 
 	if archConfig != nil {
-		androidTargets, err := decodeArchSettings(archConfig)
+		androidTargets, err := decodeArchSettings(Android, archConfig)
 		if err != nil {
 			return Config{}, err
 		}
@@ -649,7 +649,7 @@
 
 func (c *config) EnableXOM() bool {
 	if c.productVariables.EnableXOM == nil {
-		return false
+		return true
 	} else {
 		return Bool(c.productVariables.EnableXOM)
 	}
diff --git a/android/module.go b/android/module.go
index d2f84ce..303d8c6 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1619,27 +1619,6 @@
 	}
 }
 
-type ModulesByName struct {
-	slice []blueprint.Module
-	ctx   interface {
-		ModuleName(blueprint.Module) string
-		ModuleSubDir(blueprint.Module) string
-	}
-}
-
-func (s ModulesByName) Len() int { return len(s.slice) }
-func (s ModulesByName) Less(i, j int) bool {
-	mi, mj := s.slice[i], s.slice[j]
-	ni, nj := s.ctx.ModuleName(mi), s.ctx.ModuleName(mj)
-
-	if ni != nj {
-		return ni < nj
-	} else {
-		return s.ctx.ModuleSubDir(mi) < s.ctx.ModuleSubDir(mj)
-	}
-}
-func (s ModulesByName) Swap(i, j int) { s.slice[i], s.slice[j] = s.slice[j], s.slice[i] }
-
 // Collect information for opening IDE project files in java/jdeps.go.
 type IDEInfo interface {
 	IDEInfo(ideInfo *IdeInfo)
diff --git a/android/neverallow.go b/android/neverallow.go
index f6caebc..18744e8 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -100,7 +100,6 @@
 		"core-all",
 		"core-oj",
 		"core-libart",
-		"core-simple",
 		"okhttp",
 		"bouncycastle",
 		"conscrypt",
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
index f7d08cc..40da653 100644
--- a/android/prebuilt_etc.go
+++ b/android/prebuilt_etc.go
@@ -17,6 +17,7 @@
 import (
 	"fmt"
 	"io"
+	"strings"
 )
 
 // prebuilt_etc is for prebuilts that will be installed to
@@ -148,6 +149,7 @@
 			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(OUT_DIR)/"+p.installDirPath.RelPathString())
 			fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", p.outputFilePath.Base())
 			fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !p.Installable())
+			fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(data.Required, " "))
 			if p.additionalDependencies != nil {
 				fmt.Fprint(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=")
 				for _, path := range *p.additionalDependencies {
diff --git a/apex/apex.go b/apex/apex.go
index e711c8b..6269868 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -482,6 +482,11 @@
 	}
 }
 
+func (a *apexBundle) IsSanitizerEnabled() bool {
+	// APEX can be mutated for sanitizers
+	return true
+}
+
 func getCopyManifestForNativeLibrary(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
 	// Decide the APEX-local directory by the multilib of the library
 	// In the future, we may query this to the module.
@@ -903,6 +908,9 @@
 				fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
 
 				for _, fi := range a.filesInfo {
+					if cc, ok := fi.module.(*cc.Module); ok && cc.Properties.HideFromMake {
+						continue
+					}
 					fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
 					fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
 					fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName)
diff --git a/cc/cc.go b/cc/cc.go
index 85e3a67..4717b72 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -60,6 +60,7 @@
 		ctx.BottomUp("tsan", sanitizerMutator(tsan)).Parallel()
 
 		ctx.TopDown("sanitize_runtime_deps", sanitizerRuntimeDepsMutator)
+		ctx.BottomUp("sanitize_runtime", sanitizerRuntimeMutator).Parallel()
 
 		ctx.BottomUp("coverage", coverageLinkingMutator).Parallel()
 		ctx.TopDown("vndk_deps", sabiDepsMutator)
@@ -524,6 +525,8 @@
 func (c *Module) IsStubs() bool {
 	if library, ok := c.linker.(*libraryDecorator); ok {
 		return library.buildStubs()
+	} else if _, ok := c.linker.(*llndkStubDecorator); ok {
+		return true
 	}
 	return false
 }
@@ -569,12 +572,7 @@
 }
 
 func (ctx *moduleContextImpl) staticBinary() bool {
-	if static, ok := ctx.mod.linker.(interface {
-		staticBinary() bool
-	}); ok {
-		return static.staticBinary()
-	}
-	return false
+	return ctx.mod.staticBinary()
 }
 
 func (ctx *moduleContextImpl) useSdk() bool {
@@ -891,7 +889,7 @@
 	}
 }
 
-func (c *Module) toolchain(ctx BaseModuleContext) config.Toolchain {
+func (c *Module) toolchain(ctx android.BaseContext) config.Toolchain {
 	if c.cachedToolchain == nil {
 		c.cachedToolchain = config.FindToolchain(ctx.Os(), ctx.Arch())
 	}
@@ -1708,6 +1706,15 @@
 	return false
 }
 
+func (c *Module) staticBinary() bool {
+	if static, ok := c.linker.(interface {
+		staticBinary() bool
+	}); ok {
+		return static.staticBinary()
+	}
+	return false
+}
+
 func (c *Module) getMakeLinkType() string {
 	if c.useVndk() {
 		if inList(c.Name(), vndkCoreLibraries) || inList(c.Name(), vndkSpLibraries) || inList(c.Name(), llndkLibraries) {
diff --git a/cc/config/global.go b/cc/config/global.go
index 13ad27c..5d98d67 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -120,8 +120,8 @@
 
 	// prebuilts/clang default settings.
 	ClangDefaultBase         = "prebuilts/clang/host"
-	ClangDefaultVersion      = "clang-r346389b"
-	ClangDefaultShortVersion = "8.0.6"
+	ClangDefaultVersion      = "clang-r346389c"
+	ClangDefaultShortVersion = "8.0.7"
 
 	// Directories with warnings from Android.bp files.
 	WarningAllowedProjects = []string{
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index ff8a6da..381f7e7 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -81,7 +81,7 @@
 		"aes_ni",
 		"avx",
 		"popcnt")
-	android.RegisterArchVariantFeatures(android.X86_64, "",
+	android.RegisterDefaultArchVariantFeatures(android.Android, android.X86_64,
 		"ssse3",
 		"sse4",
 		"sse4_1",
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 47994a8..ffeeb69 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -103,6 +103,10 @@
 	return nil
 }
 
+func (p *prebuiltLibraryLinker) shared() bool {
+	return p.libraryDecorator.shared()
+}
+
 func prebuiltSharedLibraryFactory() android.Module {
 	module, _ := NewPrebuiltSharedLibrary(android.HostAndDeviceSupported)
 	return module.Init()
@@ -121,6 +125,10 @@
 	module.AddProperties(&prebuilt.properties)
 
 	android.InitPrebuiltModule(module, &prebuilt.properties.Srcs)
+
+	// Prebuilt libraries can be included in APEXes
+	android.InitApexModule(module)
+
 	return module, library
 }
 
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 8d33de5..d19e54a 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -16,7 +16,6 @@
 
 import (
 	"fmt"
-	"io"
 	"sort"
 	"strings"
 	"sync"
@@ -138,18 +137,17 @@
 		Blacklist *string
 	} `android:"arch_variant"`
 
-	SanitizerEnabled  bool `blueprint:"mutated"`
-	SanitizeDep       bool `blueprint:"mutated"`
-	MinimalRuntimeDep bool `blueprint:"mutated"`
-	UbsanRuntimeDep   bool `blueprint:"mutated"`
-	InSanitizerDir    bool `blueprint:"mutated"`
+	SanitizerEnabled  bool     `blueprint:"mutated"`
+	SanitizeDep       bool     `blueprint:"mutated"`
+	MinimalRuntimeDep bool     `blueprint:"mutated"`
+	UbsanRuntimeDep   bool     `blueprint:"mutated"`
+	InSanitizerDir    bool     `blueprint:"mutated"`
+	Sanitizers        []string `blueprint:"mutated"`
+	DiagSanitizers    []string `blueprint:"mutated"`
 }
 
 type sanitize struct {
 	Properties SanitizeProperties
-
-	runtimeLibrary          string
-	androidMkRuntimeLibrary string
 }
 
 func init() {
@@ -405,46 +403,6 @@
 		return flags
 	}
 
-	var sanitizers []string
-	var diagSanitizers []string
-
-	if Bool(sanitize.Properties.Sanitize.All_undefined) {
-		sanitizers = append(sanitizers, "undefined")
-	} else {
-		if Bool(sanitize.Properties.Sanitize.Undefined) {
-			sanitizers = append(sanitizers,
-				"bool",
-				"integer-divide-by-zero",
-				"return",
-				"returns-nonnull-attribute",
-				"shift-exponent",
-				"unreachable",
-				"vla-bound",
-				// TODO(danalbert): The following checks currently have compiler performance issues.
-				//"alignment",
-				//"bounds",
-				//"enum",
-				//"float-cast-overflow",
-				//"float-divide-by-zero",
-				//"nonnull-attribute",
-				//"null",
-				//"shift-base",
-				//"signed-integer-overflow",
-				// TODO(danalbert): Fix UB in libc++'s __tree so we can turn this on.
-				// https://llvm.org/PR19302
-				// http://reviews.llvm.org/D6974
-				// "object-size",
-			)
-		}
-		sanitizers = append(sanitizers, sanitize.Properties.Sanitize.Misc_undefined...)
-	}
-
-	if Bool(sanitize.Properties.Sanitize.Diag.Undefined) {
-		diagSanitizers = append(diagSanitizers, "undefined")
-	}
-
-	diagSanitizers = append(diagSanitizers, sanitize.Properties.Sanitize.Diag.Misc_undefined...)
-
 	if Bool(sanitize.Properties.Sanitize.Address) {
 		if ctx.Arch().ArchType == android.Arm {
 			// Frame pointer based unwinder in ASan requires ARM frame setup.
@@ -465,34 +423,22 @@
 				flags.DynamicLinker += "64"
 			}
 		}
-		sanitizers = append(sanitizers, "address")
-		diagSanitizers = append(diagSanitizers, "address")
 	}
 
 	if Bool(sanitize.Properties.Sanitize.Hwaddress) {
 		flags.CFlags = append(flags.CFlags, hwasanCflags...)
-		sanitizers = append(sanitizers, "hwaddress")
-	}
-
-	if Bool(sanitize.Properties.Sanitize.Thread) {
-		sanitizers = append(sanitizers, "thread")
 	}
 
 	if Bool(sanitize.Properties.Sanitize.Coverage) {
 		flags.CFlags = append(flags.CFlags, "-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp")
 	}
 
-	if Bool(sanitize.Properties.Sanitize.Safestack) {
-		sanitizers = append(sanitizers, "safe-stack")
-	}
-
 	if Bool(sanitize.Properties.Sanitize.Cfi) {
 		if ctx.Arch().ArchType == android.Arm {
 			// __cfi_check needs to be built as Thumb (see the code in linker_cfi.cpp). LLVM is not set up
 			// to do this on a function basis, so force Thumb on the entire module.
 			flags.RequiredInstructionSet = "thumb"
 		}
-		sanitizers = append(sanitizers, "cfi")
 
 		flags.CFlags = append(flags.CFlags, cfiCflags...)
 		flags.AsFlags = append(flags.AsFlags, cfiAsflags...)
@@ -502,9 +448,6 @@
 			flags.CFlags = append(flags.CFlags, "-fvisibility=default")
 		}
 		flags.LdFlags = append(flags.LdFlags, cfiLdflags...)
-		if Bool(sanitize.Properties.Sanitize.Diag.Cfi) {
-			diagSanitizers = append(diagSanitizers, "cfi")
-		}
 
 		if ctx.staticBinary() {
 			_, flags.CFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.CFlags)
@@ -513,25 +456,11 @@
 	}
 
 	if Bool(sanitize.Properties.Sanitize.Integer_overflow) {
-		sanitizers = append(sanitizers, "unsigned-integer-overflow")
-		sanitizers = append(sanitizers, "signed-integer-overflow")
 		flags.CFlags = append(flags.CFlags, intOverflowCflags...)
-		if Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) {
-			diagSanitizers = append(diagSanitizers, "unsigned-integer-overflow")
-			diagSanitizers = append(diagSanitizers, "signed-integer-overflow")
-		}
 	}
 
-	if Bool(sanitize.Properties.Sanitize.Scudo) {
-		sanitizers = append(sanitizers, "scudo")
-	}
-
-	if Bool(sanitize.Properties.Sanitize.Scs) {
-		sanitizers = append(sanitizers, "shadow-call-stack")
-	}
-
-	if len(sanitizers) > 0 {
-		sanitizeArg := "-fsanitize=" + strings.Join(sanitizers, ",")
+	if len(sanitize.Properties.Sanitizers) > 0 {
+		sanitizeArg := "-fsanitize=" + strings.Join(sanitize.Properties.Sanitizers, ",")
 
 		flags.CFlags = append(flags.CFlags, sanitizeArg)
 		flags.AsFlags = append(flags.AsFlags, sanitizeArg)
@@ -556,8 +485,8 @@
 		}
 	}
 
-	if len(diagSanitizers) > 0 {
-		flags.CFlags = append(flags.CFlags, "-fno-sanitize-trap="+strings.Join(diagSanitizers, ","))
+	if len(sanitize.Properties.DiagSanitizers) > 0 {
+		flags.CFlags = append(flags.CFlags, "-fno-sanitize-trap="+strings.Join(sanitize.Properties.DiagSanitizers, ","))
 	}
 	// FIXME: enable RTTI if diag + (cfi or vptr)
 
@@ -571,46 +500,6 @@
 			strings.Join(sanitize.Properties.Sanitize.Diag.No_recover, ","))
 	}
 
-	// Link a runtime library if needed.
-	runtimeLibrary := ""
-	if Bool(sanitize.Properties.Sanitize.Address) {
-		runtimeLibrary = config.AddressSanitizerRuntimeLibrary(ctx.toolchain())
-	} else if Bool(sanitize.Properties.Sanitize.Hwaddress) {
-		runtimeLibrary = config.HWAddressSanitizerRuntimeLibrary(ctx.toolchain())
-	} else if Bool(sanitize.Properties.Sanitize.Thread) {
-		runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(ctx.toolchain())
-	} else if Bool(sanitize.Properties.Sanitize.Scudo) {
-		if len(diagSanitizers) == 0 && !sanitize.Properties.UbsanRuntimeDep {
-			runtimeLibrary = config.ScudoMinimalRuntimeLibrary(ctx.toolchain())
-		} else {
-			runtimeLibrary = config.ScudoRuntimeLibrary(ctx.toolchain())
-		}
-	} else if len(diagSanitizers) > 0 || sanitize.Properties.UbsanRuntimeDep {
-		runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(ctx.toolchain())
-	}
-
-	if runtimeLibrary != "" {
-		runtimeLibraryPath := "${config.ClangAsanLibDir}/" + runtimeLibrary
-		if !ctx.static() {
-			runtimeLibraryPath = runtimeLibraryPath + ctx.toolchain().ShlibSuffix()
-		} else {
-			runtimeLibraryPath = runtimeLibraryPath + ".a"
-		}
-
-		// ASan runtime library must be the first in the link order.
-		flags.libFlags = append([]string{runtimeLibraryPath}, flags.libFlags...)
-		sanitize.runtimeLibrary = runtimeLibrary
-
-		// When linking against VNDK, use the vendor variant of the runtime lib
-		if ctx.useVndk() {
-			sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary + vendorSuffix
-		} else if ctx.inRecovery() {
-			sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary + recoverySuffix
-		} else {
-			sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary
-		}
-	}
-
 	blacklist := android.OptionalPathForModuleSrc(ctx, sanitize.Properties.Sanitize.Blacklist)
 	if blacklist.Valid() {
 		flags.CFlags = append(flags.CFlags, "-fsanitize-blacklist="+blacklist.String())
@@ -621,12 +510,6 @@
 }
 
 func (sanitize *sanitize) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
-	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
-		if sanitize.androidMkRuntimeLibrary != "" {
-			fmt.Fprintln(w, "LOCAL_SHARED_LIBRARIES += "+sanitize.androidMkRuntimeLibrary)
-		}
-	})
-
 	// Add a suffix for CFI-enabled static libraries to allow surfacing both to make without a
 	// name conflict.
 	if ret.Class == "STATIC_LIBRARIES" && Bool(sanitize.Properties.Sanitize.Cfi) {
@@ -782,6 +665,159 @@
 	}
 }
 
+// Add the dependency to the runtime library for each of the sanitizer variants
+func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) {
+	if mctx.Os() != android.Android {
+		return
+	}
+	if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
+		var sanitizers []string
+		var diagSanitizers []string
+
+		if Bool(c.sanitize.Properties.Sanitize.All_undefined) {
+			sanitizers = append(sanitizers, "undefined")
+		} else {
+			if Bool(c.sanitize.Properties.Sanitize.Undefined) {
+				sanitizers = append(sanitizers,
+					"bool",
+					"integer-divide-by-zero",
+					"return",
+					"returns-nonnull-attribute",
+					"shift-exponent",
+					"unreachable",
+					"vla-bound",
+					// TODO(danalbert): The following checks currently have compiler performance issues.
+					//"alignment",
+					//"bounds",
+					//"enum",
+					//"float-cast-overflow",
+					//"float-divide-by-zero",
+					//"nonnull-attribute",
+					//"null",
+					//"shift-base",
+					//"signed-integer-overflow",
+					// TODO(danalbert): Fix UB in libc++'s __tree so we can turn this on.
+					// https://llvm.org/PR19302
+					// http://reviews.llvm.org/D6974
+					// "object-size",
+				)
+			}
+			sanitizers = append(sanitizers, c.sanitize.Properties.Sanitize.Misc_undefined...)
+		}
+
+		if Bool(c.sanitize.Properties.Sanitize.Diag.Undefined) {
+			diagSanitizers = append(diagSanitizers, "undefined")
+		}
+
+		diagSanitizers = append(diagSanitizers, c.sanitize.Properties.Sanitize.Diag.Misc_undefined...)
+
+		if Bool(c.sanitize.Properties.Sanitize.Address) {
+			sanitizers = append(sanitizers, "address")
+			diagSanitizers = append(diagSanitizers, "address")
+		}
+
+		if Bool(c.sanitize.Properties.Sanitize.Hwaddress) {
+			sanitizers = append(sanitizers, "hwaddress")
+		}
+
+		if Bool(c.sanitize.Properties.Sanitize.Thread) {
+			sanitizers = append(sanitizers, "thread")
+		}
+
+		if Bool(c.sanitize.Properties.Sanitize.Safestack) {
+			sanitizers = append(sanitizers, "safe-stack")
+		}
+
+		if Bool(c.sanitize.Properties.Sanitize.Cfi) {
+			sanitizers = append(sanitizers, "cfi")
+
+			if Bool(c.sanitize.Properties.Sanitize.Diag.Cfi) {
+				diagSanitizers = append(diagSanitizers, "cfi")
+			}
+		}
+
+		if Bool(c.sanitize.Properties.Sanitize.Integer_overflow) {
+			sanitizers = append(sanitizers, "unsigned-integer-overflow")
+			sanitizers = append(sanitizers, "signed-integer-overflow")
+			if Bool(c.sanitize.Properties.Sanitize.Diag.Integer_overflow) {
+				diagSanitizers = append(diagSanitizers, "unsigned-integer-overflow")
+				diagSanitizers = append(diagSanitizers, "signed-integer-overflow")
+			}
+		}
+
+		if Bool(c.sanitize.Properties.Sanitize.Scudo) {
+			sanitizers = append(sanitizers, "scudo")
+		}
+
+		if Bool(c.sanitize.Properties.Sanitize.Scs) {
+			sanitizers = append(sanitizers, "shadow-call-stack")
+		}
+
+		// Save the list of sanitizers. These will be used again when generating
+		// the build rules (for Cflags, etc.)
+		c.sanitize.Properties.Sanitizers = sanitizers
+		c.sanitize.Properties.DiagSanitizers = diagSanitizers
+
+		// Determine the runtime library required
+		runtimeLibrary := ""
+		toolchain := c.toolchain(mctx)
+		if Bool(c.sanitize.Properties.Sanitize.Address) {
+			runtimeLibrary = config.AddressSanitizerRuntimeLibrary(toolchain)
+		} else if Bool(c.sanitize.Properties.Sanitize.Hwaddress) {
+			if c.staticBinary() {
+				runtimeLibrary = config.HWAddressSanitizerStaticLibrary(toolchain)
+			} else {
+				runtimeLibrary = config.HWAddressSanitizerRuntimeLibrary(toolchain)
+			}
+		} else if Bool(c.sanitize.Properties.Sanitize.Thread) {
+			runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(toolchain)
+		} else if Bool(c.sanitize.Properties.Sanitize.Scudo) {
+			if len(diagSanitizers) == 0 && !c.sanitize.Properties.UbsanRuntimeDep {
+				runtimeLibrary = config.ScudoMinimalRuntimeLibrary(toolchain)
+			} else {
+				runtimeLibrary = config.ScudoRuntimeLibrary(toolchain)
+			}
+		} else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep {
+			runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
+		}
+
+		if mctx.Device() && runtimeLibrary != "" {
+			if inList(runtimeLibrary, llndkLibraries) && !c.static() {
+				runtimeLibrary = runtimeLibrary + llndkLibrarySuffix
+			}
+
+			// Adding dependency to the runtime library. We are using *FarVariation*
+			// because the runtime libraries themselves are not mutated by sanitizer
+			// mutators and thus don't have sanitizer variants whereas this module
+			// has been already mutated.
+			//
+			// Note that by adding dependency with {static|shared}DepTag, the lib is
+			// added to libFlags and LOCAL_SHARED_LIBRARIES by cc.Module
+			if c.staticBinary() {
+				// static executable gets static runtime libs
+				mctx.AddFarVariationDependencies([]blueprint.Variation{
+					{Mutator: "link", Variation: "static"},
+					{Mutator: "arch", Variation: mctx.Target().String()},
+				}, staticDepTag, runtimeLibrary)
+			} else if !c.static() {
+				// dynamic executable andshared libs get shared runtime libs
+				mctx.AddFarVariationDependencies([]blueprint.Variation{
+					{Mutator: "link", Variation: "shared"},
+					{Mutator: "arch", Variation: mctx.Target().String()},
+				}, sharedDepTag, runtimeLibrary)
+			}
+			// static lib does not have dependency to the runtime library. The
+			// dependency will be added to the executables or shared libs using
+			// the static lib.
+		}
+	}
+}
+
+type Sanitizeable interface {
+	android.Module
+	IsSanitizerEnabled() bool
+}
+
 // Create sanitized variants for modules that need them
 func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) {
 	return func(mctx android.BottomUpMutatorContext) {
@@ -883,6 +919,9 @@
 				}
 			}
 			c.sanitize.Properties.SanitizeDep = false
+		} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled() {
+			// APEX modules fall here
+			mctx.CreateVariations(t.String())
 		}
 	}
 }
diff --git a/java/androidmk.go b/java/androidmk.go
index 70d0f7f..4d3af12 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -157,6 +157,12 @@
 				func(w io.Writer, outputFile android.Path) {
 					fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", binary.headerJarFile.String())
 					fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", binary.implementationAndResourcesJar.String())
+					if binary.dexJarFile != nil {
+						fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", binary.dexJarFile.String())
+					}
+					if len(binary.dexpreopter.builtInstalled) > 0 {
+						fmt.Fprintln(w, "LOCAL_SOONG_BUILT_INSTALLED :=", strings.Join(binary.dexpreopter.builtInstalled, " "))
+					}
 				},
 			},
 			Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
diff --git a/java/config/config.go b/java/config/config.go
index da4eed7..92cfb84 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -43,7 +43,6 @@
 		"android.car7",
 		"core-oj",
 		"core-libart",
-		"core-simple",
 	}
 
 	ManifestMergerClasspath = []string{
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 55a9590..941e665 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -134,11 +134,6 @@
 	// Defaults to "android.annotation".
 	Srcs_lib_whitelist_pkgs []string
 
-	// if set to true, create stubs through Metalava instead of Doclava. Javadoc/Doclava is
-	// currently still used for documentation generation, and will be replaced by Dokka soon.
-	// Defaults to true.
-	Metalava_enabled *bool
-
 	// TODO: determines whether to create HTML doc or not
 	//Html_doc *bool
 }
@@ -447,9 +442,6 @@
 			Local_include_dirs []string
 		}
 	}{}
-	droiddocProps := struct {
-		Custom_template *string
-	}{}
 
 	props.Name = proptools.StringPtr(module.docsName(apiScope))
 	props.Srcs = append(props.Srcs, module.properties.Srcs...)
@@ -462,25 +454,12 @@
 	props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
 	props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
 
-	if module.properties.Metalava_enabled == nil {
-		module.properties.Metalava_enabled = proptools.BoolPtr(true)
-	}
-
-	droiddocArgs := ""
-	if Bool(module.properties.Metalava_enabled) == true {
-		droiddocArgs = " --stub-packages " + strings.Join(module.properties.Api_packages, ":") +
-			" " + android.JoinWithPrefix(module.properties.Hidden_api_packages, " --hide-package ") +
-			" " + android.JoinWithPrefix(module.properties.Droiddoc_options, " ") +
-			" --hide MissingPermission --hide BroadcastBehavior " +
-			"--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
-			"--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo"
-	} else {
-		droiddocProps.Custom_template = proptools.StringPtr("droiddoc-templates-sdk")
-		droiddocArgs = " -stubpackages " + strings.Join(module.properties.Api_packages, ":") +
-			" " + android.JoinWithPrefix(module.properties.Hidden_api_packages, " -hidePackage ") +
-			" " + android.JoinWithPrefix(module.properties.Droiddoc_options, " ") +
-			" -hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128 -nodocs"
-	}
+	droiddocArgs := " --stub-packages " + strings.Join(module.properties.Api_packages, ":") +
+		" " + android.JoinWithPrefix(module.properties.Hidden_api_packages, " --hide-package ") +
+		" " + android.JoinWithPrefix(module.properties.Droiddoc_options, " ") +
+		" --hide MissingPermission --hide BroadcastBehavior " +
+		"--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
+		"--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo"
 
 	switch apiScope {
 	case apiScopeSystem:
@@ -519,45 +498,11 @@
 		module.latestApiFilegroupName(apiScope))
 	props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
 		module.latestRemovedApiFilegroupName(apiScope))
-	if Bool(module.properties.Metalava_enabled) == false {
-		// any change is reported as error
-		props.Check_api.Current.Args = proptools.StringPtr("-error 2 -error 3 -error 4 -error 5 " +
-			"-error 6 -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 " +
-			"-error 14 -error 15 -error 16 -error 17 -error 18 -error 19 -error 20 " +
-			"-error 21 -error 23 -error 24 -error 25 -error 26 -error 27")
+	props.Srcs_lib = module.properties.Srcs_lib
+	props.Srcs_lib_whitelist_dirs = module.properties.Srcs_lib_whitelist_dirs
+	props.Srcs_lib_whitelist_pkgs = module.properties.Srcs_lib_whitelist_pkgs
 
-		// backward incompatible changes are reported as error
-		props.Check_api.Last_released.Args = proptools.StringPtr("-hide 2 -hide 3 -hide 4 -hide 5 " +
-			"-hide 6 -hide 24 -hide 25 -hide 26 -hide 27 " +
-			"-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 " +
-			"-error 15 -error 16 -error 17 -error 18")
-
-		// Include the part of the framework source. This is required for the case when
-		// API class is extending from the framework class. In that case, doclava needs
-		// to know whether the base class is hidden or not. Since that information is
-		// encoded as @hide string in the comment, we need source files for the classes,
-		// not the compiled ones.
-		props.Srcs_lib = proptools.StringPtr("framework")
-		props.Srcs_lib_whitelist_dirs = []string{"core/java"}
-
-		// Add android.annotation package to give access to the framework-defined
-		// annotations such as SystemApi, NonNull, etc.
-		if module.properties.Srcs_lib_whitelist_pkgs != nil {
-			props.Srcs_lib_whitelist_pkgs = module.properties.Srcs_lib_whitelist_pkgs
-		} else {
-			props.Srcs_lib_whitelist_pkgs = []string{"android.annotation"}
-		}
-	} else {
-		props.Srcs_lib = module.properties.Srcs_lib
-		props.Srcs_lib_whitelist_dirs = module.properties.Srcs_lib_whitelist_dirs
-		props.Srcs_lib_whitelist_pkgs = module.properties.Srcs_lib_whitelist_pkgs
-	}
-
-	if Bool(module.properties.Metalava_enabled) == true {
-		mctx.CreateModule(android.ModuleFactoryAdaptor(DroidstubsFactory), &props)
-	} else {
-		mctx.CreateModule(android.ModuleFactoryAdaptor(DroiddocFactory), &props, &droiddocProps)
-	}
+	mctx.CreateModule(android.ModuleFactoryAdaptor(DroidstubsFactory), &props)
 }
 
 // Creates the runtime library. This is not directly linkable from other modules.
diff --git a/python/androidmk.go b/python/androidmk.go
index 20861cb..c1eaa5e 100644
--- a/python/androidmk.go
+++ b/python/androidmk.go
@@ -70,6 +70,11 @@
 		if p.testProperties.Test_config != nil {
 			fmt.Fprintln(w, "LOCAL_TEST_CONFIG :=",
 				*p.testProperties.Test_config)
+		} else {
+			if p.testConfig != nil {
+				fmt.Fprintln(w, "LOCAL_FULL_TEST_CONFIG :=",
+					p.testConfig.String())
+			}
 		}
 	})
 	base.subAndroidMk(ret, p.binaryDecorator.pythonInstaller)
diff --git a/python/test.go b/python/test.go
index 39326f0..43ee54c 100644
--- a/python/test.go
+++ b/python/test.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/tradefed"
 )
 
 // This file contains the module types for building Python test.
@@ -29,12 +30,18 @@
 	// the name of the test configuration (for example "AndroidTest.xml") that should be
 	// installed with the module.
 	Test_config *string `android:"arch_variant"`
+
+	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
+	// should be installed with the module.
+	Test_config_template *string `android:"arch_variant"`
 }
 
 type testDecorator struct {
 	*binaryDecorator
 
 	testProperties TestProperties
+
+	testConfig android.Path
 }
 
 func (test *testDecorator) bootstrapperProps() []interface{} {
@@ -42,6 +49,9 @@
 }
 
 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.pythonInstaller.dir = "nativetest"
 	test.binaryDecorator.pythonInstaller.dir64 = "nativetest64"
 
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index 131fdc4..e6a1b48 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -118,6 +118,22 @@
 	return path
 }
 
+func AutoGenPythonBinaryHostTestConfig(ctx android.ModuleContext, testConfigProp *string,
+	testConfigTemplateProp *string) android.Path {
+
+	path, autogenPath := testConfigPath(ctx, testConfigProp)
+	if autogenPath != nil {
+		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
+		if templatePath.Valid() {
+			autogenTemplate(ctx, autogenPath, templatePath.String())
+		} else {
+			autogenTemplate(ctx, autogenPath, "${PythonBinaryHostTestConfigTemplate}")
+		}
+		return autogenPath
+	}
+	return path
+}
+
 var autogenInstrumentationTest = pctx.StaticRule("autogenInstrumentationTest", blueprint.RuleParams{
 	Command: "${AutoGenTestConfigScript} $out $in ${EmptyTestConfig} $template",
 	CommandDeps: []string{
diff --git a/tradefed/config.go b/tradefed/config.go
index 2c432d0..141e0c5 100644
--- a/tradefed/config.go
+++ b/tradefed/config.go
@@ -30,6 +30,7 @@
 	pctx.SourcePathVariable("NativeBenchmarkTestConfigTemplate", "build/make/core/native_benchmark_test_config_template.xml")
 	pctx.SourcePathVariable("NativeHostTestConfigTemplate", "build/make/core/native_host_test_config_template.xml")
 	pctx.SourcePathVariable("NativeTestConfigTemplate", "build/make/core/native_test_config_template.xml")
+	pctx.SourcePathVariable("PythonBinaryHostTestConfigTemplate", "build/make/core/python_binary_host_test_config_template.xml")
 
 	pctx.SourcePathVariable("EmptyTestConfig", "build/make/core/empty_test_config.xml")
 }
diff --git a/tradefed/makevars.go b/tradefed/makevars.go
index 3ec7997..aad7273 100644
--- a/tradefed/makevars.go
+++ b/tradefed/makevars.go
@@ -30,6 +30,7 @@
 	ctx.Strict("NATIVE_BENCHMARK_TEST_CONFIG_TEMPLATE", "${NativeBenchmarkTestConfigTemplate}")
 	ctx.Strict("NATIVE_HOST_TEST_CONFIG_TEMPLATE", "${NativeHostTestConfigTemplate}")
 	ctx.Strict("NATIVE_TEST_CONFIG_TEMPLATE", "${NativeTestConfigTemplate}")
+	ctx.Strict("PYTHON_BINARY_HOST_TEST_CONFIG_TEMPLATE", "${PythonBinaryHostTestConfigTemplate}")
 
 	ctx.Strict("EMPTY_TEST_CONFIG", "${EmptyTestConfig}")
 }
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 835f820..cb41579 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -59,6 +59,7 @@
 		"-w", "missingdepfile=err")
 
 	cmd := Command(ctx, config, "ninja", executable, args...)
+	cmd.Sandbox = ninjaSandbox
 	if config.HasKatiSuffix() {
 		cmd.Environment.AppendFromKati(config.KatiEnvFile())
 	}
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 1afcf55..f4ef034 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -107,7 +107,6 @@
 	"python":    Allowed,
 	"python2.7": Allowed,
 	"python3":   Allowed,
-	"readlink":  Allowed,
 	"realpath":  Allowed,
 	"rm":        Allowed,
 	"rsync":     Allowed,
@@ -116,7 +115,6 @@
 	"sha1sum":   Allowed,
 	"sha256sum": Allowed,
 	"sha512sum": Allowed,
-	"sort":      Allowed,
 	"tar":       Allowed,
 	"timeout":   Allowed,
 	"tr":        Allowed,
@@ -163,9 +161,11 @@
 	"od":       Toybox,
 	"paste":    Toybox,
 	"pwd":      Toybox,
+	"readlink": Toybox,
 	"rmdir":    Toybox,
 	"setsid":   Toybox,
 	"sleep":    Toybox,
+	"sort":     Toybox,
 	"stat":     Toybox,
 	"tail":     Toybox,
 	"tee":      Toybox,
diff --git a/ui/build/sandbox_darwin.go b/ui/build/sandbox_darwin.go
index 7e75167..43c5480 100644
--- a/ui/build/sandbox_darwin.go
+++ b/ui/build/sandbox_darwin.go
@@ -21,12 +21,12 @@
 type Sandbox string
 
 const (
-	noSandbox            = ""
-	globalSandbox        = "build/soong/ui/build/sandbox/darwin/global.sb"
-	dumpvarsSandbox      = globalSandbox
-	soongSandbox         = globalSandbox
-	katiSandbox          = globalSandbox
-	katiCleanSpecSandbox = globalSandbox
+	noSandbox       = ""
+	globalSandbox   = "build/soong/ui/build/sandbox/darwin/global.sb"
+	dumpvarsSandbox = globalSandbox
+	soongSandbox    = globalSandbox
+	katiSandbox     = globalSandbox
+	ninjaSandbox    = noSandbox
 )
 
 var sandboxExecPath string
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index f2bfac2..f77eebb 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -14,20 +14,151 @@
 
 package build
 
-type Sandbox bool
-
-const (
-	noSandbox            = false
-	globalSandbox        = false
-	dumpvarsSandbox      = false
-	soongSandbox         = false
-	katiSandbox          = false
-	katiCleanSpecSandbox = false
+import (
+	"bytes"
+	"os"
+	"os/exec"
+	"os/user"
+	"strings"
+	"sync"
 )
 
+type Sandbox struct {
+	Enabled              bool
+	DisableWhenUsingGoma bool
+}
+
+var (
+	noSandbox    = Sandbox{}
+	basicSandbox = Sandbox{
+		Enabled: true,
+	}
+
+	dumpvarsSandbox = basicSandbox
+	katiSandbox     = basicSandbox
+	soongSandbox    = basicSandbox
+	ninjaSandbox    = Sandbox{
+		Enabled:              true,
+		DisableWhenUsingGoma: true,
+	}
+)
+
+const nsjailPath = "prebuilts/build-tools/linux-x86/bin/nsjail"
+
+var sandboxConfig struct {
+	once sync.Once
+
+	working bool
+	group   string
+}
+
 func (c *Cmd) sandboxSupported() bool {
-	return false
+	if !c.Sandbox.Enabled {
+		return false
+	}
+
+	// Goma is incompatible with PID namespaces and Mount namespaces. b/122767582
+	if c.Sandbox.DisableWhenUsingGoma && c.config.UseGoma() {
+		return false
+	}
+
+	sandboxConfig.once.Do(func() {
+		sandboxConfig.group = "nogroup"
+		if _, err := user.LookupGroup(sandboxConfig.group); err != nil {
+			sandboxConfig.group = "nobody"
+		}
+
+		cmd := exec.CommandContext(c.ctx.Context, nsjailPath,
+			"-H", "android-build",
+			"-e",
+			"-u", "nobody",
+			"-g", sandboxConfig.group,
+			"-B", "/",
+			"--disable_clone_newcgroup",
+			"--",
+			"/bin/bash", "-c", `if [ $(hostname) == "android-build" ]; then echo "Android" "Success"; else echo Failure; fi`)
+		cmd.Env = c.config.Environment().Environ()
+
+		c.ctx.Verboseln(cmd.Args)
+		data, err := cmd.CombinedOutput()
+		if err == nil && bytes.Contains(data, []byte("Android Success")) {
+			sandboxConfig.working = true
+			return
+		}
+
+		c.ctx.Println("Build sandboxing disabled due to nsjail error. This may become fatal in the future.")
+		c.ctx.Println("Please let us know why nsjail doesn't work in your environment at:")
+		c.ctx.Println("  https://groups.google.com/forum/#!forum/android-building")
+		c.ctx.Println("  https://issuetracker.google.com/issues/new?component=381517")
+
+		for _, line := range strings.Split(strings.TrimSpace(string(data)), "\n") {
+			c.ctx.Verboseln(line)
+		}
+
+		if err == nil {
+			c.ctx.Verboseln("nsjail exited successfully, but without the correct output")
+		} else if e, ok := err.(*exec.ExitError); ok {
+			c.ctx.Verbosef("nsjail failed with %v", e.ProcessState.String())
+		} else {
+			c.ctx.Verbosef("nsjail failed with %v", err)
+		}
+	})
+
+	return sandboxConfig.working
 }
 
 func (c *Cmd) wrapSandbox() {
+	wd, _ := os.Getwd()
+
+	sandboxArgs := []string{
+		// The executable to run
+		"-x", c.Path,
+
+		// Set the hostname to something consistent
+		"-H", "android-build",
+
+		// Use the current working dir
+		"--cwd", wd,
+
+		// No time limit
+		"-t", "0",
+
+		// Keep all environment variables, we already filter them out
+		// in soong_ui
+		"-e",
+
+		// Use a consistent user & group.
+		// Note that these are mapped back to the real UID/GID when
+		// doing filesystem operations, so they're rather arbitrary.
+		"-u", "nobody",
+		"-g", sandboxConfig.group,
+
+		// Set high values, as nsjail uses low defaults.
+		"--rlimit_as", "soft",
+		"--rlimit_core", "soft",
+		"--rlimit_cpu", "soft",
+		"--rlimit_fsize", "soft",
+		"--rlimit_nofile", "soft",
+
+		// For now, just map everything. Eventually we should limit this, especially to make most things readonly.
+		"-B", "/",
+
+		// Disable newcgroup for now, since it may require newer kernels
+		// TODO: try out cgroups
+		"--disable_clone_newcgroup",
+
+		// Only log important warnings / errors
+		"-q",
+
+		// Stop parsing arguments
+		"--",
+	}
+	c.Args = append(sandboxArgs, c.Args[1:]...)
+	c.Path = nsjailPath
+
+	env := Environment(c.Env)
+	if _, hasUser := env.Get("USER"); hasUser {
+		env.Set("USER", "nobody")
+	}
+	c.Env = []string(env)
 }