Merge changes from topic "gcov-prefix-permissions-fix"

* changes:
  Wrap getenv when linking a coverage-enabled binary
  Refactor libprofile-extras to be added as a whole static library
diff --git a/README.md b/README.md
index ebbe8bc..531ef4c 100644
--- a/README.md
+++ b/README.md
@@ -337,6 +337,19 @@
 This will bind mount the Soong source directories into the directory in the layout expected by
 the IDE.
 
+### Running Soong in a debugger
+
+To run the soong_build process in a debugger, install `dlv` and then start the build with
+`SOONG_DELVE=<listen addr>` in the environment.
+For examle:
+```bash
+SOONG_DELVE=:1234 m nothing
+```
+and then in another terminal:
+```
+dlv connect :1234
+```
+
 ## Contact
 
 Email android-building@googlegroups.com (external) for any questions, or see
diff --git a/android/androidmk.go b/android/androidmk.go
index 7d0aa3b..9bc2692 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -216,7 +216,10 @@
 		}
 		a.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(amod.commonProperties.Device_specific))
 		a.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(amod.commonProperties.Product_specific))
-		a.SetBoolIfTrue("LOCAL_PRODUCT_SERVICES_MODULE", Bool(amod.commonProperties.Product_services_specific))
+		// TODO(b/135957588) product_services_specific is matched to LOCAL_PRODUCT_MODULE
+		// as a workaround. Remove this after clearing all Android.bp
+		a.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(amod.commonProperties.Product_services_specific))
+		a.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(amod.commonProperties.System_ext_specific))
 		if amod.commonProperties.Owner != nil {
 			a.SetString("LOCAL_MODULE_OWNER", *amod.commonProperties.Owner)
 		}
diff --git a/android/config.go b/android/config.go
index e4012fa..c0ed50f 100644
--- a/android/config.go
+++ b/android/config.go
@@ -901,11 +901,11 @@
 	return "product"
 }
 
