Install tradefed dynamic config file in soong-only builds

Make has this behavior where it will find a DynamicConfig.xml file in
the same directory in the module and install it next to the main
tradefed config file. Recreate that behavior in soong-only builds.
https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/base_rules.mk;l=859;drc=6a8fff595ba4cbb87b7e124fd630f548c5c4e2cb

Bug: 396761822
Test: SOONG_ONLY=true atest -m -c CtsNetTestCases -- --test-arg com.android.testutils.ConnectivityTestTargetPreparer:ignore-mobile-data-check:true
Change-Id: I69f1c262200d62cc0d3c590b6adbeb401af63ab9
diff --git a/cc/test.go b/cc/test.go
index b3b2ae8..2c5c36e 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -418,6 +418,10 @@
 			if test.testConfig != nil {
 				ctx.InstallFile(testCases, ctx.ModuleName()+".config", test.testConfig)
 			}
+			dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+			if dynamicConfig.Valid() {
+				ctx.InstallFile(testCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
+			}
 			for _, extraTestConfig := range test.extraTestConfigs {
 				ctx.InstallFile(testCases, extraTestConfig.Base(), extraTestConfig)
 			}
diff --git a/java/app.go b/java/app.go
index 89d688d..02e65be 100644
--- a/java/app.go
+++ b/java/app.go
@@ -1627,6 +1627,10 @@
 		if a.testConfig != nil {
 			ctx.InstallFile(pathInTestCases, ctx.Module().Name()+".config", a.testConfig)
 		}
+		dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+		if dynamicConfig.Valid() {
+			ctx.InstallFile(pathInTestCases, ctx.Module().Name()+".dynamic", dynamicConfig.Path())
+		}
 		testDeps := append(a.data, a.extraTestConfigs...)
 		for _, data := range android.SortedUniquePaths(testDeps) {
 			dataPath := android.DataPath{SrcPath: data}
diff --git a/java/java.go b/java/java.go
index c5dee0c..af2b86e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1910,6 +1910,10 @@
 		if j.testConfig != nil {
 			ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".config", j.testConfig)
 		}
+		dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+		if dynamicConfig.Valid() {
+			ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
+		}
 		testDeps := append(j.data, j.extraTestConfigs...)
 		for _, data := range android.SortedUniquePaths(testDeps) {
 			dataPath := android.DataPath{SrcPath: data}
diff --git a/python/test.go b/python/test.go
index 5e70fc1..df62ab7 100644
--- a/python/test.go
+++ b/python/test.go
@@ -224,6 +224,10 @@
 			if p.testConfig != nil {
 				ctx.InstallFile(testCases, ctx.ModuleName()+".config", p.testConfig)
 			}
+			dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+			if dynamicConfig.Valid() {
+				ctx.InstallFile(testCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
+			}
 		}
 		// Install tests and data in arch specific subdir $PRODUCT_OUT/testcases/$module/$arch
 		testCases = testCases.Join(ctx, ctx.Target().Arch.ArchType.String())
diff --git a/rust/test.go b/rust/test.go
index b658ae2..5c183bc 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -208,6 +208,10 @@
 			if test.testConfig != nil {
 				ctx.InstallFile(testCases, ctx.ModuleName()+".config", test.testConfig)
 			}
+			dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+			if dynamicConfig.Valid() {
+				ctx.InstallFile(testCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
+			}
 		}
 		// Install tests and data in arch specific subdir $PRODUCT_OUT/testcases/$module/$arch
 		testCases = testCases.Join(ctx, ctx.Target().Arch.ArchType.String())