1 /*
2 * Copyright 2020 HIMSA II K/S - www.himsa.dk.
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 <bluetooth/log.h>
19 #include <com_android_bluetooth_flags.h>
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22
23 #include <vector>
24
25 #include "bta/test/common/fake_osi.h"
26 #include "hci/controller_interface_mock.h"
27 #include "stack/include/bt_hdr.h"
28 #include "stack/include/bt_psm_types.h"
29 #include "stack/include/l2cdefs.h"
30 #include "stack/test/common/mock_btif_storage.h"
31 #include "stack/test/common/mock_btm_api_layer.h"
32 #include "stack/test/common/mock_eatt.h"
33 #include "stack/test/common/mock_gatt_layer.h"
34 #include "stack/test/common/mock_l2cap_layer.h"
35 #include "test/mock/mock_main_shim_entry.h"
36 #include "test/mock/mock_stack_l2cap_interface.h"
37 #include "types/raw_address.h"
38
39 // TODO(b/369381361) Enfore -Wmissing-prototypes
40 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
41
42 using testing::_;
43 using testing::DoAll;
44 using testing::MockFunction;
45 using testing::NiceMock;
46 using testing::NotNull;
47 using testing::Return;
48 using testing::SaveArg;
49 using testing::SaveArgPointee;
50 using testing::StrictMock;
51
52 using bluetooth::eatt::EattChannel;
53 using bluetooth::eatt::EattChannelState;
54 using namespace bluetooth;
55
56 #define BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK 0x01
57
58 extern struct fake_osi_alarm_set_on_mloop fake_osi_alarm_set_on_mloop_;
59
60 /* Needed for testing context */
61 static tGATT_TCB test_tcb;
btif_storage_add_eatt_supported(const RawAddress &)62 void btif_storage_add_eatt_supported(const RawAddress& /*addr*/) { return; }
gatt_consolidate(const RawAddress &,const RawAddress &)63 void gatt_consolidate(const RawAddress& /*identity_addr*/, const RawAddress& /*rpa*/) {}
gatt_data_process(tGATT_TCB &,uint16_t,BT_HDR *)64 void gatt_data_process(tGATT_TCB& /*tcb*/, uint16_t /*cid*/, BT_HDR* /*p_buf*/) { return; }
gatt_find_tcb_by_addr(const RawAddress &,tBT_TRANSPORT)65 tGATT_TCB* gatt_find_tcb_by_addr(const RawAddress& /*bda*/, tBT_TRANSPORT /*transport*/) {
66 log::info("");
67 return &test_tcb;
68 }
69
70 namespace {
71 const RawAddress test_address({0x11, 0x11, 0x11, 0x11, 0x11, 0x11});
72 std::vector<uint16_t> test_local_cids{61, 62, 63, 64, 65};
73
74 class EattTest : public ::testing::Test {
75 protected:
ConnectDeviceEattSupported(int num_of_accepted_connections,bool collision=false)76 void ConnectDeviceEattSupported(int num_of_accepted_connections, bool collision = false) {
77 ON_CALL(gatt_interface_, ClientReadSupportedFeatures)
78 .WillByDefault([](const RawAddress& addr,
79 base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
80 std::move(cb).Run(addr, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK);
81 return true;
82 });
83 EXPECT_CALL(gatt_interface_, GetEattSupport).WillRepeatedly([](const RawAddress& /*addr*/) {
84 return true;
85 });
86
87 EXPECT_CALL(mock_stack_l2cap_interface_,
88 L2CA_ConnectCreditBasedReq(BT_PSM_EATT, test_address, _))
89 .WillOnce(Return(test_local_cids));
90 ON_CALL(mock_stack_l2cap_interface_, L2CA_DisconnectReq(test_local_cids[0]))
91 .WillByDefault(Return(true));
92
93 eatt_instance_->Connect(test_address);
94
95 if (collision) {
96 /* Collision should be handled only if all channels has been rejected in
97 * first place.*/
98 if (num_of_accepted_connections == 0) {
99 EXPECT_CALL(mock_stack_l2cap_interface_,
100 L2CA_ConnectCreditBasedReq(BT_PSM_EATT, test_address, _))
101 .Times(1);
102 }
103
104 l2cap_app_info_.pL2CA_CreditBasedCollisionInd_Cb(test_address);
105 }
106
107 int i = 0;
108 for (uint16_t cid : test_local_cids) {
109 EattChannel* channel = eatt_instance_->FindEattChannelByCid(test_address, cid);
110 ASSERT_TRUE(channel != nullptr);
111 ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_PENDING);
112
113 if (i < num_of_accepted_connections) {
114 l2cap_app_info_.pL2CA_CreditBasedConnectCfm_Cb(
115 test_address, cid, EATT_MIN_MTU_MPS,
116 tL2CAP_LE_RESULT_CODE::L2CAP_LE_RESULT_CONN_OK);
117 connected_cids_.push_back(cid);
118
119 ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
120 ASSERT_TRUE(channel->tx_mtu_ == EATT_MIN_MTU_MPS);
121 } else {
122 l2cap_app_info_.pL2CA_Error_Cb(cid,
123 static_cast<uint16_t>(tL2CAP_CONN::L2CAP_CONN_NO_RESOURCES));
124
125 EattChannel* channel = eatt_instance_->FindEattChannelByCid(test_address, cid);
126 ASSERT_TRUE(channel == nullptr);
127 }
128 i++;
129 }
130
131 ASSERT_TRUE(test_tcb.eatt == num_of_accepted_connections);
132 }
133
ConnectDeviceBothSides(int num_of_accepted_connections,std::vector<uint16_t> & incoming_cids)134 void ConnectDeviceBothSides(int num_of_accepted_connections,
135 std::vector<uint16_t>& incoming_cids) {
136 base::OnceCallback<void(const RawAddress&, uint8_t)> eatt_supp_feat_cb;
137
138 ON_CALL(gatt_interface_, ClientReadSupportedFeatures)
139 .WillByDefault(
140 [&eatt_supp_feat_cb](const RawAddress& /*addr*/,
141 base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
142 eatt_supp_feat_cb = std::move(cb);
143 return true;
144 });
145
146 // Return false to trigger supported features request
147 ON_CALL(gatt_interface_, GetEattSupport).WillByDefault([](const RawAddress& /*addr*/) {
148 return false;
149 });
150
151 std::vector<uint16_t> test_local_cids{61, 62, 63, 64, 65};
152 EXPECT_CALL(mock_stack_l2cap_interface_,
153 L2CA_ConnectCreditBasedReq(BT_PSM_EATT, test_address, _))
154 .WillOnce(Return(test_local_cids));
155
156 eatt_instance_->Connect(test_address);
157
158 // Let the remote connect while we are trying to connect
159 EXPECT_CALL(mock_stack_l2cap_interface_,
160 L2CA_ConnectCreditBasedRsp(test_address, 1, incoming_cids,
161 tL2CAP_LE_RESULT_CODE::L2CAP_LE_RESULT_CONN_OK, _))
162 .WillOnce(Return(true));
163 l2cap_app_info_.pL2CA_CreditBasedConnectInd_Cb(test_address, incoming_cids, BT_PSM_EATT,
164 EATT_MIN_MTU_MPS, 1);
165
166 // Respond to feature request scheduled by the connect request
167 ASSERT_TRUE(eatt_supp_feat_cb);
168 if (eatt_supp_feat_cb) {
169 std::move(eatt_supp_feat_cb).Run(test_address, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK);
170 }
171
172 int i = 0;
173 for (uint16_t cid : test_local_cids) {
174 EattChannel* channel = eatt_instance_->FindEattChannelByCid(test_address, cid);
175 ASSERT_TRUE(channel != nullptr);
176 ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_PENDING);
177
178 if (i < num_of_accepted_connections) {
179 l2cap_app_info_.pL2CA_CreditBasedConnectCfm_Cb(
180 test_address, cid, EATT_MIN_MTU_MPS,
181 tL2CAP_LE_RESULT_CODE::L2CAP_LE_RESULT_CONN_OK);
182 connected_cids_.push_back(cid);
183
184 ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
185 ASSERT_TRUE(channel->tx_mtu_ == EATT_MIN_MTU_MPS);
186 } else {
187 l2cap_app_info_.pL2CA_Error_Cb(cid,
188 static_cast<uint16_t>(tL2CAP_CONN::L2CAP_CONN_NO_RESOURCES));
189
190 EattChannel* channel = eatt_instance_->FindEattChannelByCid(test_address, cid);
191 ASSERT_TRUE(channel == nullptr);
192 }
193 i++;
194 }
195
196 // Check the incoming CIDs as well
197 for (auto cid : incoming_cids) {
198 EattChannel* channel = eatt_instance_->FindEattChannelByCid(test_address, cid);
199 ASSERT_NE(nullptr, channel);
200 ASSERT_EQ(channel->state_, EattChannelState::EATT_CHANNEL_OPENED);
201 ASSERT_TRUE(channel->tx_mtu_ == EATT_MIN_MTU_MPS);
202 }
203
204 ASSERT_EQ(test_tcb.eatt, num_of_accepted_connections + incoming_cids.size());
205 }
206
DisconnectEattByPeer(void)207 void DisconnectEattByPeer(void) {
208 for (uint16_t cid : connected_cids_) {
209 l2cap_app_info_.pL2CA_DisconnectInd_Cb(cid, true);
210 }
211 ASSERT_EQ(0, test_tcb.eatt);
212 }
213
DisconnectEattDevice(std::vector<uint16_t> cids)214 void DisconnectEattDevice(std::vector<uint16_t> cids) {
215 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_DisconnectReq(_)).Times(cids.size());
216 eatt_instance_->Disconnect(test_address);
217
218 ASSERT_EQ(0, test_tcb.eatt);
219 }
220
SetUp()221 void SetUp() override {
222 bluetooth::testing::stack::l2cap::set_interface(&mock_stack_l2cap_interface_);
223 tL2CAP_APPL_INFO l2cap_callbacks{};
224
225 le_buffer_size_.le_data_packet_length_ = 128;
226 le_buffer_size_.total_num_le_packets_ = 24;
227 EXPECT_CALL(controller_, GetLeBufferSize).WillRepeatedly(Return(le_buffer_size_));
228 bluetooth::l2cap::SetMockInterface(&l2cap_interface_);
229 bluetooth::manager::SetMockBtmApiInterface(&btm_api_interface_);
230 bluetooth::manager::SetMockBtifStorageInterface(&btif_storage_interface_);
231 bluetooth::gatt::SetMockGattInterface(&gatt_interface_);
232 bluetooth::hci::testing::mock_controller_ = &controller_;
233
234 // Clear the static memory for each test case
235 memset(&test_tcb, 0, sizeof(test_tcb));
236
237 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_RegisterLECoc(BT_PSM_EATT, _, _, _))
238 .WillOnce(DoAll(SaveArg<1>(&l2cap_app_info_), ::testing::ReturnArg<0>()));
239
240 ON_CALL(btif_storage_interface_, LoadBondedEatt).WillByDefault([]() { return; });
241
242 hci_role_ = HCI_ROLE_CENTRAL;
243
244 EXPECT_CALL(l2cap_interface_, LeCreditDefault()).WillRepeatedly(DoAll(Return(0xfff)));
245
246 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_GetBleConnRole(_))
247 .WillRepeatedly(DoAll(Return(hci_role_)));
248
249 eatt_instance_ = EattExtension::GetInstance();
250 eatt_instance_->Start();
251
252 Test::SetUp();
253 }
254
TearDown()255 void TearDown() override {
256 com::android::bluetooth::flags::provider_->reset_flags();
257
258 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_DeregisterLECoc(BT_PSM_EATT)).Times(1);
259
260 eatt_instance_->Stop();
261 eatt_instance_ = nullptr;
262 hci_role_ = HCI_ROLE_CENTRAL;
263 connected_cids_.clear();
264
265 bluetooth::gatt::SetMockGattInterface(nullptr);
266 bluetooth::l2cap::SetMockInterface(nullptr);
267 bluetooth::testing::stack::l2cap::reset_interface();
268 bluetooth::manager::SetMockBtifStorageInterface(nullptr);
269 bluetooth::manager::SetMockBtmApiInterface(nullptr);
270 bluetooth::hci::testing::mock_controller_ = nullptr;
271
272 Test::TearDown();
273 }
274
275 tL2CAP_APPL_INFO reg_info_;
276
277 bluetooth::manager::MockBtifStorageInterface btif_storage_interface_;
278 bluetooth::manager::MockBtmApiInterface btm_api_interface_;
279 bluetooth::l2cap::MockL2capInterface l2cap_interface_;
280 bluetooth::testing::stack::l2cap::Mock mock_stack_l2cap_interface_;
281 bluetooth::gatt::MockGattInterface gatt_interface_;
282 bluetooth::hci::testing::MockControllerInterface controller_;
283 bluetooth::hci::LeBufferSize le_buffer_size_;
284
285 tL2CAP_APPL_INFO l2cap_app_info_;
286 EattExtension* eatt_instance_;
287 std::vector<uint16_t> connected_cids_;
288 tHCI_ROLE hci_role_ = HCI_ROLE_CENTRAL;
289 };
290
TEST_F(EattTest,ConnectSucceed)291 TEST_F(EattTest, ConnectSucceed) {
292 ConnectDeviceEattSupported(1);
293 DisconnectEattDevice(connected_cids_);
294 }
295
TEST_F(EattTest,IncomingEattConnectionByUnknownDevice)296 TEST_F(EattTest, IncomingEattConnectionByUnknownDevice) {
297 std::vector<uint16_t> incoming_cids{71, 72, 73, 74, 75};
298
299 ON_CALL(btm_api_interface_, IsEncrypted)
300 .WillByDefault(
301 [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return true; });
302 EXPECT_CALL(mock_stack_l2cap_interface_,
303 L2CA_ConnectCreditBasedRsp(test_address, 1, incoming_cids,
304 tL2CAP_LE_RESULT_CODE::L2CAP_LE_RESULT_CONN_OK, _))
305 .WillOnce(Return(true));
306
307 l2cap_app_info_.pL2CA_CreditBasedConnectInd_Cb(test_address, incoming_cids, BT_PSM_EATT,
308 EATT_MIN_MTU_MPS, 1);
309
310 DisconnectEattDevice(incoming_cids);
311 }
312
TEST_F(EattTest,IncomingEattConnectionByKnownDevice)313 TEST_F(EattTest, IncomingEattConnectionByKnownDevice) {
314 hci_role_ = HCI_ROLE_PERIPHERAL;
315 ON_CALL(btm_api_interface_, IsEncrypted)
316 .WillByDefault(
317 [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return true; });
318 ON_CALL(gatt_interface_, ClientReadSupportedFeatures)
319 .WillByDefault([](const RawAddress& addr,
320 base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
321 std::move(cb).Run(addr, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK);
322 return true;
323 });
324 ON_CALL(gatt_interface_, GetEattSupport).WillByDefault([](const RawAddress& /*addr*/) {
325 return true;
326 });
327
328 eatt_instance_->Connect(test_address);
329 std::vector<uint16_t> incoming_cids{71, 72, 73, 74, 75};
330
331 EXPECT_CALL(mock_stack_l2cap_interface_,
332 L2CA_ConnectCreditBasedRsp(test_address, 1, incoming_cids,
333 tL2CAP_LE_RESULT_CODE::L2CAP_LE_RESULT_CONN_OK, _))
334 .WillOnce(Return(true));
335
336 l2cap_app_info_.pL2CA_CreditBasedConnectInd_Cb(test_address, incoming_cids, BT_PSM_EATT,
337 EATT_MIN_MTU_MPS, 1);
338
339 DisconnectEattDevice(incoming_cids);
340
341 hci_role_ = HCI_ROLE_CENTRAL;
342 }
343
TEST_F(EattTest,IncomingEattConnectionByKnownDeviceEncryptionOff)344 TEST_F(EattTest, IncomingEattConnectionByKnownDeviceEncryptionOff) {
345 hci_role_ = HCI_ROLE_PERIPHERAL;
346 ON_CALL(btm_api_interface_, IsEncrypted)
347 .WillByDefault(
348 [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return false; });
349 ON_CALL(btm_api_interface_, IsLinkKeyKnown)
350 .WillByDefault(
351 [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return true; });
352 ON_CALL(gatt_interface_, ClientReadSupportedFeatures)
353 .WillByDefault([](const RawAddress& addr,
354 base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
355 std::move(cb).Run(addr, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK);
356 return true;
357 });
358 ON_CALL(gatt_interface_, GetEattSupport).WillByDefault([](const RawAddress& /*addr*/) {
359 return true;
360 });
361
362 eatt_instance_->Connect(test_address);
363 std::vector<uint16_t> incoming_cids{71, 72, 73, 74, 75};
364
365 EXPECT_CALL(
366 mock_stack_l2cap_interface_,
367 L2CA_ConnectCreditBasedRsp(test_address, 1, _,
368 tL2CAP_LE_RESULT_CODE::L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP, _))
369 .WillOnce(Return(true));
370
371 l2cap_app_info_.pL2CA_CreditBasedConnectInd_Cb(test_address, incoming_cids, BT_PSM_EATT,
372 EATT_MIN_MTU_MPS, 1);
373
374 hci_role_ = HCI_ROLE_CENTRAL;
375 }
376
TEST_F(EattTest,IncomingEattConnectionByUnknownDeviceEncryptionOff)377 TEST_F(EattTest, IncomingEattConnectionByUnknownDeviceEncryptionOff) {
378 std::vector<uint16_t> incoming_cids{71, 72, 73, 74, 75};
379
380 ON_CALL(btm_api_interface_, IsEncrypted)
381 .WillByDefault(
382 [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return false; });
383 ON_CALL(btm_api_interface_, IsLinkKeyKnown)
384 .WillByDefault(
385 [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return false; });
386 EXPECT_CALL(mock_stack_l2cap_interface_,
387 L2CA_ConnectCreditBasedRsp(
388 test_address, 1, _,
389 tL2CAP_LE_RESULT_CODE::L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION, _))
390 .WillOnce(Return(true));
391
392 l2cap_app_info_.pL2CA_CreditBasedConnectInd_Cb(test_address, incoming_cids, BT_PSM_EATT,
393 EATT_MIN_MTU_MPS, 1);
394 }
395
TEST_F(EattTest,ReconnectInitiatedByRemoteSucceed)396 TEST_F(EattTest, ReconnectInitiatedByRemoteSucceed) {
397 ConnectDeviceEattSupported(1);
398 DisconnectEattDevice(connected_cids_);
399 std::vector<uint16_t> incoming_cids{71, 72, 73, 74, 75};
400
401 ON_CALL(btm_api_interface_, IsEncrypted)
402 .WillByDefault(
403 [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return true; });
404
405 EXPECT_CALL(mock_stack_l2cap_interface_,
406 L2CA_ConnectCreditBasedRsp(test_address, 1, incoming_cids,
407 tL2CAP_LE_RESULT_CODE::L2CAP_LE_RESULT_CONN_OK, _))
408 .WillOnce(Return(true));
409
410 l2cap_app_info_.pL2CA_CreditBasedConnectInd_Cb(test_address, incoming_cids, BT_PSM_EATT,
411 EATT_MIN_MTU_MPS, 1);
412
413 DisconnectEattDevice(incoming_cids);
414 }
415
TEST_F(EattTest,ConnectInitiatedWhenRemoteConnects)416 TEST_F(EattTest, ConnectInitiatedWhenRemoteConnects) {
417 ON_CALL(btm_api_interface_, IsEncrypted)
418 .WillByDefault(
419 [](const RawAddress& /*addr*/, tBT_TRANSPORT /*transport*/) { return true; });
420
421 std::vector<uint16_t> incoming_cids{71, 72, 73, 74};
422 ConnectDeviceBothSides(1, incoming_cids);
423
424 std::vector<uint16_t> disconnecting_cids;
425 disconnecting_cids.insert(disconnecting_cids.end(), incoming_cids.begin(), incoming_cids.end());
426 disconnecting_cids.insert(disconnecting_cids.end(), connected_cids_.begin(),
427 connected_cids_.end());
428 DisconnectEattDevice(disconnecting_cids);
429 }
430
TEST_F(EattTest,ConnectSucceedMultipleChannels)431 TEST_F(EattTest, ConnectSucceedMultipleChannels) {
432 ConnectDeviceEattSupported(5);
433 DisconnectEattDevice(connected_cids_);
434 }
435
TEST_F(EattTest,ConnectFailedEattNotSupported)436 TEST_F(EattTest, ConnectFailedEattNotSupported) {
437 ON_CALL(gatt_interface_, ClientReadSupportedFeatures)
438 .WillByDefault([](const RawAddress& addr,
439 base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
440 std::move(cb).Run(addr, 0);
441 return true;
442 });
443 ON_CALL(gatt_interface_, GetEattSupport).WillByDefault([](const RawAddress& /*addr*/) {
444 return false;
445 });
446
447 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectCreditBasedReq(BT_PSM_EATT, test_address, _))
448 .Times(0);
449 eatt_instance_->Connect(test_address);
450 ASSERT_TRUE(eatt_instance_->IsEattSupportedByPeer(test_address) == false);
451 }
452
TEST_F(EattTest,ConnectFailedSlaveOnTheLink)453 TEST_F(EattTest, ConnectFailedSlaveOnTheLink) {
454 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectCreditBasedReq(BT_PSM_EATT, test_address, _))
455 .Times(0);
456
457 hci_role_ = HCI_ROLE_PERIPHERAL;
458 eatt_instance_->Connect(test_address);
459
460 /* Back to default btm role */
461 hci_role_ = HCI_ROLE_CENTRAL;
462 }
463
TEST_F(EattTest,DisonnectByPeerSucceed)464 TEST_F(EattTest, DisonnectByPeerSucceed) {
465 ConnectDeviceEattSupported(2);
466
467 uint16_t cid = connected_cids_[0];
468 EattChannel* channel = eatt_instance_->FindEattChannelByCid(test_address, cid);
469 ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
470
471 DisconnectEattByPeer();
472
473 channel = eatt_instance_->FindEattChannelByCid(test_address, cid);
474 ASSERT_TRUE(channel == nullptr);
475 }
476
TEST_F(EattTest,ReconfigAllSucceed)477 TEST_F(EattTest, ReconfigAllSucceed) {
478 ConnectDeviceEattSupported(3);
479
480 std::vector<uint16_t> cids;
481 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ReconfigCreditBasedConnsReq(_, _, _))
482 .WillOnce(DoAll(SaveArg<1>(&cids), Return(true)));
483
484 uint16_t new_mtu = 300;
485 eatt_instance_->ReconfigureAll(test_address, new_mtu);
486
487 ASSERT_TRUE(cids.size() == connected_cids_.size());
488
489 tL2CAP_LE_CFG_INFO cfg = {.result = tL2CAP_CFG_RESULT::L2CAP_CFG_OK, .mtu = new_mtu};
490
491 for (uint16_t cid : cids) {
492 l2cap_app_info_.pL2CA_CreditBasedReconfigCompleted_Cb(test_address, cid, true, &cfg);
493
494 EattChannel* channel = eatt_instance_->FindEattChannelByCid(test_address, cid);
495 ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
496 ASSERT_TRUE(channel->rx_mtu_ == new_mtu);
497 }
498
499 DisconnectEattDevice(connected_cids_);
500 }
501
TEST_F(EattTest,ReconfigAllFailed)502 TEST_F(EattTest, ReconfigAllFailed) {
503 ConnectDeviceEattSupported(4);
504
505 std::vector<uint16_t> cids;
506 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ReconfigCreditBasedConnsReq(_, _, _))
507 .WillOnce(DoAll(SaveArg<1>(&cids), Return(true)));
508
509 uint16_t new_mtu = 300;
510 eatt_instance_->ReconfigureAll(test_address, new_mtu);
511
512 ASSERT_TRUE(cids.size() == connected_cids_.size());
513
514 tL2CAP_LE_CFG_INFO cfg = {.result = tL2CAP_CFG_RESULT::L2CAP_CFG_FAILED_NO_REASON,
515 .mtu = new_mtu};
516
517 for (uint16_t cid : cids) {
518 l2cap_app_info_.pL2CA_CreditBasedReconfigCompleted_Cb(test_address, cid, true, &cfg);
519
520 EattChannel* channel = eatt_instance_->FindEattChannelByCid(test_address, cid);
521 ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
522 ASSERT_TRUE(channel->rx_mtu_ != new_mtu);
523 }
524
525 DisconnectEattDevice(connected_cids_);
526 }
527
TEST_F(EattTest,ReconfigSingleSucceed)528 TEST_F(EattTest, ReconfigSingleSucceed) {
529 ConnectDeviceEattSupported(2);
530
531 std::vector<uint16_t> cids;
532 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ReconfigCreditBasedConnsReq(_, _, _))
533 .WillOnce(DoAll(SaveArg<1>(&cids), Return(true)));
534
535 uint16_t new_mtu = 300;
536 eatt_instance_->Reconfigure(test_address, connected_cids_[1], new_mtu);
537
538 ASSERT_EQ(1U, cids.size());
539
540 tL2CAP_LE_CFG_INFO cfg = {.result = tL2CAP_CFG_RESULT::L2CAP_CFG_OK, .mtu = new_mtu};
541
542 auto it = std::find(connected_cids_.begin(), connected_cids_.end(), cids[0]);
543 ASSERT_TRUE(it != connected_cids_.end());
544
545 l2cap_app_info_.pL2CA_CreditBasedReconfigCompleted_Cb(test_address, cids[0], true, &cfg);
546 EattChannel* channel = eatt_instance_->FindEattChannelByCid(test_address, cids[0]);
547 ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
548 ASSERT_TRUE(channel->rx_mtu_ == new_mtu);
549
550 DisconnectEattDevice(connected_cids_);
551 }
552
TEST_F(EattTest,ReconfigSingleFailed)553 TEST_F(EattTest, ReconfigSingleFailed) {
554 ConnectDeviceEattSupported(2);
555
556 std::vector<uint16_t> cids;
557 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ReconfigCreditBasedConnsReq(_, _, _))
558 .WillOnce(DoAll(SaveArg<1>(&cids), Return(true)));
559
560 uint16_t new_mtu = 300;
561 eatt_instance_->ReconfigureAll(test_address, new_mtu);
562
563 ASSERT_TRUE(cids.size() == connected_cids_.size());
564
565 tL2CAP_LE_CFG_INFO cfg = {.result = tL2CAP_CFG_RESULT::L2CAP_CFG_FAILED_NO_REASON,
566 .mtu = new_mtu};
567
568 auto it = std::find(connected_cids_.begin(), connected_cids_.end(), cids[0]);
569 ASSERT_TRUE(it != connected_cids_.end());
570
571 l2cap_app_info_.pL2CA_CreditBasedReconfigCompleted_Cb(test_address, cids[0], true, &cfg);
572 EattChannel* channel = eatt_instance_->FindEattChannelByCid(test_address, cids[0]);
573 ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
574 ASSERT_TRUE(channel->rx_mtu_ != new_mtu);
575
576 DisconnectEattDevice(connected_cids_);
577 }
578
TEST_F(EattTest,ReconfigPeerSucceed)579 TEST_F(EattTest, ReconfigPeerSucceed) {
580 ConnectDeviceEattSupported(3);
581
582 uint16_t new_mtu = 300;
583 tL2CAP_LE_CFG_INFO cfg = {.result = tL2CAP_CFG_RESULT::L2CAP_CFG_OK, .mtu = new_mtu};
584
585 for (uint16_t cid : connected_cids_) {
586 l2cap_app_info_.pL2CA_CreditBasedReconfigCompleted_Cb(test_address, cid, false, &cfg);
587
588 EattChannel* channel = eatt_instance_->FindEattChannelByCid(test_address, cid);
589 ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
590 ASSERT_TRUE(channel->tx_mtu_ == new_mtu);
591 }
592
593 DisconnectEattDevice(connected_cids_);
594 }
595
TEST_F(EattTest,ReconfigPeerFailed)596 TEST_F(EattTest, ReconfigPeerFailed) {
597 ConnectDeviceEattSupported(2);
598
599 uint16_t new_mtu = 300;
600 tL2CAP_LE_CFG_INFO cfg = {.result = tL2CAP_CFG_RESULT::L2CAP_CFG_FAILED_NO_REASON,
601 .mtu = new_mtu};
602
603 for (uint16_t cid : connected_cids_) {
604 l2cap_app_info_.pL2CA_CreditBasedReconfigCompleted_Cb(test_address, cid, false, &cfg);
605
606 EattChannel* channel = eatt_instance_->FindEattChannelByCid(test_address, cid);
607 ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
608 ASSERT_TRUE(channel->tx_mtu_ != new_mtu);
609 }
610
611 DisconnectEattDevice(connected_cids_);
612 }
613
TEST_F(EattTest,DoubleDisconnect)614 TEST_F(EattTest, DoubleDisconnect) {
615 ConnectDeviceEattSupported(1);
616 DisconnectEattDevice(connected_cids_);
617
618 /* Force second disconnect */
619 eatt_instance_->Disconnect(test_address);
620 }
621
TEST_F(EattTest,TestCollisionHandling)622 TEST_F(EattTest, TestCollisionHandling) {
623 ConnectDeviceEattSupported(0, true /* collision*/);
624 ConnectDeviceEattSupported(5, true /* collision*/);
625 }
626
TEST_F(EattTest,ChannelUnavailableWhileOpening)627 TEST_F(EattTest, ChannelUnavailableWhileOpening) {
628 // arrange
629 ON_CALL(gatt_interface_, ClientReadSupportedFeatures)
630 .WillByDefault([](const RawAddress& addr,
631 base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
632 std::move(cb).Run(addr, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK);
633 return true;
634 });
635 ON_CALL(gatt_interface_, GetEattSupport).WillByDefault(Return(true));
636
637 // expect
638 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectCreditBasedReq(BT_PSM_EATT, test_address, _))
639 .WillOnce(Return(std::vector<uint16_t>{61}));
640
641 // act: start
642 eatt_instance_->Connect(test_address);
643 auto available_channel_for_request =
644 eatt_instance_->GetChannelAvailableForClientRequest(test_address);
645 auto available_channel_for_indication =
646 eatt_instance_->GetChannelAvailableForIndication(test_address);
647
648 // assert
649 ASSERT_EQ(available_channel_for_request, nullptr);
650 ASSERT_EQ(available_channel_for_indication, nullptr);
651 }
652
TEST_F(EattTest,ChannelUnavailableWhileReconfiguring)653 TEST_F(EattTest, ChannelUnavailableWhileReconfiguring) {
654 // arrange
655 ON_CALL(mock_stack_l2cap_interface_, L2CA_ReconfigCreditBasedConnsReq(_, _, _))
656 .WillByDefault(Return(true));
657 ConnectDeviceEattSupported(/* num_of_accepted_connections = */ 1);
658
659 // act: reconfigure, then get available channels
660 eatt_instance_->Reconfigure(test_address, connected_cids_[0], 300);
661 auto available_channel_for_request =
662 eatt_instance_->GetChannelAvailableForClientRequest(test_address);
663 auto available_channel_for_indication =
664 eatt_instance_->GetChannelAvailableForIndication(test_address);
665
666 // assert
667 ASSERT_EQ(available_channel_for_request, nullptr);
668 ASSERT_EQ(available_channel_for_indication, nullptr);
669 }
670
TEST_F(EattTest,DisconnectChannelOnIndicationConfirmationTimeout)671 TEST_F(EattTest, DisconnectChannelOnIndicationConfirmationTimeout) {
672 com::android::bluetooth::flags::provider_->gatt_disconnect_fix(true);
673 ConnectDeviceEattSupported(1);
674
675 eatt_instance_->StartIndicationConfirmationTimer(test_address, test_local_cids[0]);
676
677 EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_DisconnectReq(test_local_cids[0])).Times(1);
678 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
679 }
680
681 } // namespace
682