-func (c *deviceConfig) ProductServicesPath() string {
-	if c.config.productVariables.ProductServicesPath != nil {
-		return *c.config.productVariables.ProductServicesPath
+func (c *deviceConfig) SystemExtPath() string {
+	if c.config.productVariables.SystemExtPath != nil {
+		return *c.config.productVariables.SystemExtPath
 	}
-	return "product_services"
+	return "system_ext"
 }
 
 func (c *deviceConfig) BtConfigIncludeDir() string {
diff --git a/android/defaults.go b/android/defaults.go
index 844b4d4..ae2c820 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -63,9 +63,28 @@
 
 type DefaultsModuleBase struct {
 	DefaultableModuleBase
-	defaultProperties []interface{}
 }
 
+// The common pattern for defaults modules is to register separate instances of
+// the xxxProperties structs in the AddProperties calls, rather than reusing the
+// ones inherited from Module.
+//
+// The effect is that e.g. myDefaultsModuleInstance.base().xxxProperties won't
+// contain the values that have been set for the defaults module. Rather, to
+// retrieve the values it is necessary to iterate over properties(). E.g. to get
+// the commonProperties instance that have the real values:
+//
+//   d := myModule.(Defaults)
+//   for _, props := range d.properties() {
+//     if cp, ok := props.(*commonProperties); ok {
+//       ... access property values in cp ...
+//     }
+//   }
+//
+// The rationale is that the properties on a defaults module apply to the
+// defaultable modules using it, not to the defaults module itself. E.g. setting
+// the "enabled" property false makes inheriting modules disabled by default,
+// rather than disabling the defaults module itself.
 type Defaults interface {
 	Defaultable
 	isDefaults() bool
diff --git a/android/env.go b/android/env.go
index 469dfff..d9f2db2 100644
--- a/android/env.go
+++ b/android/env.go
@@ -16,6 +16,7 @@
 
 import (
 	"os"
+	"os/exec"
 	"strings"
 
 	"android/soong/env"
@@ -29,8 +30,16 @@
 // a manifest regeneration.
 
 var originalEnv map[string]string
+var SoongDelveListen string
+var SoongDelvePath string
 
 func init() {
+	// Delve support needs to read this environment variable very early, before NewConfig has created a way to
+	// access originalEnv with dependencies.  Store the value where soong_build can find it, it will manually
+	// ensure the dependencies are created.
+	SoongDelveListen = os.Getenv("SOONG_DELVE")
+	SoongDelvePath, _ = exec.LookPath("dlv")
+
 	originalEnv = make(map[string]string)
 	for _, env := range os.Environ() {
 		idx := strings.IndexRune(env, '=')
@@ -38,6 +47,8 @@
 			originalEnv[env[:idx]] = env[idx+1:]
 		}
 	}
+	// Clear the environment to prevent use of os.Getenv(), which would not provide dependencies on environment
+	// variable values.  The environment is available through ctx.Config().Getenv, ctx.Config().IsEnvTrue, etc.
 	os.Clearenv()
 }
 
diff --git a/android/hooks.go b/android/hooks.go
index 2d2f797..5810996 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -129,6 +129,8 @@
 
 func LoadHookMutator(ctx TopDownMutatorContext) {
 	if m, ok := ctx.Module().(Module); ok {
+		m.base().commonProperties.DebugName = ctx.ModuleName()
+
 		// Cast through *topDownMutatorContext because AppendProperties is implemented
 		// on *topDownMutatorContext but not exposed through TopDownMutatorContext
 		var loadHookCtx LoadHookContext = ctx.(*topDownMutatorContext)
diff --git a/android/module.go b/android/module.go
index 43b8763..adb9454 100644
--- a/android/module.go
+++ b/android/module.go
@@ -126,7 +126,7 @@
 	DeviceSpecific() bool
 	SocSpecific() bool
 	ProductSpecific() bool
-	ProductServicesSpecific() bool
+	SystemExtSpecific() bool
 	AConfig() Config
 	DeviceConfig() DeviceConfig
 }
@@ -203,6 +203,9 @@
 	RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
 	VariablesForTests() map[string]string
 
+	// String returns a string that includes the module name and variants for printing during debugging.
+	String() string
+
 	// Get the qualified module id for this module.
 	qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleName
 
@@ -347,11 +350,15 @@
 	// /system/product if product partition does not exist).
 	Product_specific *bool
 
-	// whether this module provides services owned by the OS provider to the core platform. When set
-	// to true, it is installed into  /product_services (or /system/product_services if
-	// product_services partition does not exist).
+	// TODO(b/135957588) Product_services_specific will be removed once we clear all Android.bp
+	// files that have 'product_services_specific: true'. This will be converted to
+	// Product_speicific as a workaround.
 	Product_services_specific *bool
 
+	// whether this module extends system. When set to true, it is installed into /system_ext
+	// (or /system/system_ext if system_ext partition does not exist).
+	System_ext_specific *bool
+
 	// Whether this module is installed to recovery partition
 	Recovery *bool
 
@@ -408,6 +415,11 @@
 	NamespaceExportedToMake bool `blueprint:"mutated"`
 
 	MissingDeps []string `blueprint:"mutated"`
+
+	// Name and variant strings stored by mutators to enable Module.String()
+	DebugName       string   `blueprint:"mutated"`
+	DebugMutators   []string `blueprint:"mutated"`
+	DebugVariations []string `blueprint:"mutated"`
 }
 
 type hostAndDeviceProperties struct {
@@ -461,7 +473,7 @@
 	deviceSpecificModule
 	socSpecificModule
 	productSpecificModule
-	productServicesSpecificModule
+	systemExtSpecificModule
 )
 
 func (k moduleKind) String() string {
@@ -474,8 +486,8 @@
 		return "soc-specific"
 	case productSpecificModule:
 		return "product-specific"
-	case productServicesSpecificModule:
-		return "productservices-specific"
+	case systemExtSpecificModule:
+		return "systemext-specific"
 	default:
 		panic(fmt.Errorf("unknown module kind %d", k))
 	}
@@ -625,6 +637,23 @@
 	return String(m.nameProperties.Name)
 }
 
+// String returns a string that includes the module name and variants for printing during debugging.
+func (m *ModuleBase) String() string {
+	sb := strings.Builder{}
+	sb.WriteString(m.commonProperties.DebugName)
+	sb.WriteString("{")
+	for i := range m.commonProperties.DebugMutators {
+		if i != 0 {
+			sb.WriteString(",")
+		}
+		sb.WriteString(m.commonProperties.DebugMutators[i])
+		sb.WriteString(":")
+		sb.WriteString(m.commonProperties.DebugVariations[i])
+	}
+	sb.WriteString("}")
+	return sb.String()
+}
+
 // BaseModuleName returns the name of the module as specified in the blueprints file.
 func (m *ModuleBase) BaseModuleName() string {
 	return String(m.nameProperties.Name)
@@ -713,7 +742,7 @@
 }
 
 func (m *ModuleBase) Platform() bool {
-	return !m.DeviceSpecific() && !m.SocSpecific() && !m.ProductSpecific() && !m.ProductServicesSpecific()
+	return !m.DeviceSpecific() && !m.SocSpecific() && !m.ProductSpecific() && !m.SystemExtSpecific()
 }
 
 func (m *ModuleBase) DeviceSpecific() bool {
@@ -728,8 +757,8 @@
 	return Bool(m.commonProperties.Product_specific)
 }
 
-func (m *ModuleBase) ProductServicesSpecific() bool {
-	return Bool(m.commonProperties.Product_services_specific)
+func (m *ModuleBase) SystemExtSpecific() bool {
+	return Bool(m.commonProperties.System_ext_specific)
 }
 
 func (m *ModuleBase) Enabled() bool {
@@ -850,7 +879,7 @@
 	var socSpecific = Bool(m.commonProperties.Vendor) || Bool(m.commonProperties.Proprietary) || Bool(m.commonProperties.Soc_specific)
 	var deviceSpecific = Bool(m.commonProperties.Device_specific)
 	var productSpecific = Bool(m.commonProperties.Product_specific)
-	var productServicesSpecific = Bool(m.commonProperties.Product_services_specific)
+	var systemExtSpecific = Bool(m.commonProperties.System_ext_specific)
 
 	msg := "conflicting value set here"
 	if socSpecific && deviceSpecific {
@@ -866,16 +895,16 @@
 		}
 	}
 
-	if productSpecific && productServicesSpecific {
-		ctx.PropertyErrorf("product_specific", "a module cannot be specific to product and product_services at the same time.")
-		ctx.PropertyErrorf("product_services_specific", msg)
+	if productSpecific && systemExtSpecific {
+		ctx.PropertyErrorf("product_specific", "a module cannot be specific to product and system_ext at the same time.")
+		ctx.PropertyErrorf("system_ext_specific", msg)
 	}
 
-	if (socSpecific || deviceSpecific) && (productSpecific || productServicesSpecific) {
+	if (socSpecific || deviceSpecific) && (productSpecific || systemExtSpecific) {
 		if productSpecific {
 			ctx.PropertyErrorf("product_specific", "a module cannot be specific to SoC or device and product at the same time.")
 		} else {
-			ctx.PropertyErrorf("product_services_specific", "a module cannot be specific to SoC or device and product_services at the same time.")
+			ctx.PropertyErrorf("system_ext_specific", "a module cannot be specific to SoC or device and system_ext at the same time.")
 		}
 		if deviceSpecific {
 			ctx.PropertyErrorf("device_specific", msg)
@@ -894,8 +923,8 @@
 
 	if productSpecific {
 		return productSpecificModule
-	} else if productServicesSpecific {
-		return productServicesSpecificModule
+	} else if systemExtSpecific {
+		return systemExtSpecificModule
 	} else if deviceSpecific {
 		return deviceSpecificModule
 	} else if socSpecific {
@@ -1408,18 +1437,18 @@
 	return b.kind == productSpecificModule
 }
 
-func (b *baseModuleContext) ProductServicesSpecific() bool {
-	return b.kind == productServicesSpecificModule
+func (b *baseModuleContext) SystemExtSpecific() bool {
+	return b.kind == systemExtSpecificModule
 }
 
 // Makes this module a platform module, i.e. not specific to soc, device,
-// product, or product_services.
+// product, or system_ext.
 func (m *ModuleBase) MakeAsPlatform() {
 	m.commonProperties.Vendor = boolPtr(false)
 	m.commonProperties.Proprietary = boolPtr(false)
 	m.commonProperties.Soc_specific = boolPtr(false)
 	m.commonProperties.Product_specific = boolPtr(false)
-	m.commonProperties.Product_services_specific = boolPtr(false)
+	m.commonProperties.System_ext_specific = boolPtr(false)
 }
 
 func (m *ModuleBase) EnableNativeBridgeSupportByDefault() {
diff --git a/android/mutator.go b/android/mutator.go
index 070b420..b799432 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -117,6 +117,8 @@
 type TopDownMutatorContext interface {
 	BaseModuleContext
 
+	MutatorName() string
+
 	Rename(name string)
 
 	CreateModule(blueprint.ModuleFactory, ...interface{})
@@ -132,6 +134,8 @@
 type BottomUpMutatorContext interface {
 	BaseModuleContext
 
+	MutatorName() string
+
 	Rename(name string)
 
 	AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string)
@@ -229,16 +233,26 @@
 // non-overridden method has to be forwarded.  There are fewer non-overridden methods, so use the latter.  The following
 // methods forward to the identical blueprint versions for topDownMutatorContext and bottomUpMutatorContext.
 
+func (t *topDownMutatorContext) MutatorName() string {
+	return t.bp.MutatorName()
+}
+
 func (t *topDownMutatorContext) Rename(name string) {
 	t.bp.Rename(name)
+	t.Module().base().commonProperties.DebugName = name
 }
 
 func (t *topDownMutatorContext) CreateModule(factory blueprint.ModuleFactory, props ...interface{}) {
 	t.bp.CreateModule(factory, props...)
 }
 
+func (b *bottomUpMutatorContext) MutatorName() string {
+	return b.bp.MutatorName()
+}
+
 func (b *bottomUpMutatorContext) Rename(name string) {
 	b.bp.Rename(name)
+	b.Module().base().commonProperties.DebugName = name
 }
 
 func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) {
@@ -250,11 +264,27 @@
 }
 
 func (b *bottomUpMutatorContext) CreateVariations(variations ...string) []blueprint.Module {
-	return b.bp.CreateVariations(variations...)
+	modules := b.bp.CreateVariations(variations...)
+
+	for i := range variations {
+		base := modules[i].(Module).base()
+		base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, b.MutatorName())
+		base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variations[i])
+	}
+
+	return modules
 }
 
 func (b *bottomUpMutatorContext) CreateLocalVariations(variations ...string) []blueprint.Module {
-	return b.bp.CreateLocalVariations(variations...)
+	modules := b.bp.CreateLocalVariations(variations...)
+
+	for i := range variations {
+		base := modules[i].(Module).base()
+		base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, b.MutatorName())
+		base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variations[i])
+	}
+
+	return modules
 }
 
 func (b *bottomUpMutatorContext) SetDependencyVariation(variation string) {
diff --git a/android/mutator_test.go b/android/mutator_test.go
index 4cef400..0b23434 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -15,8 +15,6 @@
 package android
 
 import (
-	"io/ioutil"
-	"os"
 	"reflect"
 	"testing"
 
@@ -26,6 +24,8 @@
 type mutatorTestModule struct {
 	ModuleBase
 	props struct {
+		Deps_missing_deps    []string
+		Mutator_missing_deps []string
 	}
 
 	missingDeps []string
@@ -48,20 +48,14 @@
 }
 
 func (m *mutatorTestModule) DepsMutator(ctx BottomUpMutatorContext) {
-	ctx.AddDependency(ctx.Module(), nil, "regular_missing_dep")
+	ctx.AddDependency(ctx.Module(), nil, m.props.Deps_missing_deps...)
 }
 
 func addMissingDependenciesMutator(ctx TopDownMutatorContext) {
-	ctx.AddMissingDependencies([]string{"added_missing_dep"})
+	ctx.AddMissingDependencies(ctx.Module().(*mutatorTestModule).props.Mutator_missing_deps)
 }
 
 func TestMutatorAddMissingDependencies(t *testing.T) {
-	buildDir, err := ioutil.TempDir("", "soong_mutator_test")
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer os.RemoveAll(buildDir)
-
 	config := TestConfig(buildDir, nil)
 	config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
 
@@ -76,6 +70,8 @@
 	bp := `
 		test {
 			name: "foo",
+			deps_missing_deps: ["regular_missing_dep"],
+			mutator_missing_deps: ["added_missing_dep"],
 		}
 	`
 
@@ -97,3 +93,107 @@
 		t.Errorf("want foo missing deps %q, got %q", w, g)
 	}
 }
+
+func TestModuleString(t *testing.T) {
+	ctx := NewTestContext()
+
+	var moduleStrings []string
+
+	ctx.PreArchMutators(func(ctx RegisterMutatorsContext) {
+		ctx.BottomUp("pre_arch", func(ctx BottomUpMutatorContext) {
+			moduleStrings = append(moduleStrings, ctx.Module().String())
+			ctx.CreateVariations("a", "b")
+		})
+		ctx.TopDown("rename_top_down", func(ctx TopDownMutatorContext) {
+			moduleStrings = append(moduleStrings, ctx.Module().String())
+			ctx.Rename(ctx.Module().base().Name() + "_renamed1")
+		})
+	})
+
+	ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+		ctx.BottomUp("pre_deps", func(ctx BottomUpMutatorContext) {
+			moduleStrings = append(moduleStrings, ctx.Module().String())
+			ctx.CreateVariations("c", "d")
+		})
+	})
+
+	ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
+		ctx.BottomUp("post_deps", func(ctx BottomUpMutatorContext) {
+			moduleStrings = append(moduleStrings, ctx.Module().String())
+			ctx.CreateLocalVariations("e", "f")
+		})
+		ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) {
+			moduleStrings = append(moduleStrings, ctx.Module().String())
+			ctx.Rename(ctx.Module().base().Name() + "_renamed2")
+		})
+		ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
+			moduleStrings = append(moduleStrings, ctx.Module().String())
+		})
+	})
+
+	ctx.RegisterModuleType("test", ModuleFactoryAdaptor(mutatorTestModuleFactory))
+
+	bp := `
+		test {
+			name: "foo",
+		}
+	`
+
+	mockFS := map[string][]byte{
+		"Android.bp": []byte(bp),
+	}
+
+	ctx.MockFileSystem(mockFS)
+
+	ctx.Register()
+
+	config := TestConfig(buildDir, nil)
+
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	FailIfErrored(t, errs)
+
+	want := []string{
+		// Initial name.
+		"foo{}",
+
+		// After pre_arch (reversed because rename_top_down is TopDown so it visits in reverse order).
+		"foo{pre_arch:b}",
+		"foo{pre_arch:a}",
+
+		// After rename_top_down.
+		"foo_renamed1{pre_arch:a}",
+		"foo_renamed1{pre_arch:b}",
+
+		// After pre_deps.
+		"foo_renamed1{pre_arch:a,pre_deps:c}",
+		"foo_renamed1{pre_arch:a,pre_deps:d}",
+		"foo_renamed1{pre_arch:b,pre_deps:c}",
+		"foo_renamed1{pre_arch:b,pre_deps:d}",
+
+		// After post_deps.
+		"foo_renamed1{pre_arch:a,pre_deps:c,post_deps:e}",
+		"foo_renamed1{pre_arch:a,pre_deps:c,post_deps:f}",
+		"foo_renamed1{pre_arch:a,pre_deps:d,post_deps:e}",
+		"foo_renamed1{pre_arch:a,pre_deps:d,post_deps:f}",
+		"foo_renamed1{pre_arch:b,pre_deps:c,post_deps:e}",
+		"foo_renamed1{pre_arch:b,pre_deps:c,post_deps:f}",
+		"foo_renamed1{pre_arch:b,pre_deps:d,post_deps:e}",
+		"foo_renamed1{pre_arch:b,pre_deps:d,post_deps:f}",
+
+		// After rename_bottom_up.
+		"foo_renamed2{pre_arch:a,pre_deps:c,post_deps:e}",
+		"foo_renamed2{pre_arch:a,pre_deps:c,post_deps:f}",
+		"foo_renamed2{pre_arch:a,pre_deps:d,post_deps:e}",
+		"foo_renamed2{pre_arch:a,pre_deps:d,post_deps:f}",
+		"foo_renamed2{pre_arch:b,pre_deps:c,post_deps:e}",
+		"foo_renamed2{pre_arch:b,pre_deps:c,post_deps:f}",
+		"foo_renamed2{pre_arch:b,pre_deps:d,post_deps:e}",
+		"foo_renamed2{pre_arch:b,pre_deps:d,post_deps:f}",
+	}
+
+	if !reflect.DeepEqual(moduleStrings, want) {
+		t.Errorf("want module String() values:\n%q\ngot:\n%q", want, moduleStrings)
+	}
+}
diff --git a/android/notices.go b/android/notices.go
index dbb88fc..8503593 100644
--- a/android/notices.go
+++ b/android/notices.go
@@ -27,6 +27,13 @@
 	pctx.HostBinToolVariable("minigzip", "minigzip")
 }
 
