1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "device/bluetooth/test/bluetooth_test_cast.h"
6
7 #include "base/callback_helpers.h"
8 #include "base/task/post_task.h"
9 #include "chromecast/device/bluetooth/bluetooth_util.h"
10 #include "chromecast/device/bluetooth/le/mock_gatt_client_manager.h"
11 #include "chromecast/device/bluetooth/le/remote_device.h"
12 #include "device/bluetooth/cast/bluetooth_adapter_cast.h"
13
14 using ::testing::ByMove;
15 using ::testing::Return;
16
17 namespace device {
18
19 class BluetoothTestCast::GattClientManager
20 : public chromecast::bluetooth::MockGattClientManager {
21 public:
22 GattClientManager() = default;
23 ~GattClientManager() override = default;
24
25 // chromecast::bluetooth::GattClientManager implementation:
GetDevice(const chromecast::bluetooth_v2_shlib::Addr & addr,base::OnceCallback<void (scoped_refptr<chromecast::bluetooth::RemoteDevice>)> cb)26 void GetDevice(
27 const chromecast::bluetooth_v2_shlib::Addr& addr,
28 base::OnceCallback<void(
29 scoped_refptr<chromecast::bluetooth::RemoteDevice>)> cb) override {
30 auto it = addr_to_remote_device_.find(addr);
31 if (it != addr_to_remote_device_.end()) {
32 std::move(cb).Run(it->second);
33 return;
34 }
35
36 auto device =
37 base::MakeRefCounted<chromecast::bluetooth::MockRemoteDevice>(addr);
38 addr_to_remote_device_.emplace(addr, device);
39 std::move(cb).Run(device);
40 }
41
42 private:
43 std::map<chromecast::bluetooth_v2_shlib::Addr,
44 scoped_refptr<chromecast::bluetooth::MockRemoteDevice>>
45 addr_to_remote_device_;
46 };
47
BluetoothTestCast()48 BluetoothTestCast::BluetoothTestCast()
49 : gatt_client_manager_(std::make_unique<GattClientManager>()) {
50 ON_CALL(le_scan_manager_, RequestScan)
51 .WillByDefault(Return(ByMove(
52 std::unique_ptr<chromecast::bluetooth::LeScanManager::ScanHandle>(
53 std::make_unique<chromecast::bluetooth::MockLeScanManager::
54 MockScanHandle>()))));
55 }
56
~BluetoothTestCast()57 BluetoothTestCast::~BluetoothTestCast() {
58 // Destroy |discovery_sesions_| before adapter, which may hold references to
59 // it.
60 discovery_sessions_.clear();
61
62 // Tear down adapter, which relies on members in the subclass.
63 adapter_ = nullptr;
64 }
65
InitWithFakeAdapter()66 void BluetoothTestCast::InitWithFakeAdapter() {
67 adapter_ =
68 new BluetoothAdapterCast(gatt_client_manager_.get(), &le_scan_manager_);
69 adapter_->SetPowered(true, base::DoNothing(), base::DoNothing());
70 }
71
PlatformSupportsLowEnergy()72 bool BluetoothTestCast::PlatformSupportsLowEnergy() {
73 return true;
74 }
75
SimulateLowEnergyDevice(int device_ordinal)76 BluetoothDevice* BluetoothTestCast::SimulateLowEnergyDevice(
77 int device_ordinal) {
78 if (device_ordinal > 7 || device_ordinal < 1)
79 return nullptr;
80
81 base::Optional<std::string> device_name = std::string(kTestDeviceName);
82 std::string device_address = kTestDeviceAddress1;
83 std::vector<std::string> service_uuids;
84 std::map<std::string, std::vector<uint8_t>> service_data;
85 std::map<uint16_t, std::vector<uint8_t>> manufacturer_data;
86
87 switch (device_ordinal) {
88 case 1:
89 service_uuids.push_back(kTestUUIDGenericAccess);
90 service_uuids.push_back(kTestUUIDGenericAttribute);
91 service_data[kTestUUIDHeartRate] = {0x01};
92 manufacturer_data[kTestManufacturerId] = {1, 2, 3, 4};
93 break;
94 case 2:
95 service_uuids.push_back(kTestUUIDImmediateAlert);
96 service_uuids.push_back(kTestUUIDLinkLoss);
97 service_data[kTestUUIDHeartRate] = {};
98 service_data[kTestUUIDImmediateAlert] = {0x00, 0x02};
99 manufacturer_data[kTestManufacturerId] = {};
100 break;
101 case 3:
102 device_name = std::string(kTestDeviceNameEmpty);
103 break;
104 case 4:
105 device_name = std::string(kTestDeviceNameEmpty);
106 device_address = kTestDeviceAddress2;
107 break;
108 case 5:
109 device_name = base::nullopt;
110 break;
111 default:
112 NOTREACHED();
113 }
114 UpdateAdapter(device_address, device_name, service_uuids, service_data,
115 manufacturer_data);
116 return adapter_->GetDevice(device_address);
117 }
118
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)119 void BluetoothTestCast::UpdateAdapter(
120 const std::string& address,
121 const base::Optional<std::string>& name,
122 const std::vector<std::string>& service_uuids,
123 const std::map<std::string, std::vector<uint8_t>>& service_data,
124 const std::map<uint16_t, std::vector<uint8_t>>& manufacturer_data) {
125 // Create a scan result with the desired values.
126 chromecast::bluetooth::LeScanResult result;
127 ASSERT_TRUE(chromecast::bluetooth::util::ParseAddr(address, &result.addr));
128 if (name) {
129 result.type_to_data[chromecast::bluetooth::LeScanResult::kGapCompleteName]
130 .push_back(std::vector<uint8_t>(name->begin(), name->end()));
131 }
132
133 // Add service_uuids.
134 std::vector<uint8_t> data;
135 for (const auto& uuid_str : service_uuids) {
136 chromecast::bluetooth_v2_shlib::Uuid uuid;
137 ASSERT_TRUE(chromecast::bluetooth::util::ParseUuid(uuid_str, &uuid));
138 data.insert(data.end(), uuid.rbegin(), uuid.rend());
139 }
140 result
141 .type_to_data
142 [chromecast::bluetooth::LeScanResult::kGapComplete128BitServiceUuids]
143 .push_back(std::move(data));
144
145 // Add service data.
146 for (const auto& it : service_data) {
147 chromecast::bluetooth_v2_shlib::Uuid uuid;
148 ASSERT_TRUE(chromecast::bluetooth::util::ParseUuid(it.first, &uuid));
149 std::vector<uint8_t> data(uuid.rbegin(), uuid.rend());
150 data.insert(data.end(), it.second.begin(), it.second.end());
151 result
152 .type_to_data
153 [chromecast::bluetooth::LeScanResult::kGapServicesData128bit]
154 .push_back(std::move(data));
155 }
156
157 // Add manufacturer data.
158 for (const auto& it : manufacturer_data) {
159 std::vector<uint8_t> data({(it.first & 0xFF), ((it.first >> 8) & 0xFF)});
160 data.insert(data.end(), it.second.begin(), it.second.end());
161 result
162 .type_to_data[chromecast::bluetooth::LeScanResult::kGapManufacturerData]
163 .push_back(std::move(data));
164 }
165
166 // Update the adapter with the ScanResult.
167 le_scan_manager_.observer_->OnNewScanResult(result);
168 task_environment_.RunUntilIdle();
169 }
170
171 } // namespace device
172