blob: 31728ba28b7e6d3e1f47c7e70e7a344c44b15005 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// 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/bind_helpers.h"
#include "base/task_scheduler/post_task.h"
#include "chromecast/device/bluetooth/bluetooth_util.h"
#include "chromecast/device/bluetooth/le/gatt_client_manager_impl.h"
#include "chromecast/device/bluetooth/le/remote_device.h"
#include "device/bluetooth/cast/bluetooth_adapter_cast.h"
#include "device/bluetooth/test/bluetooth_test_cast.h"
namespace device {
class BluetoothTestCast::FakeLeScanManager
: public chromecast::bluetooth::LeScanManager {
public:
FakeLeScanManager() = default;
~FakeLeScanManager() override = default;
void AddObserver(Observer* o) override {
DCHECK(!observer_);
observer_ = o;
}
void RemoveObserver(Observer* o) override {
DCHECK_EQ(observer_, o);
observer_ = nullptr;
}
void SetScanEnable(bool enable, SetScanEnableCallback cb) override {
std::move(cb).Run(true);
}
void GetScanResults(GetScanResultsCallback cb,
base::Optional<chromecast::bluetooth::ScanFilter>
scan_filter = base::nullopt) override {}
void ClearScanResults() override {}
Observer* observer() {
DCHECK(observer_);
return observer_;
}
private:
Observer* observer_ = nullptr;
};
BluetoothTestCast::BluetoothTestCast()
: io_task_runner_(base::CreateSingleThreadTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BACKGROUND})),
gatt_client_manager_(
new chromecast::bluetooth::GattClientManagerImpl(&mock_gatt_client_)),
fake_le_scan_manager_(new FakeLeScanManager()) {
gatt_client_manager_->Initialize(io_task_runner_);
mock_gatt_client_.SetDelegate(gatt_client_manager_.get());
}
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;
gatt_client_manager_->Finalize();
}
void BluetoothTestCast::InitWithFakeAdapter() {
adapter_ = new BluetoothAdapterCast(gatt_client_manager_.get(),
fake_le_scan_manager_.get());
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;
base::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 = base::nullopt;
break;
default:
NOTREACHED();
}
UpdateAdapter(device_address, device_name, service_uuids, service_data,
manufacturer_data);
return adapter_->GetDevice(device_address);
}
void BluetoothTestCast::UpdateAdapter(
const std::string& address,
const base::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 address and name.
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 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({(it.first & 0xFF), ((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.
fake_le_scan_manager_->observer()->OnNewScanResult(result);
scoped_task_environment_.RunUntilIdle();
// Add the services.
std::vector<chromecast::bluetooth_v2_shlib::Gatt::Service> services;
for (const auto& uuid : service_uuids) {
chromecast::bluetooth_v2_shlib::Gatt::Service service;
ASSERT_TRUE(chromecast::bluetooth::util::ParseUuid(uuid, &service.uuid));
services.push_back(service);
}
mock_gatt_client_.delegate()->OnServicesAdded(result.addr, services);
scoped_task_environment_.RunUntilIdle();
}
} // namespace device