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