+type NoticeOutputs struct {
+	Merged       OptionalPath
+	TxtOutput    OptionalPath
+	HtmlOutput   OptionalPath
+	HtmlGzOutput OptionalPath
+}
+
 var (
 	mergeNoticesRule = pctx.AndroidStaticRule("mergeNoticesRule", blueprint.RuleParams{
 		Command:     `${merge_notices} --output $out $in`,
@@ -35,13 +42,13 @@
 	})
 
 	generateNoticeRule = pctx.AndroidStaticRule("generateNoticeRule", blueprint.RuleParams{
-		Command: `rm -rf $tmpDir $$(dirname $out) && ` +
-			`mkdir -p $tmpDir $$(dirname $out) && ` +
-			`${generate_notice} --text-output $tmpDir/NOTICE.txt --html-output $tmpDir/NOTICE.html -t "$title" -s $inputDir && ` +
-			`${minigzip} -c $tmpDir/NOTICE.html > $out`,
+		Command: `rm -rf $$(dirname $txtOut) $$(dirname htmlOut) $$(dirname $out) && ` +
+			`mkdir -p $$(dirname $txtOut) $$(dirname htmlOut)  $$(dirname $out) && ` +
+			`${generate_notice} --text-output $txtOut --html-output $htmlOut -t "$title" -s $inputDir && ` +
+			`${minigzip} -c $htmlOut > $out`,
 		CommandDeps: []string{"${generate_notice}", "${minigzip}"},
 		Description: "produce notice file $out",
-	}, "tmpDir", "title", "inputDir")
+	}, "txtOut", "htmlOut", "title", "inputDir")
 )
 
 func MergeNotices(ctx ModuleContext, mergedNotice WritablePath, noticePaths []Path) {
@@ -54,7 +61,7 @@
 }
 
 func BuildNoticeOutput(ctx ModuleContext, installPath OutputPath, installFilename string,
-	noticePaths []Path) ModuleOutPath {
+	noticePaths []Path) NoticeOutputs {
 	// Merge all NOTICE files into one.
 	// TODO(jungjw): We should just produce a well-formatted NOTICE.html file in a single pass.
 	//
@@ -68,20 +75,28 @@
 	MergeNotices(ctx, mergedNotice, noticePaths)
 
 	// Transform the merged NOTICE file into a gzipped HTML file.
-	noticeOutput := PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
-	tmpDir := PathForModuleOut(ctx, "NOTICE_tmp")
+	txtOuptut := PathForModuleOut(ctx, "NOTICE_txt", "NOTICE.txt")
+	htmlOutput := PathForModuleOut(ctx, "NOTICE_html", "NOTICE.html")
+	htmlGzOutput := PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
 	title := "Notices for " + ctx.ModuleName()
 	ctx.Build(pctx, BuildParams{
-		Rule:        generateNoticeRule,
-		Description: "generate notice output",
-		Input:       mergedNotice,
-		Output:      noticeOutput,
+		Rule:            generateNoticeRule,
+		Description:     "generate notice output",
+		Input:           mergedNotice,
+		Output:          htmlGzOutput,
+		ImplicitOutputs: WritablePaths{txtOuptut, htmlOutput},
 		Args: map[string]string{
-			"tmpDir":   tmpDir.String(),
+			"txtOut":   txtOuptut.String(),
+			"htmlOut":  htmlOutput.String(),
 			"title":    title,
 			"inputDir": PathForModuleOut(ctx, "NOTICE_FILES/src").String(),
 		},
 	})
 
-	return noticeOutput
+	return NoticeOutputs{
+		Merged:       OptionalPathForPath(mergedNotice),
+		TxtOutput:    OptionalPathForPath(txtOuptut),
+		HtmlOutput:   OptionalPathForPath(htmlOutput),
+		HtmlGzOutput: OptionalPathForPath(htmlGzOutput),
+	}
 }
