1 /*
2 * Copyright 2021 HIMSA II K/S - www.himsa.com.
3 * Represented by EHIMA - www.ehima.com
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include "devices.h"
19
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22
23 #include <map>
24
25 #include "bta_gatt_api_mock.h"
26 #include "bta_gatt_queue_mock.h"
27 #include "btm_api_mock.h"
28 #include "gatt/database_builder.h"
29
30 namespace bluetooth {
31 namespace vc {
32 namespace internal {
33
34 using ::testing::_;
35 using ::testing::DoAll;
36 using ::testing::Invoke;
37 using ::testing::Mock;
38 using ::testing::Return;
39 using ::testing::SetArgPointee;
40 using ::testing::Test;
41
GetTestAddress(int index)42 RawAddress GetTestAddress(int index) {
43 CHECK_LT(index, UINT8_MAX);
44 RawAddress result = {
45 {0xC0, 0xDE, 0xC0, 0xDE, 0x00, static_cast<uint8_t>(index)}};
46 return result;
47 }
48
49 class VolumeControlDevicesTest : public ::testing::Test {
50 protected:
SetUp()51 void SetUp() override {
52 devices_ = new VolumeControlDevices();
53 gatt::SetMockBtaGattInterface(&gatt_interface);
54 gatt::SetMockBtaGattQueue(&gatt_queue);
55 }
56
TearDown()57 void TearDown() override {
58 gatt::SetMockBtaGattQueue(nullptr);
59 gatt::SetMockBtaGattInterface(nullptr);
60 delete devices_;
61 }
62
63 VolumeControlDevices* devices_ = nullptr;
64 gatt::MockBtaGattInterface gatt_interface;
65 gatt::MockBtaGattQueue gatt_queue;
66 };
67
TEST_F(VolumeControlDevicesTest,test_add)68 TEST_F(VolumeControlDevicesTest, test_add) {
69 RawAddress test_address_0 = GetTestAddress(0);
70 ASSERT_EQ((size_t)0, devices_->Size());
71 devices_->Add(test_address_0, true);
72 ASSERT_EQ((size_t)1, devices_->Size());
73 }
74
TEST_F(VolumeControlDevicesTest,test_add_twice)75 TEST_F(VolumeControlDevicesTest, test_add_twice) {
76 RawAddress test_address_0 = GetTestAddress(0);
77 ASSERT_EQ((size_t)0, devices_->Size());
78 devices_->Add(test_address_0, true);
79 devices_->Add(test_address_0, true);
80 ASSERT_EQ((size_t)1, devices_->Size());
81 }
82
TEST_F(VolumeControlDevicesTest,test_remove)83 TEST_F(VolumeControlDevicesTest, test_remove) {
84 RawAddress test_address_0 = GetTestAddress(0);
85 RawAddress test_address_1 = GetTestAddress(1);
86 devices_->Add(test_address_0, true);
87 devices_->Add(test_address_1, true);
88 ASSERT_EQ((size_t)2, devices_->Size());
89 devices_->Remove(test_address_0);
90 ASSERT_EQ((size_t)1, devices_->Size());
91 }
92
TEST_F(VolumeControlDevicesTest,test_clear)93 TEST_F(VolumeControlDevicesTest, test_clear) {
94 RawAddress test_address_0 = GetTestAddress(0);
95 ASSERT_EQ((size_t)0, devices_->Size());
96 devices_->Add(test_address_0, true);
97 ASSERT_EQ((size_t)1, devices_->Size());
98 devices_->Clear();
99 ASSERT_EQ((size_t)0, devices_->Size());
100 }
101
TEST_F(VolumeControlDevicesTest,test_find_by_address)102 TEST_F(VolumeControlDevicesTest, test_find_by_address) {
103 RawAddress test_address_0 = GetTestAddress(0);
104 RawAddress test_address_1 = GetTestAddress(1);
105 RawAddress test_address_2 = GetTestAddress(2);
106 devices_->Add(test_address_0, true);
107 devices_->Add(test_address_1, false);
108 devices_->Add(test_address_2, true);
109 VolumeControlDevice* device = devices_->FindByAddress(test_address_1);
110 ASSERT_NE(nullptr, device);
111 ASSERT_EQ(test_address_1, device->address);
112 }
113
TEST_F(VolumeControlDevicesTest,test_find_by_conn_id)114 TEST_F(VolumeControlDevicesTest, test_find_by_conn_id) {
115 RawAddress test_address_0 = GetTestAddress(0);
116 devices_->Add(test_address_0, true);
117 VolumeControlDevice* test_device = devices_->FindByAddress(test_address_0);
118 test_device->connection_id = 0x0005;
119 ASSERT_NE(nullptr, devices_->FindByConnId(test_device->connection_id));
120 }
121
TEST_F(VolumeControlDevicesTest,test_disconnect)122 TEST_F(VolumeControlDevicesTest, test_disconnect) {
123 RawAddress test_address_0 = GetTestAddress(0);
124 RawAddress test_address_1 = GetTestAddress(1);
125 devices_->Add(test_address_0, true);
126 devices_->Add(test_address_1, true);
127 VolumeControlDevice* test_device_0 = devices_->FindByAddress(test_address_0);
128 test_device_0->connection_id = 0x0005;
129 tGATT_IF gatt_if = 8;
130 EXPECT_CALL(gatt_interface, Close(test_device_0->connection_id));
131 EXPECT_CALL(gatt_interface, CancelOpen(gatt_if, test_address_1, _));
132 devices_->Disconnect(gatt_if);
133 }
134
TEST_F(VolumeControlDevicesTest,test_control_point_operation)135 TEST_F(VolumeControlDevicesTest, test_control_point_operation) {
136 uint8_t opcode = 50;
137 std::vector<RawAddress> devices;
138
139 for (int i = 5; i > 0; i--) {
140 RawAddress test_address = GetTestAddress(i);
141 devices.push_back(test_address);
142 uint8_t change_counter = 10 * i;
143 uint16_t control_point_handle = 0x0020 + i;
144 uint16_t connection_id = i;
145 devices_->Add(test_address, true);
146 VolumeControlDevice* device = devices_->FindByAddress(test_address);
147 device->connection_id = connection_id;
148 device->change_counter = change_counter;
149 device->volume_control_point_handle = control_point_handle;
150 std::vector<uint8_t> data_expected({opcode, change_counter});
151
152 EXPECT_CALL(gatt_queue,
153 WriteCharacteristic(connection_id, control_point_handle,
154 data_expected, GATT_WRITE, _, _));
155 }
156
157 const std::vector<uint8_t>* arg = nullptr;
158 GATT_WRITE_OP_CB cb = nullptr;
159 void* cb_data = nullptr;
160 devices_->ControlPointOperation(devices, opcode, arg, cb, cb_data);
161 }
162
TEST_F(VolumeControlDevicesTest,test_control_point_operation_args)163 TEST_F(VolumeControlDevicesTest, test_control_point_operation_args) {
164 uint8_t opcode = 60;
165 uint8_t arg_1 = 0x02;
166 uint8_t arg_2 = 0x05;
167 std::vector<RawAddress> devices;
168
169 for (int i = 5; i > 0; i--) {
170 RawAddress test_address = GetTestAddress(i);
171 devices.push_back(test_address);
172 uint8_t change_counter = 10 * i;
173 uint16_t control_point_handle = 0x0020 + i;
174 uint16_t connection_id = i;
175 devices_->Add(test_address, true);
176 VolumeControlDevice* device = devices_->FindByAddress(test_address);
177 device->connection_id = connection_id;
178 device->change_counter = change_counter;
179 device->volume_control_point_handle = control_point_handle;
180 std::vector<uint8_t> data_expected({opcode, change_counter, arg_1, arg_2});
181
182 EXPECT_CALL(gatt_queue,
183 WriteCharacteristic(connection_id, control_point_handle,
184 data_expected, GATT_WRITE, _, _));
185 }
186
187 std::vector<uint8_t> arg({arg_1, arg_2});
188 GATT_WRITE_OP_CB cb = nullptr;
189 void* cb_data = nullptr;
190 devices_->ControlPointOperation(devices, opcode, &arg, cb, cb_data);
191 }
192
TEST_F(VolumeControlDevicesTest,test_control_point_skip_not_connected)193 TEST_F(VolumeControlDevicesTest, test_control_point_skip_not_connected) {
194 RawAddress test_address = GetTestAddress(1);
195 devices_->Add(test_address, true);
196 VolumeControlDevice* device = devices_->FindByAddress(test_address);
197 device->connection_id = GATT_INVALID_CONN_ID;
198 uint16_t control_point_handle = 0x0020;
199 device->volume_control_point_handle = control_point_handle;
200
201 EXPECT_CALL(gatt_queue,
202 WriteCharacteristic(_, control_point_handle, _, _, _, _))
203 .Times(0);
204
205 uint8_t opcode = 5;
206 std::vector<RawAddress> devices = {test_address};
207 const std::vector<uint8_t>* arg = nullptr;
208 GATT_WRITE_OP_CB cb = nullptr;
209 void* cb_data = nullptr;
210 devices_->ControlPointOperation(devices, opcode, arg, cb, cb_data);
211 }
212
213 class VolumeControlDeviceTest : public ::testing::Test {
214 protected:
SetUp()215 void SetUp() override {
216 device = new VolumeControlDevice(GetTestAddress(1), true);
217 gatt::SetMockBtaGattInterface(&gatt_interface);
218 gatt::SetMockBtaGattQueue(&gatt_queue);
219 bluetooth::manager::SetMockBtmInterface(&btm_interface);
220
221 ON_CALL(gatt_interface, GetCharacteristic(_, _))
222 .WillByDefault(
223 Invoke([&](uint16_t conn_id,
224 uint16_t handle) -> const gatt::Characteristic* {
225 for (auto const& service : services) {
226 for (auto const& characteristic : service.characteristics) {
227 if (characteristic.value_handle == handle) {
228 return &characteristic;
229 }
230 }
231 }
232
233 return nullptr;
234 }));
235
236 ON_CALL(gatt_interface, GetOwningService(_, _))
237 .WillByDefault(Invoke(
238 [&](uint16_t conn_id, uint16_t handle) -> const gatt::Service* {
239 for (auto const& service : services) {
240 if (service.handle <= handle && service.end_handle >= handle) {
241 return &service;
242 }
243 }
244
245 return nullptr;
246 }));
247
248 ON_CALL(gatt_interface, GetServices(_)).WillByDefault(Return(&services));
249 }
250
TearDown()251 void TearDown() override {
252 bluetooth::manager::SetMockBtmInterface(nullptr);
253 gatt::SetMockBtaGattQueue(nullptr);
254 gatt::SetMockBtaGattInterface(nullptr);
255 delete device;
256 }
257
258 /* sample database 1xVCS, 2xAICS, 2xVOCS */
SetSampleDatabase1(void)259 void SetSampleDatabase1(void) {
260 gatt::DatabaseBuilder builder;
261 builder.AddService(0x0001, 0x0016, kVolumeControlUuid, true);
262 builder.AddCharacteristic(
263 0x0010, 0x0011, kVolumeControlStateUuid,
264 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
265 builder.AddDescriptor(0x0012,
266 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
267 builder.AddCharacteristic(0x0013, 0x0014, kVolumeControlPointUuid,
268 GATT_CHAR_PROP_BIT_WRITE);
269 builder.AddCharacteristic(0x0015, 0x0016, kVolumeFlagsUuid,
270 GATT_CHAR_PROP_BIT_READ);
271 builder.AddService(0x00a0, 0x00a3,
272 Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER), true);
273 builder.AddCharacteristic(0x00a1, 0x00a2,
274 Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD),
275 GATT_CHAR_PROP_BIT_NOTIFY);
276 builder.AddDescriptor(0x00a3,
277 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
278 services = builder.Build().Services();
279 ASSERT_EQ(true, device->UpdateHandles());
280 }
281
282 /* sample database no VCS */
SetSampleDatabase2(void)283 void SetSampleDatabase2(void) {
284 gatt::DatabaseBuilder builder;
285 builder.AddService(0x0001, 0x0003, Uuid::From16Bit(0x1800), true);
286 builder.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2a00),
287 GATT_CHAR_PROP_BIT_READ);
288 services = builder.Build().Services();
289 ASSERT_EQ(false, device->UpdateHandles());
290 }
291
292 VolumeControlDevice* device = nullptr;
293 gatt::MockBtaGattInterface gatt_interface;
294 gatt::MockBtaGattQueue gatt_queue;
295 bluetooth::manager::MockBtmInterface btm_interface;
296 std::list<gatt::Service> services;
297 };
298
TEST_F(VolumeControlDeviceTest,test_service_volume_control_not_found)299 TEST_F(VolumeControlDeviceTest, test_service_volume_control_not_found) {
300 SetSampleDatabase2();
301 ASSERT_EQ(false, device->HasHandles());
302 }
303
TEST_F(VolumeControlDeviceTest,test_service_volume_control_incomplete)304 TEST_F(VolumeControlDeviceTest, test_service_volume_control_incomplete) {
305 gatt::DatabaseBuilder builder;
306 builder.AddService(0x0001, 0x0006, kVolumeControlUuid, true);
307 builder.AddCharacteristic(
308 0x0002, 0x0003, kVolumeControlStateUuid,
309 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
310 builder.AddDescriptor(0x0004, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
311 builder.AddCharacteristic(0x0005, 0x0006, kVolumeControlPointUuid,
312 GATT_CHAR_PROP_BIT_WRITE);
313 /* no Volume Control Flags characteristic */
314 services = builder.Build().Services();
315 ASSERT_EQ(false, device->UpdateHandles());
316 ASSERT_EQ(0x0000, device->volume_state_handle);
317 ASSERT_EQ(0x0000, device->volume_state_ccc_handle);
318 ASSERT_EQ(0x0000, device->volume_control_point_handle);
319 ASSERT_EQ(0x0000, device->volume_flags_handle);
320 ASSERT_EQ(0x0000, device->volume_flags_ccc_handle);
321 ASSERT_EQ(false, device->HasHandles());
322 }
323
TEST_F(VolumeControlDeviceTest,test_services_changed)324 TEST_F(VolumeControlDeviceTest, test_services_changed) {
325 SetSampleDatabase1();
326 ASSERT_NE(0, device->volume_state_handle);
327 ASSERT_NE(0, device->volume_control_point_handle);
328 ASSERT_NE(0, device->volume_flags_handle);
329 ASSERT_EQ(true, device->HasHandles());
330 SetSampleDatabase2();
331 ASSERT_EQ(0, device->volume_state_handle);
332 ASSERT_EQ(0, device->volume_control_point_handle);
333 ASSERT_EQ(0, device->volume_flags_handle);
334 ASSERT_EQ(false, device->HasHandles());
335 }
336
TEST_F(VolumeControlDeviceTest,test_enqueue_initial_requests)337 TEST_F(VolumeControlDeviceTest, test_enqueue_initial_requests) {
338 SetSampleDatabase1();
339
340 tGATT_IF gatt_if = 0x0001;
341 std::vector<uint8_t> register_for_notification_data({0x01, 0x00});
342
343 std::map<uint16_t, uint16_t> expected_to_read_write{
344 {0x0011, 0x0012} /* volume control state */};
345
346 for (auto const& handle_pair : expected_to_read_write) {
347 EXPECT_CALL(gatt_queue, ReadCharacteristic(_, handle_pair.first, _, _));
348 EXPECT_CALL(gatt_queue, WriteDescriptor(_, handle_pair.second,
349 register_for_notification_data,
350 GATT_WRITE, _, _));
351 EXPECT_CALL(gatt_interface,
352 RegisterForNotifications(gatt_if, _, handle_pair.first));
353 }
354
355 auto chrc_read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
356 uint16_t len, uint8_t* value, void* data) {};
357 auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status,
358 uint16_t handle, void* data) {};
359 ASSERT_EQ(true, device->EnqueueInitialRequests(gatt_if, chrc_read_cb,
360 cccd_write_cb));
361 };
362
TEST_F(VolumeControlDeviceTest,test_device_ready)363 TEST_F(VolumeControlDeviceTest, test_device_ready) {
364 SetSampleDatabase1();
365
366 // grab all the handles requested
367 std::vector<uint16_t> requested_handles;
368 ON_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _))
369 .WillByDefault(Invoke(
370 [&requested_handles](
371 uint16_t conn_id, uint16_t handle, std::vector<uint8_t> value,
372 tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
373 void* cb_data) -> void { requested_handles.push_back(handle); }));
374 ON_CALL(gatt_queue, ReadCharacteristic(_, _, _, _))
375 .WillByDefault(Invoke(
376 [&requested_handles](uint16_t conn_id, uint16_t handle,
377 GATT_READ_OP_CB cb, void* cb_data) -> void {
378 requested_handles.push_back(handle);
379 }));
380
381 auto chrc_read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
382 uint16_t len, uint8_t* value, void* data) {};
383 auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status,
384 uint16_t handle, void* data) {};
385 ASSERT_EQ(true, device->EnqueueInitialRequests(0x0001, chrc_read_cb,
386 cccd_write_cb));
387 ASSERT_NE((size_t)0, requested_handles.size());
388
389 // indicate non-pending requests
390 ASSERT_EQ(false, device->device_ready);
391 device->VerifyReady(0xffff);
392
393 for (uint16_t handle : requested_handles) {
394 ASSERT_EQ(false, device->device_ready);
395 device->VerifyReady(handle);
396 }
397
398 ASSERT_EQ(true, device->device_ready);
399 }
400
TEST_F(VolumeControlDeviceTest,test_enqueue_remaining_requests)401 TEST_F(VolumeControlDeviceTest, test_enqueue_remaining_requests) {
402 SetSampleDatabase1();
403
404 tGATT_IF gatt_if = 0x0001;
405 std::vector<uint8_t> register_for_notification_data({0x01, 0x00});
406
407 std::vector<uint16_t> expected_to_read{0x0016 /* volume flags */};
408
409 std::map<uint16_t, uint16_t> expected_to_write_value_ccc_handle_map{};
410
411 for (uint16_t handle : expected_to_read) {
412 EXPECT_CALL(gatt_queue, ReadCharacteristic(_, handle, _, _));
413 }
414
415 for (auto const& handle_pair : expected_to_write_value_ccc_handle_map) {
416 EXPECT_CALL(gatt_queue, WriteDescriptor(_, handle_pair.second,
417 register_for_notification_data,
418 GATT_WRITE, _, _));
419 EXPECT_CALL(gatt_interface,
420 RegisterForNotifications(gatt_if, _, handle_pair.first));
421 }
422
423 auto chrc_read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
424 uint16_t len, uint8_t* value, void* data) {};
425 auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status,
426 uint16_t handle, void* data) {};
427 device->EnqueueRemainingRequests(gatt_if, chrc_read_cb, cccd_write_cb);
428 }
429
TEST_F(VolumeControlDeviceTest,test_check_link_encrypted)430 TEST_F(VolumeControlDeviceTest, test_check_link_encrypted) {
431 ON_CALL(btm_interface, GetSecurityFlagsByTransport(_, _, _))
432 .WillByDefault(
433 DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
434 ASSERT_EQ(true, device->IsEncryptionEnabled());
435
436 ON_CALL(btm_interface, GetSecurityFlagsByTransport(_, _, _))
437 .WillByDefault(DoAll(SetArgPointee<1>(0), Return(false)));
438 ASSERT_NE(true, device->IsEncryptionEnabled());
439
440 ON_CALL(btm_interface, GetSecurityFlagsByTransport(_, _, _))
441 .WillByDefault(DoAll(SetArgPointee<1>(0), Return(true)));
442 ASSERT_NE(true, device->IsEncryptionEnabled());
443 }
444
TEST_F(VolumeControlDeviceTest,test_control_point_operation)445 TEST_F(VolumeControlDeviceTest, test_control_point_operation) {
446 GATT_WRITE_OP_CB write_cb = [](uint16_t conn_id, tGATT_STATUS status,
447 uint16_t handle, void* data) {};
448 SetSampleDatabase1();
449 device->change_counter = 0x01;
450 std::vector<uint8_t> expected_data({0x03, 0x01});
451 EXPECT_CALL(gatt_queue, WriteCharacteristic(_, 0x0014, expected_data,
452 GATT_WRITE, write_cb, nullptr));
453 device->ControlPointOperation(0x03, nullptr, write_cb, nullptr);
454 }
455
TEST_F(VolumeControlDeviceTest,test_control_point_operation_arg)456 TEST_F(VolumeControlDeviceTest, test_control_point_operation_arg) {
457 GATT_WRITE_OP_CB write_cb = [](uint16_t conn_id, tGATT_STATUS status,
458 uint16_t handle, void* data) {};
459 SetSampleDatabase1();
460 device->change_counter = 0x55;
461 std::vector<uint8_t> expected_data({0x01, 0x55, 0x02, 0x03});
462 EXPECT_CALL(gatt_queue, WriteCharacteristic(_, 0x0014, expected_data,
463 GATT_WRITE, write_cb, nullptr));
464 std::vector<uint8_t> arg({0x02, 0x03});
465 device->ControlPointOperation(0x01, &arg, write_cb, nullptr);
466 }
467
468 } // namespace internal
469 } // namespace vc
470 } // namespace bluetooth
471