1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_bluetooth_sapphire/internal/host/hci/low_energy_connector.h"
16
17 #include <vector>
18
19 #include "pw_async/heap_dispatcher.h"
20 #include "pw_bluetooth_sapphire/internal/host/common/macros.h"
21 #include "pw_bluetooth_sapphire/internal/host/hci-spec/defaults.h"
22 #include "pw_bluetooth_sapphire/internal/host/hci/fake_local_address_delegate.h"
23 #include "pw_bluetooth_sapphire/internal/host/hci/fake_low_energy_connection.h"
24 #include "pw_bluetooth_sapphire/internal/host/testing/controller_test.h"
25 #include "pw_bluetooth_sapphire/internal/host/testing/fake_controller.h"
26 #include "pw_bluetooth_sapphire/internal/host/testing/fake_peer.h"
27
28 namespace bt::hci {
29 namespace {
30
31 using bt::testing::FakeController;
32 using bt::testing::FakePeer;
33 using TestingBase = bt::testing::FakeDispatcherControllerTest<FakeController>;
34
35 const DeviceAddress kLocalAddress(DeviceAddress::Type::kLEPublic, {0xFF});
36 const DeviceAddress kRandomAddress(DeviceAddress::Type::kLERandom, {0xFE});
37 const DeviceAddress kTestAddress(DeviceAddress::Type::kLEPublic, {1});
38 const hci_spec::LEPreferredConnectionParameters kTestParams(6, 6, 1, 10);
39 constexpr pw::chrono::SystemClock::duration kPwConnectTimeout =
40 std::chrono::seconds(10);
41
42 class LowEnergyConnectorTest : public TestingBase,
43 public ::testing::WithParamInterface<bool> {
44 public:
45 LowEnergyConnectorTest() = default;
46 ~LowEnergyConnectorTest() override = default;
47
48 protected:
SetUp()49 void SetUp() override {
50 TestingBase::SetUp();
51 InitializeACLDataChannel();
52
53 FakeController::Settings settings;
54 settings.ApplyLegacyLEConfig();
55 test_device()->set_settings(settings);
56
57 fake_address_delegate_.set_local_address(kLocalAddress);
58
59 bool use_extended_operations = GetParam();
60 connector_ = std::make_unique<LowEnergyConnector>(
61 transport()->GetWeakPtr(),
62 &fake_address_delegate_,
63 dispatcher(),
64 fit::bind_member<&LowEnergyConnectorTest::OnIncomingConnectionCreated>(
65 this),
66 use_extended_operations);
67
68 test_device()->set_connection_state_callback(
69 fit::bind_member<&LowEnergyConnectorTest::OnConnectionStateChanged>(
70 this));
71 }
72
TearDown()73 void TearDown() override {
74 connector_ = nullptr;
75 in_connections_.clear();
76 test_device()->Stop();
77 TestingBase::TearDown();
78 }
79
CreateConnectionCompleteSubevent(hci_spec::ConnectionHandle conn_handle,const DeviceAddress & peer_address) const80 EventPacket CreateConnectionCompleteSubevent(
81 hci_spec::ConnectionHandle conn_handle,
82 const DeviceAddress& peer_address) const {
83 auto packet = hci::EventPacket::New<
84 pw::bluetooth::emboss::LEEnhancedConnectionCompleteSubeventV1Writer>(
85 hci_spec::kLEMetaEventCode);
86 auto params = packet.view_t();
87
88 params.le_meta_event().subevent_code().Write(
89 hci_spec::kLEEnhancedConnectionCompleteSubeventCode);
90 params.status().Write(pw::bluetooth::emboss::StatusCode::SUCCESS);
91 params.connection_handle().Write(conn_handle);
92 params.role().Write(pw::bluetooth::emboss::ConnectionRole::PERIPHERAL);
93 params.peer_address_type().Write(
94 pw::bluetooth::emboss::LEAddressType::PUBLIC);
95 params.peer_address().CopyFrom(peer_address.value().view());
96 params.connection_interval().Write(
97 hci_spec::defaults::kLEConnectionIntervalMin);
98 params.peripheral_latency().Write(0);
99 params.supervision_timeout().Write(10);
100 params.central_clock_accuracy().Write(
101 pw::bluetooth::emboss::LEClockAccuracy::PPM_20);
102
103 // there are also local_resolvable_private_address and
104 // peer_resolvable_private_address fields available within
105 // LEEnhancedConnectionCompleteSubeventV1. However, these fields are only
106 // valid when we use either the identity addresses in
107 // HCI_LE_Enhanced_Create_Connection for either the local device or peer
108 // device. Our tests mainly use public or random addresses, as if they
109 // have already resolved the addresses. We ignore setting these fields
110 // here to prevent confusion.
111
112 return packet;
113 }
114
heap_dispatcher()115 pw::async::HeapDispatcher& heap_dispatcher() { return heap_dispatcher_; }
DeleteConnector()116 void DeleteConnector() { connector_ = nullptr; }
request_canceled() const117 bool request_canceled() const { return request_canceled_; }
connector() const118 LowEnergyConnector* connector() const { return connector_.get(); }
119
in_connections() const120 const std::vector<std::unique_ptr<LowEnergyConnection>>& in_connections()
121 const {
122 return in_connections_;
123 }
124
fake_address_delegate()125 FakeLocalAddressDelegate* fake_address_delegate() {
126 return &fake_address_delegate_;
127 }
128
129 private:
OnIncomingConnectionCreated(hci_spec::ConnectionHandle handle,pw::bluetooth::emboss::ConnectionRole role,const DeviceAddress & peer_address,const hci_spec::LEConnectionParameters &)130 void OnIncomingConnectionCreated(hci_spec::ConnectionHandle handle,
131 pw::bluetooth::emboss::ConnectionRole role,
132 const DeviceAddress& peer_address,
133 const hci_spec::LEConnectionParameters&) {
134 in_connections_.push_back(
135 std::make_unique<testing::FakeLowEnergyConnection>(
136 handle,
137 kLocalAddress,
138 peer_address,
139 role,
140 transport()->GetWeakPtr()));
141 }
142
OnConnectionStateChanged(const DeviceAddress &,hci_spec::ConnectionHandle,bool,bool canceled)143 void OnConnectionStateChanged(const DeviceAddress&,
144 hci_spec::ConnectionHandle,
145 bool,
146 bool canceled) {
147 request_canceled_ = canceled;
148 }
149
150 bool request_canceled_ = false;
151 FakeLocalAddressDelegate fake_address_delegate_{dispatcher()};
152 std::unique_ptr<LowEnergyConnector> connector_;
153 std::vector<std::unique_ptr<LowEnergyConnection>> in_connections_;
154 pw::async::HeapDispatcher heap_dispatcher_{dispatcher()};
155
156 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LowEnergyConnectorTest);
157 };
158
159 INSTANTIATE_TEST_SUITE_P(LowEnergyConnectorTest,
160 LowEnergyConnectorTest,
161 ::testing::Bool());
162
TEST_P(LowEnergyConnectorTest,CreateConnection)163 TEST_P(LowEnergyConnectorTest, CreateConnection) {
164 auto fake_peer = std::make_unique<FakePeer>(kTestAddress, dispatcher());
165 test_device()->AddPeer(std::move(fake_peer));
166 // Public address would be used if privacy was disabled
167 fake_address_delegate()->EnablePrivacy(true);
168
169 EXPECT_FALSE(connector()->request_pending());
170 EXPECT_FALSE(connector()->pending_peer_address());
171
172 Result<> status = fit::ok();
173 std::unique_ptr<LowEnergyConnection> conn;
174 bool callback_called = false;
175
176 auto callback = [&](auto cb_status, auto cb_conn) {
177 status = cb_status;
178 conn = std::move(cb_conn);
179 callback_called = true;
180 };
181
182 bool ret = connector()->CreateConnection(
183 /*use_accept_list=*/false,
184 kTestAddress,
185 hci_spec::defaults::kLEScanInterval,
186 hci_spec::defaults::kLEScanWindow,
187 kTestParams,
188 callback,
189 kPwConnectTimeout);
190 EXPECT_TRUE(ret);
191 EXPECT_TRUE(connector()->request_pending());
192 EXPECT_EQ(connector()->pending_peer_address().value(), kTestAddress);
193
194 ret = connector()->CreateConnection(
195 /*use_accept_list=*/false,
196 kTestAddress,
197 hci_spec::defaults::kLEScanInterval,
198 hci_spec::defaults::kLEScanWindow,
199 kTestParams,
200 callback,
201 kPwConnectTimeout);
202 EXPECT_FALSE(ret);
203
204 RunUntilIdle();
205
206 EXPECT_FALSE(connector()->request_pending());
207 EXPECT_FALSE(connector()->pending_peer_address());
208 EXPECT_TRUE(callback_called);
209 EXPECT_EQ(fit::ok(), status);
210 EXPECT_TRUE(in_connections().empty());
211
212 ASSERT_TRUE(conn);
213 EXPECT_EQ(1u, conn->handle());
214 EXPECT_EQ(kLocalAddress, conn->local_address());
215 EXPECT_EQ(kTestAddress, conn->peer_address());
216 conn->Disconnect(
217 pw::bluetooth::emboss::StatusCode::REMOTE_USER_TERMINATED_CONNECTION);
218 }
219
220 // Controller reports error from HCI Command Status event.
TEST_P(LowEnergyConnectorTest,CreateConnectionStatusError)221 TEST_P(LowEnergyConnectorTest, CreateConnectionStatusError) {
222 auto fake_peer = std::make_unique<FakePeer>(kTestAddress, dispatcher());
223 fake_peer->set_connect_status(
224 pw::bluetooth::emboss::StatusCode::COMMAND_DISALLOWED);
225 test_device()->AddPeer(std::move(fake_peer));
226
227 EXPECT_FALSE(connector()->request_pending());
228
229 Result<> status = fit::ok();
230 std::unique_ptr<LowEnergyConnection> conn;
231 bool callback_called = false;
232
233 auto callback = [&](auto cb_status, auto cb_conn) {
234 status = cb_status;
235 conn = std::move(cb_conn);
236 callback_called = true;
237 };
238
239 bool ret = connector()->CreateConnection(
240 /*use_accept_list=*/false,
241 kTestAddress,
242 hci_spec::defaults::kLEScanInterval,
243 hci_spec::defaults::kLEScanWindow,
244 kTestParams,
245 callback,
246 kPwConnectTimeout);
247 EXPECT_TRUE(ret);
248 EXPECT_TRUE(connector()->request_pending());
249
250 RunUntilIdle();
251
252 EXPECT_FALSE(connector()->request_pending());
253 EXPECT_TRUE(callback_called);
254 EXPECT_EQ(ToResult(pw::bluetooth::emboss::StatusCode::COMMAND_DISALLOWED),
255 status);
256 EXPECT_FALSE(conn);
257 EXPECT_TRUE(in_connections().empty());
258 }
259
260 // Controller reports error from HCI LE Connection Complete event
TEST_P(LowEnergyConnectorTest,CreateConnectionEventError)261 TEST_P(LowEnergyConnectorTest, CreateConnectionEventError) {
262 auto fake_peer = std::make_unique<FakePeer>(kTestAddress, dispatcher());
263 fake_peer->set_connect_response(
264 pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_SECURITY);
265 test_device()->AddPeer(std::move(fake_peer));
266
267 EXPECT_FALSE(connector()->request_pending());
268
269 Result<> status = fit::ok();
270 std::unique_ptr<LowEnergyConnection> conn;
271 bool callback_called = false;
272
273 auto callback = [&](auto cb_status, auto cb_conn) {
274 status = cb_status;
275 callback_called = true;
276 conn = std::move(cb_conn);
277 };
278
279 bool ret = connector()->CreateConnection(
280 /*use_accept_list=*/false,
281 kTestAddress,
282 hci_spec::defaults::kLEScanInterval,
283 hci_spec::defaults::kLEScanWindow,
284 kTestParams,
285 callback,
286 kPwConnectTimeout);
287 EXPECT_TRUE(ret);
288 EXPECT_TRUE(connector()->request_pending());
289
290 RunUntilIdle();
291
292 EXPECT_FALSE(connector()->request_pending());
293 EXPECT_TRUE(callback_called);
294 EXPECT_EQ(
295 ToResult(pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_SECURITY),
296 status);
297 EXPECT_TRUE(in_connections().empty());
298 EXPECT_FALSE(conn);
299 }
300
301 // Controller reports error from HCI LE Connection Complete event
TEST_P(LowEnergyConnectorTest,Cancel)302 TEST_P(LowEnergyConnectorTest, Cancel) {
303 auto fake_peer = std::make_unique<FakePeer>(kTestAddress, dispatcher());
304
305 // Make sure the pending connect remains pending.
306 fake_peer->set_force_pending_connect(true);
307 test_device()->AddPeer(std::move(fake_peer));
308
309 hci::Result<> status = fit::ok();
310 std::unique_ptr<LowEnergyConnection> conn;
311 bool callback_called = false;
312
313 auto callback = [&](auto cb_status, auto cb_conn) {
314 status = cb_status;
315 callback_called = true;
316 conn = std::move(cb_conn);
317 };
318
319 bool ret = connector()->CreateConnection(
320 /*use_accept_list=*/false,
321 kTestAddress,
322 hci_spec::defaults::kLEScanInterval,
323 hci_spec::defaults::kLEScanWindow,
324 kTestParams,
325 callback,
326 kPwConnectTimeout);
327 EXPECT_TRUE(ret);
328 EXPECT_TRUE(connector()->request_pending());
329
330 ASSERT_FALSE(request_canceled());
331
332 connector()->Cancel();
333 EXPECT_TRUE(connector()->request_pending());
334
335 // The request timeout should be canceled regardless of whether it was posted
336 // before.
337 EXPECT_FALSE(connector()->timeout_posted());
338
339 RunUntilIdle();
340
341 EXPECT_FALSE(connector()->timeout_posted());
342 EXPECT_FALSE(connector()->request_pending());
343 EXPECT_TRUE(callback_called);
344 EXPECT_TRUE(request_canceled());
345 EXPECT_EQ(ToResult(HostError::kCanceled), status);
346 EXPECT_TRUE(in_connections().empty());
347 EXPECT_FALSE(conn);
348 }
349
TEST_P(LowEnergyConnectorTest,IncomingConnect)350 TEST_P(LowEnergyConnectorTest, IncomingConnect) {
351 EXPECT_TRUE(in_connections().empty());
352 EXPECT_FALSE(connector()->request_pending());
353
354 EventPacket packet = CreateConnectionCompleteSubevent(1, kTestAddress);
355 test_device()->SendCommandChannelPacket(packet.data());
356
357 RunUntilIdle();
358 ASSERT_EQ(1u, in_connections().size());
359
360 auto conn = in_connections()[0].get();
361 EXPECT_EQ(1u, conn->handle());
362 EXPECT_EQ(kLocalAddress, conn->local_address());
363 EXPECT_EQ(kTestAddress, conn->peer_address());
364 conn->Disconnect(
365 pw::bluetooth::emboss::StatusCode::REMOTE_USER_TERMINATED_CONNECTION);
366 }
367
TEST_P(LowEnergyConnectorTest,IncomingConnectDuringConnectionRequest)368 TEST_P(LowEnergyConnectorTest, IncomingConnectDuringConnectionRequest) {
369 const DeviceAddress kIncomingAddress(DeviceAddress::Type::kLEPublic, {2});
370
371 EXPECT_TRUE(in_connections().empty());
372 EXPECT_FALSE(connector()->request_pending());
373
374 auto fake_peer = std::make_unique<FakePeer>(kTestAddress, dispatcher());
375 test_device()->AddPeer(std::move(fake_peer));
376
377 Result<> status = fit::ok();
378 std::unique_ptr<LowEnergyConnection> conn;
379 unsigned int callback_count = 0;
380
381 auto callback = [&](auto cb_status, auto cb_conn) {
382 status = cb_status;
383 callback_count++;
384 conn = std::move(cb_conn);
385 };
386
387 connector()->CreateConnection(
388 /*use_accept_list=*/false,
389 kTestAddress,
390 hci_spec::defaults::kLEScanInterval,
391 hci_spec::defaults::kLEScanWindow,
392 kTestParams,
393 callback,
394 kPwConnectTimeout);
395
396 (void)heap_dispatcher().Post(
397 [kIncomingAddress, this](pw::async::Context /*ctx*/, pw::Status status) {
398 if (!status.ok()) {
399 return;
400 }
401
402 EventPacket packet =
403 CreateConnectionCompleteSubevent(2, kIncomingAddress);
404 test_device()->SendCommandChannelPacket(packet.data());
405 });
406
407 RunUntilIdle();
408
409 EXPECT_EQ(fit::ok(), status);
410 EXPECT_EQ(1u, callback_count);
411 ASSERT_EQ(1u, in_connections().size());
412
413 const auto& in_conn = in_connections().front();
414
415 EXPECT_EQ(1u, conn->handle());
416 EXPECT_EQ(2u, in_conn->handle());
417 EXPECT_EQ(kTestAddress, conn->peer_address());
418 EXPECT_EQ(kIncomingAddress, in_conn->peer_address());
419
420 conn->Disconnect(
421 pw::bluetooth::emboss::StatusCode::REMOTE_USER_TERMINATED_CONNECTION);
422 in_conn->Disconnect(
423 pw::bluetooth::emboss::StatusCode::REMOTE_USER_TERMINATED_CONNECTION);
424 }
425
TEST_P(LowEnergyConnectorTest,CreateConnectionTimeout)426 TEST_P(LowEnergyConnectorTest, CreateConnectionTimeout) {
427 // We do not set up any fake devices. This will cause the request to time out.
428 EXPECT_FALSE(connector()->request_pending());
429
430 Result<> status = fit::ok();
431 std::unique_ptr<LowEnergyConnection> conn;
432 bool callback_called = false;
433
434 auto callback = [&](auto cb_status, auto cb_conn) {
435 status = cb_status;
436 callback_called = true;
437 conn = std::move(cb_conn);
438 };
439
440 connector()->CreateConnection(
441 /*use_accept_list=*/false,
442 kTestAddress,
443 hci_spec::defaults::kLEScanInterval,
444 hci_spec::defaults::kLEScanWindow,
445 kTestParams,
446 callback,
447 kPwConnectTimeout);
448 EXPECT_TRUE(connector()->request_pending());
449
450 EXPECT_FALSE(request_canceled());
451
452 // Make the connection attempt time out.
453 RunFor(kPwConnectTimeout);
454
455 EXPECT_FALSE(connector()->request_pending());
456 EXPECT_TRUE(callback_called);
457 EXPECT_TRUE(request_canceled());
458 EXPECT_EQ(ToResult(HostError::kTimedOut), status);
459 EXPECT_TRUE(in_connections().empty());
460 EXPECT_FALSE(conn);
461 }
462
TEST_P(LowEnergyConnectorTest,SendRequestAndDelete)463 TEST_P(LowEnergyConnectorTest, SendRequestAndDelete) {
464 auto fake_peer = std::make_unique<FakePeer>(kTestAddress, dispatcher());
465
466 // Make sure the pending connect remains pending.
467 fake_peer->set_force_pending_connect(true);
468 test_device()->AddPeer(std::move(fake_peer));
469
470 bool ret = connector()->CreateConnection(
471 /*use_accept_list=*/
472 false,
473 kTestAddress,
474 hci_spec::defaults::kLEScanInterval,
475 hci_spec::defaults::kLEScanWindow,
476 kTestParams,
477 [](auto, auto) {},
478 kPwConnectTimeout);
479 EXPECT_TRUE(ret);
480 EXPECT_TRUE(connector()->request_pending());
481
482 DeleteConnector();
483 RunUntilIdle();
484
485 EXPECT_TRUE(request_canceled());
486 EXPECT_TRUE(in_connections().empty());
487 }
488
TEST_P(LowEnergyConnectorTest,AllowsRandomAddressChange)489 TEST_P(LowEnergyConnectorTest, AllowsRandomAddressChange) {
490 EXPECT_TRUE(connector()->AllowsRandomAddressChange());
491
492 auto fake_peer = std::make_unique<FakePeer>(kTestAddress, dispatcher());
493 test_device()->AddPeer(std::move(fake_peer));
494
495 // Address change should not be allowed while the procedure is pending.
496 connector()->CreateConnection(
497 /*use_accept_list=*/
498 false,
499 kTestAddress,
500 hci_spec::defaults::kLEScanInterval,
501 hci_spec::defaults::kLEScanWindow,
502 kTestParams,
503 [](auto, auto) {},
504 kPwConnectTimeout);
505 EXPECT_TRUE(connector()->request_pending());
506 EXPECT_FALSE(connector()->AllowsRandomAddressChange());
507
508 RunUntilIdle();
509 EXPECT_TRUE(connector()->AllowsRandomAddressChange());
510 }
511
TEST_P(LowEnergyConnectorTest,AllowsRandomAddressChangeWhileRequestingLocalAddress)512 TEST_P(LowEnergyConnectorTest,
513 AllowsRandomAddressChangeWhileRequestingLocalAddress) {
514 // Make the local address delegate report its result asynchronously.
515 fake_address_delegate()->set_async(true);
516
517 // The connector should be in the "request pending" state without initiating
518 // controller procedures that would prevent a local address change.
519 connector()->CreateConnection(
520 /*use_accept_list=*/
521 false,
522 kTestAddress,
523 hci_spec::defaults::kLEScanInterval,
524 hci_spec::defaults::kLEScanWindow,
525 kTestParams,
526 [](auto, auto) {},
527 kPwConnectTimeout);
528 EXPECT_TRUE(connector()->request_pending());
529 EXPECT_TRUE(connector()->AllowsRandomAddressChange());
530
531 // Initiating a new connection should fail in this state.
532 bool result = connector()->CreateConnection(
533 /*use_accept_list=*/
534 false,
535 kTestAddress,
536 hci_spec::defaults::kLEScanInterval,
537 hci_spec::defaults::kLEScanWindow,
538 kTestParams,
539 [](auto, auto) {},
540 kPwConnectTimeout);
541 EXPECT_FALSE(result);
542
543 // After the loop runs the request should remain pending (since we added no
544 // fake device, the request would eventually timeout) but address change
545 // should no longer be allowed.
546 RunUntilIdle();
547 EXPECT_TRUE(connector()->request_pending());
548 EXPECT_FALSE(connector()->AllowsRandomAddressChange());
549 }
550
TEST_P(LowEnergyConnectorTest,ConnectUsingAcceptList)551 TEST_P(LowEnergyConnectorTest, ConnectUsingAcceptList) {
552 auto fake_peer = std::make_unique<FakePeer>(kTestAddress, dispatcher());
553 test_device()->AddPeer(std::move(fake_peer));
554 connector()->CreateConnection(
555 /*use_accept_list=*/
556 true,
557 kTestAddress,
558 hci_spec::defaults::kLEScanInterval,
559 hci_spec::defaults::kLEScanWindow,
560 kTestParams,
561 [](auto, auto) {},
562 kPwConnectTimeout);
563 RunUntilIdle();
564 ASSERT_TRUE(test_device()->le_connect_params());
565 EXPECT_EQ(pw::bluetooth::emboss::LEOwnAddressType::PUBLIC,
566 test_device()->le_connect_params()->own_address_type);
567 }
568
TEST_P(LowEnergyConnectorTest,ConnectUsingPublicAddress)569 TEST_P(LowEnergyConnectorTest, ConnectUsingPublicAddress) {
570 auto fake_peer = std::make_unique<FakePeer>(kTestAddress, dispatcher());
571 test_device()->AddPeer(std::move(fake_peer));
572 connector()->CreateConnection(
573 /*use_accept_list=*/
574 false,
575 kTestAddress,
576 hci_spec::defaults::kLEScanInterval,
577 hci_spec::defaults::kLEScanWindow,
578 kTestParams,
579 [](auto, auto) {},
580 kPwConnectTimeout);
581 RunUntilIdle();
582 ASSERT_TRUE(test_device()->le_connect_params());
583 EXPECT_EQ(pw::bluetooth::emboss::LEOwnAddressType::PUBLIC,
584 test_device()->le_connect_params()->own_address_type);
585 }
586
TEST_P(LowEnergyConnectorTest,ConnectUsingRandomAddress)587 TEST_P(LowEnergyConnectorTest, ConnectUsingRandomAddress) {
588 fake_address_delegate()->set_local_address(kRandomAddress);
589 fake_address_delegate()->EnablePrivacy(true);
590
591 auto fake_peer = std::make_unique<FakePeer>(kTestAddress, dispatcher());
592 test_device()->AddPeer(std::move(fake_peer));
593 connector()->CreateConnection(
594 /*use_accept_list=*/
595 false,
596 kTestAddress,
597 hci_spec::defaults::kLEScanInterval,
598 hci_spec::defaults::kLEScanWindow,
599 kTestParams,
600 [](auto, auto) {},
601 kPwConnectTimeout);
602 RunUntilIdle();
603 ASSERT_TRUE(test_device()->le_connect_params());
604 EXPECT_EQ(pw::bluetooth::emboss::LEOwnAddressType::RANDOM,
605 test_device()->le_connect_params()->own_address_type);
606 }
607
TEST_P(LowEnergyConnectorTest,ConnectUsingRandomPeerAddress)608 TEST_P(LowEnergyConnectorTest, ConnectUsingRandomPeerAddress) {
609 auto fake_peer = std::make_unique<FakePeer>(kRandomAddress, dispatcher());
610 test_device()->AddPeer(std::move(fake_peer));
611 connector()->CreateConnection(
612 /*use_accept_list=*/
613 false,
614 kRandomAddress,
615 hci_spec::defaults::kLEScanInterval,
616 hci_spec::defaults::kLEScanWindow,
617 kTestParams,
618 [](auto, auto) {},
619 kPwConnectTimeout);
620 RunUntilIdle();
621 ASSERT_TRUE(test_device()->le_connect_params());
622 EXPECT_EQ(DeviceAddress::Type::kLERandom,
623 test_device()->le_connect_params()->peer_address.type());
624 }
625
TEST_P(LowEnergyConnectorTest,CancelConnectWhileWaitingForLocalAddress)626 TEST_P(LowEnergyConnectorTest, CancelConnectWhileWaitingForLocalAddress) {
627 Result<> status = fit::ok();
628 std::unique_ptr<LowEnergyConnection> conn;
629 auto callback = [&](auto s, auto c) {
630 status = s;
631 conn = std::move(c);
632 };
633 fake_address_delegate()->set_async(true);
634 connector()->CreateConnection(
635 /*use_accept_list=*/false,
636 kTestAddress,
637 hci_spec::defaults::kLEScanInterval,
638 hci_spec::defaults::kLEScanWindow,
639 kTestParams,
640 std::move(callback),
641 kPwConnectTimeout);
642
643 // Should be waiting for the address.
644 EXPECT_TRUE(connector()->request_pending());
645 EXPECT_TRUE(connector()->AllowsRandomAddressChange());
646
647 connector()->Cancel();
648 RunUntilIdle();
649 EXPECT_FALSE(connector()->request_pending());
650 EXPECT_TRUE(connector()->AllowsRandomAddressChange());
651
652 // The controller should have received no command from us.
653 EXPECT_FALSE(test_device()->le_connect_params());
654 EXPECT_FALSE(request_canceled());
655
656 // Our request should have resulted in an error.
657 EXPECT_EQ(ToResult(HostError::kCanceled), status);
658 EXPECT_FALSE(conn);
659 }
660
TEST_P(LowEnergyConnectorTest,UseLocalIdentityAddress)661 TEST_P(LowEnergyConnectorTest, UseLocalIdentityAddress) {
662 // Public identity address and a random current local address.
663 fake_address_delegate()->set_identity_address(kLocalAddress);
664 fake_address_delegate()->set_local_address(kRandomAddress);
665
666 connector()->UseLocalIdentityAddress();
667
668 auto fake_peer = std::make_unique<FakePeer>(kTestAddress, dispatcher());
669 test_device()->AddPeer(std::move(fake_peer));
670 connector()->CreateConnection(
671 /*use_accept_list=*/
672 false,
673 kTestAddress,
674 hci_spec::defaults::kLEScanInterval,
675 hci_spec::defaults::kLEScanWindow,
676 kTestParams,
677 [](auto, auto) {},
678 kPwConnectTimeout);
679 RunUntilIdle();
680 ASSERT_TRUE(test_device()->le_connect_params());
681
682 // The public address should have been used.
683 EXPECT_EQ(pw::bluetooth::emboss::LEOwnAddressType::PUBLIC,
684 test_device()->le_connect_params()->own_address_type);
685 }
686
TEST_P(LowEnergyConnectorTest,ExtendedCreateConnectionUsesSameParameters)687 TEST_P(LowEnergyConnectorTest, ExtendedCreateConnectionUsesSameParameters) {
688 bool use_extended_operations = GetParam();
689 if (!use_extended_operations) {
690 // For this specific test, we want to test only the LE Extended Create
691 // Connection functionality. Since this is only a single test, skipping the
692 // LE Create Connection option seemed simpler. If tests for LE Extended
693 // Create Connection grow in number, we should create a separate file, test
694 // suite, etc.
695 return;
696 }
697
698 using LEConnectParams = FakeController::LEConnectParams;
699 using InitiatingPHYs = LEConnectParams::InitiatingPHYs;
700
701 auto fake_peer = std::make_unique<FakePeer>(kTestAddress, dispatcher());
702 test_device()->AddPeer(std::move(fake_peer));
703
704 connector()->CreateConnection(
705 /*use_accept_list=*/
706 true,
707 kTestAddress,
708 hci_spec::defaults::kLEScanInterval,
709 hci_spec::defaults::kLEScanWindow,
710 kTestParams,
711 [](auto, auto) {},
712 kPwConnectTimeout);
713 RunUntilIdle();
714
715 const std::optional<LEConnectParams>& params =
716 test_device()->le_connect_params();
717 ASSERT_EQ(3u, params->phy_conn_params.size());
718 const auto& le_1m =
719 params->phy_conn_params.find(InitiatingPHYs::kLE_1M)->second;
720 const auto& le_2m =
721 params->phy_conn_params.find(InitiatingPHYs::kLE_2M)->second;
722 const auto& le_coded =
723 params->phy_conn_params.find(InitiatingPHYs::kLE_Coded)->second;
724
725 ASSERT_EQ(le_1m.scan_interval, le_2m.scan_interval);
726 ASSERT_EQ(le_1m.scan_window, le_2m.scan_window);
727 ASSERT_EQ(le_1m.connection_interval_min, le_2m.connection_interval_min);
728 ASSERT_EQ(le_1m.connection_interval_max, le_2m.connection_interval_max);
729 ASSERT_EQ(le_1m.max_latency, le_2m.max_latency);
730 ASSERT_EQ(le_1m.supervision_timeout, le_2m.supervision_timeout);
731 ASSERT_EQ(le_1m.min_ce_length, le_2m.min_ce_length);
732 ASSERT_EQ(le_1m.max_ce_length, le_2m.max_ce_length);
733
734 ASSERT_EQ(le_2m.scan_interval, le_coded.scan_interval);
735 ASSERT_EQ(le_2m.scan_window, le_coded.scan_window);
736 ASSERT_EQ(le_2m.connection_interval_min, le_coded.connection_interval_min);
737 ASSERT_EQ(le_2m.connection_interval_max, le_coded.connection_interval_max);
738 ASSERT_EQ(le_2m.max_latency, le_coded.max_latency);
739 ASSERT_EQ(le_2m.supervision_timeout, le_coded.supervision_timeout);
740 ASSERT_EQ(le_2m.min_ce_length, le_coded.min_ce_length);
741 ASSERT_EQ(le_2m.max_ce_length, le_coded.max_ce_length);
742 }
743
744 } // namespace
745 } // namespace bt::hci
746