• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "stack/include/bt_uuid16.h"
30 #include "types/bluetooth/uuid.h"
31 #include "types/raw_address.h"
32 
33 namespace bluetooth {
34 namespace vc {
35 namespace internal {
36 
37 using ::testing::_;
38 using ::testing::DoAll;
39 using ::testing::Invoke;
40 using ::testing::Mock;
41 using ::testing::Return;
42 using ::testing::SetArgPointee;
43 using ::testing::Test;
44 
GetTestAddress(int index)45 RawAddress GetTestAddress(int index) {
46   EXPECT_LT(index, UINT8_MAX);
47   RawAddress result = {
48       {0xC0, 0xDE, 0xC0, 0xDE, 0x00, static_cast<uint8_t>(index)}};
49   return result;
50 }
51 
52 class VolumeControlDevicesTest : public ::testing::Test {
53  protected:
SetUp()54   void SetUp() override {
55     devices_ = new VolumeControlDevices();
56     gatt::SetMockBtaGattInterface(&gatt_interface);
57     gatt::SetMockBtaGattQueue(&gatt_queue);
58   }
59 
TearDown()60   void TearDown() override {
61     gatt::SetMockBtaGattQueue(nullptr);
62     gatt::SetMockBtaGattInterface(nullptr);
63     delete devices_;
64   }
65 
66   VolumeControlDevices* devices_ = nullptr;
67   gatt::MockBtaGattInterface gatt_interface;
68   gatt::MockBtaGattQueue gatt_queue;
69 };
70 
TEST_F(VolumeControlDevicesTest,test_add)71 TEST_F(VolumeControlDevicesTest, test_add) {
72   RawAddress test_address_0 = GetTestAddress(0);
73   ASSERT_EQ((size_t)0, devices_->Size());
74   devices_->Add(test_address_0, true);
75   ASSERT_EQ((size_t)1, devices_->Size());
76 }
77 
TEST_F(VolumeControlDevicesTest,test_add_twice)78 TEST_F(VolumeControlDevicesTest, test_add_twice) {
79   RawAddress test_address_0 = GetTestAddress(0);
80   ASSERT_EQ((size_t)0, devices_->Size());
81   devices_->Add(test_address_0, true);
82   devices_->Add(test_address_0, true);
83   ASSERT_EQ((size_t)1, devices_->Size());
84 }
85 
TEST_F(VolumeControlDevicesTest,test_remove)86 TEST_F(VolumeControlDevicesTest, test_remove) {
87   RawAddress test_address_0 = GetTestAddress(0);
88   RawAddress test_address_1 = GetTestAddress(1);
89   devices_->Add(test_address_0, true);
90   devices_->Add(test_address_1, true);
91   ASSERT_EQ((size_t)2, devices_->Size());
92   devices_->Remove(test_address_0);
93   ASSERT_EQ((size_t)1, devices_->Size());
94 }
95 
TEST_F(VolumeControlDevicesTest,test_clear)96 TEST_F(VolumeControlDevicesTest, test_clear) {
97   RawAddress test_address_0 = GetTestAddress(0);
98   ASSERT_EQ((size_t)0, devices_->Size());
99   devices_->Add(test_address_0, true);
100   ASSERT_EQ((size_t)1, devices_->Size());
101   devices_->Clear();
102   ASSERT_EQ((size_t)0, devices_->Size());
103 }
104 
TEST_F(VolumeControlDevicesTest,test_find_by_address)105 TEST_F(VolumeControlDevicesTest, test_find_by_address) {
106   RawAddress test_address_0 = GetTestAddress(0);
107   RawAddress test_address_1 = GetTestAddress(1);
108   RawAddress test_address_2 = GetTestAddress(2);
109   devices_->Add(test_address_0, true);
110   devices_->Add(test_address_1, false);
111   devices_->Add(test_address_2, true);
112   VolumeControlDevice* device = devices_->FindByAddress(test_address_1);
113   ASSERT_NE(nullptr, device);
114   ASSERT_EQ(test_address_1, device->address);
115 }
116 
TEST_F(VolumeControlDevicesTest,test_find_by_conn_id)117 TEST_F(VolumeControlDevicesTest, test_find_by_conn_id) {
118   RawAddress test_address_0 = GetTestAddress(0);
119   devices_->Add(test_address_0, true);
120   VolumeControlDevice* test_device = devices_->FindByAddress(test_address_0);
121   test_device->connection_id = 0x0005;
122   ASSERT_NE(nullptr, devices_->FindByConnId(test_device->connection_id));
123 }
124 
TEST_F(VolumeControlDevicesTest,test_disconnect)125 TEST_F(VolumeControlDevicesTest, test_disconnect) {
126   RawAddress test_address_0 = GetTestAddress(0);
127   RawAddress test_address_1 = GetTestAddress(1);
128   devices_->Add(test_address_0, true);
129   devices_->Add(test_address_1, true);
130   VolumeControlDevice* test_device_0 = devices_->FindByAddress(test_address_0);
131   test_device_0->connection_id = 0x0005;
132   tGATT_IF gatt_if = 8;
133   EXPECT_CALL(gatt_interface, Close(test_device_0->connection_id));
134   devices_->Disconnect(gatt_if);
135 }
136 
TEST_F(VolumeControlDevicesTest,test_control_point_operation)137 TEST_F(VolumeControlDevicesTest, test_control_point_operation) {
138   uint8_t opcode = 50;
139   std::vector<RawAddress> devices;
140 
141   for (int i = 5; i > 0; i--) {
142     RawAddress test_address = GetTestAddress(i);
143     devices.push_back(test_address);
144     uint8_t change_counter = 10 * i;
145     uint16_t control_point_handle = 0x0020 + i;
146     uint16_t connection_id = i;
147     devices_->Add(test_address, true);
148     VolumeControlDevice* device = devices_->FindByAddress(test_address);
149     device->connection_id = connection_id;
150     device->change_counter = change_counter;
151     device->volume_control_point_handle = control_point_handle;
152     std::vector<uint8_t> data_expected({opcode, change_counter});
153 
154     EXPECT_CALL(gatt_queue,
155                 WriteCharacteristic(connection_id, control_point_handle,
156                                     data_expected, GATT_WRITE, _, _));
157   }
158 
159   const std::vector<uint8_t>* arg = nullptr;
160   GATT_WRITE_OP_CB cb = nullptr;
161   void* cb_data = nullptr;
162   devices_->ControlPointOperation(devices, opcode, arg, cb, cb_data);
163 }
164 
TEST_F(VolumeControlDevicesTest,test_control_point_operation_args)165 TEST_F(VolumeControlDevicesTest, test_control_point_operation_args) {
166   uint8_t opcode = 60;
167   uint8_t arg_1 = 0x02;
168   uint8_t arg_2 = 0x05;
169   std::vector<RawAddress> devices;
170 
171   for (int i = 5; i > 0; i--) {
172     RawAddress test_address = GetTestAddress(i);
173     devices.push_back(test_address);
174     uint8_t change_counter = 10 * i;
175     uint16_t control_point_handle = 0x0020 + i;
176     uint16_t connection_id = i;
177     devices_->Add(test_address, true);
178     VolumeControlDevice* device = devices_->FindByAddress(test_address);
179     device->connection_id = connection_id;
180     device->change_counter = change_counter;
181     device->volume_control_point_handle = control_point_handle;
182     std::vector<uint8_t> data_expected({opcode, change_counter, arg_1, arg_2});
183 
184     EXPECT_CALL(gatt_queue,
185                 WriteCharacteristic(connection_id, control_point_handle,
186                                     data_expected, GATT_WRITE, _, _));
187   }
188 
189   std::vector<uint8_t> arg({arg_1, arg_2});
190   GATT_WRITE_OP_CB cb = nullptr;
191   void* cb_data = nullptr;
192   devices_->ControlPointOperation(devices, opcode, &arg, cb, cb_data);
193 }
194 
TEST_F(VolumeControlDevicesTest,test_control_point_skip_not_connected)195 TEST_F(VolumeControlDevicesTest, test_control_point_skip_not_connected) {
196   RawAddress test_address = GetTestAddress(1);
197   devices_->Add(test_address, true);
198   VolumeControlDevice* device = devices_->FindByAddress(test_address);
199   device->connection_id = GATT_INVALID_CONN_ID;
200   uint16_t control_point_handle = 0x0020;
201   device->volume_control_point_handle = control_point_handle;
202 
203   EXPECT_CALL(gatt_queue,
204               WriteCharacteristic(_, control_point_handle, _, _, _, _))
205       .Times(0);
206 
207   uint8_t opcode = 5;
208   std::vector<RawAddress> devices = {test_address};
209   const std::vector<uint8_t>* arg = nullptr;
210   GATT_WRITE_OP_CB cb = nullptr;
211   void* cb_data = nullptr;
212   devices_->ControlPointOperation(devices, opcode, arg, cb, cb_data);
213 }
214 
215 class VolumeControlDeviceTest : public ::testing::Test {
216  protected:
SetUp()217   void SetUp() override {
218     device = new VolumeControlDevice(GetTestAddress(1), true);
219     gatt::SetMockBtaGattInterface(&gatt_interface);
220     gatt::SetMockBtaGattQueue(&gatt_queue);
221     bluetooth::manager::SetMockBtmInterface(&btm_interface);
222 
223     ON_CALL(gatt_interface, GetCharacteristic(_, _))
224         .WillByDefault(
225             Invoke([&](uint16_t conn_id,
226                        uint16_t handle) -> const gatt::Characteristic* {
227               for (auto const& service : services) {
228                 for (auto const& characteristic : service.characteristics) {
229                   if (characteristic.value_handle == handle) {
230                     return &characteristic;
231                   }
232                 }
233               }
234 
235               return nullptr;
236             }));
237 
238     ON_CALL(gatt_interface, GetOwningService(_, _))
239         .WillByDefault(Invoke(
240             [&](uint16_t conn_id, uint16_t handle) -> const gatt::Service* {
241               for (auto const& service : services) {
242                 if (service.handle <= handle && service.end_handle >= handle) {
243                   return &service;
244                 }
245               }
246 
247               return nullptr;
248             }));
249 
250     ON_CALL(gatt_interface, GetServices(_)).WillByDefault(Return(&services));
251   }
252 
TearDown()253   void TearDown() override {
254     bluetooth::manager::SetMockBtmInterface(nullptr);
255     gatt::SetMockBtaGattQueue(nullptr);
256     gatt::SetMockBtaGattInterface(nullptr);
257     delete device;
258   }
259 
260   /* sample database 1xVCS, 2xAICS, 2xVOCS */
SetSampleDatabase1(void)261   void SetSampleDatabase1(void) {
262     gatt::DatabaseBuilder builder;
263     builder.AddService(0x0001, 0x0016, kVolumeControlUuid, true);
264     builder.AddIncludedService(0x0004, kVolumeOffsetUuid, 0x0060, 0x0069);
265     builder.AddIncludedService(0x0005, kVolumeOffsetUuid, 0x0080, 0x008b);
266     builder.AddCharacteristic(
267         0x0010, 0x0011, kVolumeControlStateUuid,
268         GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
269     builder.AddDescriptor(0x0012,
270                           Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
271     builder.AddCharacteristic(0x0013, 0x0014, kVolumeControlPointUuid,
272                               GATT_CHAR_PROP_BIT_WRITE);
273     builder.AddCharacteristic(0x0015, 0x0016, kVolumeFlagsUuid,
274                               GATT_CHAR_PROP_BIT_READ);
275     builder.AddService(0x0060, 0x0069, kVolumeOffsetUuid, false);
276     builder.AddCharacteristic(
277         0x0061, 0x0062, kVolumeOffsetStateUuid,
278         GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
279     builder.AddDescriptor(0x0063,
280                           Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
281     builder.AddCharacteristic(0x0064, 0x0065, kVolumeOffsetLocationUuid,
282                               GATT_CHAR_PROP_BIT_READ);
283     builder.AddCharacteristic(0x0066, 0x0067, kVolumeOffsetControlPointUuid,
284                               GATT_CHAR_PROP_BIT_WRITE);
285     builder.AddCharacteristic(0x0068, 0x0069,
286                               kVolumeOffsetOutputDescriptionUuid,
287                               GATT_CHAR_PROP_BIT_READ);
288     builder.AddService(0x0080, 0x008b, kVolumeOffsetUuid, false);
289     builder.AddCharacteristic(
290         0x0081, 0x0082, kVolumeOffsetStateUuid,
291         GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
292     builder.AddDescriptor(0x0083,
293                           Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
294     builder.AddCharacteristic(0x0084, 0x0085, kVolumeOffsetLocationUuid,
295                               GATT_CHAR_PROP_BIT_READ |
296                                   GATT_CHAR_PROP_BIT_WRITE_NR |
297                                   GATT_CHAR_PROP_BIT_NOTIFY);
298     builder.AddDescriptor(0x0086,
299                           Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
300     builder.AddCharacteristic(0x0087, 0x0088, kVolumeOffsetControlPointUuid,
301                               GATT_CHAR_PROP_BIT_WRITE);
302     builder.AddCharacteristic(
303         0x0089, 0x008a, kVolumeOffsetOutputDescriptionUuid,
304         GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_WRITE_NR |
305             GATT_CHAR_PROP_BIT_NOTIFY);
306     builder.AddDescriptor(0x008b,
307                           Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
308     builder.AddService(0x00a0, 0x00a3,
309                        Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER), true);
310     builder.AddCharacteristic(0x00a1, 0x00a2,
311                               Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD),
312                               GATT_CHAR_PROP_BIT_NOTIFY);
313     builder.AddDescriptor(0x00a3,
314                           Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
315     services = builder.Build().Services();
316     ASSERT_EQ(true, device->UpdateHandles());
317   }
318 
319   /* sample database no VCS */
SetSampleDatabase2(void)320   void SetSampleDatabase2(void) {
321     gatt::DatabaseBuilder builder;
322     builder.AddService(0x0001, 0x0003, Uuid::From16Bit(0x1800), true);
323     builder.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2a00),
324                               GATT_CHAR_PROP_BIT_READ);
325     services = builder.Build().Services();
326     ASSERT_EQ(false, device->UpdateHandles());
327   }
328 
329   VolumeControlDevice* device = nullptr;
330   gatt::MockBtaGattInterface gatt_interface;
331   gatt::MockBtaGattQueue gatt_queue;
332   bluetooth::manager::MockBtmInterface btm_interface;
333   std::list<gatt::Service> services;
334 };
335 
TEST_F(VolumeControlDeviceTest,test_service_volume_control_not_found)336 TEST_F(VolumeControlDeviceTest, test_service_volume_control_not_found) {
337   SetSampleDatabase2();
338   ASSERT_EQ(false, device->HasHandles());
339 }
340 
TEST_F(VolumeControlDeviceTest,test_service_volume_control_incomplete)341 TEST_F(VolumeControlDeviceTest, test_service_volume_control_incomplete) {
342   gatt::DatabaseBuilder builder;
343   builder.AddService(0x0001, 0x0006, kVolumeControlUuid, true);
344   builder.AddCharacteristic(
345       0x0002, 0x0003, kVolumeControlStateUuid,
346       GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
347   builder.AddDescriptor(0x0004, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
348   builder.AddCharacteristic(0x0005, 0x0006, kVolumeControlPointUuid,
349                             GATT_CHAR_PROP_BIT_WRITE);
350   /* no Volume Control Flags characteristic */
351   services = builder.Build().Services();
352   ASSERT_EQ(false, device->UpdateHandles());
353   ASSERT_EQ(0x0000, device->volume_state_handle);
354   ASSERT_EQ(0x0000, device->volume_state_ccc_handle);
355   ASSERT_EQ(0x0000, device->volume_control_point_handle);
356   ASSERT_EQ(0x0000, device->volume_flags_handle);
357   ASSERT_EQ(0x0000, device->volume_flags_ccc_handle);
358   ASSERT_EQ(false, device->HasHandles());
359 }
360 
TEST_F(VolumeControlDeviceTest,test_service_vocs_incomplete)361 TEST_F(VolumeControlDeviceTest, test_service_vocs_incomplete) {
362   gatt::DatabaseBuilder builder;
363   builder.AddService(0x0001, 0x000a, kVolumeControlUuid, true);
364   builder.AddIncludedService(0x0002, kVolumeOffsetUuid, 0x000b, 0x0013);
365   builder.AddCharacteristic(
366       0x0003, 0x0004, kVolumeControlStateUuid,
367       GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
368   builder.AddDescriptor(0x0005, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
369   builder.AddCharacteristic(0x0006, 0x0007, kVolumeControlPointUuid,
370                             GATT_CHAR_PROP_BIT_WRITE);
371   builder.AddCharacteristic(
372       0x0008, 0x0009, kVolumeFlagsUuid,
373       GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
374   builder.AddDescriptor(0x000a, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
375   builder.AddService(0x000b, 0x0013, kVolumeOffsetUuid, false);
376   builder.AddCharacteristic(
377       0x000c, 0x000d, kVolumeOffsetStateUuid,
378       GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
379   builder.AddDescriptor(0x000e, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
380   builder.AddCharacteristic(
381       0x000f, 0x0010, kVolumeOffsetLocationUuid,
382       GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
383   builder.AddDescriptor(0x0011, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
384   builder.AddCharacteristic(0x0012, 0x0013, kVolumeOffsetControlPointUuid,
385                             GATT_CHAR_PROP_BIT_WRITE);
386   /* no Audio Output Description characteristic */
387   services = builder.Build().Services();
388   ASSERT_EQ(true, device->UpdateHandles());
389   ASSERT_EQ((size_t)0, device->audio_offsets.Size());
390   ASSERT_EQ(0x0004, device->volume_state_handle);
391   ASSERT_EQ(0x0005, device->volume_state_ccc_handle);
392   ASSERT_EQ(0x0007, device->volume_control_point_handle);
393   ASSERT_EQ(0x0009, device->volume_flags_handle);
394   ASSERT_EQ(0x000a, device->volume_flags_ccc_handle);
395   ASSERT_EQ(true, device->HasHandles());
396 }
397 
TEST_F(VolumeControlDeviceTest,test_service_vocs_found)398 TEST_F(VolumeControlDeviceTest, test_service_vocs_found) {
399   gatt::DatabaseBuilder builder;
400   builder.AddService(0x0001, 0x000a, kVolumeControlUuid, true);
401   builder.AddIncludedService(0x0002, kVolumeOffsetUuid, 0x000b, 0x0015);
402   builder.AddCharacteristic(
403       0x0003, 0x0004, kVolumeControlStateUuid,
404       GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
405   builder.AddDescriptor(0x0005, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
406   builder.AddCharacteristic(0x0006, 0x0007, kVolumeControlPointUuid,
407                             GATT_CHAR_PROP_BIT_WRITE);
408   builder.AddCharacteristic(
409       0x0008, 0x0009, kVolumeFlagsUuid,
410       GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
411   builder.AddDescriptor(0x000a, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
412   builder.AddService(0x000b, 0x0015, kVolumeOffsetUuid, false);
413   builder.AddCharacteristic(
414       0x000c, 0x000d, kVolumeOffsetStateUuid,
415       GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
416   builder.AddDescriptor(0x000e, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
417   builder.AddCharacteristic(
418       0x000f, 0x0010, kVolumeOffsetLocationUuid,
419       GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
420   builder.AddDescriptor(0x0011, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
421   builder.AddCharacteristic(0x0012, 0x0013, kVolumeOffsetControlPointUuid,
422                             GATT_CHAR_PROP_BIT_WRITE);
423   builder.AddCharacteristic(0x0014, 0x0015, kVolumeOffsetOutputDescriptionUuid,
424                             GATT_CHAR_PROP_BIT_READ);
425   services = builder.Build().Services();
426   ASSERT_EQ(true, device->UpdateHandles());
427   ASSERT_EQ((size_t)1, device->audio_offsets.Size());
428   VolumeOffset* offset = device->audio_offsets.FindByServiceHandle(0x000b);
429   ASSERT_NE(nullptr, offset);
430   ASSERT_EQ(0x000d, offset->state_handle);
431   ASSERT_EQ(0x000e, offset->state_ccc_handle);
432   ASSERT_EQ(0x0010, offset->audio_location_handle);
433   ASSERT_EQ(0x0011, offset->audio_location_ccc_handle);
434   ASSERT_EQ(0x0013, offset->control_point_handle);
435   ASSERT_EQ(0x0015, offset->audio_descr_handle);
436   ASSERT_EQ(0x0000, offset->audio_descr_ccc_handle);
437   ASSERT_EQ(true, device->HasHandles());
438 }
439 
TEST_F(VolumeControlDeviceTest,test_multiple_services_found)440 TEST_F(VolumeControlDeviceTest, test_multiple_services_found) {
441   SetSampleDatabase1();
442   ASSERT_EQ((size_t)2, device->audio_offsets.Size());
443   VolumeOffset* offset_1 = device->audio_offsets.FindById(1);
444   VolumeOffset* offset_2 = device->audio_offsets.FindById(2);
445   ASSERT_NE(nullptr, offset_1);
446   ASSERT_NE(nullptr, offset_2);
447   ASSERT_NE(offset_1->service_handle, offset_2->service_handle);
448 }
449 
TEST_F(VolumeControlDeviceTest,test_services_changed)450 TEST_F(VolumeControlDeviceTest, test_services_changed) {
451   SetSampleDatabase1();
452   ASSERT_NE((size_t)0, device->audio_offsets.Size());
453   ASSERT_NE(0, device->volume_state_handle);
454   ASSERT_NE(0, device->volume_control_point_handle);
455   ASSERT_NE(0, device->volume_flags_handle);
456   ASSERT_EQ(true, device->HasHandles());
457   SetSampleDatabase2();
458   ASSERT_EQ((size_t)0, device->audio_offsets.Size());
459   ASSERT_EQ(0, device->volume_state_handle);
460   ASSERT_EQ(0, device->volume_control_point_handle);
461   ASSERT_EQ(0, device->volume_flags_handle);
462   ASSERT_EQ(false, device->HasHandles());
463 }
464 
TEST_F(VolumeControlDeviceTest,test_enqueue_initial_requests)465 TEST_F(VolumeControlDeviceTest, test_enqueue_initial_requests) {
466   SetSampleDatabase1();
467 
468   tGATT_IF gatt_if = 0x0001;
469   std::vector<uint8_t> register_for_notification_data({0x01, 0x00});
470 
471   std::map<uint16_t, uint16_t> expected_to_read_write{
472       {0x0011, 0x0012} /* volume control state */,
473       {0x0062, 0x0063} /* volume offset state 1 */,
474       {0x0082, 0x0083} /* volume offset state 2 */};
475 
476   for (auto const& handle_pair : expected_to_read_write) {
477     EXPECT_CALL(gatt_queue, ReadCharacteristic(_, handle_pair.first, _, _));
478     EXPECT_CALL(gatt_queue, WriteDescriptor(_, handle_pair.second,
479                                             register_for_notification_data,
480                                             GATT_WRITE, _, _));
481     EXPECT_CALL(gatt_interface,
482                 RegisterForNotifications(gatt_if, _, handle_pair.first));
483   }
484 
485   auto chrc_read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
486                          uint16_t len, uint8_t* value, void* data) {};
487   auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status,
488                           uint16_t handle, uint16_t len, const uint8_t* value,
489                           void* data) {};
490   ASSERT_EQ(true, device->EnqueueInitialRequests(gatt_if, chrc_read_cb,
491                                                  cccd_write_cb));
492 };
493 
TEST_F(VolumeControlDeviceTest,test_device_ready)494 TEST_F(VolumeControlDeviceTest, test_device_ready) {
495   SetSampleDatabase1();
496 
497   // grab all the handles requested
498   std::vector<uint16_t> requested_handles;
499   ON_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _))
500       .WillByDefault(Invoke(
501           [&requested_handles](
502               uint16_t conn_id, uint16_t handle, std::vector<uint8_t> value,
503               tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
504               void* cb_data) -> void { requested_handles.push_back(handle); }));
505   ON_CALL(gatt_queue, ReadCharacteristic(_, _, _, _))
506       .WillByDefault(Invoke(
507           [&requested_handles](uint16_t conn_id, uint16_t handle,
508                                GATT_READ_OP_CB cb, void* cb_data) -> void {
509             requested_handles.push_back(handle);
510           }));
511 
512   auto chrc_read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
513                          uint16_t len, uint8_t* value, void* data) {};
514   auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status,
515                           uint16_t handle, uint16_t len, const uint8_t* value,
516                           void* data) {};
517   ASSERT_EQ(true, device->EnqueueInitialRequests(0x0001, chrc_read_cb,
518                                                  cccd_write_cb));
519   ASSERT_NE((size_t)0, requested_handles.size());
520 
521   // indicate non-pending requests
522   ASSERT_EQ(false, device->device_ready);
523   device->VerifyReady(0xffff);
524 
525   for (uint16_t handle : requested_handles) {
526     ASSERT_EQ(false, device->device_ready);
527     device->VerifyReady(handle);
528   }
529 
530   ASSERT_EQ(true, device->device_ready);
531 }
532 
TEST_F(VolumeControlDeviceTest,test_enqueue_remaining_requests)533 TEST_F(VolumeControlDeviceTest, test_enqueue_remaining_requests) {
534   SetSampleDatabase1();
535 
536   tGATT_IF gatt_if = 0x0001;
537   std::vector<uint8_t> register_for_notification_data({0x01, 0x00});
538 
539   std::vector<uint16_t> expected_to_read{
540       0x0016 /* volume flags */, 0x0065 /* audio location 1 */,
541       0x0069 /* audio output description 1 */, 0x0085 /* audio location 1 */,
542       0x008a /* audio output description 1 */};
543 
544   std::map<uint16_t, uint16_t> expected_to_write_value_ccc_handle_map{
545       {0x0085, 0x0086} /* audio location ccc 2 */,
546       {0x008a, 0x008b} /* audio output description ccc */
547   };
548 
549   for (uint16_t handle : expected_to_read) {
550     EXPECT_CALL(gatt_queue, ReadCharacteristic(_, handle, _, _));
551   }
552 
553   for (auto const& handle_pair : expected_to_write_value_ccc_handle_map) {
554     EXPECT_CALL(gatt_queue, WriteDescriptor(_, handle_pair.second,
555                                             register_for_notification_data,
556                                             GATT_WRITE, _, _));
557     EXPECT_CALL(gatt_interface,
558                 RegisterForNotifications(gatt_if, _, handle_pair.first));
559   }
560 
561   auto chrc_read_cb = [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
562                          uint16_t len, uint8_t* value, void* data) {};
563   auto cccd_write_cb = [](uint16_t conn_id, tGATT_STATUS status,
564                           uint16_t handle, uint16_t len, const uint8_t* value,
565                           void* data) {};
566   device->EnqueueRemainingRequests(gatt_if, chrc_read_cb, cccd_write_cb);
567 }
568 
TEST_F(VolumeControlDeviceTest,test_check_link_encrypted)569 TEST_F(VolumeControlDeviceTest, test_check_link_encrypted) {
570   ON_CALL(btm_interface, BTM_IsEncrypted(_, _))
571       .WillByDefault(DoAll(Return(true)));
572   ASSERT_EQ(true, device->IsEncryptionEnabled());
573 
574   ON_CALL(btm_interface, BTM_IsEncrypted(_, _))
575       .WillByDefault(DoAll(Return(false)));
576   ASSERT_NE(true, device->IsEncryptionEnabled());
577 }
578 
TEST_F(VolumeControlDeviceTest,test_control_point_operation)579 TEST_F(VolumeControlDeviceTest, test_control_point_operation) {
580   GATT_WRITE_OP_CB write_cb = [](uint16_t conn_id, tGATT_STATUS status,
581                                  uint16_t handle, uint16_t len,
582                                  const uint8_t* value, void* data) {};
583   SetSampleDatabase1();
584   device->change_counter = 0x01;
585   std::vector<uint8_t> expected_data({0x03, 0x01});
586   EXPECT_CALL(gatt_queue, WriteCharacteristic(_, 0x0014, expected_data,
587                                               GATT_WRITE, write_cb, nullptr));
588   device->ControlPointOperation(0x03, nullptr, write_cb, nullptr);
589 }
590 
TEST_F(VolumeControlDeviceTest,test_control_point_operation_arg)591 TEST_F(VolumeControlDeviceTest, test_control_point_operation_arg) {
592   GATT_WRITE_OP_CB write_cb = [](uint16_t conn_id, tGATT_STATUS status,
593                                  uint16_t handle, uint16_t len,
594                                  const uint8_t* value, void* data) {};
595   SetSampleDatabase1();
596   device->change_counter = 0x55;
597   std::vector<uint8_t> expected_data({0x01, 0x55, 0x02, 0x03});
598   EXPECT_CALL(gatt_queue, WriteCharacteristic(_, 0x0014, expected_data,
599                                               GATT_WRITE, write_cb, nullptr));
600   std::vector<uint8_t> arg({0x02, 0x03});
601   device->ControlPointOperation(0x01, &arg, write_cb, nullptr);
602 }
603 
TEST_F(VolumeControlDeviceTest,test_get_ext_audio_out_volume_offset)604 TEST_F(VolumeControlDeviceTest, test_get_ext_audio_out_volume_offset) {
605   GATT_READ_OP_CB read_cb = [](uint16_t conn_id, tGATT_STATUS status,
606                                uint16_t handle, uint16_t len, uint8_t* value,
607                                void* data) {};
608   SetSampleDatabase1();
609   EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0062, read_cb, nullptr));
610   device->GetExtAudioOutVolumeOffset(1, read_cb, nullptr);
611 }
612 
TEST_F(VolumeControlDeviceTest,test_get_ext_audio_out_location)613 TEST_F(VolumeControlDeviceTest, test_get_ext_audio_out_location) {
614   GATT_READ_OP_CB read_cb = [](uint16_t conn_id, tGATT_STATUS status,
615                                uint16_t handle, uint16_t len, uint8_t* value,
616                                void* data) {};
617   SetSampleDatabase1();
618   EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0085, read_cb, nullptr));
619   device->GetExtAudioOutLocation(2, read_cb, nullptr);
620 }
621 
TEST_F(VolumeControlDeviceTest,test_set_ext_audio_out_location)622 TEST_F(VolumeControlDeviceTest, test_set_ext_audio_out_location) {
623   SetSampleDatabase1();
624   std::vector<uint8_t> expected_data({0x44, 0x33, 0x22, 0x11});
625   EXPECT_CALL(gatt_queue,
626               WriteCharacteristic(_, 0x0085, expected_data, GATT_WRITE_NO_RSP,
627                                   nullptr, nullptr));
628   device->SetExtAudioOutLocation(2, 0x11223344);
629 }
630 
TEST_F(VolumeControlDeviceTest,test_set_ext_audio_out_location_non_writable)631 TEST_F(VolumeControlDeviceTest, test_set_ext_audio_out_location_non_writable) {
632   SetSampleDatabase1();
633   EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0);
634   device->SetExtAudioOutLocation(1, 0x11223344);
635 }
636 
TEST_F(VolumeControlDeviceTest,test_get_ext_audio_out_description)637 TEST_F(VolumeControlDeviceTest, test_get_ext_audio_out_description) {
638   GATT_READ_OP_CB read_cb = [](uint16_t conn_id, tGATT_STATUS status,
639                                uint16_t handle, uint16_t len, uint8_t* value,
640                                void* data) {};
641   SetSampleDatabase1();
642   EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x008a, read_cb, nullptr));
643   device->GetExtAudioOutDescription(2, read_cb, nullptr);
644 }
645 
TEST_F(VolumeControlDeviceTest,test_set_ext_audio_out_description)646 TEST_F(VolumeControlDeviceTest, test_set_ext_audio_out_description) {
647   SetSampleDatabase1();
648   std::string descr = "right front";
649   std::vector<uint8_t> expected_data(descr.begin(), descr.end());
650   EXPECT_CALL(gatt_queue,
651               WriteCharacteristic(_, 0x008a, expected_data, GATT_WRITE_NO_RSP,
652                                   nullptr, nullptr));
653   device->SetExtAudioOutDescription(2, descr);
654 }
655 
TEST_F(VolumeControlDeviceTest,test_set_ext_audio_out_description_non_writable)656 TEST_F(VolumeControlDeviceTest,
657        test_set_ext_audio_out_description_non_writable) {
658   SetSampleDatabase1();
659   std::string descr = "left front";
660   EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0);
661   device->SetExtAudioOutDescription(1, descr);
662 }
663 
TEST_F(VolumeControlDeviceTest,test_ext_audio_out_control_point_operation)664 TEST_F(VolumeControlDeviceTest, test_ext_audio_out_control_point_operation) {
665   GATT_WRITE_OP_CB write_cb = [](uint16_t conn_id, tGATT_STATUS status,
666                                  uint16_t handle, uint16_t len,
667                                  const uint8_t* value, void* data) {};
668   SetSampleDatabase1();
669   VolumeOffset* offset = device->audio_offsets.FindById(1);
670   ASSERT_NE(nullptr, offset);
671   offset->change_counter = 0x09;
672   std::vector<uint8_t> expected_data({0x0b, 0x09});
673   EXPECT_CALL(gatt_queue, WriteCharacteristic(_, 0x0067, expected_data,
674                                               GATT_WRITE, write_cb, nullptr));
675   device->ExtAudioOutControlPointOperation(1, 0x0b, nullptr, write_cb, nullptr);
676 }
677 
TEST_F(VolumeControlDeviceTest,test_ext_audio_out_control_point_operation_arg)678 TEST_F(VolumeControlDeviceTest,
679        test_ext_audio_out_control_point_operation_arg) {
680   GATT_WRITE_OP_CB write_cb = [](uint16_t conn_id, tGATT_STATUS status,
681                                  uint16_t handle, uint16_t len,
682                                  const uint8_t* value, void* data) {};
683   SetSampleDatabase1();
684   VolumeOffset* offset = device->audio_offsets.FindById(1);
685   ASSERT_NE(nullptr, offset);
686   offset->change_counter = 0x09;
687   std::vector<uint8_t> expected_data({0x0b, 0x09, 0x01, 0x02, 0x03, 0x04});
688   std::vector<uint8_t> arg({0x01, 0x02, 0x03, 0x04});
689   EXPECT_CALL(gatt_queue, WriteCharacteristic(_, 0x0067, expected_data,
690                                               GATT_WRITE, write_cb, nullptr));
691   device->ExtAudioOutControlPointOperation(1, 0x0b, &arg, write_cb, nullptr);
692 }
693 
694 }  // namespace internal
695 }  // namespace vc
696 }  // namespace bluetooth
697