Merge "Add support for running Android lint on java and android modules."
diff --git a/android/config.go b/android/config.go
index e1d597a..b906108 100644
--- a/android/config.go
+++ b/android/config.go
@@ -712,10 +712,17 @@
 	return Bool(c.productVariables.Allow_missing_dependencies)
 }
 
+// Returns true if building without full platform sources.
 func (c *config) UnbundledBuild() bool {
 	return Bool(c.productVariables.Unbundled_build)
 }
 
+// Returns true if building apps that aren't bundled with the platform.
+// UnbundledBuild() is always true when this is true.
+func (c *config) UnbundledBuildApps() bool {
+	return Bool(c.productVariables.Unbundled_build_apps)
+}
+
 func (c *config) UnbundledBuildUsePrebuiltSdks() bool {
 	return Bool(c.productVariables.Unbundled_build) && !Bool(c.productVariables.Unbundled_build_sdks_from_source)
 }
@@ -1029,6 +1036,27 @@
 	return Bool(c.config.productVariables.SamplingPGO)
 }
 
+// JavaCoverageEnabledForPath returns whether Java code coverage is enabled for
+// path. Coverage is enabled by default when the product variable
+// JavaCoveragePaths is empty. If JavaCoveragePaths is not empty, coverage is
+// enabled for any path which is part of this variable (and not part of the
+// JavaCoverageExcludePaths product variable). Value "*" in JavaCoveragePaths
+// represents any path.
+func (c *deviceConfig) JavaCoverageEnabledForPath(path string) bool {
+	coverage := false
+	if c.config.productVariables.JavaCoveragePaths == nil ||
+		InList("*", c.config.productVariables.JavaCoveragePaths) ||
+		HasAnyPrefix(path, c.config.productVariables.JavaCoveragePaths) {
+		coverage = true
+	}
+	if coverage && c.config.productVariables.JavaCoverageExcludePaths != nil {
+		if HasAnyPrefix(path, c.config.productVariables.JavaCoverageExcludePaths) {
+			coverage = false
+		}
+	}
+	return coverage
+}
+
 func (c *config) NativeLineCoverage() bool {
 	return Bool(c.productVariables.NativeLineCoverage)
 }
diff --git a/android/variable.go b/android/variable.go
index 4440cee..b2149c3 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -216,6 +216,7 @@
 
 	Allow_missing_dependencies       *bool `json:",omitempty"`
 	Unbundled_build                  *bool `json:",omitempty"`
+	Unbundled_build_apps             *bool `json:",omitempty"`
 	Unbundled_build_sdks_from_source *bool `json:",omitempty"`
 	Malloc_not_svelte                *bool `json:",omitempty"`
 	Malloc_zero_contents             *bool `json:",omitempty"`
@@ -266,6 +267,9 @@
 
 	SamplingPGO *bool `json:",omitempty"`
 
+	JavaCoveragePaths        []string `json:",omitempty"`
+	JavaCoverageExcludePaths []string `json:",omitempty"`
+
 	NativeLineCoverage         *bool    `json:",omitempty"`
 	Native_coverage            *bool    `json:",omitempty"`
 	ClangCoverage              *bool    `json:",omitempty"`
diff --git a/androidmk/androidmk/androidmk.go b/androidmk/androidmk/androidmk.go
index 9d0c3ac..4aadbe8 100644
--- a/androidmk/androidmk/androidmk.go
+++ b/androidmk/androidmk/androidmk.go
@@ -124,6 +124,7 @@
 
 	var conds []*conditional
 	var assignmentCond *conditional
+	var tree *bpparser.File
 
 	for _, node := range nodes {
 		file.setMkPos(p.Unpack(node.Pos()), p.Unpack(node.End()))
@@ -200,24 +201,27 @@
 		}
 	}
 
-	tree := &bpparser.File{
+	tree = &bpparser.File{
 		Defs:     file.defs,
 		Comments: file.comments,
 	}
 
 	// check for common supported but undesirable structures and clean them up
 	fixer := bpfix.NewFixer(tree)
-	tree, err := fixer.Fix(bpfix.NewFixRequest().AddAll())
-	if err != nil {
-		return "", []error{err}
+	fixedTree, fixerErr := fixer.Fix(bpfix.NewFixRequest().AddAll())
+	if fixerErr != nil {
+		errs = append(errs, fixerErr)
+	} else {
+		tree = fixedTree
 	}
 
 	out, err := bpparser.Print(tree)
 	if err != nil {
-		return "", []error{err}
+		errs = append(errs, err)
+		return "", errs
 	}
 
-	return string(out), nil
+	return string(out), errs
 }
 
 func handleAssignment(file *bpFile, assignment *mkparser.Assignment, c *conditional) {
diff --git a/androidmk/cmd/androidmk.go b/androidmk/cmd/androidmk.go
index 00488eb..d2f4324 100644
--- a/androidmk/cmd/androidmk.go
+++ b/androidmk/cmd/androidmk.go
@@ -45,12 +45,13 @@
 	}
 
 	output, errs := androidmk.ConvertFile(os.Args[1], bytes.NewBuffer(b))
+	if len(output) > 0 {
+		fmt.Print(output)
+	}
 	if len(errs) > 0 {
 		for _, err := range errs {
 			fmt.Fprintln(os.Stderr, "ERROR: ", err)
 		}
 		os.Exit(1)
 	}
-
-	fmt.Print(output)
 }
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 774b62d..4dd14d8 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -184,7 +184,7 @@
 			// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
 			// we will have foo.jar.jar
 			fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.Stem(), ".jar"))