diff --git a/android/package_test.go b/android/package_test.go
index f1f47ac..e5b0556 100644
--- a/android/package_test.go
+++ b/android/package_test.go
@@ -1,8 +1,6 @@
 package android
 
 import (
-	"io/ioutil"
-	"os"
 	"testing"
 )
 
@@ -58,15 +56,9 @@
 }
 
 func TestPackage(t *testing.T) {
-	buildDir, err := ioutil.TempDir("", "soong_package_test")
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer os.RemoveAll(buildDir)
-
 	for _, test := range packageTests {
 		t.Run(test.name, func(t *testing.T) {
-			_, errs := testPackage(buildDir, test.fs)
+			_, errs := testPackage(test.fs)
 
 			expectedErrors := test.expectedErrors
 			if expectedErrors == nil {
@@ -89,7 +81,7 @@
 	}
 }
 
-func testPackage(buildDir string, fs map[string][]byte) (*TestContext, []error) {
+func testPackage(fs map[string][]byte) (*TestContext, []error) {
 
 	// Create a new config per test as visibility information is stored in the config.
 	config := TestArchConfig(buildDir, nil)
diff --git a/android/path_properties_test.go b/android/path_properties_test.go
index fa187fa..e98c136 100644
--- a/android/path_properties_test.go
+++ b/android/path_properties_test.go
@@ -15,8 +15,6 @@
 package android
 
 import (
-	"io/ioutil"
-	"os"
 	"reflect"
 	"testing"
 )
@@ -85,12 +83,6 @@
 		},
 	}
 
-	buildDir, err := ioutil.TempDir("", "soong_path_properties_test")
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer os.RemoveAll(buildDir)
-
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
 			config := TestArchConfig(buildDir, nil)
diff --git a/android/paths.go b/android/paths.go
index 20b8b82..0ea4447 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1145,8 +1145,8 @@
 		partition = ctx.DeviceConfig().OdmPath()
 	} else if ctx.ProductSpecific() {
 		partition = ctx.DeviceConfig().ProductPath()
-	} else if ctx.ProductServicesSpecific() {
-		partition = ctx.DeviceConfig().ProductServicesPath()
+	} else if ctx.SystemExtSpecific() {
+		partition = ctx.DeviceConfig().SystemExtPath()
 	} else {
 		partition = "system"
 	}
diff --git a/android/paths_test.go b/android/paths_test.go
index 7bcfe41..8286e9a 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -294,15 +294,15 @@
 			out: "target/product/test_device/product/bin/my_test",
 		},
 		{
-			name: "product_services binary",
+			name: "system_ext binary",
 			ctx: &moduleInstallPathContextImpl{
 				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
-					kind:   productServicesSpecificModule,
+					kind:   systemExtSpecificModule,
 				},
 			},
 			in:  []string{"bin", "my_test"},
-			out: "target/product/test_device/product_services/bin/my_test",
+			out: "target/product/test_device/system_ext/bin/my_test",
 		},
 
 		{
@@ -354,11 +354,11 @@
 		},
 
 		{
-			name: "product_services native test binary",
+			name: "system_ext native test binary",
 			ctx: &moduleInstallPathContextImpl{
 				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
-					kind:   productServicesSpecificModule,
+					kind:   systemExtSpecificModule,
 				},
 				inData: true,
 			},
@@ -415,16 +415,16 @@
 		},
 
 		{
-			name: "sanitized product_services binary",
+			name: "sanitized system_ext binary",
 			ctx: &moduleInstallPathContextImpl{
 				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
-					kind:   productServicesSpecificModule,
+					kind:   systemExtSpecificModule,
 				},
 				inSanitizerDir: true,
 			},
 			in:  []string{"bin", "my_test"},
-			out: "target/product/test_device/data/asan/product_services/bin/my_test",
+			out: "target/product/test_device/data/asan/system_ext/bin/my_test",
 		},
 
 		{
@@ -479,11 +479,11 @@
 			out: "target/product/test_device/data/asan/data/nativetest/my_test",
 		},
 		{
-			name: "sanitized product_services native test binary",
+			name: "sanitized system_ext native test binary",
 			ctx: &moduleInstallPathContextImpl{
 				baseModuleContext: baseModuleContext{
 					target: deviceTarget,
-					kind:   productServicesSpecificModule,
+					kind:   systemExtSpecificModule,
 				},
 				inData:         true,
 				inSanitizerDir: true,
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 8d7e74b..e53eb0d 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -267,7 +267,7 @@
 func (r *RuleBuilder) Commands() []string {
 	var commands []string
 	for _, c := range r.commands {
-		commands = append(commands, string(c.buf))
+		commands = append(commands, c.buf.String())
 	}
 	return commands
 }
@@ -358,7 +358,7 @@
 			Flag("--output-root").Text(r.sboxOutDir.String()).
 			Flags(sboxOutputs)
 
-		commandString = string(sboxCmd.buf)
+		commandString = sboxCmd.buf.String()
 		tools = append(tools, sboxCmd.tools...)
 	}
 
@@ -388,7 +388,7 @@
 // RuleBuilderCommand, so they can be used chained or unchained.  All methods that add text implicitly add a single
 // space as a separator from the previous method.
 type RuleBuilderCommand struct {
-	buf      []byte
+	buf      strings.Builder
 	inputs   Paths
 	outputs  WritablePaths
 	depFiles WritablePaths
@@ -420,10 +420,10 @@
 // Text adds the specified raw text to the command line.  The text should not contain input or output paths or the
 // rule will not have them listed in its dependencies or outputs.
 func (c *RuleBuilderCommand) Text(text string) *RuleBuilderCommand {
-	if len(c.buf) > 0 {
-		c.buf = append(c.buf, ' ')
+	if c.buf.Len() > 0 {
+		c.buf.WriteByte(' ')
 	}
-	c.buf = append(c.buf, text...)
+	c.buf.WriteString(text)
 	return c
 }
 
@@ -608,7 +608,7 @@
 
 // String returns the command line.
 func (c *RuleBuilderCommand) String() string {
-	return string(c.buf)
+	return c.buf.String()
 }
 
 func ninjaNameEscape(s string) string {
diff --git a/android/variable.go b/android/variable.go
index b4f31c6..fcd92d4 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -232,10 +232,10 @@
 	EnableXOM       *bool    `json:",omitempty"`
 	XOMExcludePaths []string `json:",omitempty"`
 
-	VendorPath          *string `json:",omitempty"`
-	OdmPath             *string `json:",omitempty"`
-	ProductPath         *string `json:",omitempty"`
-	ProductServicesPath *string `json:",omitempty"`
+	VendorPath    *string `json:",omitempty"`
+	OdmPath       *string `json:",omitempty"`
+	ProductPath   *string `json:",omitempty"`
+	SystemExtPath *string `json:",omitempty"`
 
 	ClangTidy  *bool   `json:",omitempty"`
 	TidyChecks *string `json:",omitempty"`
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index af81e43..2def179 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -192,7 +192,7 @@
 			"LOCAL_VENDOR_MODULE":              "vendor",
 			"LOCAL_ODM_MODULE":                 "device_specific",
 			"LOCAL_PRODUCT_MODULE":             "product_specific",
-			"LOCAL_PRODUCT_SERVICES_MODULE":    "product_services_specific",
+			"LOCAL_SYSTEM_EXT_MODULE":          "system_ext_specific",
 			"LOCAL_EXPORT_PACKAGE_RESOURCES":   "export_package_resources",
 			"LOCAL_PRIVILEGED_MODULE":          "privileged",
 			"LOCAL_AAPT_INCLUDE_ALL_RESOURCES": "aapt_include_all_resources",
@@ -602,8 +602,8 @@
 		return fmt.Errorf("Cannot handle appending to LOCAL_MODULE_PATH")
 	}
 	// Analyze value in order to set the correct values for the 'device_specific',
-	// 'product_specific', 'product_services_specific' 'vendor'/'soc_specific',
-	// 'product_services_specific' attribute. Two cases are allowed:
+	// 'product_specific', 'system_ext_specific' 'vendor'/'soc_specific',
+	// 'system_ext_specific' attribute. Two cases are allowed:
 	//   $(VAR)/<literal-value>
 	//   $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR)/<literal-value>
 	// The last case is equivalent to $(TARGET_OUT_VENDOR)/<literal-value>
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index 4d5180e..dbb7fde 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -957,37 +957,37 @@
 `,
 	},
 	{
-		desc: "prebuilt_etc_TARGET_OUT_PRODUCT_SERVICES/etc",
+		desc: "prebuilt_etc_TARGET_OUT_SYSTEM_EXT/etc",
 		in: `
 include $(CLEAR_VARS)
 LOCAL_MODULE := etc.test1
 LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES)/etc/foo/bar
+LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_EXT)/etc/foo/bar
 include $(BUILD_PREBUILT)
 `,
 		expected: `
 prebuilt_etc {
 	name: "etc.test1",
 	sub_dir: "foo/bar",
-	product_services_specific: true,
+	system_ext_specific: true,
 
 }
 `,
 	},
 	{
-		desc: "prebuilt_etc_TARGET_OUT_PRODUCT_SERVICES_ETC",
+		desc: "prebuilt_etc_TARGET_OUT_SYSTEM_EXT_ETC",
 		in: `
 include $(CLEAR_VARS)
 LOCAL_MODULE := etc.test1
 LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES_ETC)/foo/bar
+LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_EXT_ETC)/foo/bar
 include $(BUILD_PREBUILT)
 `,
 		expected: `
 prebuilt_etc {
 	name: "etc.test1",
 	sub_dir: "foo/bar",
-	product_services_specific: true,
+	system_ext_specific: true,
 
 
 }
diff --git a/apex/apex.go b/apex/apex.go
index a77e295..f683f96 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -108,6 +108,7 @@
 	executableTag  = dependencyTag{name: "executable"}
 	javaLibTag     = dependencyTag{name: "javaLib"}
 	prebuiltTag    = dependencyTag{name: "prebuilt"}
+	testTag        = dependencyTag{name: "test"}
 	keyTag         = dependencyTag{name: "key"}
 	certificateTag = dependencyTag{name: "certificate"}
 )
@@ -192,6 +193,8 @@
 	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"
@@ -232,7 +235,7 @@
 	// List of native shared libs that are embedded inside this APEX bundle
 	Native_shared_libs []string
 
-	// List of native executables that are embedded inside this APEX bundle
+	// List of executables that are embedded inside this APEX bundle
 	Binaries []string
 
 	// List of java libraries that are embedded inside this APEX bundle
@@ -241,6 +244,9 @@
 	// List of prebuilt files that are embedded inside this APEX bundle
 	Prebuilts []string
 
+	// List of tests that are embedded inside this APEX bundle
+	Tests []string
+
 	// Name of the apex_key module that provides the private key to sign APEX
 	Key *string
 
@@ -299,6 +305,7 @@
 	pyBinary
 	goBinary
 	javaSharedLib
+	nativeTest
 )
 
 type apexPackaging int
@@ -361,6 +368,8 @@
 		return "EXECUTABLES"
 	case javaSharedLib:
 		return "JAVA_LIBRARIES"
+	case nativeTest:
+		return "NATIVE_TESTS"
 	default:
 		panic(fmt.Errorf("unkonwn class %d", class))
 	}
@@ -406,7 +415,8 @@
 }
 
 func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
-	native_shared_libs []string, binaries []string, arch string, imageVariation string) {
+	native_shared_libs []string, binaries []string, tests []string,
+	arch string, imageVariation string) {
 	// Use *FarVariation* to be able to depend on modules having
 	// conflicting variations with this module. This is required since
 	// arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
@@ -422,6 +432,11 @@
 		{Mutator: "arch", Variation: arch},
 		{Mutator: "image", Variation: imageVariation},
 	}, executableTag, binaries...)
+
+	ctx.AddFarVariationDependencies([]blueprint.Variation{
+		{Mutator: "arch", Variation: arch},
+		{Mutator: "image", Variation: imageVariation},
+	}, testTag, tests...)
 }
 
 func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
@@ -459,10 +474,19 @@
 			{Mutator: "link", Variation: "shared"},
 		}, sharedLibTag, a.properties.Native_shared_libs...)
 
+		// When multilib.* is omitted for tests, it implies
+		// multilib.both.
+		ctx.AddFarVariationDependencies([]blueprint.Variation{
+			{Mutator: "arch", Variation: target.String()},
+			{Mutator: "image", Variation: a.getImageVariation(config)},
+		}, testTag, a.properties.Tests...)
+
 		// Add native modules targetting both ABIs
 		addDependenciesForNativeModules(ctx,
 			a.properties.Multilib.Both.Native_shared_libs,
-			a.properties.Multilib.Both.Binaries, target.String(),
+			a.properties.Multilib.Both.Binaries,
+			a.properties.Multilib.Both.Tests,
+			target.String(),
 			a.getImageVariation(config))
 
 		isPrimaryAbi := i == 0
@@ -477,7 +501,9 @@
 			// Add native modules targetting the first ABI
 			addDependenciesForNativeModules(ctx,
 				a.properties.Multilib.First.Native_shared_libs,
-				a.properties.Multilib.First.Binaries, target.String(),
+				a.properties.Multilib.First.Binaries,
+				a.properties.Multilib.First.Tests,
+				target.String(),
 				a.getImageVariation(config))
 
 			// When multilib.* is omitted for prebuilts, it implies multilib.first.
@@ -491,24 +517,32 @@
 			// Add native modules targetting 32-bit ABI
 			addDependenciesForNativeModules(ctx,
 				a.properties.Multilib.Lib32.Native_shared_libs,
-				a.properties.Multilib.Lib32.Binaries, target.String(),
+				a.properties.Multilib.Lib32.Binaries,
+				a.properties.Multilib.Lib32.Tests,
+				target.String(),
 				a.getImageVariation(config))
 
 			addDependenciesForNativeModules(ctx,
 				a.properties.Multilib.Prefer32.Native_shared_libs,
-				a.properties.Multilib.Prefer32.Binaries, target.String(),
+				a.properties.Multilib.Prefer32.Binaries,
+				a.properties.Multilib.Prefer32.Tests,
+				target.String(),
 				a.getImageVariation(config))
 		case "lib64":
 			// Add native modules targetting 64-bit ABI
 			addDependenciesForNativeModules(ctx,
 				a.properties.Multilib.Lib64.Native_shared_libs,
-				a.properties.Multilib.Lib64.Binaries, target.String(),
+				a.properties.Multilib.Lib64.Binaries,
+				a.properties.Multilib.Lib64.Tests,
+				target.String(),
 				a.getImageVariation(config))
 
 			if !has32BitTarget {
 				addDependenciesForNativeModules(ctx,
 					a.properties.Multilib.Prefer32.Native_shared_libs,
-					a.properties.Multilib.Prefer32.Binaries, target.String(),
+					a.properties.Multilib.Prefer32.Binaries,
+					a.properties.Multilib.Prefer32.Tests,
+					target.String(),
 					a.getImageVariation(config))
 			}
 
