Merge "Rename dexpreopt.config field to bring it in sync with Make."
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 609e651..7159a45 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -241,6 +241,7 @@
 	java.RegisterSystemModulesBuildComponents(ctx)
 	java.RegisterAppBuildComponents(ctx)
 	ctx.RegisterModuleType("java_sdk_library", java.SdkLibraryFactory)
+	ctx.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
 
 	ctx.PreDepsMutators(RegisterPreDepsMutators)
 	ctx.PostDepsMutators(RegisterPostDepsMutators)
@@ -5196,6 +5197,46 @@
 	`)
 }
 
+func TestApexKeysTxt(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		prebuilt_apex {
+			name: "myapex",
+			prefer: true,
+			arch: {
+				arm64: {
+					src: "myapex-arm64.apex",
+				},
+				arm: {
+					src: "myapex-arm.apex",
+				},
+			},
+		}
+
+		apex_set {
+			name: "myapex_set",
+			set: "myapex.apks",
+			filename: "myapex_set.apex",
+			overrides: ["myapex"],
+		}
+	`)
+
+	apexKeysText := ctx.SingletonForTests("apex_keys_text")
+	content := apexKeysText.MaybeDescription("apexkeys.txt").BuildParams.Args["content"]
+	ensureContains(t, content, `name="myapex_set.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
+	ensureNotContains(t, content, "myapex.apex")
+}
+
 func TestMain(m *testing.M) {
 	run := func() int {
 		setUp()
diff --git a/apex/key.go b/apex/key.go
index 607cac5..a68f6e1 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -106,10 +106,36 @@
 
 func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
 	s.output = android.PathForOutput(ctx, "apexkeys.txt")
-	apexModulesMap := make(map[string]android.Module)
+	type apexKeyEntry struct {
+		name                  string
+		presigned             bool
+		public_key            string
+		private_key           string
+		container_certificate string
+		container_private_key string
+		partition             string
+	}
+	toString := func(e apexKeyEntry) string {
+		format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\\n"
+		if e.presigned {
+			return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition)
+		} else {
+			return fmt.Sprintf(format, e.name, e.public_key, e.private_key, e.container_certificate, e.container_private_key, e.partition)
+		}
+	}
+
+	apexKeyMap := make(map[string]apexKeyEntry)
 	ctx.VisitAllModules(func(module android.Module) {
 		if m, ok := module.(*apexBundle); ok && m.Enabled() && m.installable() {
-			apexModulesMap[m.Name()] = m
+			apexKeyMap[m.Name()] = apexKeyEntry{
+				name:                  m.Name() + ".apex",
+				presigned:             false,
+				public_key:            m.public_key_file.String(),
+				private_key:           m.private_key_file.String(),
+				container_certificate: m.container_certificate_file.String(),
+				container_private_key: m.container_private_key_file.String(),
+				partition:             m.PartitionTag(ctx.DeviceConfig()),
+			}
 		}
 	})
 
@@ -117,35 +143,43 @@
 	ctx.VisitAllModules(func(module android.Module) {
 		if m, ok := module.(*Prebuilt); ok && m.Enabled() && m.installable() &&
 			m.Prebuilt().UsePrebuilt() {
-			apexModulesMap[m.BaseModuleName()] = m
+			apexKeyMap[m.BaseModuleName()] = apexKeyEntry{
+				name:      m.InstallFilename(),
+				presigned: true,
+				partition: m.PartitionTag(ctx.DeviceConfig()),
+			}
+		}
+	})
+
+	// Find apex_set and let them override apexBundle or prebuilts. This is done in a separate pass
+	// so that apex_set are not overridden by prebuilts.
+	ctx.VisitAllModules(func(module android.Module) {
+		if m, ok := module.(*ApexSet); ok && m.Enabled() {
+			entry := apexKeyEntry{
+				name:      m.InstallFilename(),
+				presigned: true,
+				partition: m.PartitionTag(ctx.DeviceConfig()),
+			}
+
+			for _, om := range m.Overrides() {
+				if _, ok := apexKeyMap[om]; ok {
+					delete(apexKeyMap, om)
+				}
+			}
+			apexKeyMap[m.BaseModuleName()] = entry
 		}
 	})
 
 	// iterating over map does not give consistent ordering in golang
 	var moduleNames []string
-	for key, _ := range apexModulesMap {
+	for key, _ := range apexKeyMap {
 		moduleNames = append(moduleNames, key)
 	}
 	sort.Strings(moduleNames)
 
 	var filecontent strings.Builder
-	for _, key := range moduleNames {
-		module := apexModulesMap[key]
-		if m, ok := module.(*apexBundle); ok {
-			fmt.Fprintf(&filecontent,
-				"name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\\n",
-				m.Name()+".apex",
-				m.public_key_file.String(),
-				m.private_key_file.String(),
-				m.container_certificate_file.String(),
-				m.container_private_key_file.String(),
-				m.PartitionTag(ctx.DeviceConfig()))
-		} else if m, ok := module.(*Prebuilt); ok {
-			fmt.Fprintf(&filecontent,
-				"name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\\n",
-				m.InstallFilename(),
-				"PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", m.PartitionTag(ctx.DeviceConfig()))
-		}
+	for _, name := range moduleNames {
+		fmt.Fprintf(&filecontent, "%s", toString(apexKeyMap[name]))
 	}
 
 	ctx.Build(pctx, android.BuildParams{
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 03266c5..bf574dc 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -278,6 +278,10 @@
 	return a.prebuilt.Name(a.ModuleBase.Name())
 }
 
+func (a *ApexSet) Overrides() []string {
+	return a.properties.Overrides
+}
+
 // prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex.
 func apexSetFactory() android.Module {
 	module := &ApexSet{}
diff --git a/cc/builder.go b/cc/builder.go
index e571e5a..b4f9947 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -283,16 +283,19 @@
 		"cFlags")
 )
 
+func PwdPrefix() string {
+	// Darwin doesn't have /proc
+	if runtime.GOOS != "darwin" {
+		return "PWD=/proc/self/cwd"
+	}
+	return ""
+}
+
 func init() {
 	// We run gcc/clang with PWD=/proc/self/cwd to remove $TOP from the
 	// debug output. That way two builds in two different directories will
 	// create the same output.
-	if runtime.GOOS != "darwin" {
-		pctx.StaticVariable("relPwd", "PWD=/proc/self/cwd")
-	} else {
-		// Darwin doesn't have /proc
-		pctx.StaticVariable("relPwd", "")
-	}
+	pctx.StaticVariable("relPwd", PwdPrefix())
 
 	pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
 	pctx.Import("android/soong/remoteexec")
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 0e2bea3..69d0df5 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -99,7 +99,6 @@
 func (test *testDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
 	test.binaryDecorator.AndroidMk(ctx, ret)
 	ret.Class = "NATIVE_TESTS"
-	ret.SubName = test.getMutatedModuleSubName(ctx.Name())
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
 		if len(test.Properties.Test_suites) > 0 {
 			fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
diff --git a/rust/builder.go b/rust/builder.go
index fbe0e53..5069b07 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -21,6 +21,7 @@
 	"github.com/google/blueprint/pathtools"
 
 	"android/soong/android"
+	"android/soong/cc"
 )
 
 var (
@@ -161,11 +162,17 @@
 
 	if flags.Coverage {
 		var gcnoFile android.WritablePath
+		// Provide consistency with cc gcda output, see cc/builder.go init()
+		profileEmitArg := strings.TrimPrefix("PWD=", cc.PwdPrefix()) + "/"
 
 		if outputFile.Ext() != "" {
 			gcnoFile = android.PathForModuleOut(ctx, pathtools.ReplaceExtension(outputFile.Base(), "gcno"))
+			rustcFlags = append(rustcFlags, "-Z profile-emit="+profileEmitArg+android.PathForModuleOut(
+				ctx, pathtools.ReplaceExtension(outputFile.Base(), "gcda")).String())
 		} else {
 			gcnoFile = android.PathForModuleOut(ctx, outputFile.Base()+".gcno")
+			rustcFlags = append(rustcFlags, "-Z profile-emit="+profileEmitArg+android.PathForModuleOut(
+				ctx, outputFile.Base()+".gcda").String())
 		}
 
 		implicitOutputs = append(implicitOutputs, gcnoFile)
diff --git a/rust/rust.go b/rust/rust.go
index 8cf2e6d..6671dd3 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -39,7 +39,6 @@
 	android.RegisterModuleType("rust_defaults", defaultsFactory)
 	android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
-		ctx.BottomUp("rust_unit_tests", TestPerSrcMutator).Parallel()
 		ctx.BottomUp("rust_begin", BeginMutator).Parallel()
 	})
 	pctx.Import("android/soong/rust/config")
diff --git a/rust/test.go b/rust/test.go
index 10c2785..f616c06 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -15,14 +15,16 @@
 package rust
 
 import (
-	"path/filepath"
-	"strings"
-
 	"android/soong/android"
 	"android/soong/tradefed"
 )
 
 type TestProperties struct {
+	// Disables the creation of a test-specific directory when used with
+	// relative_install_path. Useful if several tests need to be in the same
+	// directory, but test_per_src doesn't work.
+	No_named_install_directory *bool
+
 	// the name of the test configuration (for example "AndroidTest.xml") that should be
 	// installed with the module.
 	Test_config *string `android:"path,arch_variant"`
@@ -64,7 +66,7 @@
 	}
 
 	module.compiler = test
-
+	module.AddProperties(&test.Properties)
 	return module, test
 }
 
@@ -72,36 +74,21 @@
 	return append(test.binaryDecorator.compilerProps(), &test.Properties)
 }
 
-func (test *testDecorator) getMutatedModuleSubName(moduleName string) string {
-	stem := String(test.baseCompiler.Properties.Stem)
-	if stem != "" && !strings.HasSuffix(moduleName, "_"+stem) {
-		// Avoid repeated suffix in the module name.
-		return "_" + stem
-	}
-	return ""
-}
-
 func (test *testDecorator) install(ctx ModuleContext, file android.Path) {
-	name := ctx.ModuleName()
-	path := test.baseCompiler.relativeInstallPath()
-	// on device, use mutated module name
-	name = name + test.getMutatedModuleSubName(name)
-	if !ctx.Device() { // on host, use mutated module name + arch type + stem name
-		stem := String(test.baseCompiler.Properties.Stem)
-		if stem == "" {
-			stem = name
-		}
-		name = filepath.Join(name, ctx.Arch().ArchType.String(), stem)
-	}
-	test.testConfig = tradefed.AutoGenRustTestConfig(ctx, name,
+	test.testConfig = tradefed.AutoGenRustTestConfig(ctx,
 		test.Properties.Test_config,
 		test.Properties.Test_config_template,
 		test.Properties.Test_suites,
+		nil,
 		test.Properties.Auto_gen_config)
+
 	// default relative install path is module name
-	if path == "" {
+	if !Bool(test.Properties.No_named_install_directory) {
 		test.baseCompiler.relative = ctx.ModuleName()
+	} else if String(test.baseCompiler.Properties.Relative_install_path) == "" {
+		ctx.PropertyErrorf("no_named_install_directory", "Module install directory may only be disabled if relative_install_path is set")
 	}
+
 	test.binaryDecorator.install(ctx, file)
 }
 
@@ -126,64 +113,3 @@
 	module, _ := NewRustTest(android.HostSupported)
 	return module.Init()
 }
-
-func (test *testDecorator) testPerSrc() bool {
-	return true
-}
-
-func (test *testDecorator) srcs() []string {
-	return test.binaryDecorator.Properties.Srcs
-}
-
-func (test *testDecorator) setSrc(name, src string) {
-	test.binaryDecorator.Properties.Srcs = []string{src}
-	test.baseCompiler.Properties.Stem = StringPtr(name)
-}
-
-func (test *testDecorator) unsetSrc() {
-	test.binaryDecorator.Properties.Srcs = nil
-	test.baseCompiler.Properties.Stem = StringPtr("")
-}
-
-type testPerSrc interface {
-	testPerSrc() bool
-	srcs() []string
-	setSrc(string, string)
-	unsetSrc()
-}
-
-var _ testPerSrc = (*testDecorator)(nil)
-
-func TestPerSrcMutator(mctx android.BottomUpMutatorContext) {
-	if m, ok := mctx.Module().(*Module); ok {
-		if test, ok := m.compiler.(testPerSrc); ok {
-			numTests := len(test.srcs())
-			if test.testPerSrc() && numTests > 0 {
-				if duplicate, found := android.CheckDuplicate(test.srcs()); found {
-					mctx.PropertyErrorf("srcs", "found a duplicate entry %q", duplicate)
-					return
-				}
-				// Rust compiler always compiles one source file at a time and
-				// uses the crate name as output file name.
-				// Cargo uses the test source file name as default crate name,
-				// but that can be redefined.
-				// So when there are multiple source files, the source file names will
-				// be the output file names, but when there is only one test file,
-				// use the crate name.
-				testNames := make([]string, numTests)
-				for i, src := range test.srcs() {
-					testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
-				}
-				crateName := m.compiler.crateName()
-				if numTests == 1 && crateName != "" {
-					testNames[0] = crateName
-				}
-				// TODO(chh): Add an "all tests" variation like cc/test.go?
-				tests := mctx.CreateLocalVariations(testNames...)
-				for i, src := range test.srcs() {
-					tests[i].(*Module).compiler.(testPerSrc).setSrc(testNames[i], src)
-				}
-			}
-		}
-	}
-}
diff --git a/rust/test_test.go b/rust/test_test.go
index f131c6e..2382b18 100644
--- a/rust/test_test.go
+++ b/rust/test_test.go
@@ -19,45 +19,17 @@
 	"testing"
 )
 
-// Check if rust_test_host accepts multiple source files and applies --test flag.
 func TestRustTest(t *testing.T) {
 	ctx := testRust(t, `
 		rust_test_host {
 			name: "my_test",
-			srcs: ["foo.rs", "src/bar.rs"],
-			crate_name: "new_test", // not used for multiple source files
-			relative_install_path: "rust/my-test",
-		}`)
-
-	for _, name := range []string{"foo", "bar"} {
-		testingModule := ctx.ModuleForTests("my_test", "linux_glibc_x86_64_"+name)
-		testingBuildParams := testingModule.Output(name)
-		rustcFlags := testingBuildParams.Args["rustcFlags"]
-		if !strings.Contains(rustcFlags, "--test") {
-			t.Errorf("%v missing --test flag, rustcFlags: %#v", name, rustcFlags)
-		}
-		outPath := "/my_test/linux_glibc_x86_64_" + name + "/" + name
-		if !strings.Contains(testingBuildParams.Output.String(), outPath) {
-			t.Errorf("wrong output: %v  expect: %v", testingBuildParams.Output, outPath)
-		}
-	}
-}
-
-// crate_name is output file name, when there is only one source file.
-func TestRustTestSingleFile(t *testing.T) {
-	ctx := testRust(t, `
-		rust_test_host {
-			name: "my-test",
 			srcs: ["foo.rs"],
-			crate_name: "new_test",
-			relative_install_path: "my-pkg",
 		}`)
 
-	name := "new_test"
-	testingModule := ctx.ModuleForTests("my-test", "linux_glibc_x86_64_"+name)
-	outPath := "/my-test/linux_glibc_x86_64_" + name + "/" + name
-	testingBuildParams := testingModule.Output(name)
-	if !strings.Contains(testingBuildParams.Output.String(), outPath) {
-		t.Errorf("wrong output: %v  expect: %v", testingBuildParams.Output, outPath)
+	testingModule := ctx.ModuleForTests("my_test", "linux_glibc_x86_64")
+	expectedOut := "my_test/linux_glibc_x86_64/my_test"
+	outPath := testingModule.Output("my_test").Output.String()
+	if !strings.Contains(outPath, expectedOut) {
+		t.Errorf("wrong output path: %v;  expected: %v", outPath, expectedOut)
 	}
 }
diff --git a/rust/testing.go b/rust/testing.go
index f94af71..4e186d3 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -97,7 +97,6 @@
 	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		// rust mutators
 		ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
-		ctx.BottomUp("rust_unit_tests", TestPerSrcMutator).Parallel()
 		ctx.BottomUp("rust_begin", BeginMutator).Parallel()
 	})
 	ctx.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index 2829146..1cb874d 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -112,7 +112,7 @@
 }
 
 func autogenTemplateWithName(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config) {
-	autogenTemplateWithNameAndOutputFile(ctx, ctx.ModuleName(), output, template, configs, "")
+	autogenTemplateWithNameAndOutputFile(ctx, name, output, template, configs, "")
 }
 
 func autogenTemplateWithNameAndOutputFile(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config, outputFileName string) {
@@ -220,19 +220,20 @@
 	return path
 }
 
-func AutoGenRustTestConfig(ctx android.ModuleContext, name string, testConfigProp *string,
-	testConfigTemplateProp *string, testSuites []string, autoGenConfig *bool) android.Path {
+func AutoGenRustTestConfig(ctx android.ModuleContext, testConfigProp *string,
+	testConfigTemplateProp *string, testSuites []string, config []Config, autoGenConfig *bool) android.Path {
 	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
 	if autogenPath != nil {
-		templatePathString := "${RustHostTestConfigTemplate}"
-		if ctx.Device() {
-			templatePathString = "${RustDeviceTestConfigTemplate}"
-		}
 		templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
 		if templatePath.Valid() {
-			templatePathString = templatePath.String()
+			autogenTemplate(ctx, autogenPath, templatePath.String(), config)
+		} else {
+			if ctx.Device() {
+				autogenTemplate(ctx, autogenPath, "${RustDeviceTestConfigTemplate}", config)
+			} else {
+				autogenTemplate(ctx, autogenPath, "${RustHostTestConfigTemplate}", config)
+			}
 		}
-		autogenTemplateWithName(ctx, name, autogenPath, templatePathString, nil)
 		return autogenPath
 	}
 	return path