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