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 "bta/vc/devices.h"
19
20 #include <com_android_bluetooth_flags.h>
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include <log/log.h>
24
25 #include <list>
26 #include <map>
27
28 #include "bta/test/common/bta_gatt_api_mock.h"
29 #include "bta/test/common/bta_gatt_queue_mock.h"
30 #include "bta/test/common/btm_api_mock.h"
31 #include "gatt/database_builder.h"
32 #include "stack/include/bt_uuid16.h"
33 #include "types/bluetooth/uuid.h"
34 #include "types/raw_address.h"
35
36 // TODO(b/369381361) Enfore -Wmissing-prototypes
37 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
38
39 namespace bluetooth {
40 namespace vc {
41 namespace internal {
42
43 using ::testing::_;
44 using ::testing::DoAll;
45 using ::testing::Invoke;
46 using ::testing::Mock;
47 using ::testing::NiceMock;
48 using ::testing::Return;
49 using ::testing::SaveArg;
50 using ::testing::SetArgPointee;
51 using ::testing::Test;
52
GetTestAddress(int index)53 RawAddress GetTestAddress(int index) {
54 EXPECT_LT(index, UINT8_MAX);
55 RawAddress result = {{0xC0, 0xDE, 0xC0, 0xDE, 0x00, static_cast<uint8_t>(index)}};
56 return result;
57 }
58
59 class VolumeControlDevicesTest : public ::testing::Test {
60 protected:
SetUp()61 void SetUp() override {
62 com::android::bluetooth::flags::provider_->leaudio_add_aics_support(true);
63 __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE);
64 devices_ = new VolumeControlDevices();
65 gatt::SetMockBtaGattInterface(&gatt_interface);
66 gatt::SetMockBtaGattQueue(&gatt_queue);
67 }
68
TearDown()69 void TearDown() override {
70 com::android::bluetooth::flags::provider_->reset_flags();
71
72 gatt::SetMockBtaGattQueue(nullptr);
73 gatt::SetMockBtaGattInterface(nullptr);
74 delete devices_;
75 }
76
77 VolumeControlDevices* devices_ = nullptr;
78 NiceMock<gatt::MockBtaGattInterface> gatt_interface;
79 NiceMock<gatt::MockBtaGattQueue> gatt_queue;
80 };
81
TEST_F(VolumeControlDevicesTest,test_add)82 TEST_F(VolumeControlDevicesTest, test_add) {
83 RawAddress test_address_0 = GetTestAddress(0);
84 ASSERT_EQ((size_t)0, devices_->Size());
85 devices_->Add(test_address_0, true);
86 ASSERT_EQ((size_t)1, devices_->Size());
87 }
88
TEST_F(VolumeControlDevicesTest,test_add_twice)89 TEST_F(VolumeControlDevicesTest, test_add_twice) {
90 RawAddress test_address_0 = GetTestAddress(0);
91 ASSERT_EQ((size_t)0, devices_->Size());
92 devices_->Add(test_address_0, true);
93 devices_->Add(test_address_0, true);
94 ASSERT_EQ((size_t)1, devices_->Size());
95 }
96
TEST_F(VolumeControlDevicesTest,test_remove)97 TEST_F(VolumeControlDevicesTest, test_remove) {
98 RawAddress test_address_0 = GetTestAddress(0);
99 RawAddress test_address_1 = GetTestAddress(1);
100 devices_->Add(test_address_0, true);
101 devices_->Add(test_address_1, true);
102 ASSERT_EQ((size_t)2, devices_->Size());
103 devices_->Remove(test_address_0);
104 ASSERT_EQ((size_t)1, devices_->Size());
105 }
106
TEST_F(VolumeControlDevicesTest,test_clear)107 TEST_F(VolumeControlDevicesTest, test_clear) {
108 RawAddress test_address_0 = GetTestAddress(0);
109 ASSERT_EQ((size_t)0, devices_->Size());
110 devices_->Add(test_address_0, true);
111 ASSERT_EQ((size_t)1, devices_->Size());
112 devices_->Clear();
113 ASSERT_EQ((size_t)0, devices_->Size());
114 }
115
TEST_F(VolumeControlDevicesTest,test_find_by_address)116 TEST_F(VolumeControlDevicesTest, test_find_by_address) {
117 RawAddress test_address_0 = GetTestAddress(0);
118 RawAddress test_address_1 = GetTestAddress(1);
119 RawAddress test_address_2 = GetTestAddress(2);
120 devices_->Add(test_address_0, true);
121 devices_->Add(test_address_1, false);
122 devices_->Add(test_address_2, true);
123 VolumeControlDevice* device = devices_->FindByAddress(test_address_1);
124 ASSERT_NE(nullptr, device);
125 ASSERT_EQ(test_address_1, device->address);
126 }
127
TEST_F(VolumeControlDevicesTest,test_find_by_conn_id)128 TEST_F(VolumeControlDevicesTest, test_find_by_conn_id) {
129 RawAddress test_address_0 = GetTestAddress(0);
130 devices_->Add(test_address_0, true);
131 VolumeControlDevice* test_device = devices_->FindByAddress(test_address_0);
132 test_device->connection_id = 0x0005;
133 ASSERT_NE(nullptr, devices_->FindByConnId(test_device->connection_id));
134 }
135
TEST_F(VolumeControlDevicesTest,test_disconnect)136 TEST_F(VolumeControlDevicesTest, test_disconnect) {
137 RawAddress test_address_0 = GetTestAddress(0);
138 RawAddress test_address_1 = GetTestAddress(1);
139 devices_->Add(test_address_0, true);
140 devices_->Add(test_address_1, true);
141 VolumeControlDevice* test_device_0 = devices_->FindByAddress(test_address_0);
142 test_device_0->connection_id = 0x0005;
143 tGATT_IF gatt_if = 8;
144 EXPECT_CALL(gatt_interface, Close(test_device_0->connection_id));
145 devices_->Disconnect(gatt_if);
146 }
147
TEST_F(VolumeControlDevicesTest,test_control_point_operation)148 TEST_F(VolumeControlDevicesTest, test_control_point_operation) {
149 uint8_t opcode = 50;
150 std::vector<RawAddress> devices;
151
152 for (int i = 5; i > 0; i--) {
153 RawAddress test_address = GetTestAddress(i);
154 devices.push_back(test_address);
155 uint8_t change_counter = 10 * i;
156 uint16_t control_point_handle = 0x0020 + i;
157 uint16_t connection_id = i;
158 devices_->Add(test_address, true);
159 VolumeControlDevice* device = devices_->FindByAddress(test_address);
160 device->connection_id = connection_id;
161 device->change_counter = change_counter;
162 device->volume_control_point_handle = control_point_handle;
163 std::vector<uint8_t> data_expected({opcode, change_counter});
164
165 EXPECT_CALL(gatt_queue, WriteCharacteristic(connection_id, control_point_handle, data_expected,
166 GATT_WRITE, _, _));
167 }
168
169 const std::vector<uint8_t>* arg = nullptr;
170 GATT_WRITE_OP_CB cb = nullptr;
171 void* cb_data = nullptr;
172 devices_->ControlPointOperation(devices, opcode, arg, cb, cb_data);
173 }
174
TEST_F(VolumeControlDevicesTest,test_control_point_operation_args)175 TEST_F(VolumeControlDevicesTest, test_control_point_operation_args) {
176 uint8_t opcode = 60;
177 uint8_t arg_1 = 0x02;
178 uint8_t arg_2 = 0x05;
179 std::vector<RawAddress> devices;
180
181 for (int i = 5; i > 0; i--) {
182 RawAddress test_address = GetTestAddress(i);
183 devices.push_back(test_address);
184 uint8_t change_counter = 10 * i;
185 uint16_t control_point_handle = 0x0020 + i;
186 uint16_t connection_id = i;
187 devices_->Add(test_address, true);
188 VolumeControlDevice* device = devices_->FindByAddress(test_address);
189 device->connection_id = connection_id;
190 device->change_counter = change_counter;
191 device->volume_control_point_handle = control_point_handle;
192 std::vector<uint8_t> data_expected({opcode, change_counter, arg_1, arg_2});
193
194 EXPECT_CALL(gatt_queue, WriteCharacteristic(connection_id, control_point_handle, data_expected,
195 GATT_WRITE, _, _));
196 }
197
198 std::vector<uint8_t> arg({arg_1, arg_2});
199 GATT_WRITE_OP_CB cb = nullptr;
200 void* cb_data = nullptr;
201 devices_->ControlPointOperation(devices, opcode, &arg, cb, cb_data);
202 }
203
TEST_F(VolumeControlDevicesTest,test_control_point_skip_not_connected)204 TEST_F(VolumeControlDevicesTest, test_control_point_skip_not_connected) {
205 RawAddress test_address = GetTestAddress(1);
206 devices_->Add(test_address, true);
207 VolumeControlDevice* device = devices_->FindByAddress(test_address);
208 device->connection_id = GATT_INVALID_CONN_ID;
209 uint16_t control_point_handle = 0x0020;
210 device->volume_control_point_handle = control_point_handle;
211
212 EXPECT_CALL(gatt_queue, WriteCharacteristic(_, control_point_handle, _, _, _, _)).Times(0);
213
214 uint8_t opcode = 5;
215 std::vector<RawAddress> devices = {test_address};
216 const std::vector<uint8_t>* arg = nullptr;
217 GATT_WRITE_OP_CB cb = nullptr;
218 void* cb_data = nullptr;
219 devices_->ControlPointOperation(devices, opcode, arg, cb, cb_data);
220 }
221
222 class VolumeControlDeviceTest : public ::testing::Test {
223 protected:
SetUp()224 void SetUp() override {
225 com::android::bluetooth::flags::provider_->leaudio_add_aics_support(true);
226 __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE);
227 device = new VolumeControlDevice(GetTestAddress(1), true);
228 gatt::SetMockBtaGattInterface(&gatt_interface);
229 gatt::SetMockBtaGattQueue(&gatt_queue);
230 bluetooth::manager::SetMockBtmInterface(&btm_interface);
231
232 ON_CALL(gatt_interface, GetCharacteristic(_, _))
233 .WillByDefault(Invoke(
234 [&](uint16_t /*conn_id*/, uint16_t handle) -> const gatt::Characteristic* {
235 for (auto const& service : services) {
236 for (auto const& characteristic : service.characteristics) {
237 if (characteristic.value_handle == handle) {
238 return &characteristic;
239 }
240 }
241 }
242
243 return nullptr;
244 }));
245
246 ON_CALL(gatt_interface, GetOwningService(_, _))
247 .WillByDefault(
248 Invoke([&](uint16_t /*conn_id*/, uint16_t handle) -> const gatt::Service* {
249 for (auto const& service : services) {
250 if (service.handle <= handle && service.end_handle >= handle) {
251 return &service;
252 }
253 }
254
255 return nullptr;
256 }));
257
258 ON_CALL(gatt_interface, GetServices(_)).WillByDefault(Return(&services));
259
260 ON_CALL(gatt_interface, RegisterForNotifications(_, _, _))
261 .WillByDefault(DoAll(Return(GATT_SUCCESS)));
262 }
263
TearDown()264 void TearDown() override {
265 com::android::bluetooth::flags::provider_->reset_flags();
266 bluetooth::manager::SetMockBtmInterface(nullptr);
267 gatt::SetMockBtaGattQueue(nullptr);
268 gatt::SetMockBtaGattInterface(nullptr);
269 delete device;
270 }
271
272 /* sample database 1xVCS, 2xAICS, 2xVOCS */
SetSampleDatabase1(void)273 void SetSampleDatabase1(void) {
274 gatt::DatabaseBuilder builder;
275 builder.AddService(0x0001, 0x0017, kVolumeControlUuid, true);
276 builder.AddIncludedService(0x0002, kVolumeAudioInputUuid, 0x0020, 0x002e);
277 builder.AddIncludedService(0x0003, kVolumeAudioInputUuid, 0x0040, 0x004f);
278 builder.AddIncludedService(0x0004, kVolumeOffsetUuid, 0x0060, 0x0069);
279 builder.AddIncludedService(0x0005, kVolumeOffsetUuid, 0x0080, 0x008b);
280 builder.AddCharacteristic(0x0010, 0x0011, kVolumeControlStateUuid,
281 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
282 builder.AddDescriptor(0x0012, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
283 builder.AddCharacteristic(0x0013, 0x0014, kVolumeControlPointUuid, GATT_CHAR_PROP_BIT_WRITE);
284 builder.AddCharacteristic(0x0015, 0x0016, kVolumeFlagsUuid,
285 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
286 builder.AddDescriptor(0x0017, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
287
288 // First AICS
289 builder.AddService(0x0020, 0x002e, kVolumeAudioInputUuid, false);
290 builder.AddCharacteristic(0x0021, 0x0022, kVolumeAudioInputStateUuid, GATT_CHAR_PROP_BIT_READ);
291 builder.AddDescriptor(0x0023, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
292 builder.AddCharacteristic(0x0024, 0x0025, kVolumeAudioInputGainSettingPropertiesUuid,
293 GATT_CHAR_PROP_BIT_READ);
294 builder.AddCharacteristic(0x0026, 0x0027, kVolumeAudioInputTypeUuid, GATT_CHAR_PROP_BIT_READ);
295 builder.AddCharacteristic(0x0028, 0x0029, kVolumeAudioInputStatusUuid,
296 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
297 builder.AddDescriptor(0x002a, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
298 builder.AddCharacteristic(0x002b, 0x002c, kVolumeAudioInputControlPointUuid,
299 GATT_CHAR_PROP_BIT_WRITE);
300 builder.AddCharacteristic(0x002d, 0x002e, kVolumeAudioInputDescriptionUuid,
301 GATT_CHAR_PROP_BIT_READ);
302
303 // Second AICS
304 builder.AddService(0x0040, 0x004f, kVolumeAudioInputUuid, false);
305 builder.AddCharacteristic(0x0041, 0x0042, kVolumeAudioInputStateUuid,
306 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
307 builder.AddDescriptor(0x0043, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
308 builder.AddCharacteristic(0x0044, 0x0045, kVolumeAudioInputGainSettingPropertiesUuid,
309 GATT_CHAR_PROP_BIT_READ);
310 builder.AddCharacteristic(0x0046, 0x0047, kVolumeAudioInputTypeUuid, GATT_CHAR_PROP_BIT_READ);
311 builder.AddCharacteristic(0x0048, 0x0049, kVolumeAudioInputStatusUuid,
312 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
313 builder.AddDescriptor(0x004a, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
314 builder.AddCharacteristic(0x004b, 0x004c, kVolumeAudioInputControlPointUuid,
315 GATT_CHAR_PROP_BIT_WRITE);
316 builder.AddCharacteristic(
317 0x004d, 0x004e, kVolumeAudioInputDescriptionUuid,
318 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_WRITE_NR | GATT_CHAR_PROP_BIT_NOTIFY);
319 builder.AddDescriptor(0x004f, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
320
321 // First VOCS
322 builder.AddService(0x0060, 0x0069, kVolumeOffsetUuid, false);
323 builder.AddCharacteristic(0x0061, 0x0062, kVolumeOffsetStateUuid,
324 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
325 builder.AddDescriptor(0x0063, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
326 builder.AddCharacteristic(0x0064, 0x0065, kVolumeOffsetLocationUuid, GATT_CHAR_PROP_BIT_READ);
327 builder.AddCharacteristic(0x0066, 0x0067, kVolumeOffsetControlPointUuid,
328 GATT_CHAR_PROP_BIT_WRITE);
329 builder.AddCharacteristic(0x0068, 0x0069, kVolumeOffsetOutputDescriptionUuid,
330 GATT_CHAR_PROP_BIT_READ);
331
332 // Second VOCS
333 builder.AddService(0x0080, 0x008b, kVolumeOffsetUuid, false);
334 builder.AddCharacteristic(0x0081, 0x0082, kVolumeOffsetStateUuid,
335 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
336 builder.AddDescriptor(0x0083, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
337 builder.AddCharacteristic(
338 0x0084, 0x0085, kVolumeOffsetLocationUuid,
339 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_WRITE_NR | GATT_CHAR_PROP_BIT_NOTIFY);
340 builder.AddDescriptor(0x0086, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
341 builder.AddCharacteristic(0x0087, 0x0088, kVolumeOffsetControlPointUuid,
342 GATT_CHAR_PROP_BIT_WRITE);
343 builder.AddCharacteristic(
344 0x0089, 0x008a, kVolumeOffsetOutputDescriptionUuid,
345 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_WRITE_NR | GATT_CHAR_PROP_BIT_NOTIFY);
346 builder.AddDescriptor(0x008b, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
347 builder.AddService(0x00a0, 0x00a3, Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER), true);
348 builder.AddCharacteristic(0x00a1, 0x00a2, Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD),
349 GATT_CHAR_PROP_BIT_NOTIFY);
350 builder.AddDescriptor(0x00a3, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
351 services = builder.Build().Services();
352 ASSERT_EQ(true, device->UpdateHandles());
353 }
354
355 /* sample database no VCS */
SetSampleDatabase2(void)356 void SetSampleDatabase2(void) {
357 gatt::DatabaseBuilder builder;
358 builder.AddService(0x0001, 0x0003, Uuid::From16Bit(0x1800), true);
359 builder.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2a00), GATT_CHAR_PROP_BIT_READ);
360 services = builder.Build().Services();
361 ASSERT_EQ(false, device->UpdateHandles());
362 }
363
364 VolumeControlDevice* device = nullptr;
365 NiceMock<gatt::MockBtaGattInterface> gatt_interface;
366 NiceMock<gatt::MockBtaGattQueue> gatt_queue;
367 NiceMock<bluetooth::manager::MockBtmInterface> btm_interface;
368 std::list<gatt::Service> services;
369 };
370
TEST_F(VolumeControlDeviceTest,test_service_volume_control_not_found)371 TEST_F(VolumeControlDeviceTest, test_service_volume_control_not_found) {
372 SetSampleDatabase2();
373 ASSERT_EQ(false, device->HasHandles());
374 }
375
TEST_F(VolumeControlDeviceTest,test_service_aics_incomplete)376 TEST_F(VolumeControlDeviceTest, test_service_aics_incomplete) {
377 gatt::DatabaseBuilder builder;
378 builder.AddService(0x0001, 0x000a, kVolumeControlUuid, true);
379 builder.AddIncludedService(0x0002, kVolumeAudioInputUuid, 0x000b, 0x0018);
380 builder.AddCharacteristic(0x0003, 0x0004, kVolumeControlStateUuid,
381 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
382 builder.AddDescriptor(0x0005, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
383 builder.AddCharacteristic(0x0006, 0x0007, kVolumeControlPointUuid, GATT_CHAR_PROP_BIT_WRITE);
384 builder.AddCharacteristic(0x0008, 0x0009, kVolumeFlagsUuid,
385 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
386 builder.AddDescriptor(0x000a, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
387 builder.AddService(0x000b, 0x0018, kVolumeAudioInputUuid, false);
388 builder.AddCharacteristic(0x000c, 0x000d, kVolumeAudioInputStateUuid,
389 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
390 builder.AddDescriptor(0x000e, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
391 builder.AddCharacteristic(0x000f, 0x0010, kVolumeAudioInputGainSettingPropertiesUuid,
392 GATT_CHAR_PROP_BIT_READ);
393 builder.AddCharacteristic(0x0011, 0x0012, kVolumeAudioInputTypeUuid, GATT_CHAR_PROP_BIT_READ);
394 builder.AddCharacteristic(0x0013, 0x0014, kVolumeAudioInputStatusUuid,
395 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
396 builder.AddDescriptor(0x0015, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
397 /* no Audio Input Control Point characteristic */
398 builder.AddCharacteristic(0x0016, 0x0017, kVolumeAudioInputDescriptionUuid,
399 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
400 builder.AddDescriptor(0x0018, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
401 services = builder.Build().Services();
402 ASSERT_EQ(true, device->UpdateHandles());
403 ASSERT_EQ((size_t)0, device->audio_inputs.Size());
404 ASSERT_EQ(0x0004, device->volume_state_handle);
405 ASSERT_EQ(0x0005, device->volume_state_ccc_handle);
406 ASSERT_EQ(0x0007, device->volume_control_point_handle);
407 ASSERT_EQ(0x0009, device->volume_flags_handle);
408 ASSERT_EQ(0x000a, device->volume_flags_ccc_handle);
409 ASSERT_EQ(true, device->HasHandles());
410 }
411
TEST_F(VolumeControlDeviceTest,test_service_aics_found)412 TEST_F(VolumeControlDeviceTest, test_service_aics_found) {
413 gatt::DatabaseBuilder builder;
414 builder.AddService(0x0001, 0x000a, kVolumeControlUuid, true);
415 builder.AddIncludedService(0x0002, kVolumeAudioInputUuid, 0x000b, 0x001a);
416 builder.AddCharacteristic(0x0003, 0x0004, kVolumeControlStateUuid,
417 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
418 builder.AddDescriptor(0x0005, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
419 builder.AddCharacteristic(0x0006, 0x0007, kVolumeControlPointUuid, GATT_CHAR_PROP_BIT_WRITE);
420 builder.AddCharacteristic(0x0008, 0x0009, kVolumeFlagsUuid,
421 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
422 builder.AddDescriptor(0x000a, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
423 builder.AddService(0x000b, 0x001a, kVolumeAudioInputUuid, false);
424 builder.AddCharacteristic(0x000c, 0x000d, kVolumeAudioInputStateUuid,
425 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
426 builder.AddDescriptor(0x000e, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
427 builder.AddCharacteristic(0x000f, 0x0010, kVolumeAudioInputGainSettingPropertiesUuid,
428 GATT_CHAR_PROP_BIT_READ);
429 builder.AddCharacteristic(0x0011, 0x0012, kVolumeAudioInputTypeUuid, GATT_CHAR_PROP_BIT_READ);
430 builder.AddCharacteristic(0x0013, 0x0014, kVolumeAudioInputStatusUuid,
431 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
432 builder.AddDescriptor(0x0015, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
433 builder.AddCharacteristic(0x0016, 0x0017, kVolumeAudioInputControlPointUuid,
434 GATT_CHAR_PROP_BIT_WRITE);
435 builder.AddCharacteristic(0x0018, 0x0019, kVolumeAudioInputDescriptionUuid,
436 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
437 builder.AddDescriptor(0x001a, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
438 services = builder.Build().Services();
439 ASSERT_EQ(true, device->UpdateHandles());
440 ASSERT_EQ((size_t)1, device->audio_inputs.Size());
441 VolumeAudioInput* input = device->audio_inputs.FindByServiceHandle(0x000b);
442 ASSERT_NE(nullptr, input);
443 ASSERT_EQ(0x000d, input->state_handle);
444 ASSERT_EQ(0x000e, input->state_ccc_handle);
445 ASSERT_EQ(0x0010, input->gain_setting_handle);
446 ASSERT_EQ(0x0012, input->type_handle);
447 ASSERT_EQ(0x0014, input->status_handle);
448 ASSERT_EQ(0x0015, input->status_ccc_handle);
449 ASSERT_EQ(0x0017, input->control_point_handle);
450 ASSERT_EQ(0x0019, input->description_handle);
451 ASSERT_EQ(0x001a, input->description_ccc_handle);
452 ASSERT_EQ(true, device->HasHandles());
453 }
454
TEST_F(VolumeControlDeviceTest,test_service_volume_control_incomplete)455 TEST_F(VolumeControlDeviceTest, test_service_volume_control_incomplete) {
456 gatt::DatabaseBuilder builder;
457 builder.AddService(0x0001, 0x0006, kVolumeControlUuid, true);
458 builder.AddCharacteristic(0x0002, 0x0003, kVolumeControlStateUuid,
459 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
460 builder.AddDescriptor(0x0004, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
461 builder.AddCharacteristic(0x0005, 0x0006, kVolumeControlPointUuid, GATT_CHAR_PROP_BIT_WRITE);
462 /* no Volume Control Flags characteristic */
463 services = builder.Build().Services();
464 ASSERT_EQ(false, device->UpdateHandles());
465 ASSERT_EQ(0x0000, device->volume_state_handle);
466 ASSERT_EQ(0x0000, device->volume_state_ccc_handle);
467 ASSERT_EQ(0x0000, device->volume_control_point_handle);
468 ASSERT_EQ(0x0000, device->volume_flags_handle);
469 ASSERT_EQ(0x0000, device->volume_flags_ccc_handle);
470 ASSERT_EQ(false, device->HasHandles());
471 }
472
TEST_F(VolumeControlDeviceTest,test_service_vocs_incomplete)473 TEST_F(VolumeControlDeviceTest, test_service_vocs_incomplete) {
474 gatt::DatabaseBuilder builder;
475 builder.AddService(0x0001, 0x000a, kVolumeControlUuid, true);
476 builder.AddIncludedService(0x0002, kVolumeOffsetUuid, 0x000b, 0x0013);
477 builder.AddCharacteristic(0x0003, 0x0004, kVolumeControlStateUuid,
478 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
479 builder.AddDescriptor(0x0005, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
480 builder.AddCharacteristic(0x0006, 0x0007, kVolumeControlPointUuid, GATT_CHAR_PROP_BIT_WRITE);
481 builder.AddCharacteristic(0x0008, 0x0009, kVolumeFlagsUuid,
482 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
483 builder.AddDescriptor(0x000a, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
484 builder.AddService(0x000b, 0x0013, kVolumeOffsetUuid, false);
485 builder.AddCharacteristic(0x000c, 0x000d, kVolumeOffsetStateUuid,
486 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
487 builder.AddDescriptor(0x000e, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
488 builder.AddCharacteristic(0x000f, 0x0010, kVolumeOffsetLocationUuid,
489 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
490 builder.AddDescriptor(0x0011, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
491 builder.AddCharacteristic(0x0012, 0x0013, kVolumeOffsetControlPointUuid,
492 GATT_CHAR_PROP_BIT_WRITE);
493 /* no Audio Output Description characteristic */
494 services = builder.Build().Services();
495 ASSERT_EQ(true, device->UpdateHandles());
496 ASSERT_EQ((size_t)0, device->audio_offsets.Size());
497 ASSERT_EQ(0x0004, device->volume_state_handle);
498 ASSERT_EQ(0x0005, device->volume_state_ccc_handle);
499 ASSERT_EQ(0x0007, device->volume_control_point_handle);
500 ASSERT_EQ(0x0009, device->volume_flags_handle);
501 ASSERT_EQ(0x000a, device->volume_flags_ccc_handle);
502 ASSERT_EQ(true, device->HasHandles());
503 }
504
TEST_F(VolumeControlDeviceTest,test_service_vocs_found)505 TEST_F(VolumeControlDeviceTest, test_service_vocs_found) {
506 gatt::DatabaseBuilder builder;
507 builder.AddService(0x0001, 0x000a, kVolumeControlUuid, true);
508 builder.AddIncludedService(0x0002, kVolumeOffsetUuid, 0x000b, 0x0015);
509 builder.AddCharacteristic(0x0003, 0x0004, kVolumeControlStateUuid,
510 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
511 builder.AddDescriptor(0x0005, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
512 builder.AddCharacteristic(0x0006, 0x0007, kVolumeControlPointUuid, GATT_CHAR_PROP_BIT_WRITE);
513 builder.AddCharacteristic(0x0008, 0x0009, kVolumeFlagsUuid,
514 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
515 builder.AddDescriptor(0x000a, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
516 builder.AddService(0x000b, 0x0015, kVolumeOffsetUuid, false);
517 builder.AddCharacteristic(0x000c, 0x000d, kVolumeOffsetStateUuid,
518 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
519 builder.AddDescriptor(0x000e, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
520 builder.AddCharacteristic(0x000f, 0x0010, kVolumeOffsetLocationUuid,
521 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
522 builder.AddDescriptor(0x0011, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
523 builder.AddCharacteristic(0x0012, 0x0013, kVolumeOffsetControlPointUuid,
524 GATT_CHAR_PROP_BIT_WRITE);
525 builder.AddCharacteristic(0x0014, 0x0015, kVolumeOffsetOutputDescriptionUuid,
526 GATT_CHAR_PROP_BIT_READ);
527 services = builder.Build().Services();
528 ASSERT_EQ(true, device->UpdateHandles());
529 ASSERT_EQ((size_t)1, device->audio_offsets.Size());
530 VolumeOffset* offset = device->audio_offsets.FindByServiceHandle(0x000b);
531 ASSERT_NE(nullptr, offset);
532 ASSERT_EQ(0x000d, offset->state_handle);
533 ASSERT_EQ(0x000e, offset->state_ccc_handle);
534 ASSERT_EQ(0x0010, offset->audio_location_handle);
535 ASSERT_EQ(0x0011, offset->audio_location_ccc_handle);
536 ASSERT_EQ(0x0013, offset->control_point_handle);
537 ASSERT_EQ(0x0015, offset->audio_descr_handle);
538 ASSERT_EQ(0x0000, offset->audio_descr_ccc_handle);
539 ASSERT_EQ(true, device->HasHandles());
540 }
541
TEST_F(VolumeControlDeviceTest,test_multiple_services_found)542 TEST_F(VolumeControlDeviceTest, test_multiple_services_found) {
543 SetSampleDatabase1();
544 ASSERT_EQ((size_t)2, device->audio_offsets.Size());
545 ASSERT_EQ((size_t)2, device->audio_inputs.Size());
546 VolumeAudioInput* input_1 = device->audio_inputs.FindById(0);
547 VolumeAudioInput* input_2 = device->audio_inputs.FindById(1);
548 ASSERT_NE(nullptr, input_1);
549 ASSERT_NE(nullptr, input_2);
550 ASSERT_NE(input_1->service_handle, input_2->service_handle);
551
552 VolumeOffset* offset_1 = device->audio_offsets.FindById(1);
553 VolumeOffset* offset_2 = device->audio_offsets.FindById(2);
554 ASSERT_NE(nullptr, offset_1);
555 ASSERT_NE(nullptr, offset_2);
556 ASSERT_NE(offset_1->service_handle, offset_2->service_handle);
557 }
558
TEST_F(VolumeControlDeviceTest,test_services_changed)559 TEST_F(VolumeControlDeviceTest, test_services_changed) {
560 SetSampleDatabase1();
561 ASSERT_NE((size_t)0, device->audio_offsets.Size());
562 ASSERT_NE((size_t)0, device->audio_inputs.Size());
563 ASSERT_NE(0, device->volume_state_handle);
564 ASSERT_NE(0, device->volume_control_point_handle);
565 ASSERT_NE(0, device->volume_flags_handle);
566 ASSERT_EQ(true, device->HasHandles());
567 SetSampleDatabase2();
568 ASSERT_EQ((size_t)0, device->audio_offsets.Size());
569 ASSERT_EQ((size_t)0, device->audio_inputs.Size());
570 ASSERT_EQ(0, device->volume_state_handle);
571 ASSERT_EQ(0, device->volume_control_point_handle);
572 ASSERT_EQ(0, device->volume_flags_handle);
573 ASSERT_EQ(false, device->HasHandles());
574 }
575
TEST_F(VolumeControlDeviceTest,test_enqueue_initial_requests)576 TEST_F(VolumeControlDeviceTest, test_enqueue_initial_requests) {
577 SetSampleDatabase1();
578
579 tGATT_IF gatt_if = 0x0001;
580 std::vector<uint8_t> register_for_notification_data({0x01, 0x00});
581
582 std::map<uint16_t, uint16_t> expected_subscriptions{
583 {0x0011, 0x0012} /* volume control state */,
584 {0x0016, 0x0017} /* volume control flags */,
585 {0x0022, 0x0023} /* audio input state 1 */,
586 {0x0029, 0x002a} /* audio input status 1 */,
587 {0x0042, 0x0043} /* audio input state 2 */,
588 {0x0049, 0x004a} /* audio input status 2 */,
589 {0x004e, 0x004f} /* audio input descriptor 2 */,
590 {0x0062, 0x0063} /* volume offset state 1 */,
591 {0x0082, 0x0083} /* volume offset state 2 */,
592 {0x0085, 0x0086} /* volume offset location 2 */,
593 {0x008a, 0x008b} /* volume offset description 2 */};
594
595 // Expected read for state and flags Volume State
596 EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0011, _, _));
597 EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0016, _, _));
598
599 for (auto const& handle_pair : expected_subscriptions) {
600 EXPECT_CALL(gatt_queue, WriteDescriptor(_, handle_pair.second, register_for_notification_data,
601 GATT_WRITE, _, _));
602 EXPECT_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, handle_pair.first));
603 }
604
605 auto chrc_read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
606 uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
607 auto cccd_write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
608 uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {};
609 ASSERT_EQ(true, device->EnqueueInitialRequests(gatt_if, chrc_read_cb, cccd_write_cb));
610 Mock::VerifyAndClearExpectations(&gatt_queue);
611 Mock::VerifyAndClearExpectations(&gatt_interface);
612 }
613
TEST_F(VolumeControlDeviceTest,test_device_ready)614 TEST_F(VolumeControlDeviceTest, test_device_ready) {
615 SetSampleDatabase1();
616
617 // grab all the handles requested
618 std::vector<uint16_t> requested_handles;
619 ON_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _))
620 .WillByDefault(Invoke(
621 [&requested_handles](
622 uint16_t /*conn_id*/, uint16_t handle, std::vector<uint8_t> /*value*/,
623 tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB /*cb*/,
624 void* /*cb_data*/) -> void { requested_handles.push_back(handle); }));
625 ON_CALL(gatt_queue, ReadCharacteristic(_, _, _, _))
626 .WillByDefault(
627 Invoke([&requested_handles](uint16_t /*conn_id*/, uint16_t handle,
628 GATT_READ_OP_CB /*cb*/, void* /*cb_data*/) -> void {
629 requested_handles.push_back(handle);
630 }));
631
632 auto chrc_read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
633 uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
634 auto cccd_write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
635 uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {};
636 ASSERT_EQ(true, device->EnqueueInitialRequests(0x0001, chrc_read_cb, cccd_write_cb));
637 ASSERT_NE((size_t)0, requested_handles.size());
638
639 // indicate non-pending requests
640 ASSERT_EQ(false, device->device_ready);
641 device->VerifyReady(0xffff);
642
643 for (uint16_t handle : requested_handles) {
644 ASSERT_EQ(false, device->device_ready);
645 device->VerifyReady(handle);
646 }
647
648 ASSERT_EQ(true, device->device_ready);
649 }
650
TEST_F(VolumeControlDeviceTest,test_enqueue_remaining_requests)651 TEST_F(VolumeControlDeviceTest, test_enqueue_remaining_requests) {
652 com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(false);
653
654 SetSampleDatabase1();
655
656 tGATT_IF gatt_if = 0x0001;
657
658 std::vector<uint16_t> expected_to_read{
659 0x0022 /* audio input state 1 */, 0x0025 /* gain setting properties 1 */,
660 0x0027 /* audio input type 1 */, 0x0029 /* audio input status 1 */,
661 0x002e /* audio input description 1 */, 0x0042 /* audio input state 2 */,
662 0x0045 /* gain setting properties 2 */, 0x0047 /* audio input type 2 */,
663 0x0049 /* audio input status 2 */, 0x004e /* audio input description 2 */,
664 0x0062 /* audio output state 1 */, 0x0065 /* audio output location 1 */,
665 0x0069 /* audio output description 1 */, 0x0082 /* audio output state 1 */,
666 0x0085 /* audio output location 1 */, 0x008a /* audio output description 1 */};
667
668 for (uint16_t handle : expected_to_read) {
669 EXPECT_CALL(gatt_queue, ReadCharacteristic(_, handle, _, _));
670 }
671
672 EXPECT_CALL(gatt_queue, WriteDescriptor(_, _, _, GATT_WRITE, _, _)).Times(0);
673 EXPECT_CALL(gatt_interface, RegisterForNotifications(_, _, _)).Times(0);
674
675 auto chrc_read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
676 uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
677 auto chrc_multi_read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/,
678 tBTA_GATTC_MULTI& /*handles*/, uint16_t /*len*/, uint8_t* /*value*/,
679 void* /*data*/) {};
680 auto cccd_write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
681 uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {};
682 device->EnqueueRemainingRequests(gatt_if, chrc_read_cb, chrc_multi_read_cb, cccd_write_cb);
683 Mock::VerifyAndClearExpectations(&gatt_queue);
684 Mock::VerifyAndClearExpectations(&gatt_interface);
685 }
686
TEST_F(VolumeControlDeviceTest,test_enqueue_remaining_requests_multiread)687 TEST_F(VolumeControlDeviceTest, test_enqueue_remaining_requests_multiread) {
688 com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(true);
689
690 SetSampleDatabase1();
691
692 tGATT_IF gatt_if = 0x0001;
693 std::vector<uint8_t> register_for_notification_data({0x01, 0x00});
694
695 tBTA_GATTC_MULTI expected_to_read_part_1 = {
696 .num_attr = 10,
697 .handles = {0x0022 /* audio input state 1 */, 0x0025 /* gain setting properties 1 */,
698 0x0027 /* audio input type 1 */, 0x0029 /* audio input status 1 */,
699 0x002e /* audio input description 1 */, 0x0042 /* audio input state 2 */,
700 0x0045 /* gain setting properties 2 */, 0x0047 /* audio input type 2 */,
701 0x0049 /* audio input status 2 */, 0x004e /* audio input description 2 */},
702 };
703
704 tBTA_GATTC_MULTI expected_to_read_part_2 = {
705 .num_attr = 6,
706 .handles = {0x0062 /* audio output state 1 */, 0x0065 /* audio output location 1 */,
707 0x0069 /* audio output description 1 */, 0x0082 /* audio output state 1 */,
708 0x0085 /* audio output location 1 */,
709 0x008a /* audio output description 1 */},
710 };
711
712 tBTA_GATTC_MULTI received_to_read_part_1{};
713 tBTA_GATTC_MULTI received_to_read_part_2{};
714
715 {
716 testing::InSequence s;
717
718 EXPECT_CALL(gatt_queue, ReadMultiCharacteristic(_, _, _, _))
719 .WillOnce(SaveArg<1>(&received_to_read_part_1));
720 EXPECT_CALL(gatt_queue, ReadMultiCharacteristic(_, _, _, _))
721 .WillOnce(SaveArg<1>(&received_to_read_part_2));
722 }
723 EXPECT_CALL(gatt_queue, WriteDescriptor(_, _, _, GATT_WRITE, _, _)).Times(0);
724 EXPECT_CALL(gatt_interface, RegisterForNotifications(_, _, _)).Times(0);
725
726 auto chrc_read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
727 uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
728 auto chrc_multi_read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/,
729 tBTA_GATTC_MULTI& /*handles*/, uint16_t /*len*/, uint8_t* /*value*/,
730 void* /*data*/) {};
731 auto cccd_write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
732 uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {};
733
734 device->EnqueueRemainingRequests(gatt_if, chrc_read_cb, chrc_multi_read_cb, cccd_write_cb);
735
736 Mock::VerifyAndClearExpectations(&gatt_queue);
737 Mock::VerifyAndClearExpectations(&gatt_interface);
738
739 ASSERT_EQ(expected_to_read_part_1.num_attr, received_to_read_part_1.num_attr);
740 ASSERT_EQ(expected_to_read_part_2.num_attr, received_to_read_part_2.num_attr);
741 }
742
TEST_F(VolumeControlDeviceTest,test_check_link_encrypted)743 TEST_F(VolumeControlDeviceTest, test_check_link_encrypted) {
744 ON_CALL(btm_interface, BTM_IsEncrypted(_, _)).WillByDefault(DoAll(Return(true)));
745 ASSERT_EQ(true, device->IsEncryptionEnabled());
746
747 ON_CALL(btm_interface, BTM_IsEncrypted(_, _)).WillByDefault(DoAll(Return(false)));
748 ASSERT_NE(true, device->IsEncryptionEnabled());
749 }
750
TEST_F(VolumeControlDeviceTest,test_control_point_operation)751 TEST_F(VolumeControlDeviceTest, test_control_point_operation) {
752 GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
753 uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {};
754 SetSampleDatabase1();
755 device->change_counter = 0x01;
756 std::vector<uint8_t> expected_data({0x03, 0x01});
757 EXPECT_CALL(gatt_queue,
758 WriteCharacteristic(_, 0x0014, expected_data, GATT_WRITE, write_cb, nullptr));
759 device->ControlPointOperation(0x03, nullptr, write_cb, nullptr);
760 }
761
TEST_F(VolumeControlDeviceTest,test_control_point_operation_arg)762 TEST_F(VolumeControlDeviceTest, test_control_point_operation_arg) {
763 GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
764 uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {};
765 SetSampleDatabase1();
766 device->change_counter = 0x55;
767 std::vector<uint8_t> expected_data({0x01, 0x55, 0x02, 0x03});
768 EXPECT_CALL(gatt_queue,
769 WriteCharacteristic(_, 0x0014, expected_data, GATT_WRITE, write_cb, nullptr));
770 std::vector<uint8_t> arg({0x02, 0x03});
771 device->ControlPointOperation(0x01, &arg, write_cb, nullptr);
772 }
773
TEST_F(VolumeControlDeviceTest,test_get_ext_audio_out_volume_offset)774 TEST_F(VolumeControlDeviceTest, test_get_ext_audio_out_volume_offset) {
775 GATT_READ_OP_CB read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
776 uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
777 SetSampleDatabase1();
778 EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0062, read_cb, nullptr));
779 device->GetExtAudioOutVolumeOffset(1, read_cb, nullptr);
780 }
781
TEST_F(VolumeControlDeviceTest,test_get_ext_audio_out_location)782 TEST_F(VolumeControlDeviceTest, test_get_ext_audio_out_location) {
783 GATT_READ_OP_CB read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
784 uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
785 SetSampleDatabase1();
786 EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0085, read_cb, nullptr));
787 device->GetExtAudioOutLocation(2, read_cb, nullptr);
788 }
789
TEST_F(VolumeControlDeviceTest,test_set_ext_audio_out_location)790 TEST_F(VolumeControlDeviceTest, test_set_ext_audio_out_location) {
791 SetSampleDatabase1();
792 std::vector<uint8_t> expected_data({0x44, 0x33, 0x22, 0x11});
793 EXPECT_CALL(gatt_queue,
794 WriteCharacteristic(_, 0x0085, expected_data, GATT_WRITE_NO_RSP, nullptr, nullptr));
795 device->SetExtAudioOutLocation(2, 0x11223344);
796 }
797
TEST_F(VolumeControlDeviceTest,test_set_ext_audio_out_location_non_writable)798 TEST_F(VolumeControlDeviceTest, test_set_ext_audio_out_location_non_writable) {
799 SetSampleDatabase1();
800 EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0);
801 device->SetExtAudioOutLocation(1, 0x11223344);
802 }
803
TEST_F(VolumeControlDeviceTest,test_get_ext_audio_out_description)804 TEST_F(VolumeControlDeviceTest, test_get_ext_audio_out_description) {
805 GATT_READ_OP_CB read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
806 uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
807 SetSampleDatabase1();
808 EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x008a, read_cb, nullptr));
809 device->GetExtAudioOutDescription(2, read_cb, nullptr);
810 }
811
TEST_F(VolumeControlDeviceTest,test_set_ext_audio_out_description)812 TEST_F(VolumeControlDeviceTest, test_set_ext_audio_out_description) {
813 SetSampleDatabase1();
814 std::string descr = "right front";
815 std::vector<uint8_t> expected_data(descr.begin(), descr.end());
816 EXPECT_CALL(gatt_queue,
817 WriteCharacteristic(_, 0x008a, expected_data, GATT_WRITE_NO_RSP, nullptr, nullptr));
818 device->SetExtAudioOutDescription(2, descr);
819 }
820
TEST_F(VolumeControlDeviceTest,test_set_ext_audio_out_description_non_writable)821 TEST_F(VolumeControlDeviceTest, test_set_ext_audio_out_description_non_writable) {
822 SetSampleDatabase1();
823 std::string descr = "left front";
824 EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0);
825 device->SetExtAudioOutDescription(1, descr);
826 }
827
TEST_F(VolumeControlDeviceTest,test_ext_audio_out_control_point_operation)828 TEST_F(VolumeControlDeviceTest, test_ext_audio_out_control_point_operation) {
829 GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
830 uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {};
831 SetSampleDatabase1();
832 VolumeOffset* offset = device->audio_offsets.FindById(1);
833 ASSERT_NE(nullptr, offset);
834 offset->change_counter = 0x09;
835 std::vector<uint8_t> expected_data({0x0b, 0x09});
836 EXPECT_CALL(gatt_queue,
837 WriteCharacteristic(_, 0x0067, expected_data, GATT_WRITE, write_cb, nullptr));
838 device->ExtAudioOutControlPointOperation(1, 0x0b, nullptr, write_cb, nullptr);
839 }
840
TEST_F(VolumeControlDeviceTest,test_ext_audio_out_control_point_operation_arg)841 TEST_F(VolumeControlDeviceTest, test_ext_audio_out_control_point_operation_arg) {
842 GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
843 uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {};
844 SetSampleDatabase1();
845 VolumeOffset* offset = device->audio_offsets.FindById(1);
846 ASSERT_NE(nullptr, offset);
847 offset->change_counter = 0x09;
848 std::vector<uint8_t> expected_data({0x0b, 0x09, 0x01, 0x02, 0x03, 0x04});
849 std::vector<uint8_t> arg({0x01, 0x02, 0x03, 0x04});
850 EXPECT_CALL(gatt_queue,
851 WriteCharacteristic(_, 0x0067, expected_data, GATT_WRITE, write_cb, nullptr));
852 device->ExtAudioOutControlPointOperation(1, 0x0b, &arg, write_cb, nullptr);
853 }
854
TEST_F(VolumeControlDeviceTest,test_get_ext_audio_in_state)855 TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_state) {
856 GATT_READ_OP_CB read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
857 uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
858 SetSampleDatabase1();
859 EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0022, read_cb, nullptr));
860 device->GetExtAudioInState(0, read_cb, nullptr);
861 }
862
TEST_F(VolumeControlDeviceTest,test_get_ext_audio_in_status)863 TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_status) {
864 GATT_READ_OP_CB read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
865 uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
866 SetSampleDatabase1();
867 EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0049, read_cb, nullptr));
868 device->GetExtAudioInStatus(1, read_cb, nullptr);
869 }
870
TEST_F(VolumeControlDeviceTest,test_get_ext_audio_in_gain_props)871 TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_gain_props) {
872 GATT_READ_OP_CB read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
873 uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
874 SetSampleDatabase1();
875 EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0025, read_cb, nullptr));
876 device->GetExtAudioInGainProps(0, read_cb, nullptr);
877 }
878
TEST_F(VolumeControlDeviceTest,test_get_ext_audio_in_description)879 TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_description) {
880 GATT_READ_OP_CB read_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
881 uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
882 SetSampleDatabase1();
883 EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x002e, read_cb, nullptr));
884 device->GetExtAudioInDescription(0, read_cb, nullptr);
885 }
886
TEST_F(VolumeControlDeviceTest,test_set_ext_audio_in_description)887 TEST_F(VolumeControlDeviceTest, test_set_ext_audio_in_description) {
888 SetSampleDatabase1();
889 std::string descr = "HDMI";
890 std::vector<uint8_t> expected_data(descr.begin(), descr.end());
891 EXPECT_CALL(gatt_queue,
892 WriteCharacteristic(_, 0x004e, expected_data, GATT_WRITE_NO_RSP, nullptr, nullptr));
893 device->SetExtAudioInDescription(1, descr);
894 }
895
TEST_F(VolumeControlDeviceTest,test_set_ext_audio_in_description_non_writable)896 TEST_F(VolumeControlDeviceTest, test_set_ext_audio_in_description_non_writable) {
897 SetSampleDatabase1();
898 std::string descr = "AUX";
899 std::vector<uint8_t> expected_data(descr.begin(), descr.end());
900 EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0);
901 device->SetExtAudioInDescription(0, descr);
902 }
903
TEST_F(VolumeControlDeviceTest,test_ext_audio_in_control_point_operation)904 TEST_F(VolumeControlDeviceTest, test_ext_audio_in_control_point_operation) {
905 GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
906 uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {};
907 SetSampleDatabase1();
908 VolumeAudioInput* input = device->audio_inputs.FindById(1);
909 ASSERT_NE(nullptr, input);
910 input->change_counter = 0x11;
911 std::vector<uint8_t> expected_data({0x0c, 0x11});
912 EXPECT_CALL(gatt_queue,
913 WriteCharacteristic(_, 0x004c, expected_data, GATT_WRITE, write_cb, nullptr));
914 device->ExtAudioInControlPointOperation(1, 0x0c, nullptr, write_cb, nullptr);
915 }
916
TEST_F(VolumeControlDeviceTest,test_ext_audio_in_control_point_operation_arg)917 TEST_F(VolumeControlDeviceTest, test_ext_audio_in_control_point_operation_arg) {
918 GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
919 uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {};
920 SetSampleDatabase1();
921 VolumeAudioInput* input = device->audio_inputs.FindById(1);
922 ASSERT_NE(nullptr, input);
923 input->change_counter = 0x12;
924 std::vector<uint8_t> expected_data({0x0d, 0x12, 0x01, 0x02, 0x03, 0x04});
925 std::vector<uint8_t> arg({0x01, 0x02, 0x03, 0x04});
926 EXPECT_CALL(gatt_queue,
927 WriteCharacteristic(_, 0x004c, expected_data, GATT_WRITE, write_cb, nullptr));
928 device->ExtAudioInControlPointOperation(1, 0x0d, &arg, write_cb, nullptr);
929 }
930
931 } // namespace internal
932 } // namespace vc
933 } // namespace bluetooth
934