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 <base/bind.h>
19 #include <base/bind_helpers.h>
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22
23 #include "bta_gatt_api_mock.h"
24 #include "bta_gatt_queue_mock.h"
25 #include "bta_vc_api.h"
26 #include "btm_api_mock.h"
27 #include "gatt/database_builder.h"
28 #include "hardware/bt_gatt_types.h"
29 #include "types.h"
30
btif_storage_add_volume_control(const RawAddress & addr,bool auto_conn)31 void btif_storage_add_volume_control(const RawAddress& addr, bool auto_conn) {}
32
33 namespace bluetooth {
34 namespace vc {
35 namespace internal {
36 namespace {
37
38 using base::Bind;
39 using base::Unretained;
40
41 using bluetooth::vc::ConnectionState;
42 using bluetooth::vc::VolumeControlCallbacks;
43
44 using testing::_;
45 using testing::DoAll;
46 using testing::DoDefault;
47 using testing::Invoke;
48 using testing::Mock;
49 using testing::NotNull;
50 using testing::Return;
51 using testing::SaveArg;
52 using testing::SetArgPointee;
53 using testing::WithArg;
54
GetTestAddress(int index)55 RawAddress GetTestAddress(int index) {
56 CHECK_LT(index, UINT8_MAX);
57 RawAddress result = {
58 {0xC0, 0xDE, 0xC0, 0xDE, 0x00, static_cast<uint8_t>(index)}};
59 return result;
60 }
61
62 class MockVolumeControlCallbacks : public VolumeControlCallbacks {
63 public:
64 MockVolumeControlCallbacks() = default;
65 ~MockVolumeControlCallbacks() override = default;
66
67 MOCK_METHOD((void), OnConnectionState,
68 (ConnectionState state, const RawAddress& address), (override));
69 MOCK_METHOD((void), OnVolumeStateChanged,
70 (const RawAddress& address, uint8_t volume, bool mute),
71 (override));
72 MOCK_METHOD((void), OnGroupVolumeStateChanged,
73 (int group_id, uint8_t volume, bool mute), (override));
74
75 private:
76 DISALLOW_COPY_AND_ASSIGN(MockVolumeControlCallbacks);
77 };
78
79 class VolumeControlTest : public ::testing::Test {
80 private:
set_sample_database(uint16_t conn_id,bool vcs,bool vcs_broken,bool aics,bool aics_broken,bool vocs,bool vocs_broken)81 void set_sample_database(uint16_t conn_id, bool vcs, bool vcs_broken,
82 bool aics, bool aics_broken, bool vocs,
83 bool vocs_broken) {
84 gatt::DatabaseBuilder builder;
85 builder.AddService(0x0001, 0x0003, Uuid::From16Bit(0x1800), true);
86 builder.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2a00),
87 GATT_CHAR_PROP_BIT_READ);
88 /* 0x0004-0x000f RFU */
89 if (vcs) {
90 /* VCS */
91 builder.AddService(0x0010, 0x0026, kVolumeControlUuid, true);
92 if (aics) {
93 /* TODO Place holder */
94 }
95 if (vocs) {
96 /* TODO Place holder */
97 }
98 /* 0x0015-0x001f RFU */
99 builder.AddCharacteristic(
100 0x0020, 0x0021, kVolumeControlStateUuid,
101 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
102 builder.AddDescriptor(0x0022,
103 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
104 if (!vcs_broken) {
105 builder.AddCharacteristic(0x0023, 0x0024, kVolumeControlPointUuid,
106 GATT_CHAR_PROP_BIT_WRITE);
107 }
108 builder.AddCharacteristic(0x0025, 0x0026, kVolumeFlagsUuid,
109 GATT_CHAR_PROP_BIT_READ);
110 /* 0x0027-0x002f RFU */
111 if (aics) {
112 /* TODO Place holder for AICS */
113 }
114 if (vocs) {
115 /* TODO Place holder for VOCS */
116 }
117 }
118 /* 0x008c-0x008f RFU */
119
120 /* GATTS */
121 builder.AddService(0x0090, 0x0093,
122 Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER), true);
123 builder.AddCharacteristic(0x0091, 0x0092,
124 Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD),
125 GATT_CHAR_PROP_BIT_NOTIFY);
126 builder.AddDescriptor(0x0093,
127 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
128 services_map[conn_id] = builder.Build().Services();
129
130 ON_CALL(gatt_queue, ReadCharacteristic(conn_id, _, _, _))
131 .WillByDefault(Invoke([&](uint16_t conn_id, uint16_t handle,
132 GATT_READ_OP_CB cb, void* cb_data) -> void {
133 std::vector<uint8_t> value;
134
135 switch (handle) {
136 case 0x0003:
137 /* device name */
138 value.resize(20);
139 break;
140
141 case 0x0021:
142 /* volume state */
143 value.resize(3);
144 break;
145
146 case 0x0026:
147 /* volume flags */
148 value.resize(1);
149 break;
150
151 default:
152 ASSERT_TRUE(false);
153 return;
154 }
155
156 cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(),
157 cb_data);
158 }));
159 }
160
161 protected:
SetUp(void)162 void SetUp(void) override {
163 bluetooth::manager::SetMockBtmInterface(&btm_interface);
164 gatt::SetMockBtaGattInterface(&gatt_interface);
165 gatt::SetMockBtaGattQueue(&gatt_queue);
166 callbacks.reset(new MockVolumeControlCallbacks());
167
168 // default action for GetCharacteristic function call
169 ON_CALL(gatt_interface, GetCharacteristic(_, _))
170 .WillByDefault(
171 Invoke([&](uint16_t conn_id,
172 uint16_t handle) -> const gatt::Characteristic* {
173 std::list<gatt::Service>& services = services_map[conn_id];
174 for (auto const& service : services) {
175 for (auto const& characteristic : service.characteristics) {
176 if (characteristic.value_handle == handle) {
177 return &characteristic;
178 }
179 }
180 }
181
182 return nullptr;
183 }));
184
185 // default action for GetOwningService function call
186 ON_CALL(gatt_interface, GetOwningService(_, _))
187 .WillByDefault(Invoke(
188 [&](uint16_t conn_id, uint16_t handle) -> const gatt::Service* {
189 std::list<gatt::Service>& services = services_map[conn_id];
190 for (auto const& service : services) {
191 if (service.handle <= handle && service.end_handle >= handle) {
192 return &service;
193 }
194 }
195
196 return nullptr;
197 }));
198
199 // default action for GetServices function call
200 ON_CALL(gatt_interface, GetServices(_))
201 .WillByDefault(WithArg<0>(
202 Invoke([&](uint16_t conn_id) -> std::list<gatt::Service>* {
203 return &services_map[conn_id];
204 })));
205
206 // default action for RegisterForNotifications function call
207 ON_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, _))
208 .WillByDefault(Return(GATT_SUCCESS));
209
210 // default action for DeregisterForNotifications function call
211 ON_CALL(gatt_interface, DeregisterForNotifications(gatt_if, _, _))
212 .WillByDefault(Return(GATT_SUCCESS));
213
214 // default action for WriteDescriptor function call
215 ON_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _))
216 .WillByDefault(
217 Invoke([](uint16_t conn_id, uint16_t handle,
218 std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type,
219 GATT_WRITE_OP_CB cb, void* cb_data) -> void {
220 if (cb) cb(conn_id, GATT_SUCCESS, handle, cb_data);
221 }));
222 }
223
TearDown(void)224 void TearDown(void) override {
225 services_map.clear();
226 callbacks.reset();
227 gatt::SetMockBtaGattQueue(nullptr);
228 gatt::SetMockBtaGattInterface(nullptr);
229 bluetooth::manager::SetMockBtmInterface(nullptr);
230 }
231
TestAppRegister(void)232 void TestAppRegister(void) {
233 BtaAppRegisterCallback app_register_callback;
234 EXPECT_CALL(gatt_interface, AppRegister(_, _, _))
235 .WillOnce(DoAll(SaveArg<0>(&gatt_callback),
236 SaveArg<1>(&app_register_callback)));
237 VolumeControl::Initialize(callbacks.get());
238 ASSERT_TRUE(gatt_callback);
239 ASSERT_TRUE(app_register_callback);
240 app_register_callback.Run(gatt_if, GATT_SUCCESS);
241 ASSERT_TRUE(VolumeControl::IsVolumeControlRunning());
242 }
243
TestAppUnregister(void)244 void TestAppUnregister(void) {
245 EXPECT_CALL(gatt_interface, AppDeregister(gatt_if));
246 VolumeControl::CleanUp();
247 ASSERT_FALSE(VolumeControl::IsVolumeControlRunning());
248 gatt_callback = nullptr;
249 }
250
TestConnect(const RawAddress & address)251 void TestConnect(const RawAddress& address) {
252 // by default indicate link as encrypted
253 ON_CALL(btm_interface, GetSecurityFlagsByTransport(address, NotNull(), _))
254 .WillByDefault(
255 DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
256
257 EXPECT_CALL(gatt_interface, Open(gatt_if, address, true, _));
258 VolumeControl::Get()->Connect(address);
259 }
260
TestDisconnect(const RawAddress & address,uint16_t conn_id)261 void TestDisconnect(const RawAddress& address, uint16_t conn_id) {
262 if (conn_id) {
263 EXPECT_CALL(gatt_interface, Close(conn_id));
264 } else {
265 EXPECT_CALL(gatt_interface, CancelOpen(gatt_if, address, _));
266 }
267 VolumeControl::Get()->Disconnect(address);
268 }
269
TestAddFromStorage(const RawAddress & address,bool auto_connect)270 void TestAddFromStorage(const RawAddress& address, bool auto_connect) {
271 // by default indicate link as encrypted
272 ON_CALL(btm_interface, GetSecurityFlagsByTransport(address, NotNull(), _))
273 .WillByDefault(
274 DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
275
276 if (auto_connect) {
277 EXPECT_CALL(gatt_interface, Open(gatt_if, address, false, _));
278 } else {
279 EXPECT_CALL(gatt_interface, Open(gatt_if, address, _, _)).Times(0);
280 }
281 VolumeControl::Get()->AddFromStorage(address, auto_connect);
282 }
283
TestSubscribeNotifications(const RawAddress & address,uint16_t conn_id,std::map<uint16_t,uint16_t> & handle_pairs)284 void TestSubscribeNotifications(const RawAddress& address, uint16_t conn_id,
285 std::map<uint16_t, uint16_t>& handle_pairs) {
286 SetSampleDatabase(conn_id);
287 TestAppRegister();
288 TestConnect(address);
289 GetConnectedEvent(address, conn_id);
290
291 EXPECT_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _))
292 .WillRepeatedly(DoDefault());
293 EXPECT_CALL(gatt_interface, RegisterForNotifications(_, _, _))
294 .WillRepeatedly(DoDefault());
295
296 std::vector<uint8_t> notify_value({0x01, 0x00});
297 for (auto const& handles : handle_pairs) {
298 EXPECT_CALL(gatt_queue, WriteDescriptor(conn_id, handles.second,
299 notify_value, GATT_WRITE, _, _))
300 .WillOnce(DoDefault());
301 EXPECT_CALL(gatt_interface,
302 RegisterForNotifications(gatt_if, address, handles.first))
303 .WillOnce(DoDefault());
304 }
305
306 GetSearchCompleteEvent(conn_id);
307 TestAppUnregister();
308 }
309
TestReadCharacteristic(const RawAddress & address,uint16_t conn_id,std::vector<uint16_t> handles)310 void TestReadCharacteristic(const RawAddress& address, uint16_t conn_id,
311 std::vector<uint16_t> handles) {
312 SetSampleDatabase(conn_id);
313 TestAppRegister();
314 TestConnect(address);
315 GetConnectedEvent(address, conn_id);
316
317 EXPECT_CALL(gatt_queue, ReadCharacteristic(conn_id, _, _, _))
318 .WillRepeatedly(DoDefault());
319 for (auto const& handle : handles) {
320 EXPECT_CALL(gatt_queue, ReadCharacteristic(conn_id, handle, _, _))
321 .WillOnce(DoDefault());
322 }
323
324 GetSearchCompleteEvent(conn_id);
325 TestAppUnregister();
326 }
327
GetConnectedEvent(const RawAddress & address,uint16_t conn_id)328 void GetConnectedEvent(const RawAddress& address, uint16_t conn_id) {
329 tBTA_GATTC_OPEN event_data = {
330 .status = GATT_SUCCESS,
331 .conn_id = conn_id,
332 .client_if = gatt_if,
333 .remote_bda = address,
334 .transport = GATT_TRANSPORT_LE,
335 .mtu = 240,
336 };
337
338 gatt_callback(BTA_GATTC_OPEN_EVT, (tBTA_GATTC*)&event_data);
339 }
340
GetDisconnectedEvent(const RawAddress & address,uint16_t conn_id)341 void GetDisconnectedEvent(const RawAddress& address, uint16_t conn_id) {
342 tBTA_GATTC_CLOSE event_data = {
343 .status = GATT_SUCCESS,
344 .conn_id = conn_id,
345 .client_if = gatt_if,
346 .remote_bda = address,
347 .reason = GATT_CONN_TERMINATE_PEER_USER,
348 };
349
350 gatt_callback(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC*)&event_data);
351 }
352
GetSearchCompleteEvent(uint16_t conn_id)353 void GetSearchCompleteEvent(uint16_t conn_id) {
354 tBTA_GATTC_SEARCH_CMPL event_data = {
355 .status = GATT_SUCCESS,
356 .conn_id = conn_id,
357 };
358
359 gatt_callback(BTA_GATTC_SEARCH_CMPL_EVT, (tBTA_GATTC*)&event_data);
360 }
361
SetEncryptionResult(const RawAddress & address,bool success)362 void SetEncryptionResult(const RawAddress& address, bool success) {
363 ON_CALL(btm_interface, GetSecurityFlagsByTransport(address, NotNull(), _))
364 .WillByDefault(DoAll(SetArgPointee<1>(0), Return(true)));
365 EXPECT_CALL(btm_interface,
366 SetEncryption(address, _, NotNull(), _, BTM_BLE_SEC_ENCRYPT))
367 .WillOnce(Invoke(
368 [&success](const RawAddress& bd_addr, tBT_TRANSPORT transport,
369 tBTM_SEC_CALLBACK* p_callback, void* p_ref_data,
370 tBTM_BLE_SEC_ACT sec_act) -> tBTM_STATUS {
371 p_callback(&bd_addr, transport, p_ref_data,
372 success ? BTM_SUCCESS : BTM_FAILED_ON_SECURITY);
373 return BTM_SUCCESS;
374 }));
375 }
376
SetSampleDatabaseVCS(uint16_t conn_id)377 void SetSampleDatabaseVCS(uint16_t conn_id) {
378 set_sample_database(conn_id, true, false, false, false, false, false);
379 }
380
SetSampleDatabaseNoVCS(uint16_t conn_id)381 void SetSampleDatabaseNoVCS(uint16_t conn_id) {
382 set_sample_database(conn_id, false, false, true, false, true, false);
383 }
384
SetSampleDatabaseVCSBroken(uint16_t conn_id)385 void SetSampleDatabaseVCSBroken(uint16_t conn_id) {
386 set_sample_database(conn_id, true, true, true, false, true, false);
387 }
388
SetSampleDatabase(uint16_t conn_id)389 void SetSampleDatabase(uint16_t conn_id) {
390 set_sample_database(conn_id, true, false, true, false, true, false);
391 }
392
393 std::unique_ptr<MockVolumeControlCallbacks> callbacks;
394 bluetooth::manager::MockBtmInterface btm_interface;
395 gatt::MockBtaGattInterface gatt_interface;
396 gatt::MockBtaGattQueue gatt_queue;
397 tBTA_GATTC_CBACK* gatt_callback;
398 const uint8_t gatt_if = 0xff;
399 std::map<uint16_t, std::list<gatt::Service>> services_map;
400 };
401
TEST_F(VolumeControlTest,test_get_uninitialized)402 TEST_F(VolumeControlTest, test_get_uninitialized) {
403 ASSERT_DEATH(VolumeControl::Get(), "");
404 }
405
TEST_F(VolumeControlTest,test_initialize)406 TEST_F(VolumeControlTest, test_initialize) {
407 VolumeControl::Initialize(callbacks.get());
408 ASSERT_TRUE(VolumeControl::IsVolumeControlRunning());
409 VolumeControl::CleanUp();
410 }
411
TEST_F(VolumeControlTest,test_initialize_twice)412 TEST_F(VolumeControlTest, test_initialize_twice) {
413 VolumeControl::Initialize(callbacks.get());
414 VolumeControl* volume_control_p = VolumeControl::Get();
415 VolumeControl::Initialize(callbacks.get());
416 ASSERT_EQ(volume_control_p, VolumeControl::Get());
417 VolumeControl::CleanUp();
418 }
419
TEST_F(VolumeControlTest,test_cleanup_initialized)420 TEST_F(VolumeControlTest, test_cleanup_initialized) {
421 VolumeControl::Initialize(callbacks.get());
422 VolumeControl::CleanUp();
423 ASSERT_FALSE(VolumeControl::IsVolumeControlRunning());
424 }
425
TEST_F(VolumeControlTest,test_cleanup_uninitialized)426 TEST_F(VolumeControlTest, test_cleanup_uninitialized) {
427 VolumeControl::CleanUp();
428 ASSERT_FALSE(VolumeControl::IsVolumeControlRunning());
429 }
430
TEST_F(VolumeControlTest,test_app_registration)431 TEST_F(VolumeControlTest, test_app_registration) {
432 TestAppRegister();
433 TestAppUnregister();
434 }
435
TEST_F(VolumeControlTest,test_connect)436 TEST_F(VolumeControlTest, test_connect) {
437 TestAppRegister();
438 TestConnect(GetTestAddress(0));
439 TestAppUnregister();
440 }
441
TEST_F(VolumeControlTest,test_add_from_storage)442 TEST_F(VolumeControlTest, test_add_from_storage) {
443 TestAppRegister();
444 TestAddFromStorage(GetTestAddress(0), true);
445 TestAddFromStorage(GetTestAddress(1), false);
446 TestAppUnregister();
447 }
448
TEST_F(VolumeControlTest,test_disconnect_non_connected)449 TEST_F(VolumeControlTest, test_disconnect_non_connected) {
450 const RawAddress test_address = GetTestAddress(0);
451 TestAppRegister();
452 TestConnect(test_address);
453 EXPECT_CALL(*callbacks,
454 OnConnectionState(ConnectionState::DISCONNECTED, test_address));
455 TestDisconnect(test_address, 0);
456 TestAppUnregister();
457 }
458
TEST_F(VolumeControlTest,test_disconnect_connected)459 TEST_F(VolumeControlTest, test_disconnect_connected) {
460 const RawAddress test_address = GetTestAddress(0);
461 TestAppRegister();
462 TestConnect(test_address);
463 GetConnectedEvent(test_address, 1);
464 EXPECT_CALL(*callbacks,
465 OnConnectionState(ConnectionState::DISCONNECTED, test_address));
466 TestDisconnect(test_address, 1);
467 TestAppUnregister();
468 }
469
TEST_F(VolumeControlTest,test_disconnected)470 TEST_F(VolumeControlTest, test_disconnected) {
471 const RawAddress test_address = GetTestAddress(0);
472 TestAppRegister();
473 TestConnect(test_address);
474 GetConnectedEvent(test_address, 1);
475 EXPECT_CALL(*callbacks,
476 OnConnectionState(ConnectionState::DISCONNECTED, test_address));
477 GetDisconnectedEvent(test_address, 1);
478 TestAppUnregister();
479 }
480
TEST_F(VolumeControlTest,test_disconnected_while_autoconnect)481 TEST_F(VolumeControlTest, test_disconnected_while_autoconnect) {
482 const RawAddress test_address = GetTestAddress(0);
483 TestAppRegister();
484 TestAddFromStorage(test_address, true);
485 GetConnectedEvent(test_address, 1);
486 // autoconnect - don't indicate disconnection
487 EXPECT_CALL(*callbacks,
488 OnConnectionState(ConnectionState::DISCONNECTED, test_address))
489 .Times(0);
490 GetDisconnectedEvent(test_address, 1);
491 TestAppUnregister();
492 }
493
TEST_F(VolumeControlTest,test_reconnect_after_encryption_failed)494 TEST_F(VolumeControlTest, test_reconnect_after_encryption_failed) {
495 const RawAddress test_address = GetTestAddress(0);
496 TestAppRegister();
497 TestAddFromStorage(test_address, true);
498 SetEncryptionResult(test_address, false);
499 // autoconnect - don't indicate disconnection
500 EXPECT_CALL(*callbacks,
501 OnConnectionState(ConnectionState::DISCONNECTED, test_address))
502 .Times(0);
503 GetConnectedEvent(test_address, 1);
504 Mock::VerifyAndClearExpectations(&btm_interface);
505 SetEncryptionResult(test_address, true);
506 GetConnectedEvent(test_address, 1);
507 TestAppUnregister();
508 }
509
TEST_F(VolumeControlTest,test_discovery_vcs_found)510 TEST_F(VolumeControlTest, test_discovery_vcs_found) {
511 const RawAddress test_address = GetTestAddress(0);
512 SetSampleDatabaseVCS(1);
513 TestAppRegister();
514 TestConnect(test_address);
515 EXPECT_CALL(*callbacks,
516 OnConnectionState(ConnectionState::CONNECTED, test_address));
517 GetConnectedEvent(test_address, 1);
518 GetSearchCompleteEvent(1);
519 Mock::VerifyAndClearExpectations(callbacks.get());
520 TestAppUnregister();
521 }
522
TEST_F(VolumeControlTest,test_discovery_vcs_not_found)523 TEST_F(VolumeControlTest, test_discovery_vcs_not_found) {
524 const RawAddress test_address = GetTestAddress(0);
525 SetSampleDatabaseNoVCS(1);
526 TestAppRegister();
527 TestConnect(test_address);
528 EXPECT_CALL(*callbacks,
529 OnConnectionState(ConnectionState::DISCONNECTED, test_address));
530 GetConnectedEvent(test_address, 1);
531
532 GetSearchCompleteEvent(1);
533 Mock::VerifyAndClearExpectations(callbacks.get());
534 TestAppUnregister();
535 }
536
TEST_F(VolumeControlTest,test_discovery_vcs_broken)537 TEST_F(VolumeControlTest, test_discovery_vcs_broken) {
538 const RawAddress test_address = GetTestAddress(0);
539 SetSampleDatabaseVCSBroken(1);
540 TestAppRegister();
541 TestConnect(test_address);
542 EXPECT_CALL(*callbacks,
543 OnConnectionState(ConnectionState::DISCONNECTED, test_address));
544 GetConnectedEvent(test_address, 1);
545 GetSearchCompleteEvent(1);
546 Mock::VerifyAndClearExpectations(callbacks.get());
547 TestAppUnregister();
548 }
549
TEST_F(VolumeControlTest,test_subscribe_vcs_volume_state)550 TEST_F(VolumeControlTest, test_subscribe_vcs_volume_state) {
551 std::map<uint16_t, uint16_t> handles({{0x0021, 0x0022}});
552 TestSubscribeNotifications(GetTestAddress(0), 1, handles);
553 }
554
TEST_F(VolumeControlTest,test_read_vcs_volume_state)555 TEST_F(VolumeControlTest, test_read_vcs_volume_state) {
556 const RawAddress test_address = GetTestAddress(0);
557 EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _));
558 std::vector<uint16_t> handles({0x0021});
559 TestReadCharacteristic(test_address, 1, handles);
560 }
561
TEST_F(VolumeControlTest,test_read_vcs_volume_flags)562 TEST_F(VolumeControlTest, test_read_vcs_volume_flags) {
563 std::vector<uint16_t> handles({0x0026});
564 TestReadCharacteristic(GetTestAddress(0), 1, handles);
565 }
566
567 class VolumeControlCallbackTest : public VolumeControlTest {
568 protected:
569 const RawAddress test_address = GetTestAddress(0);
570 uint16_t conn_id = 22;
571
SetUp(void)572 void SetUp(void) override {
573 VolumeControlTest::SetUp();
574 SetSampleDatabase(conn_id);
575 TestAppRegister();
576 TestConnect(test_address);
577 GetConnectedEvent(test_address, conn_id);
578 GetSearchCompleteEvent(conn_id);
579 }
580
TearDown(void)581 void TearDown(void) override {
582 TestAppUnregister();
583 VolumeControlTest::TearDown();
584 }
585
GetNotificationEvent(uint16_t handle,std::vector<uint8_t> & value)586 void GetNotificationEvent(uint16_t handle, std::vector<uint8_t>& value) {
587 tBTA_GATTC_NOTIFY event_data = {
588 .conn_id = conn_id,
589 .bda = test_address,
590 .handle = handle,
591 .len = (uint8_t)value.size(),
592 .is_notify = true,
593 };
594
595 std::copy(value.begin(), value.end(), event_data.value);
596 gatt_callback(BTA_GATTC_NOTIF_EVT, (tBTA_GATTC*)&event_data);
597 }
598 };
599
TEST_F(VolumeControlCallbackTest,test_volume_state_changed)600 TEST_F(VolumeControlCallbackTest, test_volume_state_changed) {
601 std::vector<uint8_t> value({0x03, 0x01, 0x02});
602 EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, 0x03, true));
603 GetNotificationEvent(0x0021, value);
604 }
605
TEST_F(VolumeControlCallbackTest,test_volume_state_changed_malformed)606 TEST_F(VolumeControlCallbackTest, test_volume_state_changed_malformed) {
607 EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _)).Times(0);
608 std::vector<uint8_t> too_short({0x03, 0x01});
609 GetNotificationEvent(0x0021, too_short);
610 std::vector<uint8_t> too_long({0x03, 0x01, 0x02, 0x03});
611 GetNotificationEvent(0x0021, too_long);
612 }
613
614 class VolumeControlValueSetTest : public VolumeControlTest {
615 protected:
616 const RawAddress test_address = GetTestAddress(0);
617 uint16_t conn_id = 22;
618
SetUp(void)619 void SetUp(void) override {
620 VolumeControlTest::SetUp();
621 SetSampleDatabase(conn_id);
622 TestAppRegister();
623 TestConnect(test_address);
624 GetConnectedEvent(test_address, conn_id);
625 GetSearchCompleteEvent(conn_id);
626 }
627
TearDown(void)628 void TearDown(void) override {
629 TestAppUnregister();
630 VolumeControlTest::TearDown();
631 }
632 };
633
TEST_F(VolumeControlValueSetTest,test_set_volume)634 TEST_F(VolumeControlValueSetTest, test_set_volume) {
635 std::vector<uint8_t> expected_data({0x04, 0x00, 0x10});
636 EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, expected_data,
637 GATT_WRITE, _, _));
638 VolumeControl::Get()->SetVolume(test_address, 0x10);
639 }
640 } // namespace
641 } // namespace internal
642 } // namespace vc
643 } // namespace bluetooth
644