// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "device/bluetooth/test/bluetooth_test_cast.h"
#include "base/functional/callback_helpers.h"
#include "chromecast/device/bluetooth/bluetooth_util.h"
#include "chromecast/device/bluetooth/le/mock_gatt_client_manager.h"
#include "chromecast/device/bluetooth/le/remote_device.h"
#include "device/bluetooth/cast/bluetooth_adapter_cast.h"
using ::testing::ByMove;
using ::testing::Return;
namespace device {
class BluetoothTestCast::GattClientManager
: public chromecast::bluetooth::MockGattClientManager {
public:
GattClientManager() = default;
~GattClientManager() override = default;
// chromecast::bluetooth::GattClientManager implementation:
void GetDevice(
const chromecast::bluetooth_v2_shlib::Addr& addr,
base::OnceCallback<void(
scoped_refptr<chromecast::bluetooth::RemoteDevice>)> cb) override {
auto it = addr_to_remote_device_.find(addr);
if (it != addr_to_remote_device_.end()) {
std::move(cb).Run(it->second);
return;
}
auto device =
base::MakeRefCounted<chromecast::bluetooth::MockRemoteDevice>(addr);
addr_to_remote_device_.emplace(addr, device);
std::move(cb).Run(device);
}
private:
std::map<chromecast::bluetooth_v2_shlib::Addr,
scoped_refptr<chromecast::bluetooth::MockRemoteDevice>>
addr_to_remote_device_;
};
BluetoothTestCast::BluetoothTestCast()
: gatt_client_manager_(std::make_unique<GattClientManager>()) {
ON_CALL(le_scan_manager_, RequestScan)
.WillByDefault(Return(ByMove(
std::unique_ptr<chromecast::bluetooth::LeScanManager::ScanHandle>(
std::make_unique<chromecast::bluetooth::MockLeScanManager::
MockScanHandle>()))));
}
BluetoothTestCast::~BluetoothTestCast() {
// Destroy |discovery_sesions_| before adapter, which may hold references to
// it.
discovery_sessions_.clear();
// Tear down adapter, which relies on members in the subclass.
adapter_ = nullptr;
}
void BluetoothTestCast::InitWithFakeAdapter() {
adapter_ =
new BluetoothAdapterCast(gatt_client_manager_.get(), &le_scan_manager_);
adapter_->SetPowered(true, base::DoNothing(), base::DoNothing());
}
bool BluetoothTestCast::PlatformSupportsLowEnergy() {
return true;
}
BluetoothDevice* BluetoothTestCast::SimulateLowEnergyDevice(
int device_ordinal) {
if (device_ordinal > 7 || device_ordinal < 1)
return nullptr;
std::optional<std::string> device_name = std::string(kTestDeviceName);
std::string device_address = kTestDeviceAddress1;
std::vector<std::string> service_uuids;
std::map<std::string, std::vector<uint8_t>> service_data;
std::map<uint16_t, std::vector<uint8_t>> manufacturer_data;
switch (device_ordinal) {
case 1:
service_uuids.push_back(kTestUUIDGenericAccess);
service_uuids.push_back(kTestUUIDGenericAttribute);
service_data[kTestUUIDHeartRate] = {0x01};
manufacturer_data[kTestManufacturerId] = {1, 2, 3, 4};
break;
case 2:
service_uuids.push_back(kTestUUIDImmediateAlert);
service_uuids.push_back(kTestUUIDLinkLoss);
service_data[kTestUUIDHeartRate] = {};
service_data[kTestUUIDImmediateAlert] = {0x00, 0x02};
manufacturer_data[kTestManufacturerId] = {};
break;
case 3:
device_name = std::string(kTestDeviceNameEmpty);
break;
case 4:
device_name = std::string(kTestDeviceNameEmpty);
device_address = kTestDeviceAddress2;
break;
case 5:
device_name = std::nullopt;
break;
default:
NOTREACHED_IN_MIGRATION();
}
UpdateAdapter(device_address, device_name, service_uuids, service_data,
manufacturer_data);
return adapter_->GetDevice(device_address);
}
void BluetoothTestCast::UpdateAdapter(
const std::string& address,
const std::optional<std::string>& name,
const std::vector<std::string>& service_uuids,
const std::map<std::string, std::vector<uint8_t>>& service_data,
const std::map<uint16_t, std::vector<uint8_t>>& manufacturer_data) {
// Create a scan result with the desired values.
chromecast::bluetooth::LeScanResult result;
ASSERT_TRUE(chromecast::bluetooth::util::ParseAddr(address, &result.addr));
if (name) {
result.type_to_data[chromecast::bluetooth::LeScanResult::kGapCompleteName]
.push_back(std::vector<uint8_t>(name->begin(), name->end()));
}
// Add service_uuids.
std::vector<uint8_t> parsed_uuids;
for (const auto& uuid_str : service_uuids) {
chromecast::bluetooth_v2_shlib::Uuid uuid;
ASSERT_TRUE(chromecast::bluetooth::util::ParseUuid(uuid_str, &uuid));
parsed_uuids.insert(parsed_uuids.end(), uuid.rbegin(), uuid.rend());
}
result
.type_to_data
[chromecast::bluetooth::LeScanResult::kGapComplete128BitServiceUuids]
.push_back(std::move(parsed_uuids));
// Add service data.
for (const auto& it : service_data) {
chromecast::bluetooth_v2_shlib::Uuid uuid;
ASSERT_TRUE(chromecast::bluetooth::util::ParseUuid(it.first, &uuid));
std::vector<uint8_t> data(uuid.rbegin(), uuid.rend());
data.insert(data.end(), it.second.begin(), it.second.end());
result
.type_to_data
[chromecast::bluetooth::LeScanResult::kGapServicesData128bit]
.push_back(std::move(data));
}
// Add manufacturer data.
for (const auto& it : manufacturer_data) {
std::vector<uint8_t> data{{static_cast<uint8_t>(it.first & 0xFF),
static_cast<uint8_t>((it.first >> 8) & 0xFF)}};
data.insert(data.end(), it.second.begin(), it.second.end());
result
.type_to_data[chromecast::bluetooth::LeScanResult::kGapManufacturerData]
.push_back(std::move(data));
}
// Update the adapter with the ScanResult.
le_scan_manager_.observer_->OnNewScanResult(result);
task_environment_.RunUntilIdle();
}
} // namespace device