mobly_driver: Pull btpeer info from test request

Add support for pulling btpeer info from test requests and make params
optional.

BUG=b:394685986
TEST=unittests

Change-Id: I21cbcfbece6432dfea1bfd9d9cbd2666d3e0ff12
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/6254248
Tested-by: Jason Stanko <jstanko@google.com>
Commit-Queue: Jason Stanko <jstanko@google.com>
Reviewed-by: Derek Beckett <dbeckett@chromium.org>
Reviewed-by: Billy Zhao <billyzhao@chromium.org>
diff --git a/src/go.chromium.org/chromiumos/test/execution/cmd/cros-test/internal/driver/mobly_config.go b/src/go.chromium.org/chromiumos/test/execution/cmd/cros-test/internal/driver/mobly_config.go
index c74bbce..9aa543d 100644
--- a/src/go.chromium.org/chromiumos/test/execution/cmd/cros-test/internal/driver/mobly_config.go
+++ b/src/go.chromium.org/chromiumos/test/execution/cmd/cros-test/internal/driver/mobly_config.go
@@ -24,6 +24,17 @@
 
 type paramMap = map[string]string
 
+// combinedParamMap combines the provided paramMaps and returns a new one.
+func combinedParamMap(maps ...paramMap) paramMap {
+	copy := paramMap{}
+	for _, p := range maps {
+		for k, v := range p {
+			copy[k] = v
+		}
+	}
+	return copy
+}
+
 type deviceParams struct {
 	deviceId string
 	params   paramMap
@@ -152,7 +163,7 @@
 	Controllers := &Controllers{
 		AndroidDevices:    GenerateAndroidDevices(serials, configParams.AndroidParams),
 		OpenWrtDevices:    GenerateOpenWrtDevices(serials, configParams.OpenWrtParams),
-		BtReferenceDevice: GenerateBtReferenceDevices(serials, configParams.BtReferenceParams),
+		BtReferenceDevice: GenerateBtReferenceDevices(serials, devices, configParams.BtReferenceParams),
 		PassportHost:      GeneratePassportHost(logger, devices, configParams.PassportParams),
 		ChameleonDevice:   GenerateChameleonDevices(serials, devices, configParams.ChameleonParams),
 	}
@@ -215,7 +226,7 @@
 	return passportHosts
 }
 