@@ -517,7 +551,7 @@
 					if sanitizer == "hwaddress" {
 						addDependenciesForNativeModules(ctx,
 							[]string{"libclang_rt.hwasan-aarch64-android"},
-							nil, target.String(), a.getImageVariation(config))
+							nil, nil, target.String(), a.getImageVariation(config))
 						break
 					}
 				}
@@ -686,6 +720,11 @@
 		return
 	}
 
+	if len(a.properties.Tests) > 0 && !a.testApex {
+		ctx.PropertyErrorf("tests", "property not allowed in apex module type")
+		return
+	}
+
 	handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
 
 	ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
@@ -747,6 +786,14 @@
 				} else {
 					ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
 				}
+			case testTag:
+				if cc, ok := child.(*cc.Module); ok {
+					fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
+					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeTest, cc, nil})
+					return true
+				} else {
+					ctx.PropertyErrorf("tests", "%q is not a cc module", depName)
+				}
 			case keyTag:
 				if key, ok := child.(*apexKey); ok {
 					a.private_key_file = key.private_key_file
@@ -858,8 +905,7 @@
 		return android.OptionalPath{}
 	}
 
-	return android.OptionalPathForPath(
-		android.BuildNoticeOutput(ctx, a.installDir, apexFileName, android.FirstUniquePaths(noticeFiles)))
+	return android.BuildNoticeOutput(ctx, a.installDir, apexFileName, android.FirstUniquePaths(noticeFiles)).HtmlGzOutput
 }
 
 func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, apexType apexPackaging) {
@@ -916,7 +962,7 @@
 		var executablePaths []string // this also includes dirs
 		for _, f := range a.filesInfo {
 			pathInApex := filepath.Join(f.installDir, f.builtFile.Base())
-			if f.installDir == "bin" {
+			if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") {
 				executablePaths = append(executablePaths, pathInApex)
 				for _, s := range f.symlinks {
 					executablePaths = append(executablePaths, filepath.Join("bin", s))
@@ -1253,11 +1299,11 @@
 }
 
 func testApexBundleFactory() android.Module {
-	return ApexBundleFactory( /*testApex*/ true)
+	return ApexBundleFactory(true /*testApex*/)
 }
 
 func apexBundleFactory() android.Module {
-	return ApexBundleFactory( /*testApex*/ false)
+	return ApexBundleFactory(false /*testApex*/)
 }
 
 func ApexBundleFactory(testApex bool) android.Module {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 2e44db7..b410425 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -57,6 +57,7 @@
 	ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(cc.LibraryHeaderFactory))
 	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("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
 	ctx.RegisterModuleType("prebuilt_etc", android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory))
@@ -168,6 +169,7 @@
 		"system/sepolicy/apex/myapex_keytest-file_contexts": nil,
 		"system/sepolicy/apex/otherapex-file_contexts":      nil,
 		"mylib.cpp":                            nil,
+		"mytest.cpp":                           nil,
 		"myprebuilt":                           nil,
 		"my_include":                           nil,
 		"vendor/foo/devkeys/test.x509.pem":     nil,
@@ -1285,6 +1287,40 @@
 	}
 }
 
+func TestApexWithTests(t *testing.T) {
+	ctx := testApex(t, `
+		apex_test {
+			name: "myapex",
+			key: "myapex.key",
+			tests: [
+				"mytest",
+			],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_test {
+			name: "mytest",
+			gtest: false,
+			srcs: ["mytest.cpp"],
+			relative_install_path: "test",
+			system_shared_libs: [],
+			static_executable: true,
+			stl: "none",
+		}
+	`)
+
+	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+
+	// Ensure that test dep is copied into apex.
+	ensureContains(t, copyCmds, "image.apex/bin/test/mytest")
+}
+
 func TestMain(m *testing.M) {
 	run := func() int {
 		setUp()
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index cac4d9a..5f1cce8 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -508,15 +508,15 @@
 	"TARGET_OUT": {{prefix: "/usr/share", modType: "prebuilt_usr_share"}, {prefix: "/fonts", modType: "prebuilt_font"},
 		{prefix: "/etc/firmware", modType: "prebuilt_firmware"}, {prefix: "/vendor/firmware", modType: "prebuilt_firmware", flags: []string{"proprietary"}},
 		{prefix: "/etc"}},
-	"TARGET_OUT_ETC":                  {{prefix: "/firmware", modType: "prebuilt_firmware"}, {prefix: ""}},
-	"TARGET_OUT_PRODUCT":              {{prefix: "/etc", flags: []string{"product_specific"}}, {prefix: "/fonts", modType: "prebuilt_font", flags: []string{"product_specific"}}},
-	"TARGET_OUT_PRODUCT_ETC":          {{prefix: "", flags: []string{"product_specific"}}},
-	"TARGET_OUT_ODM":                  {{prefix: "/etc", flags: []string{"device_specific"}}},
-	"TARGET_OUT_PRODUCT_SERVICES":     {{prefix: "/etc", flags: []string{"product_services_specific"}}},
-	"TARGET_OUT_PRODUCT_SERVICES_ETC": {{prefix: "", flags: []string{"product_services_specific"}}},
-	"TARGET_OUT_VENDOR":               {{prefix: "/etc", flags: []string{"proprietary"}}, {prefix: "/firmware", modType: "prebuilt_firmware", flags: []string{"proprietary"}}},
-	"TARGET_OUT_VENDOR_ETC":           {{prefix: "", flags: []string{"proprietary"}}},
-	"TARGET_RECOVERY_ROOT_OUT":        {{prefix: "/system/etc", flags: []string{"recovery"}}},
+	"TARGET_OUT_ETC":            {{prefix: "/firmware", modType: "prebuilt_firmware"}, {prefix: ""}},
+	"TARGET_OUT_PRODUCT":        {{prefix: "/etc", flags: []string{"product_specific"}}, {prefix: "/fonts", modType: "prebuilt_font", flags: []string{"product_specific"}}},
+	"TARGET_OUT_PRODUCT_ETC":    {{prefix: "", flags: []string{"product_specific"}}},
+	"TARGET_OUT_ODM":            {{prefix: "/etc", flags: []string{"device_specific"}}},
+	"TARGET_OUT_SYSTEM_EXT":     {{prefix: "/etc", flags: []string{"system_ext_specific"}}},
+	"TARGET_OUT_SYSTEM_EXT_ETC": {{prefix: "", flags: []string{"system_ext_specific"}}},
+	"TARGET_OUT_VENDOR":         {{prefix: "/etc", flags: []string{"proprietary"}}, {prefix: "/firmware", modType: "prebuilt_firmware", flags: []string{"proprietary"}}},
+	"TARGET_OUT_VENDOR_ETC":     {{prefix: "", flags: []string{"proprietary"}}},
+	"TARGET_RECOVERY_ROOT_OUT":  {{prefix: "/system/etc", flags: []string{"recovery"}}},
 }
 
 // rewriteAndroidPrebuiltEtc fixes prebuilt_etc rule
diff --git a/cc/library.go b/cc/library.go
index 5fbb36e..6ac0c39 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -113,8 +113,6 @@
 }
 
 type LibraryMutatedProperties struct {
-	VariantName string `blueprint:"mutated"`
-
 	// Build a static variant
 	BuildStatic bool `blueprint:"mutated"`
 	// Build a shared variant
@@ -528,7 +526,7 @@
 		}
 	}
 
-	return name + library.MutatedProperties.VariantName
+	return name
 }
 
 var versioningMacroNamesListMutex sync.Mutex
@@ -633,7 +631,7 @@
 	library.objects = deps.WholeStaticLibObjs.Copy()
 	library.objects = library.objects.Append(objs)
 
-	fileName := ctx.ModuleName() + library.MutatedProperties.VariantName + staticLibraryExtension
+	fileName := ctx.ModuleName() + staticLibraryExtension
 	outputFile := android.PathForModuleOut(ctx, fileName)
 	builderFlags := flagsToBuilderFlags(flags)
 
