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/functional/bind.h>
19 #include <bluetooth/log.h>
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22
23 #include <vector>
24
25 #include "bind_helpers.h"
26 #include "bta_csis_api.h"
27 #include "bta_dm_api_mock.h"
28 #include "bta_gatt_api_mock.h"
29 #include "bta_gatt_queue_mock.h"
30 #include "bta_le_audio_uuids.h"
31 #include "btif/include/btif_profile_storage.h"
32 #include "btm_api_mock.h"
33 #include "csis_types.h"
34 #include "gatt/database_builder.h"
35 #include "hardware/bt_gatt_types.h"
36 #include "stack/include/bt_uuid16.h"
37 #include "test/common/mock_functions.h"
38
39 // TODO(b/369381361) Enfore -Wmissing-prototypes
40 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
41
gatt_cl_read_sirk_req(const RawAddress &,base::OnceCallback<void (tGATT_STATUS status,const RawAddress &,uint8_t sirk_type,Octet16 & sirk)>)42 bool gatt_cl_read_sirk_req(const RawAddress& /*peer_bda*/,
43 base::OnceCallback<void(tGATT_STATUS status, const RawAddress&,
44 uint8_t sirk_type, Octet16& sirk)>
45 /*cb*/) {
46 return true;
47 }
48
49 namespace bluetooth {
50 namespace csis {
51 namespace internal {
52 namespace {
53
54 using base::Bind;
55 using base::Closure;
56 using base::Unretained;
57
58 using bluetooth::csis::ConnectionState;
59 using bluetooth::csis::CsisClient;
60 using bluetooth::csis::CsisClientCallbacks;
61 using bluetooth::csis::CsisClientInterface;
62 using bluetooth::csis::CsisGroupLockStatus;
63 using bluetooth::groups::DeviceGroups;
64
65 using testing::_;
66 using testing::AtLeast;
67 using testing::DoAll;
68 using testing::DoDefault;
69 using testing::Invoke;
70 using testing::Mock;
71 using testing::NotNull;
72 using testing::Return;
73 using testing::SaveArg;
74 using testing::SetArgPointee;
75 using testing::WithArg;
76
77 // Disables most likely false-positives from base::SplitString()
__asan_default_options()78 extern "C" const char* __asan_default_options() { return "detect_container_overflow=0"; }
79
GetTestAddress(int index)80 RawAddress GetTestAddress(int index) {
81 EXPECT_LT(index, UINT8_MAX);
82 RawAddress result = {{0xC0, 0xDE, 0xC0, 0xDE, 0x00, static_cast<uint8_t>(index)}};
83 return result;
84 }
85
86 /* Csis lock callback */
87 class MockCsisLockCallback {
88 public:
89 MockCsisLockCallback() = default;
90 MockCsisLockCallback(const MockCsisLockCallback&) = delete;
91 MockCsisLockCallback& operator=(const MockCsisLockCallback&) = delete;
92
93 ~MockCsisLockCallback() = default;
94 MOCK_METHOD((void), CsisGroupLockCb, (int group_id, bool locked, CsisGroupLockStatus status));
95 };
96
97 static MockCsisLockCallback* csis_lock_callback_mock;
98
SetMockCsisLockCallback(MockCsisLockCallback * mock)99 void SetMockCsisLockCallback(MockCsisLockCallback* mock) { csis_lock_callback_mock = mock; }
100
101 /* Csis callbacks to JNI */
102 class MockCsisCallbacks : public CsisClientCallbacks {
103 public:
104 MockCsisCallbacks() = default;
105 MockCsisCallbacks(const MockCsisCallbacks&) = delete;
106 MockCsisCallbacks& operator=(const MockCsisCallbacks&) = delete;
107
108 ~MockCsisCallbacks() override = default;
109
110 MOCK_METHOD((void), OnConnectionState, (const RawAddress& address, ConnectionState state),
111 (override));
112 MOCK_METHOD((void), OnDeviceAvailable,
113 (const RawAddress& address, int group_id, int group_size, int rank,
114 const bluetooth::Uuid& uuid),
115 (override));
116 MOCK_METHOD((void), OnSetMemberAvailable, (const RawAddress& address, int group_id), (override));
117 MOCK_METHOD((void), OnGroupLockChanged,
118 (int group_id, bool locked, bluetooth::csis::CsisGroupLockStatus status), (override));
119 MOCK_METHOD((void), OnGattCsisWriteLockRsp,
120 (uint16_t conn_id, tGATT_STATUS status, uint16_t handle, void* data));
121 };
122
123 class CsisClientTest : public ::testing::Test {
124 private:
set_sample_cap_included_database(uint16_t conn_id,bool csis,bool csis_broken,uint8_t rank,uint8_t sirk_msb=1)125 void set_sample_cap_included_database(uint16_t conn_id, bool csis, bool csis_broken, uint8_t rank,
126 uint8_t sirk_msb = 1) {
127 gatt::DatabaseBuilder builder;
128 builder.AddService(0x0001, 0x0003, Uuid::From16Bit(0x1800), true);
129 builder.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2a00), GATT_CHAR_PROP_BIT_READ);
130 if (csis) {
131 builder.AddService(0x0005, 0x0009, bluetooth::Uuid::From16Bit(UUID_COMMON_AUDIO_SERVICE),
132 true);
133 builder.AddIncludedService(0x0006, kCsisServiceUuid, 0x0010, 0x0030);
134
135 builder.AddService(0x0010, 0x0030, kCsisServiceUuid, true);
136 builder.AddCharacteristic(0x0020, 0x0021, kCsisSirkUuid,
137 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
138
139 builder.AddDescriptor(0x0022, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
140 builder.AddCharacteristic(0x0023, 0x0024, kCsisSizeUuid,
141 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
142 builder.AddDescriptor(0x0025, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
143 builder.AddCharacteristic(
144 0x0026, 0x0027, kCsisLockUuid,
145 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY | GATT_CHAR_PROP_BIT_WRITE);
146 builder.AddDescriptor(0x0028, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
147 builder.AddCharacteristic(0x0029, 0x0030, kCsisRankUuid, GATT_CHAR_PROP_BIT_READ);
148 }
149 if (csis_broken) {
150 builder.AddCharacteristic(0x0020, 0x0021, kCsisSirkUuid,
151 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
152
153 builder.AddDescriptor(0x0022, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
154 }
155 builder.AddService(0x0090, 0x0093, Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER), true);
156 builder.AddCharacteristic(0x0091, 0x0092, Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD),
157 GATT_CHAR_PROP_BIT_NOTIFY);
158 builder.AddDescriptor(0x0093, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
159 services_map[conn_id] = builder.Build().Services();
160
161 ON_CALL(gatt_queue, ReadCharacteristic(conn_id, _, _, _))
162 .WillByDefault(Invoke([rank, sirk_msb](uint16_t conn_id, uint16_t handle,
163 GATT_READ_OP_CB cb, void* cb_data) -> void {
164 std::vector<uint8_t> value;
165
166 switch (handle) {
167 case 0x0003:
168 /* device name */
169 value.resize(20);
170 break;
171 case 0x0021:
172 value.assign(17, 1);
173 value[16] = sirk_msb;
174 break;
175 case 0x0024:
176 value.resize(1);
177 break;
178 case 0x0027:
179 value.resize(1);
180 break;
181 case 0x0030:
182 value.resize(1);
183 value.assign(1, rank);
184 break;
185 default:
186 FAIL();
187 return;
188 }
189
190 cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
191 }));
192 }
193
set_sample_database(uint16_t conn_id,bool csis,bool csis_broken,uint8_t rank,uint8_t sirk_msb=1)194 void set_sample_database(uint16_t conn_id, bool csis, bool csis_broken, uint8_t rank,
195 uint8_t sirk_msb = 1) {
196 gatt::DatabaseBuilder builder;
197 builder.AddService(0x0001, 0x0003, Uuid::From16Bit(0x1800), true);
198 builder.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2a00), GATT_CHAR_PROP_BIT_READ);
199 if (csis) {
200 builder.AddService(0x0010, 0x0030, kCsisServiceUuid, true);
201 builder.AddCharacteristic(0x0020, 0x0021, kCsisSirkUuid,
202 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
203
204 builder.AddDescriptor(0x0022, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
205 builder.AddCharacteristic(0x0023, 0x0024, kCsisSizeUuid,
206 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
207 builder.AddDescriptor(0x0025, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
208 builder.AddCharacteristic(
209 0x0026, 0x0027, kCsisLockUuid,
210 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY | GATT_CHAR_PROP_BIT_WRITE);
211 builder.AddDescriptor(0x0028, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
212 builder.AddCharacteristic(0x0029, 0x0030, kCsisRankUuid, GATT_CHAR_PROP_BIT_READ);
213 }
214 if (csis_broken) {
215 builder.AddCharacteristic(0x0020, 0x0021, kCsisSirkUuid,
216 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
217
218 builder.AddDescriptor(0x0022, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
219 }
220 builder.AddService(0x0090, 0x0093, Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER), true);
221 builder.AddCharacteristic(0x0091, 0x0092, Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD),
222 GATT_CHAR_PROP_BIT_NOTIFY);
223 builder.AddDescriptor(0x0093, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
224 services_map[conn_id] = builder.Build().Services();
225
226 ON_CALL(gatt_queue, ReadCharacteristic(conn_id, _, _, _))
227 .WillByDefault(Invoke([rank, sirk_msb](uint16_t conn_id, uint16_t handle,
228 GATT_READ_OP_CB cb, void* cb_data) -> void {
229 std::vector<uint8_t> value;
230
231 switch (handle) {
232 case 0x0003:
233 /* device name */
234 value.resize(20);
235 break;
236 case 0x0021:
237 value.assign(17, 1);
238 value[16] = sirk_msb;
239 break;
240 case 0x0024:
241 value.resize(1);
242 break;
243 case 0x0027:
244 value.resize(1);
245 break;
246 case 0x0030:
247 value.resize(1);
248 value.assign(1, rank);
249 break;
250 default:
251 FAIL();
252 return;
253 }
254
255 cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
256 }));
257 }
258
set_sample_database_double_csis(uint16_t conn_id,uint8_t rank_1,uint8_t rank_2,bool broken,uint8_t sirk1_infill=1,uint8_t sirk2_infill=2)259 void set_sample_database_double_csis(uint16_t conn_id, uint8_t rank_1, uint8_t rank_2,
260 bool broken, uint8_t sirk1_infill = 1,
261 uint8_t sirk2_infill = 2) {
262 gatt::DatabaseBuilder builder;
263
264 builder.AddService(0x0001, 0x0003, Uuid::From16Bit(0x1800), true);
265 builder.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2a00), GATT_CHAR_PROP_BIT_READ);
266 builder.AddService(0x0010, 0x0026, bluetooth::Uuid::From16Bit(0x1850), true);
267 builder.AddIncludedService(0x0011, kCsisServiceUuid, 0x0031, 0x0041);
268 builder.AddCharacteristic(0x0031, 0x0032, kCsisSirkUuid,
269 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
270
271 builder.AddDescriptor(0x0033, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
272 builder.AddCharacteristic(0x0034, 0x0035, kCsisSizeUuid,
273 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
274 builder.AddDescriptor(0x0036, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
275 builder.AddCharacteristic(
276 0x0037, 0x0038, kCsisLockUuid,
277 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY | GATT_CHAR_PROP_BIT_WRITE);
278 builder.AddDescriptor(0x0039, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
279 builder.AddCharacteristic(0x0040, 0x0041, kCsisRankUuid, GATT_CHAR_PROP_BIT_READ);
280
281 if (broken) {
282 builder.AddCharacteristic(0x0020, 0x0021, kCsisSirkUuid,
283 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
284
285 builder.AddDescriptor(0x0022, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
286 }
287
288 builder.AddService(0x0042, 0x0044, bluetooth::Uuid::From16Bit(0x1860), true);
289 builder.AddIncludedService(0x0043, kCsisServiceUuid, 0x0045, 0x0055);
290
291 builder.AddCharacteristic(0x0045, 0x0046, kCsisSirkUuid,
292 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
293
294 builder.AddDescriptor(0x0047, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
295 builder.AddCharacteristic(0x0048, 0x0049, kCsisSizeUuid,
296 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
297 builder.AddDescriptor(0x0050, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
298 builder.AddCharacteristic(
299 0x0051, 0x0052, kCsisLockUuid,
300 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY | GATT_CHAR_PROP_BIT_WRITE);
301 builder.AddDescriptor(0x0053, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
302 builder.AddCharacteristic(0x0054, 0x0055, kCsisRankUuid, GATT_CHAR_PROP_BIT_READ);
303
304 builder.AddService(0x0090, 0x0093, Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER), true);
305 builder.AddCharacteristic(0x0091, 0x0092, Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD),
306 GATT_CHAR_PROP_BIT_NOTIFY);
307 builder.AddDescriptor(0x0093, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
308 services_map[conn_id] = builder.Build().Services();
309
310 ON_CALL(gatt_queue, ReadCharacteristic(conn_id, _, _, _))
311 .WillByDefault(Invoke([sirk1_infill, sirk2_infill, rank_1, rank_2](
312 uint16_t conn_id, uint16_t handle, GATT_READ_OP_CB cb,
313 void* cb_data) -> void {
314 std::vector<uint8_t> value;
315
316 switch (handle) {
317 case 0x0003:
318 /* device name */
319 value.resize(20);
320 break;
321 case 0x0032:
322 value.resize(17);
323 value.assign(17, sirk1_infill);
324 value[0] = 1; // Plain text SIRK
325 break;
326 case 0x0035:
327 value.resize(1);
328 value.assign(1, 2);
329 break;
330 case 0x0038:
331 value.resize(1);
332 break;
333 case 0x0041:
334 value.resize(1);
335 value.assign(1, rank_1);
336 break;
337 case 0x0046:
338 value.resize(17);
339 value.assign(17, sirk2_infill);
340 value[0] = 1; // Plain text SIRK
341 break;
342 case 0x0049:
343 value.resize(1);
344 value.assign(1, 2);
345 break;
346 case 0x0052:
347 value.resize(1);
348 break;
349 case 0x0055:
350 value.resize(1);
351 value.assign(1, rank_2);
352 break;
353 default:
354 log::error("Unknown handle? {}", handle);
355 FAIL();
356 return;
357 }
358
359 cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
360 }));
361 }
362
363 protected:
SetUp(void)364 void SetUp(void) override {
365 reset_mock_function_count_map();
366 bluetooth::manager::SetMockBtmInterface(&btm_interface);
367 dm::SetMockBtaDmInterface(&dm_interface);
368 gatt::SetMockBtaGattInterface(&gatt_interface);
369 gatt::SetMockBtaGattQueue(&gatt_queue);
370 SetMockCsisLockCallback(&csis_lock_cb);
371 callbacks.reset(new MockCsisCallbacks());
372
373 ON_CALL(btm_interface, IsLinkKeyKnown(_, _)).WillByDefault(DoAll(Return(true)));
374
375 ON_CALL(btm_interface, BTM_IsEncrypted(_, _)).WillByDefault(DoAll(Return(true)));
376
377 ON_CALL(gatt_interface, GetCharacteristic(_, _))
378 .WillByDefault(
379 Invoke([&](uint16_t conn_id, uint16_t handle) -> const gatt::Characteristic* {
380 std::list<gatt::Service>& services = services_map[conn_id];
381 for (auto const& service : services) {
382 for (auto const& characteristic : service.characteristics) {
383 if (characteristic.value_handle == handle) {
384 return &characteristic;
385 }
386 }
387 }
388
389 return nullptr;
390 }));
391
392 // default action for GetOwningService function call
393 ON_CALL(gatt_interface, GetOwningService(_, _))
394 .WillByDefault(Invoke([&](uint16_t conn_id, uint16_t handle) -> const gatt::Service* {
395 std::list<gatt::Service>& services = services_map[conn_id];
396 for (auto const& service : services) {
397 if (service.handle <= handle && service.end_handle >= handle) {
398 return &service;
399 }
400 }
401
402 return nullptr;
403 }));
404
405 // default action for GetServices function call
406 ON_CALL(gatt_interface, GetServices(_))
407 .WillByDefault(WithArg<0>(Invoke([&](uint16_t conn_id) -> std::list<gatt::Service>* {
408 return &services_map[conn_id];
409 })));
410
411 // default action for RegisterForNotifications function call
412 ON_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, _))
413 .WillByDefault(Return(GATT_SUCCESS));
414
415 // default action for DeregisterForNotifications function call
416 ON_CALL(gatt_interface, DeregisterForNotifications(gatt_if, _, _))
417 .WillByDefault(Return(GATT_SUCCESS));
418
419 // default action for WriteDescriptor function call
420 ON_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _))
421 .WillByDefault(Invoke([](uint16_t conn_id, uint16_t handle, std::vector<uint8_t> value,
422 tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb,
423 void* cb_data) -> void {
424 if (cb) {
425 cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
426 }
427 }));
428 }
429
TearDown(void)430 void TearDown(void) override {
431 services_map.clear();
432 callbacks.reset();
433 CsisClient::CleanUp();
434 gatt::SetMockBtaGattInterface(nullptr);
435 bluetooth::manager::SetMockBtmInterface(nullptr);
436 }
437
TestAppRegister(void)438 void TestAppRegister(void) {
439 BtaAppRegisterCallback app_register_callback;
440 EXPECT_CALL(gatt_interface, AppRegister(_, _, _))
441 .WillOnce(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback)));
442 CsisClient::Initialize(callbacks.get(), Bind(&btif_storage_load_bonded_csis_devices));
443 ASSERT_TRUE(gatt_callback);
444 ASSERT_TRUE(app_register_callback);
445 app_register_callback.Run(gatt_if, GATT_SUCCESS);
446 ASSERT_TRUE(CsisClient::IsCsisClientRunning());
447 }
448
TestAppUnregister(void)449 void TestAppUnregister(void) {
450 EXPECT_CALL(gatt_interface, AppDeregister(gatt_if));
451 CsisClient::CleanUp();
452 ASSERT_FALSE(CsisClient::IsCsisClientRunning());
453 gatt_callback = nullptr;
454 }
455
TestConnect(const RawAddress & address,bool encrypted=true)456 void TestConnect(const RawAddress& address, bool encrypted = true) {
457 // by default indicate link as encrypted
458 ON_CALL(btm_interface, GetSecurityFlagsByTransport(address, NotNull(), _))
459 .WillByDefault(DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(encrypted)));
460
461 EXPECT_CALL(gatt_interface, Open(gatt_if, address, BTM_BLE_DIRECT_CONNECTION, _));
462 CsisClient::Get()->Connect(address);
463 Mock::VerifyAndClearExpectations(&gatt_interface);
464 Mock::VerifyAndClearExpectations(&btm_interface);
465 }
466
TestDisconnect(const RawAddress & address,uint16_t conn_id)467 void TestDisconnect(const RawAddress& address, uint16_t conn_id) {
468 if (conn_id != GATT_INVALID_CONN_ID) {
469 EXPECT_CALL(gatt_interface, Close(conn_id));
470 EXPECT_CALL(*callbacks, OnConnectionState(test_address, ConnectionState::DISCONNECTED));
471 } else {
472 EXPECT_CALL(gatt_interface, CancelOpen(_, address, _));
473 }
474 CsisClient::Get()->Disconnect(address);
475 }
476
TestAddFromStorage(const RawAddress & address,uint16_t conn_id,std::vector<uint8_t> & storage_group_buf,std::vector<uint8_t> & storage_buf)477 void TestAddFromStorage(const RawAddress& address, uint16_t conn_id,
478 std::vector<uint8_t>& storage_group_buf,
479 std::vector<uint8_t>& storage_buf) {
480 EXPECT_CALL(*callbacks, OnConnectionState(address, ConnectionState::CONNECTED)).Times(1);
481 EXPECT_CALL(*callbacks, OnDeviceAvailable(address, _, _, _, _)).Times(AtLeast(1));
482
483 EXPECT_CALL(gatt_interface, Open(gatt_if, address, BTM_BLE_DIRECT_CONNECTION, true))
484 .WillOnce(Invoke([this, conn_id](tGATT_IF /*client_if*/, const RawAddress& remote_bda,
485 bool /*is_direct*/, bool /*opportunistic*/) {
486 InjectConnectedEvent(remote_bda, conn_id);
487 GetSearchCompleteEvent(conn_id);
488 }));
489
490 DeviceGroups::AddFromStorage(address, storage_group_buf);
491 CsisClient::AddFromStorage(address, storage_buf);
492 }
493
InjectEncryptionEvent(const RawAddress & test_address,uint16_t conn_id)494 void InjectEncryptionEvent(const RawAddress& test_address, uint16_t conn_id) {
495 tBTA_GATTC_ENC_CMPL_CB event_data = {
496 .client_if = static_cast<tGATT_IF>(conn_id),
497 .remote_bda = test_address,
498 };
499
500 gatt_callback(BTA_GATTC_ENC_CMPL_CB_EVT, (tBTA_GATTC*)&event_data);
501 }
502
InjectConnectedEvent(const RawAddress & address,uint16_t conn_id,tGATT_STATUS status=GATT_SUCCESS)503 void InjectConnectedEvent(const RawAddress& address, uint16_t conn_id,
504 tGATT_STATUS status = GATT_SUCCESS) {
505 tBTA_GATTC_OPEN event_data = {
506 .status = status,
507 .conn_id = conn_id,
508 .client_if = gatt_if,
509 .remote_bda = address,
510 .transport = BT_TRANSPORT_LE,
511 .mtu = 240,
512 };
513
514 gatt_callback(BTA_GATTC_OPEN_EVT, (tBTA_GATTC*)&event_data);
515 }
516
InjectDisconnectedEvent(const RawAddress & address,uint16_t conn_id,tGATT_DISCONN_REASON reason=GATT_CONN_TERMINATE_PEER_USER)517 void InjectDisconnectedEvent(const RawAddress& address, uint16_t conn_id,
518 tGATT_DISCONN_REASON reason = GATT_CONN_TERMINATE_PEER_USER) {
519 tBTA_GATTC_CLOSE event_data = {
520 .conn_id = conn_id,
521 .status = GATT_SUCCESS,
522 .client_if = gatt_if,
523 .remote_bda = address,
524 .reason = reason,
525 };
526
527 gatt_callback(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC*)&event_data);
528 }
529
GetSearchCompleteEvent(uint16_t conn_id)530 void GetSearchCompleteEvent(uint16_t conn_id) {
531 tBTA_GATTC_SEARCH_CMPL event_data = {
532 .conn_id = conn_id,
533 .status = GATT_SUCCESS,
534 };
535
536 gatt_callback(BTA_GATTC_SEARCH_CMPL_EVT, (tBTA_GATTC*)&event_data);
537 }
538
TestReadCharacteristic(const RawAddress & address,uint16_t conn_id,std::vector<uint16_t> handles)539 void TestReadCharacteristic(const RawAddress& address, uint16_t conn_id,
540 std::vector<uint16_t> handles) {
541 SetSampleDatabaseCsis(conn_id, 1);
542 TestAppRegister();
543 TestConnect(address);
544 InjectConnectedEvent(address, conn_id);
545
546 EXPECT_CALL(gatt_queue, ReadCharacteristic(conn_id, _, _, _)).WillRepeatedly(DoDefault());
547 for (auto const& handle : handles) {
548 EXPECT_CALL(gatt_queue, ReadCharacteristic(conn_id, handle, _, _)).WillOnce(DoDefault());
549 }
550
551 GetSearchCompleteEvent(conn_id);
552 TestAppUnregister();
553 }
554
TestGattWriteCCC(uint16_t ccc_handle,GattStatus status,int deregister_times)555 void TestGattWriteCCC(uint16_t ccc_handle, GattStatus status, int deregister_times) {
556 SetSampleDatabaseCsis(1, 1);
557 TestAppRegister();
558 TestConnect(test_address);
559 InjectConnectedEvent(test_address, 1);
560
561 auto WriteDescriptorCbGenerator = [](tGATT_STATUS status, uint16_t ccc_handle) {
562 return [status, ccc_handle](uint16_t conn_id, uint16_t handle, std::vector<uint8_t> value,
563 tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb,
564 void* cb_data) -> void {
565 if (cb) {
566 if (ccc_handle) {
567 handle = ccc_handle;
568 }
569 cb(conn_id, status, handle, value.size(), value.data(), cb_data);
570 }
571 };
572 };
573
574 // sirk, size, lock
575 EXPECT_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _))
576 .Times(3)
577 .WillOnce(Invoke(WriteDescriptorCbGenerator(GATT_SUCCESS, 0)))
578 .WillOnce(Invoke(WriteDescriptorCbGenerator(GATT_SUCCESS, 0)))
579 .WillOnce(Invoke(WriteDescriptorCbGenerator(status, ccc_handle)));
580
581 EXPECT_CALL(gatt_interface, DeregisterForNotifications(_, _, _)).Times(deregister_times);
582
583 GetSearchCompleteEvent(1);
584 Mock::VerifyAndClearExpectations(&gatt_interface);
585 }
586
GetDisconnectedEvent(const RawAddress & address,uint16_t conn_id)587 void GetDisconnectedEvent(const RawAddress& address, uint16_t conn_id) {
588 tBTA_GATTC_CLOSE event_data = {
589 .conn_id = conn_id,
590 .status = GATT_SUCCESS,
591 .client_if = gatt_if,
592 .remote_bda = address,
593 .reason = GATT_CONN_TERMINATE_PEER_USER,
594 };
595
596 gatt_callback(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC*)&event_data);
597 }
598
SetSampleCapIncludedDatabaseCsis(uint16_t conn_id,uint8_t rank,uint8_t sirk_msb=1)599 void SetSampleCapIncludedDatabaseCsis(uint16_t conn_id, uint8_t rank, uint8_t sirk_msb = 1) {
600 set_sample_cap_included_database(conn_id, true, false, rank, sirk_msb);
601 }
SetSampleDatabaseCsis(uint16_t conn_id,uint8_t rank,uint8_t sirk_msb=1)602 void SetSampleDatabaseCsis(uint16_t conn_id, uint8_t rank, uint8_t sirk_msb = 1) {
603 set_sample_database(conn_id, true, false, rank, sirk_msb);
604 }
SetSampleDatabaseNoCsis(uint16_t conn_id,uint8_t rank)605 void SetSampleDatabaseNoCsis(uint16_t conn_id, uint8_t rank) {
606 set_sample_database(conn_id, false, false, rank);
607 }
SetSampleDatabaseCsisBroken(uint16_t conn_id,uint rank)608 void SetSampleDatabaseCsisBroken(uint16_t conn_id, uint rank) {
609 set_sample_database(conn_id, false, true, rank);
610 }
SetSampleDatabaseDoubleCsis(uint16_t conn_id,uint8_t rank_1,uint8_t rank_2)611 void SetSampleDatabaseDoubleCsis(uint16_t conn_id, uint8_t rank_1, uint8_t rank_2) {
612 set_sample_database_double_csis(conn_id, rank_1, rank_2, false);
613 }
SetSampleDatabaseDoubleCsisBroken(uint16_t conn_id,uint8_t rank_1,uint8_t rank_2)614 void SetSampleDatabaseDoubleCsisBroken(uint16_t conn_id, uint8_t rank_1, uint8_t rank_2) {
615 set_sample_database_double_csis(conn_id, rank_1, rank_2, true);
616 }
617
618 std::unique_ptr<MockCsisCallbacks> callbacks;
619 std::unique_ptr<MockCsisCallbacks> lock_callback;
620 bluetooth::manager::MockBtmInterface btm_interface;
621 dm::MockBtaDmInterface dm_interface;
622 gatt::MockBtaGattInterface gatt_interface;
623 gatt::MockBtaGattQueue gatt_queue;
624 MockCsisLockCallback csis_lock_cb;
625 tBTA_GATTC_CBACK* gatt_callback;
626 const uint8_t gatt_if = 0xff;
627 std::map<uint16_t, std::list<gatt::Service>> services_map;
628
629 const RawAddress test_address = GetTestAddress(0);
630 const RawAddress test_address2 = GetTestAddress(1);
631 };
632
TEST_F(CsisClientTest,test_get_uninitialized)633 TEST_F(CsisClientTest, test_get_uninitialized) { ASSERT_EQ(CsisClient::Get(), nullptr); }
634
TEST_F(CsisClientTest,test_initialize)635 TEST_F(CsisClientTest, test_initialize) {
636 CsisClient::Initialize(callbacks.get(), base::DoNothing());
637 ASSERT_TRUE(CsisClient::IsCsisClientRunning());
638 CsisClient::CleanUp();
639 }
640
TEST_F(CsisClientTest,test_initialize_twice)641 TEST_F(CsisClientTest, test_initialize_twice) {
642 CsisClient::Initialize(callbacks.get(), base::DoNothing());
643 CsisClient* csis_p = CsisClient::Get();
644 CsisClient::Initialize(callbacks.get(), base::DoNothing());
645 ASSERT_EQ(csis_p, CsisClient::Get());
646 CsisClient::CleanUp();
647 }
648
TEST_F(CsisClientTest,test_cleanup_initialized)649 TEST_F(CsisClientTest, test_cleanup_initialized) {
650 CsisClient::Initialize(callbacks.get(), base::DoNothing());
651 CsisClient::CleanUp();
652 ASSERT_FALSE(CsisClient::IsCsisClientRunning());
653 }
654
TEST_F(CsisClientTest,test_cleanup_uninitialized)655 TEST_F(CsisClientTest, test_cleanup_uninitialized) {
656 CsisClient::CleanUp();
657 ASSERT_FALSE(CsisClient::IsCsisClientRunning());
658 }
659
TEST_F(CsisClientTest,test_app_registration)660 TEST_F(CsisClientTest, test_app_registration) {
661 TestAppRegister();
662 TestAppUnregister();
663 }
664
TEST_F(CsisClientTest,test_connect)665 TEST_F(CsisClientTest, test_connect) {
666 TestAppRegister();
667 TestConnect(GetTestAddress(0));
668 TestAppUnregister();
669 }
670
TEST_F(CsisClientTest,test_verify_opportunistic_connect_active_after_connect_timeout)671 TEST_F(CsisClientTest, test_verify_opportunistic_connect_active_after_connect_timeout) {
672 TestAppRegister();
673
674 std::vector<uint8_t> no_set_info;
675
676 DeviceGroups::AddFromStorage(test_address, no_set_info);
677 CsisClient::AddFromStorage(test_address, no_set_info);
678
679 Mock::VerifyAndClearExpectations(&gatt_interface);
680 Mock::VerifyAndClearExpectations(callbacks.get());
681
682 EXPECT_CALL(*callbacks, OnConnectionState(test_address, ConnectionState::DISCONNECTED)).Times(1);
683 TestConnect(test_address);
684
685 EXPECT_CALL(gatt_interface, CancelOpen(gatt_if, test_address, _)).Times(0);
686 EXPECT_CALL(gatt_interface, Open(gatt_if, test_address, BTM_BLE_DIRECT_CONNECTION, true))
687 .Times(1);
688
689 InjectConnectedEvent(test_address, 0, GATT_ERROR);
690 Mock::VerifyAndClearExpectations(&gatt_interface);
691 Mock::VerifyAndClearExpectations(callbacks.get());
692 TestAppUnregister();
693 }
694
TEST_F(CsisClientTest,test_disconnect_non_connected)695 TEST_F(CsisClientTest, test_disconnect_non_connected) {
696 TestAppRegister();
697 TestConnect(test_address);
698 TestDisconnect(test_address, GATT_INVALID_CONN_ID);
699 TestAppUnregister();
700 }
701
TEST_F(CsisClientTest,test_disconnect_connected)702 TEST_F(CsisClientTest, test_disconnect_connected) {
703 TestAppRegister();
704 TestConnect(test_address);
705 InjectConnectedEvent(test_address, 1);
706 TestDisconnect(test_address, 1);
707 InjectDisconnectedEvent(test_address, 1);
708 TestAppUnregister();
709 }
710
TEST_F(CsisClientTest,test_disconnected)711 TEST_F(CsisClientTest, test_disconnected) {
712 TestAppRegister();
713 TestConnect(test_address);
714 InjectConnectedEvent(test_address, 1);
715 EXPECT_CALL(*callbacks, OnConnectionState(test_address, ConnectionState::DISCONNECTED));
716 InjectDisconnectedEvent(test_address, 1);
717
718 TestAppUnregister();
719 }
720
TEST_F(CsisClientTest,test_connect_after_remove)721 TEST_F(CsisClientTest, test_connect_after_remove) {
722 TestAppRegister();
723 TestConnect(test_address);
724 InjectConnectedEvent(test_address, 1);
725 CsisClient::Get()->RemoveDevice(test_address);
726
727 EXPECT_CALL(*callbacks, OnConnectionState(test_address, ConnectionState::DISCONNECTED));
728 ON_CALL(btm_interface, IsLinkKeyKnown(_, _)).WillByDefault(Return(false));
729 CsisClient::Get()->Connect(test_address);
730 Mock::VerifyAndClearExpectations(callbacks.get());
731
732 TestAppUnregister();
733 }
734
TEST_F(CsisClientTest,test_discovery_csis_found)735 TEST_F(CsisClientTest, test_discovery_csis_found) {
736 SetSampleDatabaseCsis(1, 1);
737 TestAppRegister();
738 TestConnect(test_address);
739 EXPECT_CALL(*callbacks, OnConnectionState(test_address, ConnectionState::CONNECTED));
740 EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _, _, _, _));
741 InjectConnectedEvent(test_address, 1);
742 GetSearchCompleteEvent(1);
743 Mock::VerifyAndClearExpectations(callbacks.get());
744 TestAppUnregister();
745 }
746
TEST_F(CsisClientTest,test_discovery_csis_not_found)747 TEST_F(CsisClientTest, test_discovery_csis_not_found) {
748 SetSampleDatabaseNoCsis(1, 1);
749 TestAppRegister();
750 TestConnect(test_address);
751 EXPECT_CALL(gatt_interface, Close(1));
752 InjectConnectedEvent(test_address, 1);
753 GetSearchCompleteEvent(1);
754 Mock::VerifyAndClearExpectations(callbacks.get());
755 TestAppUnregister();
756 }
757
TEST_F(CsisClientTest,test_discovery_csis_broken)758 TEST_F(CsisClientTest, test_discovery_csis_broken) {
759 SetSampleDatabaseCsisBroken(1, 1);
760 TestAppRegister();
761 TestConnect(test_address);
762 EXPECT_CALL(gatt_interface, Close(1));
763 InjectConnectedEvent(test_address, 1);
764 GetSearchCompleteEvent(1);
765 Mock::VerifyAndClearExpectations(callbacks.get());
766 TestAppUnregister();
767 }
768
TEST_F(CsisClientTest,test_ccc_reg_fail_handle_not_found)769 TEST_F(CsisClientTest, test_ccc_reg_fail_handle_not_found) {
770 // service handle range: 0x0001 ~ 0x0030
771 uint16_t not_existed_ccc_handle = 0x0031;
772 TestGattWriteCCC(not_existed_ccc_handle, GATT_INVALID_HANDLE, 0);
773 }
774
TEST_F(CsisClientTest,test_ccc_reg_fail_handle_found)775 TEST_F(CsisClientTest, test_ccc_reg_fail_handle_found) {
776 // kCsisLockUuid ccc handle
777 uint16_t existed_ccc_hande = 0x0028;
778 TestGattWriteCCC(existed_ccc_hande, GATT_INVALID_HANDLE, 1);
779 }
780
TEST_F(CsisClientTest,test_ccc_reg_fail_out_of_sync)781 TEST_F(CsisClientTest, test_ccc_reg_fail_out_of_sync) {
782 // kCsisLockUuid ccc handle
783 uint16_t ccc_handle = 0x0028;
784 TestGattWriteCCC(ccc_handle, GATT_DATABASE_OUT_OF_SYNC, 0);
785 }
786
787 class CsisClientCallbackTest : public CsisClientTest {
788 protected:
789 const RawAddress test_address = GetTestAddress(0);
790 uint16_t conn_id = 22;
791
SetUp(void)792 void SetUp(void) override {
793 CsisClientTest::SetUp();
794 SetSampleDatabaseCsis(conn_id, 1);
795 TestAppRegister();
796 TestConnect(test_address);
797 InjectConnectedEvent(test_address, conn_id);
798 GetSearchCompleteEvent(conn_id);
799 }
800
TearDown(void)801 void TearDown(void) override {
802 TestAppUnregister();
803 CsisClientTest::TearDown();
804 }
805
GetNotificationEvent(uint16_t handle,std::vector<uint8_t> & value)806 void GetNotificationEvent(uint16_t handle, std::vector<uint8_t>& value) {
807 tBTA_GATTC_NOTIFY event_data = {
808 .conn_id = conn_id,
809 .bda = test_address,
810 .handle = handle,
811 .len = (uint8_t)value.size(),
812 .is_notify = true,
813 };
814
815 std::copy(value.begin(), value.end(), event_data.value);
816 gatt_callback(BTA_GATTC_NOTIF_EVT, (tBTA_GATTC*)&event_data);
817 }
818 };
819
TEST_F(CsisClientCallbackTest,test_on_group_lock_changed_group_not_found)820 TEST_F(CsisClientCallbackTest, test_on_group_lock_changed_group_not_found) {
821 bool callback_called = false;
822 EXPECT_CALL(*callbacks, OnGroupLockChanged(2, false, CsisGroupLockStatus::FAILED_INVALID_GROUP));
823 CsisClient::Get()->LockGroup(
824 2, true,
825 base::BindOnce(
826 [](bool* callback_called, int group_id, bool /*locked*/,
827 CsisGroupLockStatus status) {
828 if ((group_id == 2) && (status == CsisGroupLockStatus::FAILED_INVALID_GROUP)) {
829 *callback_called = true;
830 }
831 },
832 &callback_called));
833 ASSERT_TRUE(callback_called);
834 }
835
TEST_F(CsisClientTest,test_get_group_id)836 TEST_F(CsisClientTest, test_get_group_id) {
837 SetSampleDatabaseCsis(1, 1);
838 TestAppRegister();
839 TestConnect(test_address);
840 EXPECT_CALL(*callbacks, OnConnectionState(test_address, ConnectionState::CONNECTED));
841 EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _, _, _, _));
842 InjectConnectedEvent(test_address, 1);
843 GetSearchCompleteEvent(1);
844 ASSERT_EQ(1, CsisClient::Get()->GetGroupId(test_address));
845 TestAppUnregister();
846 }
847
TEST_F(CsisClientTest,test_search_complete_before_encryption)848 TEST_F(CsisClientTest, test_search_complete_before_encryption) {
849 SetSampleDatabaseCsis(1, 1);
850 TestAppRegister();
851 TestConnect(test_address, false);
852 EXPECT_CALL(*callbacks, OnConnectionState(test_address, ConnectionState::CONNECTED)).Times(0);
853 EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _, _, _, _)).Times(0);
854
855 ON_CALL(btm_interface, BTM_IsEncrypted(test_address, _)).WillByDefault(DoAll(Return(false)));
856
857 InjectConnectedEvent(test_address, 1);
858 GetSearchCompleteEvent(1);
859 Mock::VerifyAndClearExpectations(callbacks.get());
860
861 /* Incject encryption and expect device connection */
862 EXPECT_CALL(*callbacks, OnConnectionState(test_address, ConnectionState::CONNECTED)).Times(1);
863 EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _, _, _, _)).Times(1);
864
865 ON_CALL(btm_interface, BTM_IsEncrypted(test_address, _)).WillByDefault(DoAll(Return(true)));
866 EXPECT_CALL(gatt_interface, ServiceSearchRequest(_, _)).Times(1);
867
868 InjectEncryptionEvent(test_address, 1);
869 GetSearchCompleteEvent(1);
870
871 Mock::VerifyAndClearExpectations(&gatt_interface);
872 Mock::VerifyAndClearExpectations(callbacks.get());
873
874 TestAppUnregister();
875 }
876
TEST_F(CsisClientTest,test_disconnect_when_link_key_is_gone)877 TEST_F(CsisClientTest, test_disconnect_when_link_key_is_gone) {
878 SetSampleDatabaseCsis(1, 1);
879 TestAppRegister();
880 TestConnect(test_address, false);
881 EXPECT_CALL(*callbacks, OnConnectionState(test_address, ConnectionState::CONNECTED)).Times(0);
882
883 ON_CALL(btm_interface, BTM_IsEncrypted(test_address, _)).WillByDefault(DoAll(Return(false)));
884 ON_CALL(btm_interface, SetEncryption(test_address, _, _, _, _))
885 .WillByDefault(Return(tBTM_STATUS::BTM_ERR_KEY_MISSING));
886
887 EXPECT_CALL(gatt_interface, Close(1));
888
889 InjectConnectedEvent(test_address, 1);
890
891 Mock::VerifyAndClearExpectations(&gatt_interface);
892 Mock::VerifyAndClearExpectations(callbacks.get());
893
894 TestAppUnregister();
895 }
896
TEST_F(CsisClientTest,test_is_group_empty)897 TEST_F(CsisClientTest, test_is_group_empty) {
898 std::list<std::shared_ptr<CsisGroup>> csis_groups_;
899 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
900 csis_groups_.push_back(g_1);
901
902 ASSERT_TRUE(g_1->IsEmpty());
903 }
904
TEST_F(CsisClientTest,test_add_device_to_group)905 TEST_F(CsisClientTest, test_add_device_to_group) {
906 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
907 auto d_1 = std::make_shared<CsisDevice>();
908
909 ASSERT_TRUE(g_1->IsEmpty());
910 g_1->AddDevice(d_1);
911 ASSERT_FALSE(g_1->IsEmpty());
912 }
913
TEST_F(CsisClientTest,test_get_set_desired_size)914 TEST_F(CsisClientTest, test_get_set_desired_size) {
915 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
916 g_1->SetDesiredSize(10);
917 ASSERT_EQ(g_1->GetDesiredSize(), 10);
918 }
919
TEST_F(CsisClientTest,test_is_device_in_the_group)920 TEST_F(CsisClientTest, test_is_device_in_the_group) {
921 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
922 auto d_1 = std::make_shared<CsisDevice>();
923 g_1->AddDevice(d_1);
924 g_1->IsDeviceInTheGroup(d_1);
925 }
926
TEST_F(CsisClientTest,test_get_current_size)927 TEST_F(CsisClientTest, test_get_current_size) {
928 const RawAddress test_address_1 = GetTestAddress(0);
929 const RawAddress test_address_2 = GetTestAddress(1);
930 const RawAddress test_address_3 = GetTestAddress(2);
931 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
932 auto d_1 = std::make_shared<CsisDevice>(test_address_1, true);
933 auto d_2 = std::make_shared<CsisDevice>(test_address_2, true);
934 auto d_3 = std::make_shared<CsisDevice>(test_address_3, true);
935 g_1->AddDevice(d_1);
936 g_1->AddDevice(d_2);
937 g_1->AddDevice(d_3);
938 ASSERT_EQ(3, g_1->GetCurrentSize());
939 }
940
TEST_F(CsisClientTest,test_set_current_lock_state_unset)941 TEST_F(CsisClientTest, test_set_current_lock_state_unset) {
942 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
943 g_1->SetCurrentLockState(CsisLockState::CSIS_STATE_UNSET);
944 ASSERT_EQ(g_1->GetCurrentLockState(), CsisLockState::CSIS_STATE_UNSET);
945 }
946
TEST_F(CsisClientTest,test_set_current_lock_state_locked)947 TEST_F(CsisClientTest, test_set_current_lock_state_locked) {
948 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
949 g_1->SetCurrentLockState(CsisLockState::CSIS_STATE_LOCKED);
950 ASSERT_EQ(g_1->GetCurrentLockState(), CsisLockState::CSIS_STATE_LOCKED);
951 }
952
TEST_F(CsisClientTest,test_set_current_lock_state_unlocked)953 TEST_F(CsisClientTest, test_set_current_lock_state_unlocked) {
954 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
955 g_1->SetCurrentLockState(CsisLockState::CSIS_STATE_UNLOCKED);
956 ASSERT_EQ(g_1->GetCurrentLockState(), CsisLockState::CSIS_STATE_UNLOCKED);
957 }
958
TEST_F(CsisClientTest,test_set_various_lock_states)959 TEST_F(CsisClientTest, test_set_various_lock_states) {
960 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
961 g_1->SetCurrentLockState(CsisLockState::CSIS_STATE_UNLOCKED);
962 ASSERT_EQ(g_1->GetCurrentLockState(), CsisLockState::CSIS_STATE_UNLOCKED);
963 g_1->SetCurrentLockState(CsisLockState::CSIS_STATE_LOCKED);
964 ASSERT_EQ(g_1->GetCurrentLockState(), CsisLockState::CSIS_STATE_LOCKED);
965 g_1->SetCurrentLockState(CsisLockState::CSIS_STATE_UNSET);
966 ASSERT_EQ(g_1->GetCurrentLockState(), CsisLockState::CSIS_STATE_UNSET);
967 }
968
TEST_F(CsisClientTest,test_set_discovery_state_completed)969 TEST_F(CsisClientTest, test_set_discovery_state_completed) {
970 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
971 g_1->SetDiscoveryState(CsisDiscoveryState::CSIS_DISCOVERY_COMPLETED);
972 ASSERT_EQ(g_1->GetDiscoveryState(), CsisDiscoveryState::CSIS_DISCOVERY_COMPLETED);
973 }
974
TEST_F(CsisClientTest,test_set_discovery_state_idle)975 TEST_F(CsisClientTest, test_set_discovery_state_idle) {
976 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
977 g_1->SetDiscoveryState(CsisDiscoveryState::CSIS_DISCOVERY_IDLE);
978 ASSERT_EQ(g_1->GetDiscoveryState(), CsisDiscoveryState::CSIS_DISCOVERY_IDLE);
979 }
980
TEST_F(CsisClientTest,test_set_discovery_state_ongoing)981 TEST_F(CsisClientTest, test_set_discovery_state_ongoing) {
982 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
983 g_1->SetDiscoveryState(CsisDiscoveryState::CSIS_DISCOVERY_ONGOING);
984 ASSERT_EQ(g_1->GetDiscoveryState(), CsisDiscoveryState::CSIS_DISCOVERY_ONGOING);
985 }
986
TEST_F(CsisClientTest,test_set_various_discovery_states)987 TEST_F(CsisClientTest, test_set_various_discovery_states) {
988 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
989 g_1->SetDiscoveryState(CsisDiscoveryState::CSIS_DISCOVERY_COMPLETED);
990 ASSERT_EQ(g_1->GetDiscoveryState(), CsisDiscoveryState::CSIS_DISCOVERY_COMPLETED);
991 g_1->SetDiscoveryState(CsisDiscoveryState::CSIS_DISCOVERY_IDLE);
992 ASSERT_EQ(g_1->GetDiscoveryState(), CsisDiscoveryState::CSIS_DISCOVERY_IDLE);
993 g_1->SetDiscoveryState(CsisDiscoveryState::CSIS_DISCOVERY_ONGOING);
994 ASSERT_EQ(g_1->GetDiscoveryState(), CsisDiscoveryState::CSIS_DISCOVERY_ONGOING);
995 }
996
TEST_F(CsisClientTest,test_get_first_last_device)997 TEST_F(CsisClientTest, test_get_first_last_device) {
998 const RawAddress test_address_3 = GetTestAddress(3);
999 const RawAddress test_address_4 = GetTestAddress(4);
1000 const RawAddress test_address_5 = GetTestAddress(5);
1001 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
1002 auto d_1 = std::make_shared<CsisDevice>(test_address_3, true);
1003 auto d_2 = std::make_shared<CsisDevice>(test_address_4, true);
1004 auto d_3 = std::make_shared<CsisDevice>(test_address_5, true);
1005 g_1->AddDevice(d_1);
1006 g_1->AddDevice(d_2);
1007 g_1->AddDevice(d_3);
1008 ASSERT_EQ(g_1->GetLastDevice(), d_3);
1009 ASSERT_EQ(g_1->GetFirstDevice(), d_1);
1010 }
1011
TEST_F(CsisClientTest,test_get_set_sirk)1012 TEST_F(CsisClientTest, test_get_set_sirk) {
1013 auto g_1 = std::make_shared<CsisGroup>(666, bluetooth::Uuid::kEmpty);
1014 Octet16 sirk = {1};
1015 g_1->SetSirk(sirk);
1016 ASSERT_EQ(g_1->GetSirk(), sirk);
1017 }
1018
TEST_F(CsisClientTest,test_not_open_duplicate_active_scan_while_bonding_set_member)1019 TEST_F(CsisClientTest, test_not_open_duplicate_active_scan_while_bonding_set_member) {
1020 uint16_t conn_id = 0x0001;
1021 EXPECT_CALL(dm_interface, BTA_DmBleCsisObserve(true, _)).Times(1);
1022 SetSampleDatabaseCsis(conn_id, 1, 1);
1023 TestAppRegister();
1024
1025 // Here we handle background scan request
1026 Mock::VerifyAndClearExpectations(&dm_interface);
1027
1028 TestConnect(test_address);
1029 InjectConnectedEvent(test_address, 1);
1030
1031 auto ReadCharacteristicCbGenerator = []() {
1032 return [](uint16_t conn_id, uint16_t handle, GATT_READ_OP_CB cb, void* cb_data) -> void {
1033 std::vector<uint8_t> value;
1034 switch (handle) {
1035 case 0x0003:
1036 // device name
1037 value.resize(20);
1038 break;
1039 case 0x0021:
1040 // plain sirk
1041 value.resize(17);
1042 value.assign(17, 1);
1043 break;
1044 case 0x0024:
1045 // size
1046 value.resize(1);
1047 value.assign(1, 2);
1048 break;
1049 case 0x0027:
1050 // lock
1051 value.resize(2);
1052 break;
1053 case 0x0030:
1054 // rank
1055 value.resize(1);
1056 value.assign(1, 1);
1057 break;
1058 default:
1059 FAIL();
1060 return;
1061 }
1062 if (cb) {
1063 cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
1064 }
1065 };
1066 };
1067
1068 // We should read 4 times for sirk, rank, size, and lock characteristics
1069 EXPECT_CALL(gatt_queue, ReadCharacteristic(conn_id, _, _, _))
1070 .Times(4)
1071 .WillOnce(Invoke(ReadCharacteristicCbGenerator()))
1072 .WillOnce(Invoke(ReadCharacteristicCbGenerator()))
1073 .WillOnce(Invoke(ReadCharacteristicCbGenerator()))
1074 .WillOnce(Invoke(ReadCharacteristicCbGenerator()));
1075
1076 // Here is actual active scan request for the first device
1077 tBTA_DM_SEARCH_CBACK* p_results_cb = nullptr;
1078 EXPECT_CALL(dm_interface, BTA_DmBleCsisObserve(true, _))
1079 .Times(1)
1080 .WillOnce(DoAll(SaveArg<1>(&p_results_cb)));
1081
1082 GetSearchCompleteEvent(conn_id);
1083
1084 Mock::VerifyAndClearExpectations(&dm_interface);
1085
1086 // Simulate we find the set member
1087 tBTA_DM_SEARCH result;
1088 result.inq_res.include_rsi = true;
1089 std::vector<uint8_t> rsi = {0x07, 0x2e, 0x00, 0xed, 0x1a, 0x00, 0x00, 0x00};
1090 result.inq_res.p_eir = rsi.data();
1091 result.inq_res.eir_len = 8;
1092 result.inq_res.bd_addr = test_address2;
1093
1094 // CSIS client should process set member event to JNI
1095 EXPECT_CALL(*callbacks, OnSetMemberAvailable(test_address2, 1));
1096
1097 p_results_cb(BTA_DM_INQ_RES_EVT, &result);
1098
1099 Mock::VerifyAndClearExpectations(&dm_interface);
1100
1101 EXPECT_CALL(dm_interface, BTA_DmBleCsisObserve(true, _)).Times(0);
1102
1103 // Simulate getting duplicate response from remote for the first device
1104 // At this momoment we should not open second active scan because the set
1105 // member is already cached and waiting for bonding
1106 GetSearchCompleteEvent(conn_id);
1107
1108 Mock::VerifyAndClearExpectations(&dm_interface);
1109 }
1110
TEST_F(CsisClientTest,test_csis_member_not_found)1111 TEST_F(CsisClientTest, test_csis_member_not_found) {
1112 EXPECT_CALL(dm_interface, BTA_DmBleCsisObserve(true, _)).Times(1);
1113 SetSampleDatabaseDoubleCsis(0x001, 1, 2);
1114 TestAppRegister();
1115
1116 /* Here we handle Background Scan request */
1117 Mock::VerifyAndClearExpectations(&dm_interface);
1118
1119 tBTA_DM_SEARCH_CBACK* p_results_cb = nullptr;
1120 /* Here is actual Active Scan request */
1121 EXPECT_CALL(dm_interface, BTA_DmBleCsisObserve(true, _))
1122 .WillOnce(DoAll(SaveArg<1>(&p_results_cb)));
1123
1124 TestConnect(test_address);
1125 InjectConnectedEvent(test_address, 1);
1126 GetSearchCompleteEvent(1);
1127
1128 Mock::VerifyAndClearExpectations(&dm_interface);
1129 /* Verify that scanner has been called to start filtering */
1130 ASSERT_EQ(1, get_func_call_count("set_empty_filter"));
1131
1132 /* Check callback is not null and simulate no member found and scan
1133 * completed*/
1134 ASSERT_NE(p_results_cb, nullptr);
1135
1136 tBTA_DM_SEARCH result;
1137 result.observe_cmpl.num_resps = 80;
1138
1139 p_results_cb(BTA_DM_OBSERVE_CMPL_EVT, &result);
1140
1141 /* Verify that scanner has been called to stop filtering */
1142 ASSERT_EQ(2, get_func_call_count("set_empty_filter"));
1143 }
1144
1145 class CsisMultiClientTest : public CsisClientTest {
1146 protected:
1147 const RawAddress test_address_1 = GetTestAddress(1);
1148 const RawAddress test_address_2 = GetTestAddress(2);
1149
SetUp(void)1150 void SetUp(void) override {
1151 CsisClientTest::SetUp();
1152 TestAppRegister();
1153 SetSampleDatabaseDoubleCsis(0x001, 1, 2);
1154 }
1155 };
1156
1157 class CsisMultiClientTestBroken : public CsisClientTest {
1158 protected:
1159 const RawAddress test_address_1 = GetTestAddress(1);
1160 const RawAddress test_address_2 = GetTestAddress(2);
1161
SetUp(void)1162 void SetUp(void) override {
1163 CsisClientTest::SetUp();
1164 TestAppRegister();
1165 SetSampleDatabaseDoubleCsisBroken(0x001, 1, 2);
1166 }
1167 };
1168
TEST_F(CsisMultiClientTest,test_add_multiple_instances)1169 TEST_F(CsisMultiClientTest, test_add_multiple_instances) {
1170 TestAppUnregister();
1171 CsisClientTest::TearDown();
1172 }
1173
TEST_F(CsisMultiClientTest,test_cleanup_multiple_instances)1174 TEST_F(CsisMultiClientTest, test_cleanup_multiple_instances) {
1175 CsisClient::CleanUp();
1176 CsisClient::IsCsisClientRunning();
1177 }
1178
TEST_F(CsisMultiClientTest,test_connect_multiple_instances)1179 TEST_F(CsisMultiClientTest, test_connect_multiple_instances) {
1180 TestConnect(GetTestAddress(0));
1181 TestAppUnregister();
1182 }
1183
TEST_F(CsisMultiClientTest,test_disconnect_multiple_instances)1184 TEST_F(CsisMultiClientTest, test_disconnect_multiple_instances) {
1185 TestConnect(test_address);
1186 InjectConnectedEvent(test_address, 1);
1187 EXPECT_CALL(*callbacks, OnConnectionState(test_address, ConnectionState::DISCONNECTED));
1188 InjectDisconnectedEvent(test_address, 1);
1189
1190 TestAppUnregister();
1191 CsisClientTest::TearDown();
1192 }
1193
TEST_F(CsisMultiClientTest,test_lock_multiple_instances)1194 TEST_F(CsisMultiClientTest, test_lock_multiple_instances) {
1195 TestConnect(test_address);
1196 InjectConnectedEvent(test_address, 1);
1197 GetSearchCompleteEvent(1);
1198
1199 EXPECT_CALL(*callbacks, OnGroupLockChanged(1, true, CsisGroupLockStatus::SUCCESS));
1200 EXPECT_CALL(*csis_lock_callback_mock, CsisGroupLockCb(1, true, CsisGroupLockStatus::SUCCESS));
1201 ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _))
1202 .WillByDefault(Invoke([](uint16_t conn_id, uint16_t handle, std::vector<uint8_t> value,
1203 tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb,
1204 void* cb_data) -> void {
1205 if (cb) {
1206 cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
1207 }
1208 }));
1209 CsisClient::Get()->LockGroup(
1210 1, true, base::BindOnce([](int group_id, bool locked, CsisGroupLockStatus status) {
1211 csis_lock_callback_mock->CsisGroupLockCb(group_id, locked, status);
1212 }));
1213
1214 EXPECT_CALL(*callbacks, OnGroupLockChanged(2, true, CsisGroupLockStatus::SUCCESS));
1215 EXPECT_CALL(*csis_lock_callback_mock, CsisGroupLockCb(2, true, CsisGroupLockStatus::SUCCESS));
1216 CsisClient::Get()->LockGroup(
1217 2, true, base::BindOnce([](int group_id, bool locked, CsisGroupLockStatus status) {
1218 csis_lock_callback_mock->CsisGroupLockCb(group_id, locked, status);
1219 }));
1220 }
1221
TEST_F(CsisMultiClientTest,test_unlock_multiple_instances)1222 TEST_F(CsisMultiClientTest, test_unlock_multiple_instances) {
1223 TestConnect(test_address);
1224 InjectConnectedEvent(test_address, 1);
1225 GetSearchCompleteEvent(1);
1226
1227 ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _))
1228 .WillByDefault(Invoke([](uint16_t conn_id, uint16_t handle, std::vector<uint8_t> value,
1229 tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb,
1230 void* cb_data) -> void {
1231 if (cb) {
1232 cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
1233 }
1234 }));
1235 CsisClient::Get()->LockGroup(
1236 1, true, base::BindOnce([](int group_id, bool locked, CsisGroupLockStatus status) {
1237 csis_lock_callback_mock->CsisGroupLockCb(group_id, locked, status);
1238 }));
1239
1240 EXPECT_CALL(*callbacks, OnGroupLockChanged(1, false, CsisGroupLockStatus::SUCCESS));
1241 EXPECT_CALL(*csis_lock_callback_mock, CsisGroupLockCb(1, false, CsisGroupLockStatus::SUCCESS));
1242 CsisClient::Get()->LockGroup(
1243 1, false, base::BindOnce([](int group_id, bool locked, CsisGroupLockStatus status) {
1244 csis_lock_callback_mock->CsisGroupLockCb(group_id, locked, status);
1245 }));
1246 }
1247
TEST_F(CsisMultiClientTest,test_disconnect_locked_multiple_instances)1248 TEST_F(CsisMultiClientTest, test_disconnect_locked_multiple_instances) {
1249 TestConnect(test_address);
1250 InjectConnectedEvent(test_address, 1);
1251 GetSearchCompleteEvent(1);
1252
1253 TestConnect(test_address2);
1254 InjectConnectedEvent(test_address2, 2);
1255 GetSearchCompleteEvent(2);
1256
1257 EXPECT_CALL(*callbacks, OnGroupLockChanged(1, true, CsisGroupLockStatus::SUCCESS));
1258 EXPECT_CALL(*csis_lock_callback_mock, CsisGroupLockCb(1, true, CsisGroupLockStatus::SUCCESS));
1259 ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _))
1260 .WillByDefault(Invoke([](uint16_t conn_id, uint16_t handle, std::vector<uint8_t> value,
1261 tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb,
1262 void* cb_data) -> void {
1263 if (cb) {
1264 cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
1265 }
1266 }));
1267 CsisClient::Get()->LockGroup(
1268 1, true, base::BindOnce([](int group_id, bool locked, CsisGroupLockStatus status) {
1269 csis_lock_callback_mock->CsisGroupLockCb(group_id, locked, status);
1270 }));
1271
1272 EXPECT_CALL(*callbacks,
1273 OnGroupLockChanged(1, false, CsisGroupLockStatus::LOCKED_GROUP_MEMBER_LOST));
1274 InjectDisconnectedEvent(test_address, 2, GATT_CONN_TIMEOUT);
1275 }
1276
TEST_F(CsisMultiClientTest,test_discover_multiple_instances)1277 TEST_F(CsisMultiClientTest, test_discover_multiple_instances) {
1278 TestConnect(test_address);
1279 EXPECT_CALL(*callbacks, OnConnectionState(test_address, ConnectionState::CONNECTED)).Times(1);
1280 EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _, _, _, _)).Times(2);
1281 InjectConnectedEvent(test_address, 1);
1282 GetSearchCompleteEvent(1);
1283 Mock::VerifyAndClearExpectations(callbacks.get());
1284 TestAppUnregister();
1285 }
1286
TEST_F(CsisClientTest,test_storage_calls)1287 TEST_F(CsisClientTest, test_storage_calls) {
1288 SetSampleDatabaseCsis(1, 1);
1289
1290 ASSERT_EQ(0, get_func_call_count("btif_storage_load_bonded_csis_devices"));
1291 TestAppRegister();
1292 ASSERT_EQ(1, get_func_call_count("btif_storage_load_bonded_csis_devices"));
1293
1294 ASSERT_EQ(0, get_func_call_count("btif_storage_update_csis_info"));
1295 TestConnect(test_address);
1296 InjectConnectedEvent(test_address, 1);
1297 GetSearchCompleteEvent(1);
1298 ASSERT_EQ(1, get_func_call_count("btif_storage_update_csis_info"));
1299
1300 ASSERT_EQ(0, get_func_call_count("btif_storage_remove_csis_device"));
1301 CsisClient::Get()->RemoveDevice(test_address);
1302 /* It is 0 because btif_csis_client.cc calls that */
1303 ASSERT_EQ(0, get_func_call_count("btif_storage_remove_csis_device"));
1304
1305 TestAppUnregister();
1306 }
1307
TEST_F(CsisClientTest,test_storage_content)1308 TEST_F(CsisClientTest, test_storage_content) {
1309 // Two devices in one set
1310 SetSampleCapIncludedDatabaseCsis(1, 1);
1311 SetSampleCapIncludedDatabaseCsis(2, 2);
1312 // Devices in the other set
1313 SetSampleCapIncludedDatabaseCsis(3, 1, 2);
1314 SetSampleCapIncludedDatabaseCsis(4, 1, 3);
1315
1316 TestAppRegister();
1317 TestConnect(GetTestAddress(1));
1318 InjectConnectedEvent(GetTestAddress(1), 1);
1319 GetSearchCompleteEvent(1);
1320 ASSERT_EQ(1, CsisClient::Get()->GetGroupId(
1321 GetTestAddress(1), bluetooth::Uuid::From16Bit(UUID_COMMON_AUDIO_SERVICE)));
1322
1323 TestConnect(GetTestAddress(2));
1324 InjectConnectedEvent(GetTestAddress(2), 2);
1325 GetSearchCompleteEvent(2);
1326 ASSERT_EQ(1, CsisClient::Get()->GetGroupId(
1327 GetTestAddress(2), bluetooth::Uuid::From16Bit(UUID_COMMON_AUDIO_SERVICE)));
1328
1329 TestConnect(GetTestAddress(3));
1330 InjectConnectedEvent(GetTestAddress(3), 3);
1331 GetSearchCompleteEvent(3);
1332 ASSERT_EQ(2, CsisClient::Get()->GetGroupId(
1333 GetTestAddress(3), bluetooth::Uuid::From16Bit(UUID_COMMON_AUDIO_SERVICE)));
1334
1335 std::vector<uint8_t> dev1_storage;
1336 std::vector<uint8_t> dev2_storage;
1337 std::vector<uint8_t> dev3_storage;
1338
1339 // Store to byte buffer
1340 CsisClient::GetForStorage(GetTestAddress(1), dev1_storage);
1341 CsisClient::GetForStorage(GetTestAddress(2), dev2_storage);
1342 CsisClient::GetForStorage(GetTestAddress(3), dev3_storage);
1343
1344 ASSERT_NE(0u, dev1_storage.size());
1345 ASSERT_NE(0u, dev2_storage.size());
1346 ASSERT_NE(0u, dev3_storage.size());
1347
1348 std::vector<uint8_t> dev1_group_storage;
1349 std::vector<uint8_t> dev2_group_storage;
1350 std::vector<uint8_t> dev3_group_storage;
1351
1352 DeviceGroups::GetForStorage(GetTestAddress(1), dev1_group_storage);
1353 DeviceGroups::GetForStorage(GetTestAddress(2), dev2_group_storage);
1354 DeviceGroups::GetForStorage(GetTestAddress(3), dev3_group_storage);
1355
1356 ASSERT_NE(0u, dev1_group_storage.size());
1357 ASSERT_NE(0u, dev2_group_storage.size());
1358 ASSERT_NE(0u, dev3_group_storage.size());
1359
1360 // Clean it up
1361 TestAppUnregister();
1362
1363 // Reinitialize service
1364 TestAppRegister();
1365
1366 // Restore dev1 from the byte buffer
1367 TestAddFromStorage(GetTestAddress(1), 1, dev1_group_storage, dev1_storage);
1368 ASSERT_EQ(1, CsisClient::Get()->GetGroupId(
1369 GetTestAddress(1), bluetooth::Uuid::From16Bit(UUID_COMMON_AUDIO_SERVICE)));
1370
1371 // Restore dev2 from the byte buffer
1372 TestAddFromStorage(GetTestAddress(2), 2, dev2_group_storage, dev2_storage);
1373 ASSERT_EQ(1, CsisClient::Get()->GetGroupId(
1374 GetTestAddress(2), bluetooth::Uuid::From16Bit(UUID_COMMON_AUDIO_SERVICE)));
1375
1376 // Restore dev3 from the byte buffer
1377 TestAddFromStorage(GetTestAddress(3), 3, dev3_group_storage, dev3_storage);
1378 ASSERT_EQ(2, CsisClient::Get()->GetGroupId(
1379 GetTestAddress(3), bluetooth::Uuid::From16Bit(UUID_COMMON_AUDIO_SERVICE)));
1380
1381 // Restore not inerrogated dev4 - empty buffer but valid sirk for group 2
1382 std::vector<uint8_t> no_set_info;
1383 TestAddFromStorage(GetTestAddress(4), 4, no_set_info, no_set_info);
1384 ASSERT_EQ(3, CsisClient::Get()->GetGroupId(
1385 GetTestAddress(4), bluetooth::Uuid::From16Bit(UUID_COMMON_AUDIO_SERVICE)));
1386
1387 TestAppUnregister();
1388 }
1389
TEST_F(CsisClientTest,test_database_out_of_sync)1390 TEST_F(CsisClientTest, test_database_out_of_sync) {
1391 auto test_address = GetTestAddress(0);
1392 auto conn_id = 1;
1393
1394 TestAppRegister();
1395 SetSampleDatabaseCsis(conn_id, 1);
1396 TestConnect(test_address);
1397 InjectConnectedEvent(test_address, conn_id);
1398 GetSearchCompleteEvent(conn_id);
1399 ASSERT_EQ(1, CsisClient::Get()->GetGroupId(test_address, bluetooth::Uuid::From16Bit(0x0000)));
1400
1401 // Simulated database changed on the remote side.
1402 ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _))
1403 .WillByDefault(Invoke([this](uint16_t conn_id, uint16_t handle,
1404 std::vector<uint8_t> value, tGATT_WRITE_TYPE /*write_type*/,
1405 GATT_WRITE_OP_CB cb, void* cb_data) {
1406 auto* svc = gatt::FindService(services_map[conn_id], handle);
1407 if (svc == nullptr) {
1408 return;
1409 }
1410
1411 tGATT_STATUS status = GATT_DATABASE_OUT_OF_SYNC;
1412 if (cb) {
1413 cb(conn_id, status, handle, value.size(), value.data(), cb_data);
1414 }
1415 }));
1416
1417 ON_CALL(gatt_interface, ServiceSearchRequest(_, _)).WillByDefault(Return());
1418 EXPECT_CALL(gatt_interface, ServiceSearchRequest(_, _));
1419 CsisClient::Get()->LockGroup(
1420 1, true, base::BindOnce([](int group_id, bool locked, CsisGroupLockStatus status) {
1421 csis_lock_callback_mock->CsisGroupLockCb(group_id, locked, status);
1422 }));
1423 TestAppUnregister();
1424 }
1425
1426 } // namespace
1427 } // namespace internal
1428 } // namespace csis
1429 } // namespace bluetooth
1430