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 #include "pw_bluetooth_sapphire/internal/host/sco/sco_connection_manager.h"
15
16 #include <optional>
17
18 #include "pw_bluetooth_sapphire/internal/host/testing/controller_test.h"
19 #include "pw_bluetooth_sapphire/internal/host/testing/mock_controller.h"
20 #include "pw_bluetooth_sapphire/internal/host/testing/test_packets.h"
21
22 namespace bt::sco {
23 namespace {
24
25 using OpenConnectionResult = ScoConnectionManager::OpenConnectionResult;
26 using AcceptConnectionResult = ScoConnectionManager::AcceptConnectionResult;
27
28 constexpr hci_spec::ConnectionHandle kAclConnectionHandle = 0x40;
29 constexpr hci_spec::ConnectionHandle kScoConnectionHandle = 0x41;
30 const DeviceAddress kLocalAddress(DeviceAddress::Type::kBREDR,
31 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
32 const DeviceAddress kPeerAddress(DeviceAddress::Type::kBREDR,
33 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02});
34 bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter>
35 kConnectionParams;
36
37 bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter>
InitializeConnectionParams()38 InitializeConnectionParams() {
39 bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter>
40 out;
41 auto view = out.view();
42 view.transmit_bandwidth().Write(1);
43 view.receive_bandwidth().Write(2);
44 view.transmit_coding_format().coding_format().Write(
45 pw::bluetooth::emboss::CodingFormat::MSBC);
46 view.transmit_coding_format().company_id().Write(3);
47 view.transmit_coding_format().vendor_codec_id().Write(4);
48 view.receive_coding_format().coding_format().Write(
49 pw::bluetooth::emboss::CodingFormat::CVSD);
50 view.receive_coding_format().company_id().Write(5);
51 view.receive_coding_format().vendor_codec_id().Write(6);
52 view.transmit_codec_frame_size_bytes().Write(7);
53 view.receive_codec_frame_size_bytes().Write(8);
54 view.input_bandwidth().Write(9);
55 view.output_bandwidth().Write(10);
56 view.input_coding_format().coding_format().Write(
57 pw::bluetooth::emboss::CodingFormat::A_LAW);
58 view.input_coding_format().company_id().Write(11);
59 view.input_coding_format().vendor_codec_id().Write(12);
60 view.output_coding_format().coding_format().Write(
61 pw::bluetooth::emboss::CodingFormat::LINEAR_PCM);
62 view.output_coding_format().company_id().Write(13);
63 view.output_coding_format().vendor_codec_id().Write(14);
64 view.input_coded_data_size_bits().Write(15);
65 view.output_coded_data_size_bits().Write(16);
66 view.input_pcm_data_format().Write(
67 pw::bluetooth::emboss::PcmDataFormat::ONES_COMPLEMENT);
68 view.output_pcm_data_format().Write(
69 pw::bluetooth::emboss::PcmDataFormat::TWOS_COMPLEMENT);
70 view.input_pcm_sample_payload_msb_position().Write(17);
71 view.output_pcm_sample_payload_msb_position().Write(18);
72 view.input_data_path().Write(
73 pw::bluetooth::emboss::ScoDataPath::AUDIO_TEST_MODE);
74 view.output_data_path().Write(pw::bluetooth::emboss::ScoDataPath::HCI);
75 view.input_transport_unit_size_bits().Write(19);
76 view.output_transport_unit_size_bits().Write(20);
77 view.max_latency_ms().Write(21);
78 view.packet_types().BackingStorage().WriteUInt(0x003F); // All packet types
79 view.retransmission_effort().Write(
80 pw::bluetooth::emboss::SynchronousConnectionParameters::
81 ScoRetransmissionEffort::QUALITY_OPTIMIZED);
82 return out;
83 }
84
85 bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter>
ScoConnectionParams()86 ScoConnectionParams() {
87 auto params = kConnectionParams;
88 params.view().packet_types().BackingStorage().WriteUInt(0);
89 params.view().packet_types().hv3().Write(true);
90 return params;
91 }
92
93 bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter>
EscoConnectionParams()94 EscoConnectionParams() {
95 auto params = kConnectionParams;
96 params.view().packet_types().BackingStorage().WriteUInt(0);
97 params.view().packet_types().ev3().Write(true);
98 return params;
99 }
100
101 using TestingBase =
102 bt::testing::FakeDispatcherControllerTest<bt::testing::MockController>;
103
104 // Activate a SCO connection and set the close handler to call Deactivate()
activate_connection(OpenConnectionResult & result)105 void activate_connection(OpenConnectionResult& result) {
106 if (result.is_ok()) {
107 result.value()->Activate(
108 /*rx_callback=*/[]() {},
109 /*closed_callback=*/[result] { result.value()->Deactivate(); });
110 };
111 }
112
113 class ScoConnectionManagerTest : public TestingBase {
114 public:
115 ScoConnectionManagerTest() = default;
116 ~ScoConnectionManagerTest() override = default;
117
SetUp()118 void SetUp() override {
119 TestingBase::SetUp();
120 InitializeACLDataChannel();
121 InitializeScoDataChannel();
122
123 manager_ =
124 std::make_unique<ScoConnectionManager>(PeerId(1),
125 kAclConnectionHandle,
126 kPeerAddress,
127 kLocalAddress,
128 transport()->GetWeakPtr());
129 kConnectionParams = InitializeConnectionParams();
130 }
131
TearDown()132 void TearDown() override {
133 manager_.reset();
134 RunUntilIdle();
135 TestingBase::TearDown();
136 }
137
DestroyManager()138 void DestroyManager() { manager_.reset(); }
139
manager() const140 ScoConnectionManager* manager() const { return manager_.get(); }
141
142 private:
143 std::unique_ptr<ScoConnectionManager> manager_;
144
145 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ScoConnectionManagerTest);
146 };
147
TEST_F(ScoConnectionManagerTest,OpenConnectionSuccess)148 TEST_F(ScoConnectionManagerTest, OpenConnectionSuccess) {
149 auto setup_status_packet = testing::CommandStatusPacket(
150 hci_spec::kEnhancedSetupSynchronousConnection,
151 pw::bluetooth::emboss::StatusCode::SUCCESS);
152 auto conn_complete_packet = testing::SynchronousConnectionCompletePacket(
153 kScoConnectionHandle,
154 kPeerAddress,
155 hci_spec::LinkType::kExtendedSCO,
156 pw::bluetooth::emboss::StatusCode::SUCCESS);
157 EXPECT_CMD_PACKET_OUT(test_device(),
158 testing::EnhancedSetupSynchronousConnectionPacket(
159 kAclConnectionHandle, kConnectionParams),
160 &setup_status_packet,
161 &conn_complete_packet);
162
163 std::optional<OpenConnectionResult> conn_result;
164 auto conn_cb = [&conn_result](auto result) {
165 activate_connection(result);
166 conn_result = std::move(result);
167 };
168
169 auto req_handle =
170 manager()->OpenConnection(kConnectionParams, std::move(conn_cb));
171
172 RunUntilIdle();
173 ASSERT_TRUE(conn_result.has_value());
174 ASSERT_TRUE(conn_result->is_ok());
175 ASSERT_TRUE(conn_result->value().is_alive());
176 EXPECT_EQ(conn_result->value()->handle(), kScoConnectionHandle);
177
178 EXPECT_CMD_PACKET_OUT(test_device(),
179 testing::DisconnectPacket(kScoConnectionHandle));
180 conn_result->value()->Close();
181 RunUntilIdle();
182 }
183
TEST_F(ScoConnectionManagerTest,OpenConnectionAndReceiveFailureStatusEvent)184 TEST_F(ScoConnectionManagerTest, OpenConnectionAndReceiveFailureStatusEvent) {
185 auto setup_status_packet = testing::CommandStatusPacket(
186 hci_spec::kEnhancedSetupSynchronousConnection,
187 pw::bluetooth::emboss::StatusCode::CONNECTION_LIMIT_EXCEEDED);
188 EXPECT_CMD_PACKET_OUT(test_device(),
189 testing::EnhancedSetupSynchronousConnectionPacket(
190 kAclConnectionHandle, kConnectionParams),
191 &setup_status_packet);
192
193 std::optional<OpenConnectionResult> conn;
194 auto conn_cb = [&conn](auto cb_result) {
195 activate_connection(cb_result);
196 conn = std::move(cb_result);
197 };
198
199 auto req_handle =
200 manager()->OpenConnection(kConnectionParams, std::move(conn_cb));
201
202 RunUntilIdle();
203 ASSERT_TRUE(conn.has_value());
204 ASSERT_TRUE(conn->is_error());
205 EXPECT_EQ(conn->error_value(), HostError::kFailed);
206 }
207
TEST_F(ScoConnectionManagerTest,OpenConnectionAndReceiveFailureCompleteEvent)208 TEST_F(ScoConnectionManagerTest, OpenConnectionAndReceiveFailureCompleteEvent) {
209 auto setup_status_packet = testing::CommandStatusPacket(
210 hci_spec::kEnhancedSetupSynchronousConnection,
211 pw::bluetooth::emboss::StatusCode::SUCCESS);
212 auto conn_complete_packet = testing::SynchronousConnectionCompletePacket(
213 kScoConnectionHandle,
214 kPeerAddress,
215 hci_spec::LinkType::kExtendedSCO,
216 pw::bluetooth::emboss::StatusCode::CONNECTION_FAILED_TO_BE_ESTABLISHED);
217 EXPECT_CMD_PACKET_OUT(test_device(),
218 testing::EnhancedSetupSynchronousConnectionPacket(
219 kAclConnectionHandle, kConnectionParams),
220 &setup_status_packet,
221 &conn_complete_packet);
222
223 std::optional<OpenConnectionResult> conn;
224 auto conn_cb = [&conn](auto cb_result) {
225 activate_connection(cb_result);
226 conn = std::move(cb_result);
227 };
228
229 auto req_handle =
230 manager()->OpenConnection(kConnectionParams, std::move(conn_cb));
231
232 RunUntilIdle();
233 ASSERT_TRUE(conn.has_value());
234 ASSERT_TRUE(conn->is_error());
235 EXPECT_EQ(conn->error_value(), HostError::kFailed);
236 }
237
TEST_F(ScoConnectionManagerTest,AcceptConnectionCompleteEventErrorAndResultCallbackDestroysRequestHandle)238 TEST_F(
239 ScoConnectionManagerTest,
240 AcceptConnectionCompleteEventErrorAndResultCallbackDestroysRequestHandle) {
241 std::optional<AcceptConnectionResult> conn;
242 std::optional<ScoConnectionManager::RequestHandle> req_handle;
243 auto conn_cb = [&conn, &req_handle](auto cb_result) {
244 req_handle.reset();
245 conn = std::move(cb_result);
246 };
247
248 req_handle =
249 manager()->AcceptConnection({kConnectionParams}, std::move(conn_cb));
250
251 auto conn_req_packet =
252 testing::ConnectionRequestPacket(kPeerAddress, hci_spec::LinkType::kSCO);
253 test_device()->SendCommandChannelPacket(conn_req_packet);
254
255 auto accept_status_packet = testing::CommandStatusPacket(
256 hci_spec::kEnhancedAcceptSynchronousConnectionRequest,
257 pw::bluetooth::emboss::StatusCode::UNSPECIFIED_ERROR);
258 auto conn_complete_packet = testing::SynchronousConnectionCompletePacket(
259 kScoConnectionHandle,
260 kPeerAddress,
261 hci_spec::LinkType::kExtendedSCO,
262 pw::bluetooth::emboss::StatusCode::CONNECTION_ACCEPT_TIMEOUT_EXCEEDED);
263 EXPECT_CMD_PACKET_OUT(
264 test_device(),
265 testing::EnhancedAcceptSynchronousConnectionRequestPacket(
266 kPeerAddress, kConnectionParams),
267 &accept_status_packet,
268 &conn_complete_packet);
269
270 RunUntilIdle();
271 ASSERT_TRUE(conn.has_value());
272 ASSERT_TRUE(conn->is_error());
273 EXPECT_EQ(conn->error_value(), HostError::kParametersRejected);
274 }
275
TEST_F(ScoConnectionManagerTest,IgnoreWrongAddressInConnectionComplete)276 TEST_F(ScoConnectionManagerTest, IgnoreWrongAddressInConnectionComplete) {
277 auto setup_status_packet = testing::CommandStatusPacket(
278 hci_spec::kEnhancedSetupSynchronousConnection,
279 pw::bluetooth::emboss::StatusCode::SUCCESS);
280 const DeviceAddress kWrongPeerAddress(DeviceAddress::Type::kBREDR,
281 {0x00, 0x00, 0x00, 0x00, 0x00, 0x05});
282 auto conn_complete_packet_wrong =
283 testing::SynchronousConnectionCompletePacket(
284 kScoConnectionHandle,
285 kWrongPeerAddress,
286 hci_spec::LinkType::kExtendedSCO,
287 pw::bluetooth::emboss::StatusCode::SUCCESS);
288 EXPECT_CMD_PACKET_OUT(test_device(),
289 testing::EnhancedSetupSynchronousConnectionPacket(
290 kAclConnectionHandle, kConnectionParams),
291 &setup_status_packet,
292 &conn_complete_packet_wrong);
293
294 std::optional<OpenConnectionResult> conn_result;
295 auto conn_cb = [&conn_result](auto result) {
296 activate_connection(result);
297 conn_result = std::move(result);
298 };
299
300 auto req_handle =
301 manager()->OpenConnection(kConnectionParams, std::move(conn_cb));
302
303 RunUntilIdle();
304 EXPECT_FALSE(conn_result.has_value());
305
306 // Ensure subsequent correct complete packet completes request.
307 auto conn_complete_packet = testing::SynchronousConnectionCompletePacket(
308 kScoConnectionHandle,
309 kPeerAddress,
310 hci_spec::LinkType::kExtendedSCO,
311 pw::bluetooth::emboss::StatusCode::SUCCESS);
312 test_device()->SendCommandChannelPacket(conn_complete_packet);
313 RunUntilIdle();
314 ASSERT_TRUE(conn_result.has_value());
315 ASSERT_TRUE(conn_result->is_ok());
316 EXPECT_CMD_PACKET_OUT(test_device(),
317 testing::DisconnectPacket(kScoConnectionHandle));
318 }
319
TEST_F(ScoConnectionManagerTest,UnexpectedConnectionCompleteDisconnectsConnection)320 TEST_F(ScoConnectionManagerTest,
321 UnexpectedConnectionCompleteDisconnectsConnection) {
322 auto conn_complete_packet = testing::SynchronousConnectionCompletePacket(
323 kScoConnectionHandle,
324 kPeerAddress,
325 hci_spec::LinkType::kExtendedSCO,
326 pw::bluetooth::emboss::StatusCode::SUCCESS);
327 EXPECT_CMD_PACKET_OUT(test_device(),
328 testing::DisconnectPacket(kScoConnectionHandle));
329 test_device()->SendCommandChannelPacket(conn_complete_packet);
330 RunUntilIdle();
331 }
332
TEST_F(ScoConnectionManagerTest,DestroyingManagerClosesConnections)333 TEST_F(ScoConnectionManagerTest, DestroyingManagerClosesConnections) {
334 auto setup_status_packet = testing::CommandStatusPacket(
335 hci_spec::kEnhancedSetupSynchronousConnection,
336 pw::bluetooth::emboss::StatusCode::SUCCESS);
337 auto conn_complete_packet = testing::SynchronousConnectionCompletePacket(
338 kScoConnectionHandle,
339 kPeerAddress,
340 hci_spec::LinkType::kExtendedSCO,
341 pw::bluetooth::emboss::StatusCode::SUCCESS);
342 EXPECT_CMD_PACKET_OUT(test_device(),
343 testing::EnhancedSetupSynchronousConnectionPacket(
344 kAclConnectionHandle, kConnectionParams),
345 &setup_status_packet,
346 &conn_complete_packet);
347
348 std::optional<OpenConnectionResult> conn_result;
349 auto conn_cb = [&conn_result](OpenConnectionResult result) {
350 activate_connection(result);
351 conn_result = std::move(result);
352 };
353
354 auto req_handle =
355 manager()->OpenConnection(kConnectionParams, std::move(conn_cb));
356
357 RunUntilIdle();
358 ASSERT_TRUE(conn_result.has_value());
359 ASSERT_TRUE(conn_result->is_ok());
360 EXPECT_TRUE(conn_result->value().is_alive());
361
362 EXPECT_CMD_PACKET_OUT(test_device(),
363 testing::DisconnectPacket(kScoConnectionHandle));
364 DestroyManager();
365 RunUntilIdle();
366 // WeakPtr should become invalid.
367 EXPECT_FALSE(conn_result->value().is_alive());
368 }
369
TEST_F(ScoConnectionManagerTest,QueueThreeRequestsCancelsSecond)370 TEST_F(ScoConnectionManagerTest, QueueThreeRequestsCancelsSecond) {
371 const hci_spec::ConnectionHandle handle_0 = kScoConnectionHandle;
372 const hci_spec::ConnectionHandle handle_1 = handle_0 + 1;
373 const hci_spec::ConnectionHandle handle_2 = handle_1 + 1;
374
375 auto setup_status_packet = testing::CommandStatusPacket(
376 hci_spec::kEnhancedSetupSynchronousConnection,
377 pw::bluetooth::emboss::StatusCode::SUCCESS);
378 EXPECT_CMD_PACKET_OUT(test_device(),
379 testing::EnhancedSetupSynchronousConnectionPacket(
380 kAclConnectionHandle, kConnectionParams),
381 &setup_status_packet);
382
383 std::optional<OpenConnectionResult> conn_result_0;
384 auto conn_cb_0 = [&conn_result_0](auto cb_conn) {
385 // No need to activate the connection here since Deactivate is called
386 // manually.
387 conn_result_0 = std::move(cb_conn);
388 };
389 auto req_handle_0 =
390 manager()->OpenConnection(kConnectionParams, std::move(conn_cb_0));
391
392 std::optional<OpenConnectionResult> conn_result_1;
393 auto conn_cb_1 = [&conn_result_1](auto cb_result) {
394 activate_connection(cb_result);
395 conn_result_1 = std::move(cb_result);
396 };
397 auto req_handle_1 =
398 manager()->OpenConnection(kConnectionParams, std::move(conn_cb_1));
399
400 std::optional<OpenConnectionResult> conn_result_2;
401 auto conn_cb_2 = [&conn_result_2](auto cb_conn) {
402 // No need to activate the connection here since Deactivate is called
403 // manually.
404 conn_result_2 = std::move(cb_conn);
405 };
406 auto req_handle_2 =
407 manager()->OpenConnection(kConnectionParams, std::move(conn_cb_2));
408
409 RunUntilIdle();
410 EXPECT_FALSE(conn_result_0.has_value());
411 EXPECT_FALSE(conn_result_2.has_value());
412 ASSERT_TRUE(conn_result_1.has_value());
413 ASSERT_TRUE(conn_result_1->is_error());
414 EXPECT_EQ(conn_result_1->error_value(), HostError::kCanceled);
415
416 EXPECT_CMD_PACKET_OUT(test_device(),
417 testing::EnhancedSetupSynchronousConnectionPacket(
418 kAclConnectionHandle, kConnectionParams),
419 &setup_status_packet);
420
421 auto conn_complete_packet_0 = testing::SynchronousConnectionCompletePacket(
422 handle_0,
423 kPeerAddress,
424 hci_spec::LinkType::kExtendedSCO,
425 pw::bluetooth::emboss::StatusCode::SUCCESS);
426 test_device()->SendCommandChannelPacket(conn_complete_packet_0);
427 RunUntilIdle();
428 ASSERT_TRUE(conn_result_0.has_value());
429 ASSERT_TRUE(conn_result_0->is_ok());
430 EXPECT_FALSE(conn_result_2.has_value());
431
432 auto conn_complete_packet_2 = testing::SynchronousConnectionCompletePacket(
433 handle_2,
434 kPeerAddress,
435 hci_spec::LinkType::kExtendedSCO,
436 pw::bluetooth::emboss::StatusCode::SUCCESS);
437 test_device()->SendCommandChannelPacket(conn_complete_packet_2);
438 RunUntilIdle();
439 ASSERT_TRUE(conn_result_2.has_value());
440 ASSERT_TRUE(conn_result_2->is_ok());
441
442 // Send status and complete events so second disconnect command isn't queued
443 // in CommandChannel.
444 auto disconn_status_packet_0 = testing::CommandStatusPacket(
445 hci_spec::kDisconnect, pw::bluetooth::emboss::StatusCode::SUCCESS);
446 auto disconn_complete_0 = testing::DisconnectionCompletePacket(handle_0);
447 EXPECT_CMD_PACKET_OUT(test_device(),
448 testing::DisconnectPacket(handle_0),
449 &disconn_status_packet_0,
450 &disconn_complete_0);
451 conn_result_0.value()->Deactivate();
452 EXPECT_CMD_PACKET_OUT(test_device(), testing::DisconnectPacket(handle_2));
453 conn_result_2.value()->Deactivate();
454 RunUntilIdle();
455 }
456
TEST_F(ScoConnectionManagerTest,HandleReuse)457 TEST_F(ScoConnectionManagerTest, HandleReuse) {
458 auto setup_status_packet = testing::CommandStatusPacket(
459 hci_spec::kEnhancedSetupSynchronousConnection,
460 pw::bluetooth::emboss::StatusCode::SUCCESS);
461 auto conn_complete_packet = testing::SynchronousConnectionCompletePacket(
462 kScoConnectionHandle,
463 kPeerAddress,
464 hci_spec::LinkType::kExtendedSCO,
465 pw::bluetooth::emboss::StatusCode::SUCCESS);
466 EXPECT_CMD_PACKET_OUT(test_device(),
467 testing::EnhancedSetupSynchronousConnectionPacket(
468 kAclConnectionHandle, kConnectionParams),
469 &setup_status_packet,
470 &conn_complete_packet);
471
472 std::optional<OpenConnectionResult> conn_result;
473 auto conn_cb = [&conn_result](auto cb_conn) {
474 // No need to activate the connection here since Deactivate is called
475 // manually.
476 conn_result = std::move(cb_conn);
477 };
478
479 auto req_handle_0 = manager()->OpenConnection(kConnectionParams, conn_cb);
480
481 RunUntilIdle();
482 ASSERT_TRUE(conn_result.has_value());
483 ASSERT_TRUE(conn_result->is_ok());
484 ScoConnection::WeakPtr conn = conn_result->value();
485 EXPECT_EQ(conn->handle(), kScoConnectionHandle);
486
487 auto disconn_status_packet = testing::CommandStatusPacket(
488 hci_spec::kDisconnect, pw::bluetooth::emboss::StatusCode::SUCCESS);
489 auto disconn_complete =
490 testing::DisconnectionCompletePacket(kScoConnectionHandle);
491 EXPECT_CMD_PACKET_OUT(test_device(),
492 testing::DisconnectPacket(kScoConnectionHandle),
493 &disconn_status_packet,
494 &disconn_complete);
495 conn->Deactivate();
496 conn_result.reset();
497
498 EXPECT_CMD_PACKET_OUT(test_device(),
499 testing::EnhancedSetupSynchronousConnectionPacket(
500 kAclConnectionHandle, kConnectionParams),
501 &setup_status_packet,
502 &conn_complete_packet);
503
504 auto req_handle_1 = manager()->OpenConnection(kConnectionParams, conn_cb);
505
506 RunUntilIdle();
507 ASSERT_TRUE(conn_result.has_value());
508 ASSERT_TRUE(conn_result->is_ok());
509 EXPECT_EQ(conn_result->value()->handle(), kScoConnectionHandle);
510
511 EXPECT_CMD_PACKET_OUT(test_device(),
512 testing::DisconnectPacket(kScoConnectionHandle));
513 }
514
TEST_F(ScoConnectionManagerTest,AcceptConnectionSuccess)515 TEST_F(ScoConnectionManagerTest, AcceptConnectionSuccess) {
516 std::optional<AcceptConnectionResult> conn_result;
517 auto conn_cb = [&conn_result](auto cb_conn) {
518 EXPECT_TRUE(cb_conn.is_ok());
519 conn_result = std::move(cb_conn);
520 };
521 auto req_handle =
522 manager()->AcceptConnection({kConnectionParams}, std::move(conn_cb));
523
524 auto conn_req_packet =
525 testing::ConnectionRequestPacket(kPeerAddress, hci_spec::LinkType::kSCO);
526 test_device()->SendCommandChannelPacket(conn_req_packet);
527
528 auto accept_status_packet = testing::CommandStatusPacket(
529 hci_spec::kEnhancedAcceptSynchronousConnectionRequest,
530 pw::bluetooth::emboss::StatusCode::SUCCESS);
531 EXPECT_CMD_PACKET_OUT(
532 test_device(),
533 testing::EnhancedAcceptSynchronousConnectionRequestPacket(
534 kPeerAddress, kConnectionParams),
535 &accept_status_packet);
536 RunUntilIdle();
537 EXPECT_FALSE(conn_result.has_value());
538
539 test_device()->SendCommandChannelPacket(
540 testing::SynchronousConnectionCompletePacket(
541 kScoConnectionHandle,
542 kPeerAddress,
543 hci_spec::LinkType::kSCO,
544 pw::bluetooth::emboss::StatusCode::SUCCESS));
545
546 RunUntilIdle();
547 ASSERT_TRUE(conn_result.has_value());
548 ASSERT_TRUE(conn_result->is_ok());
549 EXPECT_EQ(conn_result->value().first->handle(), kScoConnectionHandle);
550
551 EXPECT_CMD_PACKET_OUT(test_device(),
552 testing::DisconnectPacket(kScoConnectionHandle));
553 }
554
TEST_F(ScoConnectionManagerTest,AcceptConnectionAndReceiveStatusAndCompleteEventWithErrors)555 TEST_F(ScoConnectionManagerTest,
556 AcceptConnectionAndReceiveStatusAndCompleteEventWithErrors) {
557 std::optional<AcceptConnectionResult> conn_result;
558 auto conn_cb = [&conn_result](auto cb_conn) {
559 conn_result = std::move(cb_conn);
560 };
561
562 auto req_handle =
563 manager()->AcceptConnection({kConnectionParams}, std::move(conn_cb));
564
565 auto conn_req_packet =
566 testing::ConnectionRequestPacket(kPeerAddress, hci_spec::LinkType::kSCO);
567 test_device()->SendCommandChannelPacket(conn_req_packet);
568
569 auto accept_status_packet = testing::CommandStatusPacket(
570 hci_spec::kEnhancedAcceptSynchronousConnectionRequest,
571 pw::bluetooth::emboss::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
572 EXPECT_CMD_PACKET_OUT(
573 test_device(),
574 testing::EnhancedAcceptSynchronousConnectionRequestPacket(
575 kPeerAddress, kConnectionParams),
576 &accept_status_packet);
577 RunUntilIdle();
578 EXPECT_FALSE(conn_result.has_value());
579
580 test_device()->SendCommandChannelPacket(
581 testing::SynchronousConnectionCompletePacket(
582 kScoConnectionHandle,
583 kPeerAddress,
584 hci_spec::LinkType::kSCO,
585 pw::bluetooth::emboss::StatusCode::
586 CONNECTION_ACCEPT_TIMEOUT_EXCEEDED));
587
588 RunUntilIdle();
589 ASSERT_TRUE(conn_result.has_value());
590 ASSERT_TRUE(conn_result->is_error());
591 EXPECT_EQ(conn_result->error_value(), HostError::kParametersRejected);
592 }
593
TEST_F(ScoConnectionManagerTest,AcceptConnectionAndReceiveCompleteEventWithFailureStatus)594 TEST_F(ScoConnectionManagerTest,
595 AcceptConnectionAndReceiveCompleteEventWithFailureStatus) {
596 std::optional<AcceptConnectionResult> conn_result;
597 auto conn_cb = [&conn_result](auto cb_conn) {
598 conn_result = std::move(cb_conn);
599 };
600
601 auto req_handle =
602 manager()->AcceptConnection({kConnectionParams}, std::move(conn_cb));
603
604 auto conn_req_packet =
605 testing::ConnectionRequestPacket(kPeerAddress, hci_spec::LinkType::kSCO);
606 test_device()->SendCommandChannelPacket(conn_req_packet);
607
608 auto accept_status_packet = testing::CommandStatusPacket(
609 hci_spec::kEnhancedAcceptSynchronousConnectionRequest,
610 pw::bluetooth::emboss::StatusCode::SUCCESS);
611 EXPECT_CMD_PACKET_OUT(
612 test_device(),
613 testing::EnhancedAcceptSynchronousConnectionRequestPacket(
614 kPeerAddress, kConnectionParams),
615 &accept_status_packet);
616 RunUntilIdle();
617 EXPECT_FALSE(conn_result.has_value());
618
619 test_device()->SendCommandChannelPacket(
620 testing::SynchronousConnectionCompletePacket(
621 kScoConnectionHandle,
622 kPeerAddress,
623 hci_spec::LinkType::kSCO,
624 pw::bluetooth::emboss::StatusCode::
625 CONNECTION_FAILED_TO_BE_ESTABLISHED));
626
627 RunUntilIdle();
628 ASSERT_TRUE(conn_result.has_value());
629 ASSERT_TRUE(conn_result->is_error());
630 EXPECT_EQ(conn_result->error_value(), HostError::kParametersRejected);
631 }
632
TEST_F(ScoConnectionManagerTest,RejectInboundRequestWhileInitiatorRequestPending)633 TEST_F(ScoConnectionManagerTest,
634 RejectInboundRequestWhileInitiatorRequestPending) {
635 size_t conn_cb_count = 0;
636 auto conn_cb = [&conn_cb_count](auto cb_conn) {
637 activate_connection(cb_conn);
638 conn_cb_count++;
639 };
640
641 auto setup_status_packet = testing::CommandStatusPacket(
642 hci_spec::kEnhancedSetupSynchronousConnection,
643 pw::bluetooth::emboss::StatusCode::SUCCESS);
644 EXPECT_CMD_PACKET_OUT(test_device(),
645 testing::EnhancedSetupSynchronousConnectionPacket(
646 kAclConnectionHandle, kConnectionParams),
647 &setup_status_packet);
648
649 auto req_handle =
650 manager()->OpenConnection(kConnectionParams, std::move(conn_cb));
651
652 auto conn_req_packet =
653 testing::ConnectionRequestPacket(kPeerAddress, hci_spec::LinkType::kSCO);
654 test_device()->SendCommandChannelPacket(conn_req_packet);
655
656 auto reject_status_packet = testing::CommandStatusPacket(
657 hci_spec::kRejectSynchronousConnectionRequest,
658 pw::bluetooth::emboss::StatusCode::SUCCESS);
659 EXPECT_CMD_PACKET_OUT(
660 test_device(),
661 testing::RejectSynchronousConnectionRequest(
662 kPeerAddress,
663 pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_BAD_BD_ADDR),
664 &reject_status_packet);
665 RunUntilIdle();
666 EXPECT_EQ(conn_cb_count, 0u);
667 // Destroy manager so that callback gets called before callback reference is
668 // invalid.
669 DestroyManager();
670 EXPECT_EQ(conn_cb_count, 1u);
671 }
672
TEST_F(ScoConnectionManagerTest,RejectInboundRequestWhenNoRequestsPending)673 TEST_F(ScoConnectionManagerTest, RejectInboundRequestWhenNoRequestsPending) {
674 auto conn_req_packet =
675 testing::ConnectionRequestPacket(kPeerAddress, hci_spec::LinkType::kSCO);
676 test_device()->SendCommandChannelPacket(conn_req_packet);
677
678 auto reject_status_packet = testing::CommandStatusPacket(
679 hci_spec::kRejectSynchronousConnectionRequest,
680 pw::bluetooth::emboss::StatusCode::SUCCESS);
681 EXPECT_CMD_PACKET_OUT(
682 test_device(),
683 testing::RejectSynchronousConnectionRequest(
684 kPeerAddress,
685 pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_BAD_BD_ADDR),
686 &reject_status_packet);
687 RunUntilIdle();
688 }
689
TEST_F(ScoConnectionManagerTest,IgnoreInboundAclRequest)690 TEST_F(ScoConnectionManagerTest, IgnoreInboundAclRequest) {
691 auto conn_req_packet =
692 testing::ConnectionRequestPacket(kPeerAddress, hci_spec::LinkType::kACL);
693 test_device()->SendCommandChannelPacket(conn_req_packet);
694 RunUntilIdle();
695 }
696
TEST_F(ScoConnectionManagerTest,IgnoreInboundRequestWrongPeerAddress)697 TEST_F(ScoConnectionManagerTest, IgnoreInboundRequestWrongPeerAddress) {
698 const DeviceAddress address(DeviceAddress::Type::kBREDR,
699 {0x00, 0x00, 0x00, 0x00, 0x00, 0x05});
700 auto conn_req_packet =
701 testing::ConnectionRequestPacket(address, hci_spec::LinkType::kACL);
702 test_device()->SendCommandChannelPacket(conn_req_packet);
703 RunUntilIdle();
704 }
705
TEST_F(ScoConnectionManagerTest,QueueTwoAcceptConnectionRequestsCancelsFirstRequest)706 TEST_F(ScoConnectionManagerTest,
707 QueueTwoAcceptConnectionRequestsCancelsFirstRequest) {
708 std::optional<AcceptConnectionResult> conn_result_0;
709 auto conn_cb = [&conn_result_0](auto cb_conn) {
710 conn_result_0 = std::move(cb_conn);
711 };
712 auto req_handle_0 = manager()->AcceptConnection({kConnectionParams}, conn_cb);
713
714 auto second_conn_params = kConnectionParams;
715 second_conn_params.view().transmit_bandwidth().Write(99);
716
717 std::optional<AcceptConnectionResult> conn_result_1;
718 auto req_handle_1 = manager()->AcceptConnection(
719 {second_conn_params},
720 [&conn_result_1](auto cb_conn) { conn_result_1 = std::move(cb_conn); });
721
722 ASSERT_TRUE(conn_result_0.has_value());
723 ASSERT_TRUE(conn_result_0->is_error());
724 EXPECT_EQ(conn_result_0->error_value(), HostError::kCanceled);
725
726 auto conn_req_packet =
727 testing::ConnectionRequestPacket(kPeerAddress, hci_spec::LinkType::kSCO);
728 test_device()->SendCommandChannelPacket(conn_req_packet);
729
730 auto accept_status_packet = testing::CommandStatusPacket(
731 hci_spec::kEnhancedAcceptSynchronousConnectionRequest,
732 pw::bluetooth::emboss::StatusCode::SUCCESS);
733 EXPECT_CMD_PACKET_OUT(
734 test_device(),
735 testing::EnhancedAcceptSynchronousConnectionRequestPacket(
736 kPeerAddress, second_conn_params),
737 &accept_status_packet);
738 RunUntilIdle();
739 EXPECT_FALSE(conn_result_1.has_value());
740
741 test_device()->SendCommandChannelPacket(
742 testing::SynchronousConnectionCompletePacket(
743 kScoConnectionHandle,
744 kPeerAddress,
745 hci_spec::LinkType::kSCO,
746 pw::bluetooth::emboss::StatusCode::SUCCESS));
747
748 RunUntilIdle();
749 ASSERT_TRUE(conn_result_1.has_value());
750 ASSERT_TRUE(conn_result_1->is_ok());
751 EXPECT_EQ(conn_result_1->value().first->handle(), kScoConnectionHandle);
752
753 EXPECT_CMD_PACKET_OUT(test_device(),
754 testing::DisconnectPacket(kScoConnectionHandle));
755 }
756
TEST_F(ScoConnectionManagerTest,QueueTwoAcceptConnectionRequestsCancelsFirstRequestAndFirstRequestCallbackDestroysRequestHandle)757 TEST_F(
758 ScoConnectionManagerTest,
759 QueueTwoAcceptConnectionRequestsCancelsFirstRequestAndFirstRequestCallbackDestroysRequestHandle) {
760 std::optional<ScoConnectionManager::RequestHandle> req_handle_0;
761 std::optional<AcceptConnectionResult> conn_result_0;
762 auto conn_cb = [&conn_result_0, &req_handle_0](auto cb_conn) {
763 conn_result_0 = std::move(cb_conn);
764 req_handle_0.reset();
765 };
766 req_handle_0 = manager()->AcceptConnection({kConnectionParams}, conn_cb);
767
768 auto second_conn_params = kConnectionParams;
769 second_conn_params.view().transmit_bandwidth().Write(99);
770
771 std::optional<AcceptConnectionResult> conn_result_1;
772 auto req_handle_1 = manager()->AcceptConnection(
773 {second_conn_params},
774 [&conn_result_1](auto cb_conn) { conn_result_1 = std::move(cb_conn); });
775
776 ASSERT_TRUE(conn_result_0.has_value());
777 ASSERT_TRUE(conn_result_0->is_error());
778 EXPECT_EQ(conn_result_0->error_value(), HostError::kCanceled);
779
780 auto conn_req_packet =
781 testing::ConnectionRequestPacket(kPeerAddress, hci_spec::LinkType::kSCO);
782 test_device()->SendCommandChannelPacket(conn_req_packet);
783
784 auto accept_status_packet = testing::CommandStatusPacket(
785 hci_spec::kEnhancedAcceptSynchronousConnectionRequest,
786 pw::bluetooth::emboss::StatusCode::SUCCESS);
787 EXPECT_CMD_PACKET_OUT(
788 test_device(),
789 testing::EnhancedAcceptSynchronousConnectionRequestPacket(
790 kPeerAddress, second_conn_params),
791 &accept_status_packet);
792 RunUntilIdle();
793 EXPECT_FALSE(conn_result_1.has_value());
794
795 test_device()->SendCommandChannelPacket(
796 testing::SynchronousConnectionCompletePacket(
797 kScoConnectionHandle,
798 kPeerAddress,
799 hci_spec::LinkType::kSCO,
800 pw::bluetooth::emboss::StatusCode::SUCCESS));
801
802 RunUntilIdle();
803 ASSERT_TRUE(conn_result_1.has_value());
804 ASSERT_TRUE(conn_result_1->is_ok());
805 EXPECT_EQ(conn_result_1->value().first->handle(), kScoConnectionHandle);
806
807 EXPECT_CMD_PACKET_OUT(test_device(),
808 testing::DisconnectPacket(kScoConnectionHandle));
809 }
810
TEST_F(ScoConnectionManagerTest,QueueSecondAcceptRequestAfterFirstRequestReceivesEvent)811 TEST_F(ScoConnectionManagerTest,
812 QueueSecondAcceptRequestAfterFirstRequestReceivesEvent) {
813 std::optional<AcceptConnectionResult> conn_result_0;
814 auto req_handle_0 = manager()->AcceptConnection(
815 {kConnectionParams},
816 [&conn_result_0](auto cb_conn) { conn_result_0 = std::move(cb_conn); });
817
818 auto conn_req_packet =
819 testing::ConnectionRequestPacket(kPeerAddress, hci_spec::LinkType::kSCO);
820 test_device()->SendCommandChannelPacket(conn_req_packet);
821
822 EXPECT_CMD_PACKET_OUT(
823 test_device(),
824 testing::EnhancedAcceptSynchronousConnectionRequestPacket(
825 kPeerAddress, kConnectionParams));
826 RunUntilIdle();
827
828 std::optional<AcceptConnectionResult> conn_result_1;
829 auto req_handle_1 = manager()->AcceptConnection(
830 {kConnectionParams},
831 [&conn_result_1](auto cb_conn) { conn_result_1 = std::move(cb_conn); });
832
833 // First request should not be cancelled because a request event was received.
834 EXPECT_FALSE(conn_result_0.has_value());
835
836 // Send failure events to fail first request.
837 test_device()->SendCommandChannelPacket(testing::CommandStatusPacket(
838 hci_spec::kEnhancedAcceptSynchronousConnectionRequest,
839 pw::bluetooth::emboss::StatusCode::COMMAND_DISALLOWED));
840 test_device()->SendCommandChannelPacket(
841 testing::SynchronousConnectionCompletePacket(
842 kScoConnectionHandle,
843 kPeerAddress,
844 hci_spec::LinkType::kSCO,
845 pw::bluetooth::emboss::StatusCode::
846 CONNECTION_ACCEPT_TIMEOUT_EXCEEDED));
847 RunUntilIdle();
848 ASSERT_TRUE(conn_result_0.has_value());
849 ASSERT_TRUE(conn_result_0->is_error());
850 EXPECT_EQ(conn_result_0->error_value(), HostError::kParametersRejected);
851
852 // Second request should now be in progress.
853 test_device()->SendCommandChannelPacket(conn_req_packet);
854
855 auto accept_status_packet = testing::CommandStatusPacket(
856 hci_spec::kEnhancedAcceptSynchronousConnectionRequest,
857 pw::bluetooth::emboss::StatusCode::SUCCESS);
858 EXPECT_CMD_PACKET_OUT(
859 test_device(),
860 testing::EnhancedAcceptSynchronousConnectionRequestPacket(
861 kPeerAddress, kConnectionParams),
862 &accept_status_packet);
863 RunUntilIdle();
864 EXPECT_FALSE(conn_result_1.has_value());
865
866 test_device()->SendCommandChannelPacket(
867 testing::SynchronousConnectionCompletePacket(
868 kScoConnectionHandle,
869 kPeerAddress,
870 hci_spec::LinkType::kSCO,
871 pw::bluetooth::emboss::StatusCode::SUCCESS));
872
873 RunUntilIdle();
874 ASSERT_TRUE(conn_result_1.has_value());
875 ASSERT_TRUE(conn_result_1->is_ok());
876 EXPECT_EQ(conn_result_1->value().first->handle(), kScoConnectionHandle);
877
878 EXPECT_CMD_PACKET_OUT(test_device(),
879 testing::DisconnectPacket(kScoConnectionHandle));
880 }
881
TEST_F(ScoConnectionManagerTest,RequestsCancelledOnManagerDestruction)882 TEST_F(ScoConnectionManagerTest, RequestsCancelledOnManagerDestruction) {
883 auto setup_status_packet = testing::CommandStatusPacket(
884 hci_spec::kEnhancedSetupSynchronousConnection,
885 pw::bluetooth::emboss::StatusCode::SUCCESS);
886 EXPECT_CMD_PACKET_OUT(test_device(),
887 testing::EnhancedSetupSynchronousConnectionPacket(
888 kAclConnectionHandle, kConnectionParams),
889 &setup_status_packet);
890
891 std::optional<OpenConnectionResult> conn_result_0;
892 auto conn_cb_0 = [&conn_result_0](auto cb_conn) {
893 activate_connection(cb_conn);
894 conn_result_0 = std::move(cb_conn);
895 };
896 auto req_handle_0 =
897 manager()->OpenConnection(kConnectionParams, std::move(conn_cb_0));
898
899 std::optional<OpenConnectionResult> conn_result_1;
900 auto conn_cb_1 = [&conn_result_1](auto cb_conn) {
901 activate_connection(cb_conn);
902 conn_result_1 = std::move(cb_conn);
903 };
904 auto req_handle_1 =
905 manager()->OpenConnection(kConnectionParams, std::move(conn_cb_1));
906
907 RunUntilIdle();
908
909 DestroyManager();
910 ASSERT_TRUE(conn_result_0.has_value());
911 ASSERT_TRUE(conn_result_0->is_error());
912 EXPECT_EQ(conn_result_0->error_value(), HostError::kCanceled);
913 ASSERT_TRUE(conn_result_1.has_value());
914 ASSERT_TRUE(conn_result_1->is_error());
915 EXPECT_EQ(conn_result_1->error_value(), HostError::kCanceled);
916 }
917
TEST_F(ScoConnectionManagerTest,AcceptConnectionExplicitlyCancelledByClient)918 TEST_F(ScoConnectionManagerTest, AcceptConnectionExplicitlyCancelledByClient) {
919 std::optional<AcceptConnectionResult> conn_result;
920 auto conn_cb = [&conn_result](auto cb_conn) {
921 conn_result = std::move(cb_conn);
922 };
923 auto req_handle =
924 manager()->AcceptConnection({kConnectionParams}, std::move(conn_cb));
925
926 req_handle.Cancel();
927 ASSERT_TRUE(conn_result.has_value());
928 ASSERT_TRUE(conn_result->is_error());
929 EXPECT_EQ(conn_result->error_value(), HostError::kCanceled);
930
931 auto conn_req_packet =
932 testing::ConnectionRequestPacket(kPeerAddress, hci_spec::LinkType::kSCO);
933 test_device()->SendCommandChannelPacket(conn_req_packet);
934
935 auto reject_status_packet = testing::CommandStatusPacket(
936 hci_spec::kRejectSynchronousConnectionRequest,
937 pw::bluetooth::emboss::StatusCode::SUCCESS);
938 EXPECT_CMD_PACKET_OUT(
939 test_device(),
940 testing::RejectSynchronousConnectionRequest(
941 kPeerAddress,
942 pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_BAD_BD_ADDR),
943 &reject_status_packet);
944 RunUntilIdle();
945 ASSERT_TRUE(conn_result->is_error());
946 EXPECT_EQ(conn_result->error_value(), HostError::kCanceled);
947 }
948
TEST_F(ScoConnectionManagerTest,AcceptConnectionCancelledByClientDestroyingHandle)949 TEST_F(ScoConnectionManagerTest,
950 AcceptConnectionCancelledByClientDestroyingHandle) {
951 std::optional<AcceptConnectionResult> conn_result;
952 auto conn_cb = [&conn_result](auto cb_conn) {
953 conn_result = std::move(cb_conn);
954 };
955
956 // req_handle destroyed at end of scope
957 {
958 auto req_handle =
959 manager()->AcceptConnection({kConnectionParams}, std::move(conn_cb));
960 }
961 ASSERT_TRUE(conn_result.has_value());
962 ASSERT_TRUE(conn_result->is_error());
963 EXPECT_EQ(conn_result->error_value(), HostError::kCanceled);
964
965 auto conn_req_packet =
966 testing::ConnectionRequestPacket(kPeerAddress, hci_spec::LinkType::kSCO);
967 test_device()->SendCommandChannelPacket(conn_req_packet);
968
969 auto reject_status_packet = testing::CommandStatusPacket(
970 hci_spec::kRejectSynchronousConnectionRequest,
971 pw::bluetooth::emboss::StatusCode::SUCCESS);
972 EXPECT_CMD_PACKET_OUT(
973 test_device(),
974 testing::RejectSynchronousConnectionRequest(
975 kPeerAddress,
976 pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_BAD_BD_ADDR),
977 &reject_status_packet);
978 RunUntilIdle();
979 ASSERT_TRUE(conn_result->is_error());
980 EXPECT_EQ(conn_result->error_value(), HostError::kCanceled);
981 }
982
TEST_F(ScoConnectionManagerTest,OpenConnectionCantBeCancelledOnceInProgress)983 TEST_F(ScoConnectionManagerTest, OpenConnectionCantBeCancelledOnceInProgress) {
984 auto setup_status_packet = testing::CommandStatusPacket(
985 hci_spec::kEnhancedSetupSynchronousConnection,
986 pw::bluetooth::emboss::StatusCode::SUCCESS);
987 auto conn_complete_packet = testing::SynchronousConnectionCompletePacket(
988 kScoConnectionHandle,
989 kPeerAddress,
990 hci_spec::LinkType::kExtendedSCO,
991 pw::bluetooth::emboss::StatusCode::SUCCESS);
992 EXPECT_CMD_PACKET_OUT(test_device(),
993 testing::EnhancedSetupSynchronousConnectionPacket(
994 kAclConnectionHandle, kConnectionParams),
995 &setup_status_packet);
996
997 std::optional<OpenConnectionResult> conn_result;
998 auto conn_cb = [&conn_result](auto cb_conn) {
999 activate_connection(cb_conn);
1000 conn_result = std::move(cb_conn);
1001 };
1002
1003 auto req_handle =
1004 manager()->OpenConnection(kConnectionParams, std::move(conn_cb));
1005 req_handle.Cancel();
1006
1007 RunUntilIdle();
1008 EXPECT_FALSE(conn_result.has_value());
1009 test_device()->SendCommandChannelPacket(conn_complete_packet);
1010
1011 RunUntilIdle();
1012 ASSERT_TRUE(conn_result.has_value());
1013 ASSERT_TRUE(conn_result->is_ok());
1014 EXPECT_EQ(conn_result->value()->handle(), kScoConnectionHandle);
1015
1016 EXPECT_CMD_PACKET_OUT(test_device(),
1017 testing::DisconnectPacket(kScoConnectionHandle));
1018 conn_result.value()->Close();
1019 RunUntilIdle();
1020 }
1021
TEST_F(ScoConnectionManagerTest,QueueTwoRequestsAndCancelSecond)1022 TEST_F(ScoConnectionManagerTest, QueueTwoRequestsAndCancelSecond) {
1023 const hci_spec::ConnectionHandle handle_0 = kScoConnectionHandle;
1024
1025 auto setup_status_packet = testing::CommandStatusPacket(
1026 hci_spec::kEnhancedSetupSynchronousConnection,
1027 pw::bluetooth::emboss::StatusCode::SUCCESS);
1028 EXPECT_CMD_PACKET_OUT(test_device(),
1029 testing::EnhancedSetupSynchronousConnectionPacket(
1030 kAclConnectionHandle, kConnectionParams),
1031 &setup_status_packet);
1032
1033 std::optional<OpenConnectionResult> conn_result_0;
1034 auto conn_cb_0 = [&conn_result_0](auto cb_conn) {
1035 // No need to activate the connection here since Deactivate is called
1036 // manually.
1037 conn_result_0 = std::move(cb_conn);
1038 };
1039 auto req_handle_0 =
1040 manager()->OpenConnection(kConnectionParams, std::move(conn_cb_0));
1041
1042 size_t cb_count_1 = 0;
1043 std::optional<OpenConnectionResult> conn_result_1;
1044 auto conn_cb_1 = [&cb_count_1, &conn_result_1](auto cb_conn) {
1045 activate_connection(cb_conn);
1046 cb_count_1++;
1047 conn_result_1 = std::move(cb_conn);
1048 };
1049 auto req_handle_1 =
1050 manager()->OpenConnection(kConnectionParams, std::move(conn_cb_1));
1051
1052 RunUntilIdle();
1053 EXPECT_FALSE(conn_result_0.has_value());
1054
1055 req_handle_1.Cancel();
1056 EXPECT_EQ(cb_count_1, 1u);
1057 ASSERT_TRUE(conn_result_1.has_value());
1058 ASSERT_TRUE(conn_result_1->is_error());
1059 EXPECT_EQ(conn_result_1->error_value(), HostError::kCanceled);
1060
1061 auto conn_complete_packet_0 = testing::SynchronousConnectionCompletePacket(
1062 handle_0,
1063 kPeerAddress,
1064 hci_spec::LinkType::kExtendedSCO,
1065 pw::bluetooth::emboss::StatusCode::SUCCESS);
1066 test_device()->SendCommandChannelPacket(conn_complete_packet_0);
1067 RunUntilIdle();
1068 ASSERT_TRUE(conn_result_0.has_value());
1069 ASSERT_TRUE(conn_result_0->is_ok());
1070 EXPECT_EQ(cb_count_1, 1u);
1071
1072 auto disconn_status_packet_0 = testing::CommandStatusPacket(
1073 hci_spec::kDisconnect, pw::bluetooth::emboss::StatusCode::SUCCESS);
1074 auto disconn_complete_0 = testing::DisconnectionCompletePacket(handle_0);
1075 EXPECT_CMD_PACKET_OUT(test_device(),
1076 testing::DisconnectPacket(handle_0),
1077 &disconn_status_packet_0,
1078 &disconn_complete_0);
1079 conn_result_0.value()->Deactivate();
1080 RunUntilIdle();
1081 }
1082
TEST_F(ScoConnectionManagerTest,QueueingThreeRequestsCancelsSecondAndRequestHandleDestroyedInResultCallback)1083 TEST_F(
1084 ScoConnectionManagerTest,
1085 QueueingThreeRequestsCancelsSecondAndRequestHandleDestroyedInResultCallback) {
1086 auto setup_status_packet = testing::CommandStatusPacket(
1087 hci_spec::kEnhancedSetupSynchronousConnection,
1088 pw::bluetooth::emboss::StatusCode::SUCCESS);
1089 EXPECT_CMD_PACKET_OUT(test_device(),
1090 testing::EnhancedSetupSynchronousConnectionPacket(
1091 kAclConnectionHandle, kConnectionParams),
1092 &setup_status_packet);
1093
1094 std::optional<OpenConnectionResult> conn_result_0;
1095 auto conn_cb_0 = [&conn_result_0](auto cb_conn) {
1096 activate_connection(cb_conn);
1097 conn_result_0 = std::move(cb_conn);
1098 };
1099 auto req_handle_0 =
1100 manager()->OpenConnection(kConnectionParams, std::move(conn_cb_0));
1101
1102 std::optional<ScoConnectionManager::RequestHandle> req_handle_1;
1103 std::optional<OpenConnectionResult> conn_result_1;
1104 auto conn_cb_1 = [&conn_result_1, &req_handle_1](auto cb_conn) {
1105 activate_connection(cb_conn);
1106 req_handle_1.reset();
1107 conn_result_1 = std::move(cb_conn);
1108 };
1109 req_handle_1 =
1110 manager()->OpenConnection(kConnectionParams, std::move(conn_cb_1));
1111
1112 std::optional<OpenConnectionResult> conn_result_2;
1113 auto conn_cb_2 = [&conn_result_2](auto cb_conn) {
1114 activate_connection(cb_conn);
1115 conn_result_2 = std::move(cb_conn);
1116 };
1117 auto req_handle_2 =
1118 manager()->OpenConnection(kConnectionParams, std::move(conn_cb_2));
1119
1120 RunUntilIdle();
1121 EXPECT_FALSE(conn_result_0.has_value());
1122 EXPECT_FALSE(conn_result_2.has_value());
1123 ASSERT_TRUE(conn_result_1.has_value());
1124 ASSERT_TRUE(conn_result_1->is_error());
1125 EXPECT_EQ(conn_result_1->error_value(), HostError::kCanceled);
1126
1127 DestroyManager();
1128 RunUntilIdle();
1129 }
1130
TEST_F(ScoConnectionManagerTest,OpenConnectionFollowedByPeerDisconnectAndSecondOpenConnectonWithHandleReuse)1131 TEST_F(
1132 ScoConnectionManagerTest,
1133 OpenConnectionFollowedByPeerDisconnectAndSecondOpenConnectonWithHandleReuse) {
1134 auto setup_status_packet = testing::CommandStatusPacket(
1135 hci_spec::kEnhancedSetupSynchronousConnection,
1136 pw::bluetooth::emboss::StatusCode::SUCCESS);
1137 auto conn_complete_packet = testing::SynchronousConnectionCompletePacket(
1138 kScoConnectionHandle,
1139 kPeerAddress,
1140 hci_spec::LinkType::kExtendedSCO,
1141 pw::bluetooth::emboss::StatusCode::SUCCESS);
1142 EXPECT_CMD_PACKET_OUT(test_device(),
1143 testing::EnhancedSetupSynchronousConnectionPacket(
1144 kAclConnectionHandle, kConnectionParams),
1145 &setup_status_packet,
1146 &conn_complete_packet);
1147
1148 std::optional<OpenConnectionResult> conn_result_0;
1149 auto conn_cb_0 = [&conn_result_0](auto result) {
1150 activate_connection(result);
1151 conn_result_0 = std::move(result);
1152 };
1153
1154 auto req_handle_0 =
1155 manager()->OpenConnection(kConnectionParams, std::move(conn_cb_0));
1156
1157 RunUntilIdle();
1158 ASSERT_TRUE(conn_result_0.has_value());
1159 ASSERT_TRUE(conn_result_0->is_ok());
1160 ASSERT_TRUE(conn_result_0->value().is_alive());
1161 EXPECT_EQ(conn_result_0->value()->handle(), kScoConnectionHandle);
1162
1163 test_device()->SendCommandChannelPacket(testing::DisconnectionCompletePacket(
1164 kScoConnectionHandle,
1165 pw::bluetooth::emboss::StatusCode::REMOTE_USER_TERMINATED_CONNECTION));
1166 RunUntilIdle();
1167
1168 EXPECT_CMD_PACKET_OUT(test_device(),
1169 testing::EnhancedSetupSynchronousConnectionPacket(
1170 kAclConnectionHandle, kConnectionParams),
1171 &setup_status_packet,
1172 &conn_complete_packet);
1173
1174 std::optional<OpenConnectionResult> conn_result_1;
1175 auto conn_cb_1 = [&conn_result_1](auto result) {
1176 activate_connection(result);
1177 conn_result_1 = std::move(result);
1178 };
1179
1180 auto req_handle_1 =
1181 manager()->OpenConnection(kConnectionParams, std::move(conn_cb_1));
1182
1183 RunUntilIdle();
1184 ASSERT_TRUE(conn_result_1.has_value());
1185 ASSERT_TRUE(conn_result_1->is_ok());
1186 ASSERT_TRUE(conn_result_1->value().is_alive());
1187 EXPECT_EQ(conn_result_1->value()->handle(), kScoConnectionHandle);
1188
1189 EXPECT_CMD_PACKET_OUT(test_device(),
1190 testing::DisconnectPacket(kScoConnectionHandle));
1191 conn_result_1.value()->Close();
1192 RunUntilIdle();
1193 }
1194
TEST_F(ScoConnectionManagerTest,DestroyManagerWhileResponderRequestInProgressAndDestroyRequestHandleInResultCallback)1195 TEST_F(
1196 ScoConnectionManagerTest,
1197 DestroyManagerWhileResponderRequestInProgressAndDestroyRequestHandleInResultCallback) {
1198 std::optional<AcceptConnectionResult> conn;
1199 std::optional<ScoConnectionManager::RequestHandle> req_handle;
1200 auto conn_cb = [&conn, &req_handle](auto cb_result) {
1201 req_handle.reset();
1202 conn = std::move(cb_result);
1203 };
1204
1205 req_handle =
1206 manager()->AcceptConnection({kConnectionParams}, std::move(conn_cb));
1207 RunUntilIdle();
1208
1209 DestroyManager();
1210 RunUntilIdle();
1211
1212 ASSERT_TRUE(conn.has_value());
1213 ASSERT_TRUE(conn->is_error());
1214 EXPECT_EQ(conn->error_value(), HostError::kCanceled);
1215 }
1216
TEST_F(ScoConnectionManagerTest,DestroyManagerWhileInitiatorRequestQueuedAndDestroyRequestHandleInResultCallback)1217 TEST_F(
1218 ScoConnectionManagerTest,
1219 DestroyManagerWhileInitiatorRequestQueuedAndDestroyRequestHandleInResultCallback) {
1220 auto setup_status_packet = testing::CommandStatusPacket(
1221 hci_spec::kEnhancedSetupSynchronousConnection,
1222 pw::bluetooth::emboss::StatusCode::SUCCESS);
1223 EXPECT_CMD_PACKET_OUT(test_device(),
1224 testing::EnhancedSetupSynchronousConnectionPacket(
1225 kAclConnectionHandle, kConnectionParams),
1226 &setup_status_packet);
1227
1228 std::optional<OpenConnectionResult> conn_result_0;
1229 auto conn_cb_0 = [&conn_result_0](auto cb_conn) {
1230 activate_connection(cb_conn);
1231 conn_result_0 = std::move(cb_conn);
1232 };
1233 auto req_handle_0 =
1234 manager()->OpenConnection(kConnectionParams, std::move(conn_cb_0));
1235
1236 std::optional<ScoConnectionManager::RequestHandle> req_handle_1;
1237 std::optional<OpenConnectionResult> conn_result_1;
1238 auto conn_cb_1 = [&conn_result_1, &req_handle_1](auto cb_conn) {
1239 activate_connection(cb_conn);
1240 req_handle_1.reset();
1241 conn_result_1 = std::move(cb_conn);
1242 };
1243 req_handle_1 =
1244 manager()->OpenConnection(kConnectionParams, std::move(conn_cb_1));
1245
1246 RunUntilIdle();
1247 EXPECT_FALSE(conn_result_0.has_value());
1248
1249 DestroyManager();
1250 ASSERT_TRUE(conn_result_0.has_value());
1251 ASSERT_TRUE(conn_result_0->is_error());
1252 EXPECT_EQ(conn_result_0->error_value(), HostError::kCanceled);
1253 ASSERT_TRUE(conn_result_1.has_value());
1254 ASSERT_TRUE(conn_result_1->is_error());
1255 EXPECT_EQ(conn_result_1->error_value(), HostError::kCanceled);
1256 }
1257
TEST_F(ScoConnectionManagerTest,AcceptConnectionFirstParametersRejectedSecondParametersAccepted)1258 TEST_F(ScoConnectionManagerTest,
1259 AcceptConnectionFirstParametersRejectedSecondParametersAccepted) {
1260 bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter>
1261 esco_params_0 = kConnectionParams;
1262 esco_params_0.view().packet_types().ev3().Write(true);
1263 bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter>
1264 esco_params_1 = kConnectionParams;
1265 esco_params_1.view().packet_types().ev4().Write(true);
1266
1267 std::optional<AcceptConnectionResult> conn_result;
1268 auto conn_cb = [&conn_result](auto cb_conn) {
1269 conn_result = std::move(cb_conn);
1270 };
1271 auto req_handle = manager()->AcceptConnection({esco_params_0, esco_params_1},
1272 std::move(conn_cb));
1273
1274 auto conn_req_packet_0 = testing::ConnectionRequestPacket(
1275 kPeerAddress, hci_spec::LinkType::kExtendedSCO);
1276 test_device()->SendCommandChannelPacket(conn_req_packet_0);
1277
1278 auto accept_status_packet_0 = testing::CommandStatusPacket(
1279 hci_spec::kEnhancedAcceptSynchronousConnectionRequest,
1280 pw::bluetooth::emboss::StatusCode::SUCCESS);
1281 EXPECT_CMD_PACKET_OUT(
1282 test_device(),
1283 testing::EnhancedAcceptSynchronousConnectionRequestPacket(kPeerAddress,
1284 esco_params_0),
1285 &accept_status_packet_0);
1286 RunUntilIdle();
1287 EXPECT_FALSE(conn_result.has_value());
1288
1289 test_device()->SendCommandChannelPacket(
1290 testing::SynchronousConnectionCompletePacket(
1291 kScoConnectionHandle,
1292 kPeerAddress,
1293 hci_spec::LinkType::kExtendedSCO,
1294 pw::bluetooth::emboss::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER));
1295
1296 RunUntilIdle();
1297 EXPECT_FALSE(conn_result.has_value());
1298
1299 auto conn_req_packet_1 = testing::ConnectionRequestPacket(
1300 kPeerAddress, hci_spec::LinkType::kExtendedSCO);
1301 test_device()->SendCommandChannelPacket(conn_req_packet_1);
1302
1303 auto accept_status_packet_1 = testing::CommandStatusPacket(
1304 hci_spec::kEnhancedAcceptSynchronousConnectionRequest,
1305 pw::bluetooth::emboss::StatusCode::SUCCESS);
1306 EXPECT_CMD_PACKET_OUT(
1307 test_device(),
1308 testing::EnhancedAcceptSynchronousConnectionRequestPacket(kPeerAddress,
1309 esco_params_1),
1310 &accept_status_packet_1);
1311 RunUntilIdle();
1312 EXPECT_FALSE(conn_result.has_value());
1313
1314 test_device()->SendCommandChannelPacket(
1315 testing::SynchronousConnectionCompletePacket(
1316 kScoConnectionHandle,
1317 kPeerAddress,
1318 hci_spec::LinkType::kExtendedSCO,
1319 pw::bluetooth::emboss::StatusCode::SUCCESS));
1320
1321 RunUntilIdle();
1322 ASSERT_TRUE(conn_result.has_value());
1323 ASSERT_TRUE(conn_result->is_ok());
1324 EXPECT_EQ(conn_result->value().first->handle(), kScoConnectionHandle);
1325 size_t result_parameter_index = conn_result->value().second;
1326 EXPECT_EQ(result_parameter_index, 1u);
1327
1328 EXPECT_CMD_PACKET_OUT(test_device(),
1329 testing::DisconnectPacket(kScoConnectionHandle));
1330 }
1331
TEST_F(ScoConnectionManagerTest,AcceptScoConnectionWithFirstParametersEscoPacketTypeAndSecondScoPacketTypeSkipsToSecondParameters)1332 TEST_F(
1333 ScoConnectionManagerTest,
1334 AcceptScoConnectionWithFirstParametersEscoPacketTypeAndSecondScoPacketTypeSkipsToSecondParameters) {
1335 std::optional<AcceptConnectionResult> conn_result;
1336 auto conn_cb = [&conn_result](auto cb_conn) {
1337 conn_result = std::move(cb_conn);
1338 };
1339 auto req_handle = manager()->AcceptConnection(
1340 {EscoConnectionParams(), ScoConnectionParams()}, std::move(conn_cb));
1341
1342 auto conn_req_packet =
1343 testing::ConnectionRequestPacket(kPeerAddress, hci_spec::LinkType::kSCO);
1344 test_device()->SendCommandChannelPacket(conn_req_packet);
1345
1346 auto accept_status_packet = testing::CommandStatusPacket(
1347 hci_spec::kEnhancedAcceptSynchronousConnectionRequest,
1348 pw::bluetooth::emboss::StatusCode::SUCCESS);
1349 EXPECT_CMD_PACKET_OUT(
1350 test_device(),
1351 testing::EnhancedAcceptSynchronousConnectionRequestPacket(
1352 kPeerAddress, ScoConnectionParams()),
1353 &accept_status_packet);
1354 RunUntilIdle();
1355 EXPECT_FALSE(conn_result.has_value());
1356
1357 test_device()->SendCommandChannelPacket(
1358 testing::SynchronousConnectionCompletePacket(
1359 kScoConnectionHandle,
1360 kPeerAddress,
1361 hci_spec::LinkType::kSCO,
1362 pw::bluetooth::emboss::StatusCode::SUCCESS));
1363
1364 RunUntilIdle();
1365 ASSERT_TRUE(conn_result.has_value());
1366 ASSERT_TRUE(conn_result->is_ok());
1367 EXPECT_EQ(conn_result->value().first->handle(), kScoConnectionHandle);
1368 size_t result_parameter_index = conn_result->value().second;
1369 EXPECT_EQ(result_parameter_index, 1u);
1370
1371 // Verify that the correct parameters were given to the ScoConnection.
1372 ASSERT_TRUE(
1373 conn_result->value().first->parameters().view().packet_types().Equals(
1374 ScoConnectionParams().view().packet_types()));
1375 EXPECT_CMD_PACKET_OUT(test_device(),
1376 testing::DisconnectPacket(kScoConnectionHandle));
1377 }
1378
TEST_F(ScoConnectionManagerTest,AcceptEscoConnectionWithFirstParametersScoPacketTypeAndSecondEscoPacketTypeSkipsToSecondParameters)1379 TEST_F(
1380 ScoConnectionManagerTest,
1381 AcceptEscoConnectionWithFirstParametersScoPacketTypeAndSecondEscoPacketTypeSkipsToSecondParameters) {
1382 std::optional<AcceptConnectionResult> conn_result;
1383 auto conn_cb = [&conn_result](auto cb_conn) {
1384 conn_result = std::move(cb_conn);
1385 };
1386 auto req_handle = manager()->AcceptConnection(
1387 {ScoConnectionParams(), EscoConnectionParams()}, std::move(conn_cb));
1388
1389 auto conn_req_packet = testing::ConnectionRequestPacket(
1390 kPeerAddress, hci_spec::LinkType::kExtendedSCO);
1391 test_device()->SendCommandChannelPacket(conn_req_packet);
1392
1393 auto accept_status_packet = testing::CommandStatusPacket(
1394 hci_spec::kEnhancedAcceptSynchronousConnectionRequest,
1395 pw::bluetooth::emboss::StatusCode::SUCCESS);
1396 EXPECT_CMD_PACKET_OUT(
1397 test_device(),
1398 testing::EnhancedAcceptSynchronousConnectionRequestPacket(
1399 kPeerAddress, EscoConnectionParams()),
1400 &accept_status_packet);
1401 RunUntilIdle();
1402 EXPECT_FALSE(conn_result.has_value());
1403
1404 test_device()->SendCommandChannelPacket(
1405 testing::SynchronousConnectionCompletePacket(
1406 kScoConnectionHandle,
1407 kPeerAddress,
1408 hci_spec::LinkType::kExtendedSCO,
1409 pw::bluetooth::emboss::StatusCode::SUCCESS));
1410
1411 RunUntilIdle();
1412 ASSERT_TRUE(conn_result.has_value());
1413 ASSERT_TRUE(conn_result->is_ok());
1414 EXPECT_EQ(conn_result->value().first->handle(), kScoConnectionHandle);
1415 size_t result_parameter_index = conn_result->value().second;
1416 EXPECT_EQ(result_parameter_index, 1u);
1417
1418 EXPECT_CMD_PACKET_OUT(test_device(),
1419 testing::DisconnectPacket(kScoConnectionHandle));
1420 }
1421
TEST_F(ScoConnectionManagerTest,AcceptScoConnectionWithEscoParametersFailsAndSendsRejectCommand)1422 TEST_F(ScoConnectionManagerTest,
1423 AcceptScoConnectionWithEscoParametersFailsAndSendsRejectCommand) {
1424 std::optional<AcceptConnectionResult> conn_result;
1425 auto conn_cb = [&conn_result](auto cb_conn) {
1426 conn_result = std::move(cb_conn);
1427 };
1428 auto req_handle =
1429 manager()->AcceptConnection({EscoConnectionParams()}, std::move(conn_cb));
1430
1431 auto conn_req_packet =
1432 testing::ConnectionRequestPacket(kPeerAddress, hci_spec::LinkType::kSCO);
1433 test_device()->SendCommandChannelPacket(conn_req_packet);
1434
1435 auto reject_status_packet = testing::CommandStatusPacket(
1436 hci_spec::kRejectSynchronousConnectionRequest,
1437 pw::bluetooth::emboss::StatusCode::SUCCESS);
1438
1439 auto conn_complete_packet = testing::SynchronousConnectionCompletePacket(
1440 /*conn=*/0,
1441 kPeerAddress,
1442 hci_spec::LinkType::kExtendedSCO,
1443 pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_LIMITED_RESOURCES);
1444
1445 EXPECT_CMD_PACKET_OUT(test_device(),
1446 testing::RejectSynchronousConnectionRequest(
1447 kPeerAddress,
1448 pw::bluetooth::emboss::StatusCode::
1449 CONNECTION_REJECTED_LIMITED_RESOURCES),
1450 &reject_status_packet);
1451 RunUntilIdle();
1452 // The AcceptConnection request should not be completed until the connection
1453 // complete event is received.
1454 EXPECT_FALSE(conn_result.has_value());
1455
1456 test_device()->SendCommandChannelPacket(conn_complete_packet);
1457 RunUntilIdle();
1458 ASSERT_TRUE(conn_result.has_value());
1459 ASSERT_TRUE(conn_result->is_error());
1460 EXPECT_EQ(conn_result->error_value(), HostError::kParametersRejected);
1461 }
1462
TEST_F(ScoConnectionManagerTest,AcceptScoConnectionWithEmptyParametersFails)1463 TEST_F(ScoConnectionManagerTest, AcceptScoConnectionWithEmptyParametersFails) {
1464 std::optional<AcceptConnectionResult> conn_result;
1465 auto conn_cb = [&conn_result](auto cb_conn) {
1466 conn_result = std::move(cb_conn);
1467 };
1468 auto req_handle =
1469 manager()->AcceptConnection(/*parameters=*/{}, std::move(conn_cb));
1470 ASSERT_TRUE(conn_result.has_value());
1471 ASSERT_TRUE(conn_result->is_error());
1472 EXPECT_EQ(conn_result->error_value(), HostError::kInvalidParameters);
1473 }
1474
TEST_F(ScoConnectionManagerTest,QueuedRequestAfterAcceptConnectionCommandCancelsNextAcceptConnectionParameterAttemptWhenThereAreMultipleParameters)1475 TEST_F(
1476 ScoConnectionManagerTest,
1477 QueuedRequestAfterAcceptConnectionCommandCancelsNextAcceptConnectionParameterAttemptWhenThereAreMultipleParameters) {
1478 std::optional<AcceptConnectionResult> conn_result_0;
1479 auto conn_cb_0 = [&conn_result_0](auto cb_conn) {
1480 conn_result_0 = std::move(cb_conn);
1481 };
1482
1483 // Queue an accept request with 2 parameters. The first parameters should fail
1484 // and the second should never be used due to the second request canceling the
1485 // first request.
1486 auto req_handle_0 = manager()->AcceptConnection(
1487 {kConnectionParams, kConnectionParams}, std::move(conn_cb_0));
1488
1489 auto conn_req_packet_0 = testing::ConnectionRequestPacket(
1490 kPeerAddress, hci_spec::LinkType::kExtendedSCO);
1491 test_device()->SendCommandChannelPacket(conn_req_packet_0);
1492
1493 auto accept_status_packet_0 = testing::CommandStatusPacket(
1494 hci_spec::kEnhancedAcceptSynchronousConnectionRequest,
1495 pw::bluetooth::emboss::StatusCode::SUCCESS);
1496 EXPECT_CMD_PACKET_OUT(
1497 test_device(),
1498 testing::EnhancedAcceptSynchronousConnectionRequestPacket(
1499 kPeerAddress, kConnectionParams),
1500 &accept_status_packet_0);
1501 RunUntilIdle();
1502 EXPECT_FALSE(conn_result_0.has_value());
1503
1504 // Second request should cancel first request when connection complete event
1505 // is received.
1506 std::optional<AcceptConnectionResult> conn_result_1;
1507 auto conn_cb_1 = [&conn_result_1](auto cb_conn) {
1508 conn_result_1 = std::move(cb_conn);
1509 };
1510 auto req_handle_1 =
1511 manager()->AcceptConnection({kConnectionParams}, std::move(conn_cb_1));
1512 EXPECT_FALSE(conn_result_0.has_value());
1513
1514 test_device()->SendCommandChannelPacket(
1515 testing::SynchronousConnectionCompletePacket(
1516 kScoConnectionHandle,
1517 kPeerAddress,
1518 hci_spec::LinkType::kExtendedSCO,
1519 pw::bluetooth::emboss::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER));
1520
1521 RunUntilIdle();
1522 ASSERT_TRUE(conn_result_0.has_value());
1523 ASSERT_TRUE(conn_result_0->is_error());
1524 EXPECT_EQ(conn_result_0->error_value(), HostError::kCanceled);
1525 EXPECT_FALSE(conn_result_1.has_value());
1526
1527 // Complete the second accept request with an incoming connection.
1528 auto conn_req_packet_1 = testing::ConnectionRequestPacket(
1529 kPeerAddress, hci_spec::LinkType::kExtendedSCO);
1530 test_device()->SendCommandChannelPacket(conn_req_packet_1);
1531 auto accept_status_packet_1 = testing::CommandStatusPacket(
1532 hci_spec::kEnhancedAcceptSynchronousConnectionRequest,
1533 pw::bluetooth::emboss::StatusCode::SUCCESS);
1534 EXPECT_CMD_PACKET_OUT(
1535 test_device(),
1536 testing::EnhancedAcceptSynchronousConnectionRequestPacket(
1537 kPeerAddress, kConnectionParams),
1538 &accept_status_packet_1);
1539 RunUntilIdle();
1540 EXPECT_FALSE(conn_result_1.has_value());
1541
1542 test_device()->SendCommandChannelPacket(
1543 testing::SynchronousConnectionCompletePacket(
1544 kScoConnectionHandle,
1545 kPeerAddress,
1546 hci_spec::LinkType::kExtendedSCO,
1547 pw::bluetooth::emboss::StatusCode::SUCCESS));
1548
1549 RunUntilIdle();
1550 ASSERT_TRUE(conn_result_1.has_value());
1551 ASSERT_TRUE(conn_result_1->is_ok());
1552 EXPECT_EQ(conn_result_1->value().first->handle(), kScoConnectionHandle);
1553 size_t result_parameter_index = conn_result_1->value().second;
1554 EXPECT_EQ(result_parameter_index, 0u);
1555
1556 EXPECT_CMD_PACKET_OUT(test_device(),
1557 testing::DisconnectPacket(kScoConnectionHandle));
1558 }
1559
1560 } // namespace
1561 } // namespace bt::sco
1562