@@ -651,8 +649,7 @@
 
 	TransformObjToStaticLib(ctx, library.objects.objFiles, builderFlags, outputFile, objs.tidyFiles)
 
-	library.coverageOutputFile = TransformCoverageFilesToZip(ctx, library.objects,
-		ctx.ModuleName()+library.MutatedProperties.VariantName)
+	library.coverageOutputFile = TransformCoverageFilesToZip(ctx, library.objects, ctx.ModuleName())
 
 	library.wholeStaticMissingDeps = ctx.GetMissingDependencies()
 
diff --git a/cmd/diff_target_files/target_files.go b/cmd/diff_target_files/target_files.go
index 8705ca7..0fa04e8 100644
--- a/cmd/diff_target_files/target_files.go
+++ b/cmd/diff_target_files/target_files.go
@@ -28,7 +28,7 @@
 	"ODM/",
 	"OEM/",
 	"PRODUCT/",
-	"PRODUCT_SERVICES/",
+	"SYSTEM_EXT/",
 	"ROOT/",
 	"SYSTEM/",
 	"SYSTEM_OTHER/",
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 41c7d46..30381e0 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -18,7 +18,12 @@
 	"flag"
 	"fmt"
 	"os"
+	"os/exec"
 	"path/filepath"
+	"strconv"
+	"strings"
+	"syscall"
+	"time"
 
 	"github.com/google/blueprint/bootstrap"
 
@@ -50,6 +55,42 @@
 }
 
 func main() {
+	if android.SoongDelveListen != "" {
+		if android.SoongDelvePath == "" {
+			fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv")
+			os.Exit(1)
+		}
+		pid := strconv.Itoa(os.Getpid())
+		cmd := []string{android.SoongDelvePath,
+			"attach", pid,
+			"--headless",
+			"-l", android.SoongDelveListen,
+			"--api-version=2",
+			"--accept-multiclient",
+			"--log",
+		}
+
+		fmt.Println("Starting", strings.Join(cmd, " "))
+		dlv := exec.Command(cmd[0], cmd[1:]...)
+		dlv.Stdout = os.Stdout
+		dlv.Stderr = os.Stderr
+		dlv.Stdin = nil
+
+		// Put dlv into its own process group so we can kill it and the child process it starts.
+		dlv.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
+
+		err := dlv.Start()
+		if err != nil {
+			// Print the error starting dlv and continue.
+			fmt.Println(err)
+		} else {
+			// Kill the process group for dlv when soong_build exits.
+			defer syscall.Kill(-dlv.Process.Pid, syscall.SIGKILL)
+			// Wait to give dlv a chance to connect and pause the process.
+			time.Sleep(time.Second)
+		}
+	}
+
 	flag.Parse()
 
 	// The top-level Blueprints file is passed as the first argument.
@@ -72,7 +113,17 @@
 
 	ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
 
-	bootstrap.Main(ctx.Context, configuration, configuration.ConfigFileName, configuration.ProductVariablesFileName)
+	extraNinjaDeps := []string{configuration.ConfigFileName, configuration.ProductVariablesFileName}
+
+	// Read the SOONG_DELVE again through configuration so that there is a dependency on the environment variable
+	// and soong_build will rerun when it is set for the first time.
+	if listen := configuration.Getenv("SOONG_DELVE"); listen != "" {
+		// Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is
+		// enabled even if it completed successfully.
+		extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve"))
+	}
+
+	bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
 
 	if docFile != "" {
 		if err := writeDocs(ctx, docFile); err != nil {
diff --git a/java/androidmk.go b/java/androidmk.go
index 39c2d13..90fdd0f 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -327,6 +327,18 @@
 					install := "$(LOCAL_MODULE_PATH)/" + strings.TrimSuffix(app.installApkName, ".apk") + split.suffix + ".apk"
 					fmt.Fprintln(w, "LOCAL_SOONG_BUILT_INSTALLED +=", split.path.String()+":"+install)
 				}
+				if app.noticeOutputs.Merged.Valid() {
+					fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
+						app.installApkName, app.noticeOutputs.Merged.String(), app.installApkName+"_NOTICE")
+				}
+				if app.noticeOutputs.TxtOutput.Valid() {
+					fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
+						app.installApkName, app.noticeOutputs.TxtOutput.String(), app.installApkName+"_NOTICE.txt")
+				}
+				if app.noticeOutputs.HtmlOutput.Valid() {
+					fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
+						app.installApkName, app.noticeOutputs.HtmlOutput.String(), app.installApkName+"_NOTICE.html")
+				}
 			},
 		},
 	}
diff --git a/java/app.go b/java/app.go
index f58b0f8..e12b56c 100644
--- a/java/app.go
+++ b/java/app.go
@@ -141,6 +141,8 @@
 	installApkName string
 
 	additionalAaptFlags []string
+
+	noticeOutputs android.NoticeOutputs
 }
 
 func (a *AndroidApp) ExportedProguardFlagFiles() android.Paths {
@@ -357,11 +359,7 @@
 	return jniJarFile
 }
 
-func (a *AndroidApp) noticeBuildActions(ctx android.ModuleContext, installDir android.OutputPath) android.OptionalPath {
-	if !Bool(a.appProperties.Embed_notices) && !ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
-		return android.OptionalPath{}
-	}
-
+func (a *AndroidApp) noticeBuildActions(ctx android.ModuleContext, installDir android.OutputPath) {
 	// Collect NOTICE files from all dependencies.
 	seenModules := make(map[android.Module]bool)
 	noticePathSet := make(map[android.Path]bool)
@@ -391,7 +389,7 @@
 	}
 
 	if len(noticePathSet) == 0 {
-		return android.OptionalPath{}
+		return
 	}
 	var noticePaths []android.Path
 	for path := range noticePathSet {
@@ -400,9 +398,8 @@
 	sort.Slice(noticePaths, func(i, j int) bool {
 		return noticePaths[i].String() < noticePaths[j].String()
 	})
-	noticeFile := android.BuildNoticeOutput(ctx, installDir, a.installApkName+".apk", noticePaths)
 
-	return android.OptionalPathForPath(noticeFile)
+	a.noticeOutputs = android.BuildNoticeOutput(ctx, installDir, a.installApkName+".apk", noticePaths)
 }
 
 // Reads and prepends a main cert from the default cert dir if it hasn't been set already, i.e. it
@@ -455,7 +452,10 @@
 		installDir = android.PathForModuleInstall(ctx, "app", a.installApkName)
 	}
 
-	a.aapt.noticeFile = a.noticeBuildActions(ctx, installDir)
+	a.noticeBuildActions(ctx, installDir)
+	if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
+		a.aapt.noticeFile = a.noticeOutputs.HtmlGzOutput
+	}
 
 	// Process all building blocks, from AAPT to certificates.
 	a.aaptBuildActions(ctx)
diff --git a/java/app_test.go b/java/app_test.go
index c7ea338..721dd4d 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1479,16 +1479,20 @@
 
 	// bar has NOTICE files to process, but embed_notices is not set.
 	bar := ctx.ModuleForTests("bar", "android_common")