-func GenerateBtReferenceDevices(serials []string, btReferenceParams []deviceParams) []*BtReferenceDevice {
+func GenerateBtReferenceDevices(serials []string, duts []*labapi.Dut, btReferenceParams []deviceParams) []*BtReferenceDevice {
 	devices := []*BtReferenceDevice{}
 	deviceKeyToSerial := map[string]string{}
 	for i, serial := range serials {
@@ -234,6 +245,26 @@
 		}
 	}
 
+	// First copy all from infra.
+	seen := make(map[string]*BtReferenceDevice)
+	for _, dut := range duts {
+		if dut.GetChromeos() == nil {
+			continue
+		}
+		for _, btpeer := range dut.GetChromeos().GetBluetoothPeers() {
+			hostname := btpeer.GetHostname()
+			device := &BtReferenceDevice{
+				Hostname: hostname,
+				Username: "root",
+				Password: "test0000",
+				Params:   combinedParamMap(paramsForEachDevice),
+			}
+			seen[device.Hostname] = device
+			devices = append(devices, device)
+		}
+	}
+
+	// Now append devices specified by btReferenceParams & update infra params if provided.
 	for _, device := range btReferenceParams {
 		deviceKey := device.deviceId
 		deviceParams := device.params
@@ -244,21 +275,17 @@
 		deviceKey = strings.ReplaceAll(deviceKey, "primary", deviceKeyToSerial["primary"])
 		deviceKey = strings.ReplaceAll(deviceKey, "secondary", deviceKeyToSerial["secondary"])
 
-		params := paramMap{}
-		for k, v := range paramsForEachDevice {
-			params[k] = v
+		if val, ok := seen[deviceKey]; ok {
+			val.Params = combinedParamMap(val.Params, deviceParams)
+		} else {
+			// This device is unknown to infra ATM, just append it.
+			devices = append(devices, &BtReferenceDevice{
+				Hostname: deviceKey,
+				Username: "root",
+				Password: "test0000",
+				Params:   combinedParamMap(paramsForEachDevice, deviceParams),
+			})
 		}
-
-		for k, v := range deviceParams {
-			params[k] = v
-		}
-
-		devices = append(devices, &BtReferenceDevice{
-			Hostname: deviceKey,
-			Username: "root",
-			Password: "test0000",
-			Params:   params,
-		})
 	}
 
 	return devices
diff --git a/src/go.chromium.org/chromiumos/test/execution/cmd/cros-test/internal/driver/mobly_config_test.go b/src/go.chromium.org/chromiumos/test/execution/cmd/cros-test/internal/driver/mobly_config_test.go
index 900b021..4378f42 100644
--- a/src/go.chromium.org/chromiumos/test/execution/cmd/cros-test/internal/driver/mobly_config_test.go
+++ b/src/go.chromium.org/chromiumos/test/execution/cmd/cros-test/internal/driver/mobly_config_test.go
@@ -50,25 +50,31 @@
 						Hostname: "SERIAL_1-btpeer1",
 						Username: "root",
 						Password: "test0000",
-						Params:   paramMap{},
+						Params:   paramMap{"fake_global_param": "True", "fake_peer1_param": "False"},
 					},
 					{
 						Hostname: "SERIAL_1-btpeer2",
 						Username: "root",
 						Password: "test0000",
-						Params:   paramMap{},
+						Params:   paramMap{"fake_global_param": "True"},
+					},
+					{
+						Hostname: "SERIAL_1-btpeer5",
+						Username: "root",
+						Password: "test0000",
+						Params:   paramMap{"fake_global_param": "True"},
 					},
 					{
 						Hostname: "SERIAL_1-btpeer3",
 						Username: "root",
 						Password: "test0000",
-						Params:   paramMap{},
+						Params:   paramMap{"fake_global_param": "True"},
 					},
 					{
 						Hostname: "SERIAL_1-btpeer4",
 						Username: "root",
 						Password: "test0000",
-						Params:   paramMap{},
+						Params:   paramMap{"fake_global_param": "True"},
 					},
 				},
 				PassportHost: []*PassportHost{
@@ -204,15 +210,24 @@
     - hostname: SERIAL_1-btpeer1
       username: root
       password: test0000
+      fake_global_param: "True"
+      fake_peer1_param: "False"
     - hostname: SERIAL_1-btpeer2
       username: root
       password: test0000
+      fake_global_param: "True"
+    - hostname: SERIAL_1-btpeer5
+      username: root
+      password: test0000
+      fake_global_param: "True"
     - hostname: SERIAL_1-btpeer3
       username: root
       password: test0000
+      fake_global_param: "True"
     - hostname: SERIAL_1-btpeer4
       username: root
       password: test0000
+      fake_global_param: "True"
     PassportHost:
     - host_topology:
         connections:
@@ -300,7 +315,7 @@
 				},
 				{
 					Flag:  "btreference-params",
-					Value: "primary-btpeer1,primary-btpeer2,primary-btpeer3,primary-btpeer4",
+					Value: "fake_global_param:True,primary-btpeer1,fake_peer1_param:False,primary-btpeer2,primary-btpeer3,primary-btpeer4",
 				},
 				{
 					Flag:  "extra-test-params",
@@ -319,6 +334,17 @@
 				{
 					DutType: &labapi.Dut_Chromeos{
 						Chromeos: &labapi.Dut_ChromeOS{
+							BluetoothPeers: []*labapi.BluetoothPeer{
+								{
+									Hostname: "SERIAL_1-btpeer1",
+								},
+								{
+									Hostname: "SERIAL_1-btpeer2",
+								},
+								{
+									Hostname: "SERIAL_1-btpeer5",
+								},
+							},
 							PasitHost: &labapi.PasitHost{
 								Devices: []*labapi.PasitHost_Device{
 									{