-			if javaModule, ok := fi.module.(java.Dependency); ok {
+			if javaModule, ok := fi.module.(java.ApexDependency); ok {
 				fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", javaModule.ImplementationAndResourcesJars()[0].String())
 				fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", javaModule.HeaderJars()[0].String())
 			} else {
@@ -233,8 +233,9 @@
 					for _, o := range a.overridableProperties.Overrides {
 						patterns = append(patterns, "%."+o+a.suffix)
 					}
-					fmt.Fprintln(w, "LOCAL_OVERRIDES_MODULES :=", strings.Join(patterns, " "))
-
+					if len(patterns) > 0 {
+						fmt.Fprintln(w, "LOCAL_OVERRIDES_MODULES :=", strings.Join(patterns, " "))
+					}
 					if len(a.compatSymlinks) > 0 {
 						// For flattened apexes, compat symlinks are attached to apex_manifest.json which is guaranteed for every apex
 						postInstallCommands = append(postInstallCommands, a.compatSymlinks...)
@@ -307,7 +308,9 @@
 				fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", a.installDir.ToMakePath().String())
 				fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", name+apexType.suffix())
 				fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable())
-				fmt.Fprintln(w, "LOCAL_OVERRIDES_MODULES :=", strings.Join(a.overridableProperties.Overrides, " "))
+				if len(a.overridableProperties.Overrides) > 0 {
+					fmt.Fprintln(w, "LOCAL_OVERRIDES_MODULES :=", strings.Join(a.overridableProperties.Overrides, " "))
+				}
 				if len(moduleNames) > 0 {
 					fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(moduleNames, " "))
 				}
diff --git a/apex/apex.go b/apex/apex.go
index 4c8575d..a4af7aa 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -986,7 +986,7 @@
 	Uses []string
 
 	// A txt file containing list of files that are allowed to be included in this APEX.
-	Whitelisted_files *string
+	Allowed_files *string
 
 	// package format of this apex variant; could be non-flattened, flattened, or zip.
 	// imageApex, zipApex or flattened
@@ -1652,7 +1652,9 @@
 func apexFileForJavaLibrary(ctx android.BaseModuleContext, lib javaDependency, module android.Module) apexFile {
 	dirInApex := "javalib"
 	fileToCopy := lib.DexJarBuildPath()
-	af := newApexFile(ctx, fileToCopy, module.Name(), dirInApex, javaSharedLib, module)
+	// Remove prebuilt_ if necessary so the source and prebuilt modules have the same name.
+	name := strings.TrimPrefix(module.Name(), "prebuilt_")
+	af := newApexFile(ctx, fileToCopy, name, dirInApex, javaSharedLib, module)
 	af.jacocoReportClassesFile = lib.JacocoReportClassesFile()
 	af.stem = lib.Stem() + ".jar"
 	return af
@@ -1975,7 +1977,7 @@
 				}
 			case javaLibTag:
 				switch child.(type) {
-				case *java.Library, *java.SdkLibrary, *java.DexImport:
+				case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport:
 					af := apexFileForJavaLibrary(ctx, child.(javaDependency), child.(android.Module))
 					if !af.Ok() {
 						ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 6a832af..a7a7765 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -66,7 +66,7 @@
 func testApex(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
 	t.Helper()
 	ctx, config := testApexContext(t, bp, handlers...)
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	_, errs := ctx.ParseBlueprintsFiles(".")
 	android.FailIfErrored(t, errs)
 	_, errs = ctx.PrepareBuildActions(config)
 	android.FailIfErrored(t, errs)
@@ -217,6 +217,11 @@
 	}
 
 	ctx := android.NewTestArchContext()
+
+	// from android package
+	android.RegisterPackageBuildComponents(ctx)
+	ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
+
 	ctx.RegisterModuleType("apex", BundleFactory)
 	ctx.RegisterModuleType("apex_test", testApexBundleFactory)
 	ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
@@ -230,6 +235,12 @@
 	ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
 
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
+
+	// Register this after the prebuilt mutators have been registered (in
+	// cc.RegisterRequiredBuildComponentsForTest) to match what happens at runtime.
+	ctx.PreArchMutators(android.RegisterVisibilityRuleGatherer)
+	ctx.PostDepsMutators(android.RegisterVisibilityRuleEnforcer)
+
 	ctx.RegisterModuleType("cc_test", cc.TestFactory)
 	ctx.RegisterModuleType("vndk_prebuilt_shared", cc.VndkPrebuiltSharedFactory)
 	ctx.RegisterModuleType("vndk_libraries_txt", cc.VndkLibrariesTxtFactory)
@@ -240,7 +251,7 @@
 	java.RegisterJavaBuildComponents(ctx)
 	java.RegisterSystemModulesBuildComponents(ctx)
 	java.RegisterAppBuildComponents(ctx)
-	ctx.RegisterModuleType("java_sdk_library", java.SdkLibraryFactory)
+	java.RegisterSdkLibraryBuildComponents(ctx)
 	ctx.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
 
 	ctx.PreDepsMutators(RegisterPreDepsMutators)
@@ -4366,6 +4377,9 @@
 	"api/system-removed.txt": nil,
 	"api/test-current.txt":   nil,
 	"api/test-removed.txt":   nil,
+
+	// For java_sdk_library_import
+	"a.jar": nil,
 }
 
 func TestJavaSDKLibrary(t *testing.T) {
@@ -4492,6 +4506,117 @@
 	}
 }
 
+func TestJavaSDKLibrary_ImportPreferred(t *testing.T) {
+	ctx, _ := testApex(t, ``,
+		withFiles(map[string][]byte{
+			"apex/a.java":             nil,
+			"apex/apex_manifest.json": nil,
+			"apex/Android.bp": []byte(`
+		package {
+			default_visibility: ["//visibility:private"],
+		}
+
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			java_libs: ["foo", "bar"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		java_library {
+			name: "bar",
+			srcs: ["a.java"],
+			libs: ["foo"],
+			apex_available: ["myapex"],
+			sdk_version: "none",
+			system_modules: "none",
+		}
+`),
+			"source/a.java":          nil,
+			"source/api/current.txt": nil,
+			"source/api/removed.txt": nil,
+			"source/Android.bp": []byte(`
+		package {
+			default_visibility: ["//visibility:private"],
+		}
+
+		java_sdk_library {
+			name: "foo",
+			visibility: ["//apex"],
+			srcs: ["a.java"],
+			api_packages: ["foo"],
+			apex_available: ["myapex"],
+			sdk_version: "none",
+			system_modules: "none",
+			public: {
+				enabled: true,
+			},
+		}
+`),
+			"prebuilt/a.jar": nil,
+			"prebuilt/Android.bp": []byte(`
+		package {
+			default_visibility: ["//visibility:private"],
+		}
+
+		java_sdk_library_import {
+			name: "foo",
+			visibility: ["//apex", "//source"],
+			apex_available: ["myapex"],
+			prefer: true,
+			public: {
+				jars: ["a.jar"],
+			},
+		}
+`),
+		}),
+	)
+
+	// java_sdk_library installs both impl jar and permission XML
+	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+		"javalib/bar.jar",
+		"javalib/foo.jar",
+		"etc/permissions/foo.xml",
+	})
+
+	// The bar library should depend on the implementation jar.
+	barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac")
+	if expected, actual := `^-classpath /[^:]*/turbine-combined/foo\.impl\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+		t.Errorf("expected %q, found %#q", expected, actual)
+	}
+}
+
+func TestJavaSDKLibrary_ImportOnly(t *testing.T) {
+	testApexError(t, `java_libs: "foo" is not configured to be compiled into dex`, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			java_libs: ["foo"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		java_sdk_library_import {
+			name: "foo",
+			apex_available: ["myapex"],
+			prefer: true,
+			public: {
+				jars: ["a.jar"],
+			},
+		}
+
+	`, withFiles(filesForSdkLibrary))
+}
+
 func TestCompatConfig(t *testing.T) {
 	ctx, _ := testApex(t, `
 		apex {
diff --git a/apex/builder.go b/apex/builder.go
index 1293588..53c1193 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -391,7 +391,7 @@
 	emitCommands = append(emitCommands, "sort -o "+imageContentFile.String()+" "+imageContentFile.String())
 	implicitInputs = append(implicitInputs, a.manifestPbOut)
 
-	if a.properties.Whitelisted_files != nil {
+	if a.properties.Allowed_files != nil {
 		ctx.Build(pctx, android.BuildParams{
 			Rule:        emitApexContentRule,
 			Implicits:   implicitInputs,
@@ -402,7 +402,7 @@
 			},
 		})
 		implicitInputs = append(implicitInputs, imageContentFile)
-		allowedFilesFile := android.PathForModuleSrc(ctx, proptools.String(a.properties.Whitelisted_files))
+		allowedFilesFile := android.PathForModuleSrc(ctx, proptools.String(a.properties.Allowed_files))
 
 		phonyOutput := android.PathForModuleOut(ctx, a.Name()+"-diff-phony-output")
 		ctx.Build(pctx, android.BuildParams{
diff --git a/cc/cc.go b/cc/cc.go
index f80c229..ebdb46c 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -3099,10 +3099,19 @@
 		}
 	} else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
 		// This will be available in /vendor (or /odm) only
-		// We assume that modules under proprietary paths are compatible for
-		// BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
-		// PLATFORM_VNDK_VERSION.
-		if isVendorProprietaryPath(mctx.ModuleDir()) {
+
+		// kernel_headers is a special module type whose exported headers
+		// are coming from DeviceKernelHeaders() which is always vendor
+		// dependent. They'll always have both vendor variants.
+		// For other modules, we assume that modules under proprietary
+		// paths are compatible for BOARD_VNDK_VERSION. The other modules
+		// are regarded as AOSP, which is PLATFORM_VNDK_VERSION.
+		if _, ok := m.linker.(*kernelHeadersDecorator); ok {
+			vendorVariants = append(vendorVariants,
+				platformVndkVersion,
+				boardVndkVersion,
+			)
+		} else if isVendorProprietaryPath(mctx.ModuleDir()) {
 			vendorVariants = append(vendorVariants, boardVndkVersion)
 		} else {
 			vendorVariants = append(vendorVariants, platformVndkVersion)
@@ -3200,6 +3209,10 @@
 	}
 }
 
+func (c *Module) IsSdkVariant() bool {
+	return c.Properties.IsSdkVariant
+}
+
 func getCurrentNdkPrebuiltVersion(ctx DepsContext) string {
 	if ctx.Config().PlatformSdkVersionInt() > config.NdkMaxPrebuiltVersionInt {
 		return strconv.Itoa(config.NdkMaxPrebuiltVersionInt)
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 9383463..62d8cc8 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -32,7 +32,7 @@
 			"-march=armv8-a",
 		},
 		"armv8-2a": []string{
-			"-march=armv8.2a",
+			"-march=armv8.2-a",
 		},
 	}
 
diff --git a/cc/library.go b/cc/library.go
index ba8b0f4..968702e 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1077,9 +1077,14 @@
 
 func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objects, fileName string, soFile android.Path) {
 	if library.shouldCreateSourceAbiDump(ctx) {
-		vndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
-		if ver := ctx.DeviceConfig().VndkVersion(); ver != "" && ver != "current" {
-			vndkVersion = ver
+		var vndkVersion string
+
+		if ctx.useVndk() {
+			// For modules linking against vndk, follow its vndk version
+			vndkVersion = ctx.Module().(*Module).VndkVersion()
+		} else {
+			// Regard the other modules as PLATFORM_VNDK_VERSION
+			vndkVersion = ctx.DeviceConfig().PlatformVndkVersion()
 		}
 
 		exportIncludeDirs := library.flagExporter.exportedIncludes(ctx)
@@ -1575,7 +1580,8 @@
 // (which is unnamed) and zero or more stubs variants.
 func VersionMutator(mctx android.BottomUpMutatorContext) {
 	if library, ok := mctx.Module().(LinkableInterface); ok && VersionVariantAvailable(library) {
-		if library.CcLibrary() && library.BuildSharedVariant() && len(library.StubsVersions()) > 0 {
+		if library.CcLibrary() && library.BuildSharedVariant() && len(library.StubsVersions()) > 0 &&
+			!library.IsSdkVariant() {
 			versions := library.StubsVersions()
 			normalizeVersions(mctx, versions)
 			if mctx.Failed() {
diff --git a/cc/linkable.go b/cc/linkable.go
index de36f90..66b1c3f 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -56,6 +56,7 @@
 
 	SdkVersion() string
 	AlwaysSdk() bool
+	IsSdkVariant() bool
 
 	ToolchainLibrary() bool
 	NdkPrebuiltStl() bool
diff --git a/cc/sdk.go b/cc/sdk.go
index a6f94af..b68baad 100644
--- a/cc/sdk.go
+++ b/cc/sdk.go
@@ -41,7 +41,7 @@
 			modules[0].(*Module).Properties.Sdk_version = nil
 			modules[1].(*Module).Properties.IsSdkVariant = true
 
-			if ctx.Config().UnbundledBuild() {
+			if ctx.Config().UnbundledBuildApps() {
 				modules[0].(*Module).Properties.HideFromMake = true
 				modules[0].(*Module).Properties.PreventInstall = true
 			} else {
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index ea94544..4dad730 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -548,6 +548,10 @@
 	if !m.IsForPlatform() || m.isSnapshotPrebuilt() || !m.inVendor() {
 		return false
 	}
+	// skip kernel_headers which always depend on vendor
+	if _, ok := m.linker.(*kernelHeadersDecorator); ok {
+		return false
+	}
 
 	// Libraries
 	if l, ok := m.linker.(snapshotLibraryInterface); ok {
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index d0cad78..c965107 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -171,7 +171,7 @@
 	buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
 	rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
 	soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
-	defer build.UploadMetrics(buildCtx, config, buildStartedMilli, buildErrorFile, rbeMetricsFile, soongMetricsFile)
+	defer build.UploadMetrics(buildCtx, config, c.forceDumbOutput, buildStartedMilli, buildErrorFile, rbeMetricsFile, soongMetricsFile)
 
 	os.MkdirAll(logsDir, 0777)
 	log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index d6eb008..df6d79d 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -35,6 +35,7 @@
 	android.RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory)
 	android.RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
 	android.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
+	android.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory)
 }
 
 type prebuiltEtcProperties struct {
@@ -293,3 +294,15 @@
 	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
 	return module
 }
+
+// prebuilt_dsp installs a DSP related file to <partition>/etc/dsp directory for system image.
+// If soc_specific property is set to true, the DSP related file is installed to the vendor <partition>/dsp
+// directory for vendor image.
+func PrebuiltDSPFactory() android.Module {
+	module := &PrebuiltEtc{}
+	module.socInstallDirBase = "dsp"
+	InitPrebuiltEtcModule(module, "etc/dsp")
+	// This module is device-only
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+	return module
+}
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index e13cb3c..4ce1984 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -65,6 +65,7 @@
 	ctx.RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory)
 	ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
 	ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
+	ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory)
 	ctx.Register(config)
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
 	android.FailIfErrored(t, errs)
@@ -281,3 +282,39 @@
 		})
 	}
 }
+
+func TestPrebuiltDSPDirPath(t *testing.T) {
+	targetPath := filepath.Join(buildDir, "/target/product/test_device")
+	tests := []struct {
+		description  string
+		config       string
+		expectedPath string
+	}{{
+		description: "prebuilt: system dsp",
+		config: `
+			prebuilt_dsp {
+				name: "foo.conf",
+				src: "foo.conf",
+			}`,
+		expectedPath: filepath.Join(targetPath, "system/etc/dsp"),
+	}, {
+		description: "prebuilt: vendor dsp",
+		config: `
+			prebuilt_dsp {
+				name: "foo.conf",
+				src: "foo.conf",
+				soc_specific: true,
+				sub_dir: "sub_dir",
+			}`,
+		expectedPath: filepath.Join(targetPath, "vendor/dsp/sub_dir"),
+	}}
+	for _, tt := range tests {
+		t.Run(tt.description, func(t *testing.T) {
+			ctx, _ := testPrebuiltEtc(t, tt.config)
+			p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
+			if p.installDirPath.String() != tt.expectedPath {
+				t.Errorf("expected %q, got %q", tt.expectedPath, p.installDirPath)
+			}
+		})
+	}
+}
diff --git a/java/app.go b/java/app.go
index 445e531..4bb292d 100755
--- a/java/app.go
+++ b/java/app.go
@@ -133,7 +133,7 @@
 	// We are assuming here that the master file in the APK
 	// set has `.apk` suffix. If it doesn't the build will fail.
 	// APK sets containing APEX files are handled elsewhere.
-	as.masterFile = ctx.ModuleName() + ".apk"
+	as.masterFile = as.BaseModuleName() + ".apk"
 	screenDensities := "all"
 	if dpis := ctx.Config().ProductAAPTPrebuiltDPI(); len(dpis) > 0 {
 		screenDensities = strings.ToUpper(strings.Join(dpis, ","))
diff --git a/java/java.go b/java/java.go
index 6c14c78..97a6747 100644
--- a/java/java.go
+++ b/java/java.go
@@ -513,11 +513,16 @@
 
 var _ android.OutputFileProducer = (*Module)(nil)
 
-type Dependency interface {
+// Methods that need to be implemented for a module that is added to apex java_libs property.
+type ApexDependency interface {
 	HeaderJars() android.Paths
+	ImplementationAndResourcesJars() android.Paths
+}
+
+type Dependency interface {
+	ApexDependency
 	ImplementationJars() android.Paths
 	ResourceJars() android.Paths
-	ImplementationAndResourcesJars() android.Paths
 	DexJarBuildPath() android.Path
 	DexJarInstallPath() android.Path
 	AidlIncludeDirs() android.Paths
@@ -618,7 +623,9 @@
 }
 
 func (j *Module) shouldInstrument(ctx android.BaseModuleContext) bool {
-	return j.properties.Instrument && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT")
+	return j.properties.Instrument &&
+		ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") &&
+		ctx.DeviceConfig().JavaCoverageEnabledForPath(ctx.ModuleDir())
 }
 
 func (j *Module) shouldInstrumentStatic(ctx android.BaseModuleContext) bool {
@@ -1182,9 +1189,9 @@
 	if flags.javaVersion.usesJavaModules() {
 		javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...)
 	}
-	if ctx.Config().MinimizeJavaDebugInfo() {
-		// Override the -g flag passed globally to remove local variable debug info to reduce
-		// disk and memory usage.
+	if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() {
+		// For non-host binaries, override the -g flag passed globally to remove
+		// local variable debug info to reduce disk and memory usage.
 		javacFlags = append(javacFlags, "-g:source,lines")
 	}
 	javacFlags = append(javacFlags, "-Xlint:-dep-ann")
diff --git a/java/java_test.go b/java/java_test.go
index b74111b..1d07e70 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -466,7 +466,41 @@
 		t.Errorf("expected binary wrapper implicits [%q], got %v",
 			barJar, barWrapperDeps)
 	}
+}
 
+func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) {
+	bp := `
+		java_library {
+			name: "target_library",
+			srcs: ["a.java"],
+		}
+
+		java_binary_host {
+			name: "host_binary",
+			srcs: ["b.java"],
+		}
+	`
+	config := testConfig(nil, bp, nil)
+	config.TestProductVariables.MinimizeJavaDebugInfo = proptools.BoolPtr(true)
+
+	ctx, _ := testJavaWithConfig(t, config)
+
+	// first, sanity check that the -g flag is added to target modules
+	targetLibrary := ctx.ModuleForTests("target_library", "android_common")
+	targetJavaFlags := targetLibrary.Module().VariablesForTests()["javacFlags"]
+	if !strings.Contains(targetJavaFlags, "-g:source,lines") {
+		t.Errorf("target library javac flags %v should contain "+
+			"-g:source,lines override with MinimizeJavaDebugInfo", targetJavaFlags)
+	}
+
+	// check that -g is not overridden for host modules
+	buildOS := android.BuildOs.String()
+	hostBinary := ctx.ModuleForTests("host_binary", buildOS+"_common")
+	hostJavaFlags := hostBinary.Module().VariablesForTests()["javacFlags"]
+	if strings.Contains(hostJavaFlags, "-g:source,lines") {
+		t.Errorf("java_binary_host javac flags %v should not have "+
+			"-g:source,lines override with MinimizeJavaDebugInfo", hostJavaFlags)
+	}
 }
 
 func TestPrebuilts(t *testing.T) {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 4b1c3e5..7ce0912 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -629,6 +629,16 @@
 	return true
 }
 
+// Module name of the runtime implementation library
+func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
+	return c.moduleBase.BaseModuleName() + ".impl"
+}
+
+// Module name of the XML file for the lib
+func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string {
+	return c.moduleBase.BaseModuleName() + sdkXmlFileSuffix
+}
+
 // Name of the java_library module that compiles the stubs source.
 func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
 	return c.namingScheme.stubsLibraryModuleName(apiScope, c.moduleBase.BaseModuleName())
@@ -858,7 +868,7 @@
 var _ SdkLibraryComponentDependency = (*Library)(nil)
 var _ SdkLibraryComponentDependency = (*Import)(nil)
 var _ SdkLibraryComponentDependency = (*SdkLibrary)(nil)
-var _ SdkLibraryComponentDependency = (*sdkLibraryImport)(nil)
+var _ SdkLibraryComponentDependency = (*SdkLibraryImport)(nil)
 
 // Provides access to sdk_version related header and implentation jars.
 type SdkLibraryDependency interface {
@@ -944,16 +954,24 @@
 	return generatedScopes
 }
 
-var xmlPermissionsFileTag = dependencyTag{name: "xml-permissions-file"}
+type sdkLibraryComponentTag struct {
+	blueprint.BaseDependencyTag
+	name string
+}
+
+// Mark this tag so dependencies that use it are excluded from visibility enforcement.
+func (t sdkLibraryComponentTag) ExcludeFromVisibilityEnforcement() {}
+
+var xmlPermissionsFileTag = sdkLibraryComponentTag{name: "xml-permissions-file"}
 
 func IsXmlPermissionsFileDepTag(depTag blueprint.DependencyTag) bool {
-	if dt, ok := depTag.(dependencyTag); ok {
+	if dt, ok := depTag.(sdkLibraryComponentTag); ok {
 		return dt == xmlPermissionsFileTag
 	}
 	return false
 }
 
-var implLibraryTag = dependencyTag{name: "impl-library"}
+var implLibraryTag = sdkLibraryComponentTag{name: "impl-library"}
 
 func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
 	for _, apiScope := range module.getGeneratedApiScopes(ctx) {
@@ -978,7 +996,7 @@
 
 		if module.sharedLibrary() {
 			// Add dependency to the rule for generating the xml permissions file
-			ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlFileName())
+			ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlPermissionsModuleName())
 		}
 
 		// Only add the deps for the library if it is actually going to be built.
@@ -1025,20 +1043,10 @@
 	}
 	entriesList := module.Library.AndroidMkEntries()
 	entries := &entriesList[0]
-	entries.Required = append(entries.Required, module.xmlFileName())
+	entries.Required = append(entries.Required, module.xmlPermissionsModuleName())
 	return entriesList
 }
 
-// Module name of the runtime implementation library
-func (module *SdkLibrary) implLibraryModuleName() string {
-	return module.BaseModuleName() + ".impl"
-}
-
-// Module name of the XML file for the lib
-func (module *SdkLibrary) xmlFileName() string {
-	return module.BaseModuleName() + sdkXmlFileSuffix
-}
-
 // The dist path of the stub artifacts
 func (module *SdkLibrary) apiDistPath(apiScope *apiScope) string {
 	if module.ModuleBase.Owner() != "" {
@@ -1330,7 +1338,7 @@
 		Lib_name       *string
 		Apex_available []string
 	}{
-		Name:           proptools.StringPtr(module.xmlFileName()),
+		Name:           proptools.StringPtr(module.xmlPermissionsModuleName()),
 		Lib_name:       proptools.StringPtr(module.BaseModuleName()),
 		Apex_available: module.ApexProperties.Apex_available,
 	}
@@ -1378,7 +1386,7 @@
 //
 // If either this or the other module are on the platform then this will return
 // false.
-func (module *SdkLibrary) withinSameApexAs(other android.Module) bool {
+func withinSameApexAs(module android.ApexModule, other android.Module) bool {
 	name := module.ApexName()
 	return name != "" && getApexNameForModule(other) == name
 }
@@ -1399,7 +1407,7 @@
 		// Only allow access to the implementation library in the following condition:
 		// * No sdk_version specified on the referencing module.
 		// * The referencing module is in the same apex as this.
-		if sdkVersion.kind == sdkPrivate || module.withinSameApexAs(ctx.Module()) {
+		if sdkVersion.kind == sdkPrivate || withinSameApexAs(module, ctx.Module()) {
 			if headerJars {
 				return module.HeaderJars()
 			} else {
@@ -1698,7 +1706,7 @@
 	Libs []string
 }
 
-type sdkLibraryImport struct {
+type SdkLibraryImport struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
 	prebuilt android.Prebuilt
@@ -1711,9 +1719,17 @@
 	scopeProperties map[*apiScope]*sdkLibraryScopeProperties
 
 	commonToSdkLibraryAndImport
+
+	// The reference to the implementation library created by the source module.
+	// Is nil if the source module does not exist.
+	implLibraryModule *Library
+
+	// The reference to the xml permissions module created by the source module.
+	// Is nil if the source module does not exist.
+	xmlPermissionsFileModule *sdkLibraryXml
 }
 
-var _ SdkLibraryDependency = (*sdkLibraryImport)(nil)
+var _ SdkLibraryDependency = (*SdkLibraryImport)(nil)
 
 // The type of a structure that contains a field of type sdkLibraryScopeProperties
 // for each apiscope in allApiScopes, e.g. something like:
@@ -1755,7 +1771,7 @@
 
 // java_sdk_library_import imports a prebuilt java_sdk_library.
 func sdkLibraryImportFactory() android.Module {
-	module := &sdkLibraryImport{}
+	module := &SdkLibraryImport{}
 
 	allScopeProperties, scopeToProperties := createPropertiesInstance()
 	module.scopeProperties = scopeToProperties
@@ -1777,15 +1793,15 @@
 	return module
 }
 
-func (module *sdkLibraryImport) Prebuilt() *android.Prebuilt {
+func (module *SdkLibraryImport) Prebuilt() *android.Prebuilt {
 	return &module.prebuilt
 }
 
-func (module *sdkLibraryImport) Name() string {
+func (module *SdkLibraryImport) Name() string {
 	return module.prebuilt.Name(module.ModuleBase.Name())
 }
 
-func (module *sdkLibraryImport) createInternalModules(mctx android.DefaultableHookContext) {
+func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHookContext) {
 
 	// If the build is configured to use prebuilts then force this to be preferred.
 	if mctx.Config().UnbundledBuildUsePrebuiltSdks() {
@@ -1810,7 +1826,7 @@
 	*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
 }
 
-func (module *sdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
 	// Creates a java import for the jar with ".stubs" suffix
 	props := struct {
 		Name        *string
@@ -1832,7 +1848,7 @@
 	mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
 }
 
-func (module *sdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
 	props := struct {
 		Name   *string
 		Srcs   []string
@@ -1846,7 +1862,7 @@
 	props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
 }
 
-func (module *sdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
+func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
 	for apiScope, scopeProperties := range module.scopeProperties {
 		if len(scopeProperties.Jars) == 0 {
 			continue
@@ -1860,13 +1876,35 @@
 			ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, module.stubsSourceModuleName(apiScope))
 		}
 	}
+
+	implName := module.implLibraryModuleName()
+	if ctx.OtherModuleExists(implName) {
+		ctx.AddVariationDependencies(nil, implLibraryTag, implName)
+
+		xmlPermissionsModuleName := module.xmlPermissionsModuleName()
+		if module.sharedLibrary() && ctx.OtherModuleExists(xmlPermissionsModuleName) {
+			// Add dependency to the rule for generating the xml permissions file
+			ctx.AddDependency(module, xmlPermissionsFileTag, xmlPermissionsModuleName)
+		}
+	}
 }
 
-func (module *sdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
+func (module *SdkLibraryImport) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool {
+	depTag := mctx.OtherModuleDependencyTag(dep)
+	if depTag == xmlPermissionsFileTag {
+		return true
+	}
+
+	// None of the other dependencies of the java_sdk_library_import are in the same apex
+	// as the one that references this module.
+	return false
+}
+
+func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
 	return module.commonOutputFiles(tag)
 }
 
-func (module *sdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	// Record the paths to the prebuilt stubs library and stubs source.
 	ctx.VisitDirectDeps(func(to android.Module) {
 		tag := ctx.OtherModuleDependencyTag(to)
@@ -1879,6 +1917,18 @@
 			// Extract information from the dependency. The exact information extracted
 			// is determined by the nature of the dependency which is determined by the tag.
 			scopeTag.extractDepInfo(ctx, to, scopePaths)
+		} else if tag == implLibraryTag {
+			if implLibrary, ok := to.(*Library); ok {
+				module.implLibraryModule = implLibrary
+			} else {
+				ctx.ModuleErrorf("implementation library must be of type *java.Library but was %T", to)
+			}
+		} else if tag == xmlPermissionsFileTag {
+			if xmlPermissionsFileModule, ok := to.(*sdkLibraryXml); ok {
+				module.xmlPermissionsFileModule = xmlPermissionsFileModule
+			} else {
+				ctx.ModuleErrorf("xml permissions file module must be of type *sdkLibraryXml but was %T", to)
+			}
 		}
 	})
 
@@ -1894,20 +1944,75 @@
 	}
 }
 
-func (module *sdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+func (module *SdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec, headerJars bool) android.Paths {
+
+	// For consistency with SdkLibrary make the implementation jar available to libraries that
+	// are within the same APEX.
+	implLibraryModule := module.implLibraryModule
+	if implLibraryModule != nil && withinSameApexAs(module, ctx.Module()) {
+		if headerJars {
+			return implLibraryModule.HeaderJars()
+		} else {
+			return implLibraryModule.ImplementationJars()
+		}
+	}
+
 	return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion)
 }
 
 // to satisfy SdkLibraryDependency interface
-func (module *sdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+func (module *SdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
 	// This module is just a wrapper for the prebuilt stubs.
-	return module.sdkJars(ctx, sdkVersion)
+	return module.sdkJars(ctx, sdkVersion, true)
 }
 
 // to satisfy SdkLibraryDependency interface
-func (module *sdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+func (module *SdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
 	// This module is just a wrapper for the stubs.
-	return module.sdkJars(ctx, sdkVersion)
+	return module.sdkJars(ctx, sdkVersion, false)
+}
+
+// to satisfy apex.javaDependency interface
+func (module *SdkLibraryImport) DexJarBuildPath() android.Path {
+	if module.implLibraryModule == nil {
+		return nil
+	} else {
+		return module.implLibraryModule.DexJarBuildPath()
+	}
+}
+
+// to satisfy apex.javaDependency interface
+func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path {
+	if module.implLibraryModule == nil {
+		return nil
+	} else {
+		return module.implLibraryModule.JacocoReportClassesFile()
+	}
+}
+
+// to satisfy apex.javaDependency interface
+func (module *SdkLibraryImport) Stem() string {
+	return module.BaseModuleName()
+}
+
+var _ ApexDependency = (*SdkLibraryImport)(nil)
+
+// to satisfy java.ApexDependency interface
+func (module *SdkLibraryImport) HeaderJars() android.Paths {
+	if module.implLibraryModule == nil {
+		return nil
+	} else {
+		return module.implLibraryModule.HeaderJars()
+	}
+}
+
+// to satisfy java.ApexDependency interface
+func (module *SdkLibraryImport) ImplementationAndResourcesJars() android.Paths {
+	if module.implLibraryModule == nil {
+		return nil
+	} else {
+		return module.implLibraryModule.ImplementationAndResourcesJars()
+	}
 }
 
 //
diff --git a/rust/binary.go b/rust/binary.go
index c25ae09..56d6f0b 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -24,9 +24,6 @@
 }
 
 type BinaryCompilerProperties struct {
-	// path to the main source file that contains the program entry point (e.g. src/main.rs)
-	Srcs []string `android:"path,arch_variant"`
-
 	// passes -C prefer-dynamic to rustc, which tells it to dynamically link the stdlib
 	// (assuming it has no dylib dependencies already)
 	Prefer_dynamic *bool
@@ -35,10 +32,7 @@
 type binaryDecorator struct {
 	*baseCompiler
 
-	Properties            BinaryCompilerProperties
-	distFile              android.OptionalPath
-	coverageOutputZipFile android.OptionalPath
-	unstrippedOutputFile  android.Path
+	Properties BinaryCompilerProperties
 }
 
 var _ compiler = (*binaryDecorator)(nil)
@@ -112,7 +106,7 @@
 func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
 	fileName := binary.getStem(ctx) + ctx.toolchain().ExecutableSuffix()
 
-	srcPath := srcPathFromModuleSrcs(ctx, binary.Properties.Srcs)
+	srcPath := srcPathFromModuleSrcs(ctx, binary.baseCompiler.Properties.Srcs)
 
 	outputFile := android.PathForModuleOut(ctx, fileName)
 	binary.unstrippedOutputFile = outputFile
diff --git a/rust/builder.go b/rust/builder.go
index 5069b07..7dbb59d 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -163,7 +163,7 @@
 	if flags.Coverage {
 		var gcnoFile android.WritablePath
 		// Provide consistency with cc gcda output, see cc/builder.go init()
-		profileEmitArg := strings.TrimPrefix("PWD=", cc.PwdPrefix()) + "/"
+		profileEmitArg := strings.TrimPrefix(cc.PwdPrefix(), "PWD=") + "/"
 
 		if outputFile.Ext() != "" {
 			gcnoFile = android.PathForModuleOut(ctx, pathtools.ReplaceExtension(outputFile.Base(), "gcno"))
diff --git a/rust/compiler.go b/rust/compiler.go
index 5f098bc..efc1ce4 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -53,6 +53,9 @@
 )
 
 type BaseCompilerProperties struct {
+	// path to the source file that is the main entry point of the program (e.g. main.rs or lib.rs)
+	Srcs []string `android:"path,arch_variant"`
+
 	// whether to pass "-D warnings" to rustc. Defaults to true.
 	Deny_warnings *bool
 
@@ -100,17 +103,10 @@
 }
 
 type baseCompiler struct {
-	Properties    BaseCompilerProperties
-	pathDeps      android.Paths
-	rustFlagsDeps android.Paths
-	linkFlagsDeps android.Paths
-	flags         string
-	linkFlags     string
-	depFlags      []string
-	linkDirs      []string
-	edition       string
-	src           android.Path //rustc takes a single src file
-	coverageFile  android.Path //rustc generates a single gcno file
+	Properties   BaseCompilerProperties
+	depFlags     []string
+	linkDirs     []string
+	coverageFile android.Path //rustc generates a single gcno file
 
 	// Install related
 	dir      string
@@ -119,6 +115,10 @@
 	relative string
 	path     android.InstallPath
 	location installLocation
+
+	coverageOutputZipFile android.OptionalPath
+	unstrippedOutputFile  android.Path
+	distFile              android.OptionalPath
 }
 
 func (compiler *baseCompiler) coverageOutputZipPath() android.OptionalPath {
diff --git a/rust/library.go b/rust/library.go
index 2e51266..704c77b 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -45,9 +45,6 @@
 	Shared VariantLibraryProperties `android:"arch_variant"`
 	Static VariantLibraryProperties `android:"arch_variant"`
 
-	// path to the source file that is the main entry point of the program (e.g. src/lib.rs)
-	Srcs []string `android:"path,arch_variant"`
-
 	// path to include directories to pass to cc_* modules, only relevant for static/shared variants.
 	Include_dirs []string `android:"path,arch_variant"`
 }
@@ -75,12 +72,9 @@
 type libraryDecorator struct {
 	*baseCompiler
 
-	Properties            LibraryCompilerProperties
-	MutatedProperties     LibraryMutatedProperties
-	distFile              android.OptionalPath
-	coverageOutputZipFile android.OptionalPath
-	unstrippedOutputFile  android.Path
-	includeDirs           android.Paths
+	Properties        LibraryCompilerProperties
+	MutatedProperties LibraryMutatedProperties
+	includeDirs       android.Paths
 }
 
 type libraryInterface interface {
@@ -350,7 +344,7 @@
 func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
 	var outputFile android.WritablePath
 
-	srcPath := srcPathFromModuleSrcs(ctx, library.Properties.Srcs)
+	srcPath := srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs)
 
 	flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
 
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 10ea1e3..42c8537 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -23,20 +23,12 @@
 }
 
 type ProcMacroCompilerProperties struct {
-	// path to the source file that is the main entry point of the program (e.g. src/lib.rs)
-	Srcs []string `android:"path,arch_variant"`
-
-	// set name of the procMacro
-	Stem   *string `android:"arch_variant"`
-	Suffix *string `android:"arch_variant"`
 }
 
 type procMacroDecorator struct {
 	*baseCompiler
 
-	Properties           ProcMacroCompilerProperties
-	distFile             android.OptionalPath
-	unstrippedOutputFile android.Path
+	Properties ProcMacroCompilerProperties
 }
 
 type procMacroInterface interface {
@@ -70,7 +62,7 @@
 	fileName := procMacro.getStem(ctx) + ctx.toolchain().ProcMacroSuffix()
 	outputFile := android.PathForModuleOut(ctx, fileName)
 
-	srcPath := srcPathFromModuleSrcs(ctx, procMacro.Properties.Srcs)
+	srcPath := srcPathFromModuleSrcs(ctx, procMacro.baseCompiler.Properties.Srcs)
 
 	procMacro.unstrippedOutputFile = outputFile
 
diff --git a/rust/project_json.go b/rust/project_json.go
index 909aebc..a50e73a 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -114,7 +114,7 @@
 		return cInfo.ID, crateName, true
 	}
 	crate := rustProjectCrate{Deps: make([]rustProjectDep, 0), Cfgs: make([]string, 0)}
-	src := rustLib.Properties.Srcs[0]
+	src := rustLib.baseCompiler.Properties.Srcs[0]
 	crate.RootModule = path.Join(ctx.ModuleDir(rModule), src)
 	crate.Edition = getEdition(rustLib.baseCompiler)
 
diff --git a/rust/rust.go b/rust/rust.go
index 6671dd3..7b82b1f 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -45,11 +45,10 @@
 }
 
 type Flags struct {
-	GlobalRustFlags []string      // Flags that apply globally to rust
-	GlobalLinkFlags []string      // Flags that apply globally to linker
-	RustFlags       []string      // Flags that apply to rust
-	LinkFlags       []string      // Flags that apply to linker
-	RustFlagsDeps   android.Paths // Files depended on by compiler flags
+	GlobalRustFlags []string // Flags that apply globally to rust
+	GlobalLinkFlags []string // Flags that apply globally to linker
+	RustFlags       []string // Flags that apply to rust
+	LinkFlags       []string // Flags that apply to linker
 	Toolchain       config.Toolchain
 	Coverage        bool
 }
@@ -196,6 +195,10 @@
 	return false
 }
 
+func (mod *Module) IsSdkVariant() bool {
+	return false
+}
+
 func (mod *Module) ToolchainLibrary() bool {
 	return false
 }
diff --git a/rust/test.go b/rust/test.go
index f616c06..416c557 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -57,7 +57,14 @@
 }
 
 func NewRustTest(hod android.HostOrDeviceSupported) (*Module, *testDecorator) {
-	module := newModule(hod, android.MultilibFirst)
+	// Build both 32 and 64 targets for device tests.
+	// Cannot build both for host tests yet if the test depends on
+	// something like proc-macro2 that cannot be built for both.
+	multilib := android.MultilibBoth
+	if hod != android.DeviceSupported && hod != android.HostAndDeviceSupported {
+		multilib = android.MultilibFirst
+	}
+	module := newModule(hod, multilib)
 
 	test := &testDecorator{
 		binaryDecorator: &binaryDecorator{
diff --git a/ui/build/upload.go b/ui/build/upload.go
index 75a5e2f..3a23a80 100644
--- a/ui/build/upload.go
+++ b/ui/build/upload.go
@@ -23,6 +23,7 @@
 	"path/filepath"
 	"time"
 
+	"android/soong/ui/metrics"
 	"github.com/golang/protobuf/proto"
 
 	upload_proto "android/soong/ui/metrics/upload_proto"
@@ -32,11 +33,21 @@
 	uploadPbFilename = ".uploader.pb"
 )
 
+var (
+	// For testing purpose
+	getTmpDir = ioutil.TempDir
+)
+
 // UploadMetrics uploads a set of metrics files to a server for analysis. An
 // uploader full path is required to be specified in order to upload the set
 // of metrics files. This is accomplished by defining the ANDROID_ENABLE_METRICS_UPLOAD
-// environment variable.
-func UploadMetrics(ctx Context, config Config, buildStartedMilli int64, files ...string) {
+// environment variable. The metrics files are copied to a temporary directory
+// and the uploader is then executed in the background to allow the user to continue
+// working.
+func UploadMetrics(ctx Context, config Config, forceDumbOutput bool, buildStartedMilli int64, files ...string) {
+	ctx.BeginTrace(metrics.RunSetupTool, "upload_metrics")
+	defer ctx.EndTrace()
+
 	uploader := config.MetricsUploaderApp()
 	// No metrics to upload if the path to the uploader was not specified.
 	if uploader == "" {
@@ -56,6 +67,22 @@
 		return
 	}
 
+	// The temporary directory cannot be deleted as the metrics uploader is started
+	// in the background and requires to exist until the operation is done. The
+	// uploader can delete the directory as it is specified in the upload proto.
+	tmpDir, err := getTmpDir("", "upload_metrics")
+	if err != nil {
+		ctx.Fatalf("failed to create a temporary directory to store the list of metrics files: %v\n", err)
+	}
+
+	for i, src := range metricsFiles {
+		dst := filepath.Join(tmpDir, filepath.Base(src))
+		if _, err := copyFile(src, dst); err != nil {
+			ctx.Fatalf("failed to copy %q to %q: %v\n", src, dst, err)
+		}
+		metricsFiles[i] = dst
+	}
+
 	// For platform builds, the branch and target name is hardcoded to specific
 	// values for later extraction of the metrics in the data metrics pipeline.
 	data, err := proto.Marshal(&upload_proto.Upload{
@@ -64,17 +91,23 @@
 		BranchName:            proto.String("developer-metrics"),
 		TargetName:            proto.String("platform-build-systems-metrics"),
 		MetricsFiles:          metricsFiles,
+		DirectoriesToDelete:   []string{tmpDir},
 	})
 	if err != nil {
 		ctx.Fatalf("failed to marshal metrics upload proto buffer message: %v\n", err)
 	}
 
-	pbFile := filepath.Join(config.OutDir(), uploadPbFilename)
+	pbFile := filepath.Join(tmpDir, uploadPbFilename)
 	if err := ioutil.WriteFile(pbFile, data, 0644); err != nil {
 		ctx.Fatalf("failed to write the marshaled metrics upload protobuf to %q: %v\n", pbFile, err)
 	}
-	// Remove the upload file as it's not longer needed after it has been processed by the uploader.
-	defer os.Remove(pbFile)
 
-	Command(ctx, config, "upload metrics", uploader, "--upload-metrics", pbFile).RunAndStreamOrFatal()
+	// Start the uploader in the background as it takes several milliseconds to start the uploader
+	// and prepare the metrics for upload. This affects small commands like "lunch".
+	cmd := Command(ctx, config, "upload metrics", uploader, "--upload-metrics", pbFile)
+	if forceDumbOutput {
+		cmd.RunOrFatal()
+	} else {
+		cmd.RunAndStreamOrFatal()
+	}
 }
diff --git a/ui/build/upload_test.go b/ui/build/upload_test.go
index adaa08d..c812730 100644
--- a/ui/build/upload_test.go
+++ b/ui/build/upload_test.go
@@ -15,6 +15,7 @@
 package build
 
 import (
+	"errors"
 	"io/ioutil"
 	"os"
 	"path/filepath"
@@ -61,6 +62,22 @@
 			}
 			defer os.RemoveAll(outDir)
 
+			// Supply our own getTmpDir to delete the temp dir once the test is done.
+			orgGetTmpDir := getTmpDir
+			getTmpDir = func(string, string) (string, error) {
+				retDir := filepath.Join(outDir, "tmp_upload_dir")
+				if err := os.Mkdir(retDir, 0755); err != nil {
+					t.Fatalf("failed to create temporary directory %q: %v", retDir, err)
+				}
+				return retDir, nil
+			}
+			defer func() { getTmpDir = orgGetTmpDir }()
+
+			metricsUploadDir := filepath.Join(outDir, ".metrics_uploader")
+			if err := os.Mkdir(metricsUploadDir, 0755); err != nil {
+				t.Fatalf("failed to create %q directory for oauth valid check: %v", metricsUploadDir, err)
+			}
+
 			var metricsFiles []string
 			if tt.createFiles {
 				for _, f := range tt.files {
@@ -80,41 +97,62 @@
 				buildDateTime: strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10),
 			}}
 
-			UploadMetrics(ctx, config, 1591031903, metricsFiles...)
-
-			if _, err := os.Stat(filepath.Join(outDir, uploadPbFilename)); err == nil {
-				t.Error("got true, want false for upload protobuf file to exist")
-			}
+			UploadMetrics(ctx, config, false, 1591031903, metricsFiles...)
 		})
 	}
 }
 
 func TestUploadMetricsErrors(t *testing.T) {
-	expectedErr := "failed to write the marshaled"
-	defer logger.Recover(func(err error) {
-		got := err.Error()
-		if !strings.Contains(got, expectedErr) {
-			t.Errorf("got %q, want %q to be contained in error", got, expectedErr)
-		}
-	})
+	ctx := testContext()
+	tests := []struct {
+		description string
+		tmpDir      string
+		tmpDirErr   error
+		expectedErr string
+	}{{
+		description: "getTmpDir returned error",
+		tmpDirErr:   errors.New("getTmpDir failed"),
+		expectedErr: "getTmpDir failed",
+	}, {
+		description: "copyFile operation error",
+		tmpDir:      "/fake_dir",
+		expectedErr: "failed to copy",
+	}}
 
-	outDir, err := ioutil.TempDir("", "")
-	if err != nil {
-		t.Fatalf("failed to create out directory: %v", outDir)
+	for _, tt := range tests {
+		t.Run(tt.description, func(t *testing.T) {
+			defer logger.Recover(func(err error) {
+				got := err.Error()
+				if !strings.Contains(got, tt.expectedErr) {
+					t.Errorf("got %q, want %q to be contained in error", got, tt.expectedErr)
+				}
+			})
+
+			outDir, err := ioutil.TempDir("", "")
+			if err != nil {
+				t.Fatalf("failed to create out directory: %v", outDir)
+			}
+			defer os.RemoveAll(outDir)
+
+			orgGetTmpDir := getTmpDir
+			getTmpDir = func(string, string) (string, error) {
+				return tt.tmpDir, tt.tmpDirErr
+			}
+			defer func() { getTmpDir = orgGetTmpDir }()
+
+			metricsFile := filepath.Join(outDir, "metrics_file_1")
+			if err := ioutil.WriteFile(metricsFile, []byte("test file"), 0644); err != nil {
+				t.Fatalf("failed to create a fake metrics file %q for uploading: %v", metricsFile, err)
+			}
+
+			config := Config{&configImpl{
+				environ: &Environment{
+					"ANDROID_ENABLE_METRICS_UPLOAD=fake",
+					"OUT_DIR=/bad",
+				}}}
+
+			UploadMetrics(ctx, config, true, 1591031903, metricsFile)
+			t.Errorf("got nil, expecting %q as a failure", tt.expectedErr)
+		})
 	}
-	defer os.RemoveAll(outDir)
-
-	metricsFile := filepath.Join(outDir, "metrics_file_1")
-	if err := ioutil.WriteFile(metricsFile, []byte("test file"), 0644); err != nil {
-		t.Fatalf("failed to create a fake metrics file %q for uploading: %v", metricsFile, err)
-	}
-
-	config := Config{&configImpl{
-		environ: &Environment{
-			"ANDROID_ENABLE_METRICS_UPLOAD=fake",
-			"OUT_DIR=/bad",
-		}}}
-
-	UploadMetrics(testContext(), config, 1591031903, metricsFile)
-	t.Errorf("got nil, expecting %q as a failure", expectedErr)
 }
diff --git a/ui/build/util.go b/ui/build/util.go
index 75e6753..d44cd6d 100644
--- a/ui/build/util.go
+++ b/ui/build/util.go
@@ -15,6 +15,7 @@
 package build
 
 import (
+	"io"
 	"os"
 	"path/filepath"
 	"strings"
@@ -124,3 +125,20 @@
 	}
 	return str[:idx], str[idx+1:], true
 }
+
+// copyFile copies a file from src to dst. filepath.Dir(dst) must exist.
+func copyFile(src, dst string) (int64, error) {
+	source, err := os.Open(src)
+	if err != nil {
+		return 0, err
+	}
+	defer source.Close()
+
+	destination, err := os.Create(dst)
+	if err != nil {
+		return 0, err
+	}
+	defer destination.Close()
+
+	return io.Copy(destination, source)
+}
diff --git a/ui/build/util_test.go b/ui/build/util_test.go
index 89bfc77..b22e997 100644
--- a/ui/build/util_test.go
+++ b/ui/build/util_test.go
@@ -15,6 +15,7 @@
 package build
 
 import (
+	"bytes"
 	"io/ioutil"
 	"os"
 	"path/filepath"
@@ -49,3 +50,72 @@
 
 	ensureEmptyDirectoriesExist(ctx, filepath.Join(tmpDir, "a"))
 }
+
+func TestCopyFile(t *testing.T) {
+	tmpDir, err := ioutil.TempDir("", "test_copy_file")
+	if err != nil {
+		t.Fatalf("failed to create temporary directory to hold test text files: %v", err)
+	}
+	defer os.Remove(tmpDir)
+
+	data := []byte("fake data")
+	src := filepath.Join(tmpDir, "src.txt")
+	if err := ioutil.WriteFile(src, data, 0755); err != nil {
+		t.Fatalf("failed to create a src file %q for copying: %v", src, err)
+	}
+
+	dst := filepath.Join(tmpDir, "dst.txt")
+
+	l, err := copyFile(src, dst)
+	if err != nil {
+		t.Fatalf("got %v, expecting nil error on copyFile operation", err)
+	}
+
+	if l != int64(len(data)) {
+		t.Errorf("got %d, expecting %d for copied bytes", l, len(data))
+	}
+
+	dstData, err := ioutil.ReadFile(dst)
+	if err != nil {
+		t.Fatalf("got %v, expecting nil error reading dst %q file", err, dst)
+	}
+
+	if bytes.Compare(data, dstData) != 0 {
+		t.Errorf("got %q, expecting data %q from dst %q text file", string(data), string(dstData), dst)
+	}
+}
+
+func TestCopyFileErrors(t *testing.T) {
+	tmpDir, err := ioutil.TempDir("", "test_copy_file_errors")
+	if err != nil {
+		t.Fatalf("failed to create temporary directory to hold test text files: %v", err)
+	}
+	defer os.Remove(tmpDir)
+
+	srcExists := filepath.Join(tmpDir, "src_exist.txt")
+	if err := ioutil.WriteFile(srcExists, []byte("fake data"), 0755); err != nil {
+		t.Fatalf("failed to create a src file %q for copying: %v", srcExists, err)
+	}
+
+	tests := []struct {
+		description string
+		src         string
+		dst         string
+	}{{
+		description: "src file does not exist",
+		src:         "/src/not/exist",
+		dst:         "/dst/not/exist",
+	}, {
+		description: "dst directory does not exist",
+		src:         srcExists,
+		dst:         "/dst/not/exist",
+	}}
+
+	for _, tt := range tests {
+		t.Run(tt.description, func(t *testing.T) {
+			if _, err := copyFile(tt.src, tt.dst); err == nil {
+				t.Errorf("got nil, expecting error")
+			}
+		})
+	}
+}
diff --git a/ui/metrics/upload_proto/upload.pb.go b/ui/metrics/upload_proto/upload.pb.go
index 1b1e5e8..614d4c7 100644
--- a/ui/metrics/upload_proto/upload.pb.go
+++ b/ui/metrics/upload_proto/upload.pb.go
@@ -30,7 +30,10 @@
 	// The target name.
 	TargetName *string `protobuf:"bytes,4,opt,name=target_name,json=targetName" json:"target_name,omitempty"`
 	// A list of metrics filepaths to upload.
-	MetricsFiles         []string `protobuf:"bytes,5,rep,name=metrics_files,json=metricsFiles" json:"metrics_files,omitempty"`
+	MetricsFiles []string `protobuf:"bytes,5,rep,name=metrics_files,json=metricsFiles" json:"metrics_files,omitempty"`
+	// A list of directories to delete after the copy of metrics files
+	// is completed for uploading.
+	DirectoriesToDelete  []string `protobuf:"bytes,6,rep,name=directories_to_delete,json=directoriesToDelete" json:"directories_to_delete,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
 	XXX_sizecache        int32    `json:"-"`
@@ -96,6 +99,13 @@
 	return nil
 }
 
+func (m *Upload) GetDirectoriesToDelete() []string {
+	if m != nil {
+		return m.DirectoriesToDelete
+	}
+	return nil
+}
+
 func init() {
 	proto.RegisterType((*Upload)(nil), "soong_metrics_upload.Upload")
 }
@@ -105,18 +115,20 @@
 }
 
 var fileDescriptor_91b94b655bd2a7e5 = []byte{
-	// 201 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x2d, 0xc8, 0xc9,
-	0x4f, 0x4c, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x29, 0xce, 0xcf, 0xcf, 0x4b, 0x8f,
-	0xcf, 0x4d, 0x2d, 0x29, 0xca, 0x4c, 0x2e, 0x8e, 0x87, 0xc8, 0x29, 0xdd, 0x66, 0xe4, 0x62, 0x0b,
-	0x05, 0x33, 0x85, 0x8c, 0xb8, 0x44, 0x93, 0x8b, 0x52, 0x13, 0x4b, 0x32, 0xf3, 0xf3, 0xe2, 0x4b,
-	0x32, 0x73, 0x53, 0x8b, 0x4b, 0x12, 0x73, 0x0b, 0xe2, 0x73, 0x8b, 0x25, 0x18, 0x15, 0x18, 0x35,
-	0x58, 0x82, 0x84, 0x61, 0x92, 0x21, 0x30, 0x39, 0xdf, 0x62, 0x21, 0x33, 0x2e, 0xf1, 0xe4, 0xfc,
-	0xdc, 0x82, 0x9c, 0x54, 0x4c, 0x5d, 0x4c, 0x60, 0x5d, 0xa2, 0x08, 0x69, 0x64, 0x7d, 0xf2, 0x5c,
-	0xdc, 0x49, 0x45, 0x89, 0x79, 0xc9, 0x19, 0xf1, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0xcc, 0x0a, 0x8c,
-	0x1a, 0x9c, 0x41, 0x5c, 0x10, 0x21, 0xbf, 0xc4, 0xdc, 0x54, 0x90, 0x82, 0x92, 0xc4, 0xa2, 0xf4,
-	0xd4, 0x12, 0x88, 0x02, 0x16, 0x88, 0x02, 0x88, 0x10, 0x58, 0x81, 0x32, 0x17, 0x2f, 0xcc, 0x2b,
-	0x69, 0x99, 0x39, 0xa9, 0xc5, 0x12, 0xac, 0x0a, 0xcc, 0x1a, 0x9c, 0x41, 0x3c, 0x50, 0x41, 0x37,
-	0x90, 0x98, 0x93, 0x4c, 0x94, 0x14, 0x36, 0x5f, 0xc7, 0x83, 0x43, 0x04, 0x10, 0x00, 0x00, 0xff,
-	0xff, 0xe2, 0x01, 0x74, 0x65, 0x20, 0x01, 0x00, 0x00,
+	// 230 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xb1, 0x4a, 0x04, 0x31,
+	0x10, 0x86, 0xd9, 0xbb, 0xf3, 0xe0, 0xe2, 0xd9, 0xec, 0x79, 0x18, 0x44, 0x70, 0xd1, 0x66, 0x2b,
+	0x0b, 0x0b, 0x1f, 0x40, 0xc4, 0x4e, 0x8b, 0xe5, 0x6c, 0x6c, 0x86, 0x98, 0x1d, 0xd7, 0x40, 0x92,
+	0x09, 0xc9, 0xf8, 0x1c, 0xbe, 0xb2, 0x6c, 0xe2, 0xe2, 0x82, 0x76, 0xc3, 0xff, 0x7d, 0x7f, 0x31,
+	0xbf, 0xd8, 0x7e, 0x06, 0x4b, 0xaa, 0xbf, 0x09, 0x91, 0x98, 0xea, 0xd3, 0x44, 0xe4, 0x07, 0x70,
+	0xc8, 0xd1, 0xe8, 0x04, 0x85, 0x5d, 0x7d, 0x2d, 0xc4, 0xfa, 0x25, 0x9f, 0xf5, 0xad, 0xd8, 0xeb,
+	0x88, 0x8a, 0x0d, 0x79, 0x60, 0xe3, 0x30, 0xb1, 0x72, 0x01, 0x5c, 0x92, 0x55, 0x53, 0xb5, 0xab,
+	0x6e, 0x37, 0xc1, 0xc3, 0xc4, 0x9e, 0x52, 0x7d, 0x27, 0xce, 0x34, 0xb9, 0x60, 0xf1, 0x6f, 0x6b,
+	0x91, 0x5b, 0xfb, 0x5f, 0x3c, 0xef, 0x5d, 0x8a, 0xe3, 0xb7, 0xa8, 0xbc, 0xfe, 0x00, 0xaf, 0x1c,
+	0xca, 0x65, 0x53, 0xb5, 0x9b, 0x4e, 0x94, 0xe8, 0x59, 0x39, 0x1c, 0x05, 0x56, 0x71, 0x40, 0x2e,
+	0xc2, 0xaa, 0x08, 0x25, 0xca, 0xc2, 0xb5, 0x38, 0x99, 0x5e, 0x79, 0x37, 0x16, 0x93, 0x3c, 0x6a,
+	0x96, 0xed, 0xa6, 0xdb, 0xfe, 0x84, 0x8f, 0x63, 0x36, 0xbe, 0xd4, 0x9b, 0x88, 0x9a, 0x29, 0x1a,
+	0x4c, 0xc0, 0x04, 0x3d, 0x5a, 0x64, 0x94, 0xeb, 0x2c, 0xef, 0x66, 0xf0, 0x40, 0x0f, 0x19, 0xdd,
+	0x5f, 0xbc, 0x9e, 0xff, 0xb7, 0x14, 0xe4, 0x15, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x64, 0x04,
+	0xa8, 0xf4, 0x54, 0x01, 0x00, 0x00,
 }
diff --git a/ui/metrics/upload_proto/upload.proto b/ui/metrics/upload_proto/upload.proto
index 7a9f080..bcd0ab2 100644
--- a/ui/metrics/upload_proto/upload.proto
+++ b/ui/metrics/upload_proto/upload.proto
@@ -32,4 +32,8 @@
 
   // A list of metrics filepaths to upload.
   repeated string metrics_files = 5;
+
+  // A list of directories to delete after the copy of metrics files
+  // is completed for uploading.
+  repeated string directories_to_delete = 6;
 }