-	mergeNotices = bar.MaybeRule("mergeNoticesRule")
-	if mergeNotices.Rule != nil {
-		t.Errorf("mergeNotices shouldn't have run for bar")
+	res = bar.Output("package-res.apk")
+	aapt2Flags = res.Args["flags"]
+	e = "-A " + buildDir + "/.intermediates/bar/android_common/NOTICE"
+	if strings.Contains(aapt2Flags, e) {
+		t.Errorf("bar shouldn't have the asset dir flag for NOTICE: %q", e)
 	}
 
 	// baz's embed_notice is true, but it doesn't have any NOTICE files.
 	baz := ctx.ModuleForTests("baz", "android_common")
-	mergeNotices = baz.MaybeRule("mergeNoticesRule")
-	if mergeNotices.Rule != nil {
-		t.Errorf("mergeNotices shouldn't have run for baz")
+	res = baz.Output("package-res.apk")
+	aapt2Flags = res.Args["flags"]
+	e = "-A " + buildDir + "/.intermediates/baz/android_common/NOTICE"
+	if strings.Contains(aapt2Flags, e) {
+		t.Errorf("baz shouldn't have the asset dir flag for NOTICE: %q", e)
 	}
 }
 
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index c47f614..8e7f96a 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -111,7 +111,7 @@
 		productOut("system_other"),
 		productOut("vendor"),
 		productOut("product"),
-		productOut("product_services"),
+		productOut("system_ext"),
 		productOut("oem"),
 		productOut("obj/FAKE"),
 		productOut("breakpad"),
diff --git a/ui/build/config.go b/ui/build/config.go
index 4a70f06..4e19e9e 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -266,6 +266,10 @@
 	if err != nil {
 		ctx.Fatalf("Error retrieving top directory: %v", err)
 	}
+	dir, err = filepath.EvalSymlinks(dir)
+	if err != nil {
+		ctx.Fatalf("Unable to evaluate symlink of %s: %v", dir, err)
+	}
 	dir, err = filepath.Abs(dir)
 	if err != nil {
 		ctx.Fatalf("Unable to find absolute path %s: %v", dir, err)
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index 856af11..7a1ee17 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -690,6 +690,9 @@
 	// Build files that exists in the source tree.
 	buildFiles []string
 
+	// Create root symlink that points to topDir.
+	rootSymlink bool
+
 	// ********* Action *********
 	// Arguments passed in to soong_ui.
 	args []string
@@ -738,6 +741,22 @@
 	createDirectories(t, topDir, tt.dirsInTrees)
 	createBuildFiles(t, topDir, tt.buildFiles)
 
+	if tt.rootSymlink {
+		// Create a secondary root source tree which points to the true root source tree.
+		symlinkTopDir, err := ioutil.TempDir("", "")
+		if err != nil {
+			t.Fatalf("failed to create symlink temp dir: %v", err)
+		}
+		defer os.RemoveAll(symlinkTopDir)
+
+		symlinkTopDir = filepath.Join(symlinkTopDir, "root")
+		err = os.Symlink(topDir, symlinkTopDir)
+		if err != nil {
+			t.Fatalf("failed to create symlink: %v", err)
+		}
+		topDir = symlinkTopDir
+	}
+
 	r := setTop(t, topDir)
 	defer r()
 
@@ -796,7 +815,17 @@
 		dirsInTrees:     []string{"0/1/2", "0/2", "0/3"},
 		buildFiles:      []string{"0/1/2/Android.mk", "0/2/Android.bp"},
 		args:            []string{},
-		curDir:          "1/2/3/4/5/6/7/8/9",
+		curDir:          "0/2",
+		tidyOnly:        "",
+		expectedArgs:    []string{},
+		expectedEnvVars: []envVar{},
+	}, {
+		description:     "normal execution in symlink root source tree, no args",
+		dirsInTrees:     []string{"0/1/2", "0/2", "0/3"},
+		buildFiles:      []string{"0/1/2/Android.mk", "0/2/Android.bp"},
+		rootSymlink:     true,
+		args:            []string{},
+		curDir:          "0/2",
 		tidyOnly:        "",
 		expectedArgs:    []string{},
 		expectedEnvVars: []envVar{},
@@ -932,6 +961,17 @@
 			description:     "build action executed at root directory",
 			dirsInTrees:     []string{},
 			buildFiles:      []string{},
+			rootSymlink:     false,
+			args:            []string{},
+			curDir:          ".",
+			tidyOnly:        "",
+			expectedArgs:    []string{},
+			expectedEnvVars: []envVar{},
+		}, {
+			description:     "build action executed at root directory in symlink",
+			dirsInTrees:     []string{},
+			buildFiles:      []string{},
+			rootSymlink:     true,
 			args:            []string{},
 			curDir:          ".",
 			tidyOnly:        "",
@@ -1080,6 +1120,20 @@
 		description:  "normal execution from top dir directory",
 		dirsInTrees:  []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
 		buildFiles:   []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/3/Android.bp", "0/2/Android.bp"},
+		rootSymlink:  false,
+		args:         []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
+		curDir:       ".",
+		tidyOnly:     "",
+		expectedArgs: []string{"MODULES-IN-0-1-2-3.1", "MODULES-IN-0-1-2-3.2", "MODULES-IN-0-1-3", "MODULES-IN-0-2"},
+		expectedEnvVars: []envVar{
+			envVar{
+				name:  "ONE_SHOT_MAKEFILE",
+				value: ""}},
+	}, {
+		description:  "normal execution from top dir directory in symlink",
+		dirsInTrees:  []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
+		buildFiles:   []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/3/Android.bp", "0/2/Android.bp"},
+		rootSymlink:  true,
 		args:         []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
 		curDir:       ".",
 		tidyOnly:     "",
diff --git a/ui/build/exec.go b/ui/build/exec.go
index 5c312bc..e435c53 100644
--- a/ui/build/exec.go
+++ b/ui/build/exec.go
@@ -15,7 +15,10 @@
 package build
 
 import (
+	"bufio"
+	"io"
 	"os/exec"
+	"strings"
 )
 
 // Cmd is a wrapper of os/exec.Cmd that integrates with the build context for
@@ -139,3 +142,34 @@
 	st.Finish()
 	c.reportError(err)
 }
+
+// RunAndStreamOrFatal will run the command, while running print
+// any output, then handle any errors with a call to ctx.Fatal
+func (c *Cmd) RunAndStreamOrFatal() {
+	out, err := c.StdoutPipe()
+	if err != nil {
+		c.ctx.Fatal(err)
+	}
+	c.Stderr = c.Stdout
+
+	st := c.ctx.Status.StartTool()
+
+	c.StartOrFatal()
+
+	buf := bufio.NewReaderSize(out, 2*1024*1024)
+	for {
+		// Attempt to read whole lines, but write partial lines that are too long to fit in the buffer or hit EOF
+		line, err := buf.ReadString('\n')
+		if line != "" {
+			st.Print(strings.TrimSuffix(line, "\n"))
+		} else if err == io.EOF {
+			break
+		} else if err != nil {
+			c.ctx.Fatal(err)
+		}
+	}
+
+	err = c.Wait()
+	st.Finish()
+	c.reportError(err)
+}
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 7994f3a..b41ac20 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -103,7 +103,7 @@
 	}()
 
 	ctx.Status.Status("Starting ninja...")
-	cmd.RunAndPrintOrFatal()
+	cmd.RunAndStreamOrFatal()
 }
 
 type statusChecker struct {
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index e2c5043..a4be2ac 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -81,6 +81,7 @@
 	"bzip2":    Allowed,
 	"dd":       Allowed,
 	"diff":     Allowed,
+	"dlv":      Allowed,
 	"egrep":    Allowed,
 	"expr":     Allowed,
 	"find":     Allowed,
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index b94db74..11ff667 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -162,6 +162,10 @@
 		c.ctx.Printf("AllowBuildBrokenUsesNetwork: %v", c.Sandbox.AllowBuildBrokenUsesNetwork)
 		c.ctx.Printf("BuildBrokenUsesNetwork: %v", c.config.BuildBrokenUsesNetwork())
 		sandboxArgs = append(sandboxArgs, "-N")
+	} else if dlv, _ := c.config.Environment().Get("SOONG_DELVE"); dlv != "" {
+		// The debugger is enabled and soong_build will pause until a remote delve process connects, allow
+		// network connections.
+		sandboxArgs = append(sandboxArgs, "-N")
 	}
 
 	// Stop nsjail from parsing arguments
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 2ce1ac9..3388417 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -120,7 +120,7 @@
 			"--frontend_file", fifo,
 			"-f", filepath.Join(config.SoongOutDir(), file))
 		cmd.Sandbox = soongSandbox
-		cmd.RunAndPrintOrFatal()
+		cmd.RunAndStreamOrFatal()
 	}
 
 	ninja("minibootstrap", ".minibootstrap/build.ninja")