1 /*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "acl_connection_handler.h"
18
19 #include <hci/hci_packets.h>
20
21 #include "hci/address.h"
22 #include "log.h"
23
24 namespace rootcanal {
25
26 using ::bluetooth::hci::Address;
27 using ::bluetooth::hci::AddressType;
28 using ::bluetooth::hci::AddressWithType;
29
RegisterTaskScheduler(std::function<AsyncTaskId (std::chrono::milliseconds,const TaskCallback &)> event_scheduler)30 void AclConnectionHandler::RegisterTaskScheduler(
31 std::function<AsyncTaskId(std::chrono::milliseconds, const TaskCallback&)>
32 event_scheduler) {
33 schedule_task_ = event_scheduler;
34 }
35
HasHandle(uint16_t handle) const36 bool AclConnectionHandler::HasHandle(uint16_t handle) const {
37 return acl_connections_.count(handle) != 0;
38 }
39
HasScoHandle(uint16_t handle) const40 bool AclConnectionHandler::HasScoHandle(uint16_t handle) const {
41 return sco_connections_.count(handle) != 0;
42 }
43
GetUnusedHandle()44 uint16_t AclConnectionHandler::GetUnusedHandle() {
45 while (HasHandle(last_handle_) || HasScoHandle(last_handle_) ||
46 isochronous_connection_handler_.HasHandle(last_handle_)) {
47 last_handle_ = (last_handle_ + 1) % kReservedHandle;
48 }
49 uint16_t unused_handle = last_handle_;
50 last_handle_ = (last_handle_ + 1) % kReservedHandle;
51 return unused_handle;
52 }
53
CreatePendingConnection(Address addr,bool authenticate_on_connect)54 bool AclConnectionHandler::CreatePendingConnection(
55 Address addr, bool authenticate_on_connect) {
56 if (classic_connection_pending_) {
57 return false;
58 }
59 classic_connection_pending_ = true;
60 pending_connection_address_ = addr;
61 authenticate_pending_classic_connection_ = authenticate_on_connect;
62 return true;
63 }
64
HasPendingConnection(Address addr) const65 bool AclConnectionHandler::HasPendingConnection(Address addr) const {
66 return classic_connection_pending_ && pending_connection_address_ == addr;
67 }
68
AuthenticatePendingConnection() const69 bool AclConnectionHandler::AuthenticatePendingConnection() const {
70 return authenticate_pending_classic_connection_;
71 }
72
CancelPendingConnection(Address addr)73 bool AclConnectionHandler::CancelPendingConnection(Address addr) {
74 if (!classic_connection_pending_ || pending_connection_address_ != addr) {
75 return false;
76 }
77 classic_connection_pending_ = false;
78 pending_connection_address_ = Address::kEmpty;
79 pending_le_connection_resolved_address_ = AddressWithType();
80 return true;
81 }
82
CreatePendingLeConnection(AddressWithType peer,AddressWithType resolved_peer,AddressWithType local_address)83 bool AclConnectionHandler::CreatePendingLeConnection(
84 AddressWithType peer, AddressWithType resolved_peer,
85 AddressWithType local_address) {
86 for (auto pair : acl_connections_) {
87 auto connection = std::get<AclConnection>(pair);
88 if (connection.GetAddress() == peer ||
89 connection.GetResolvedAddress() == resolved_peer) {
90 LOG_INFO("%s: %s is already connected", __func__,
91 peer.ToString().c_str());
92 if (connection.GetResolvedAddress() == resolved_peer) {
93 LOG_INFO("%s: allowing a second connection with %s", __func__,
94 resolved_peer.ToString().c_str());
95 } else {
96 return false;
97 }
98 }
99 }
100 if (le_connection_pending_) {
101 LOG_INFO("%s: connection already pending", __func__);
102 return false;
103 }
104 le_connection_pending_ = true;
105 pending_le_connection_address_ = peer;
106 pending_le_connection_own_address_ = local_address;
107 pending_le_connection_resolved_address_ = resolved_peer;
108 return true;
109 }
110
HasPendingLeConnection(AddressWithType addr) const111 bool AclConnectionHandler::HasPendingLeConnection(AddressWithType addr) const {
112 return le_connection_pending_ && pending_le_connection_address_ == addr;
113 }
114
CancelPendingLeConnection(AddressWithType addr)115 bool AclConnectionHandler::CancelPendingLeConnection(AddressWithType addr) {
116 if (!le_connection_pending_ || pending_le_connection_address_ != addr) {
117 return false;
118 }
119 le_connection_pending_ = false;
120 pending_le_connection_address_ =
121 AddressWithType{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
122 pending_le_connection_resolved_address_ =
123 AddressWithType{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
124 return true;
125 }
126
CreateConnection(Address addr,Address own_addr)127 uint16_t AclConnectionHandler::CreateConnection(Address addr,
128 Address own_addr) {
129 if (CancelPendingConnection(addr)) {
130 uint16_t handle = GetUnusedHandle();
131 acl_connections_.emplace(
132 handle,
133 AclConnection{
134 AddressWithType{addr, AddressType::PUBLIC_DEVICE_ADDRESS},
135 AddressWithType{own_addr, AddressType::PUBLIC_DEVICE_ADDRESS},
136 AddressWithType(), Phy::Type::BR_EDR,
137 bluetooth::hci::Role::CENTRAL});
138 return handle;
139 }
140 return kReservedHandle;
141 }
142
CreateLeConnection(AddressWithType addr,AddressWithType own_addr,bluetooth::hci::Role role)143 uint16_t AclConnectionHandler::CreateLeConnection(AddressWithType addr,
144 AddressWithType own_addr,
145 bluetooth::hci::Role role) {
146 AddressWithType resolved_peer = pending_le_connection_resolved_address_;
147 if (CancelPendingLeConnection(addr)) {
148 uint16_t handle = GetUnusedHandle();
149 acl_connections_.emplace(handle,
150 AclConnection{addr, own_addr, resolved_peer,
151 Phy::Type::LOW_ENERGY, role});
152 return handle;
153 }
154 return kReservedHandle;
155 }
156
Disconnect(uint16_t handle,std::function<void (AsyncTaskId)> stopStream)157 bool AclConnectionHandler::Disconnect(
158 uint16_t handle, std::function<void(AsyncTaskId)> stopStream) {
159 if (HasScoHandle(handle)) {
160 sco_connections_.at(handle).StopStream(std::move(stopStream));
161 sco_connections_.erase(handle);
162 return true;
163 }
164 if (HasHandle(handle)) {
165 // It is the responsibility of the caller to remove SCO connections
166 // with connected peer first.
167 uint16_t sco_handle = GetScoHandle(GetAddress(handle).GetAddress());
168 ASSERT(!HasScoHandle(sco_handle));
169 acl_connections_.erase(handle);
170 return true;
171 }
172 return false;
173 }
174
GetHandle(AddressWithType addr) const175 uint16_t AclConnectionHandler::GetHandle(AddressWithType addr) const {
176 for (auto pair : acl_connections_) {
177 if (std::get<AclConnection>(pair).GetAddress() == addr) {
178 return std::get<0>(pair);
179 }
180 }
181 return kReservedHandle;
182 }
183
GetHandleOnlyAddress(bluetooth::hci::Address addr) const184 uint16_t AclConnectionHandler::GetHandleOnlyAddress(
185 bluetooth::hci::Address addr) const {
186 for (auto pair : acl_connections_) {
187 if (std::get<AclConnection>(pair).GetAddress().GetAddress() == addr) {
188 return std::get<0>(pair);
189 }
190 }
191 return kReservedHandle;
192 }
193
GetAddress(uint16_t handle) const194 AddressWithType AclConnectionHandler::GetAddress(uint16_t handle) const {
195 ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle);
196 return acl_connections_.at(handle).GetAddress();
197 }
198
GetScoAddress(uint16_t handle) const199 Address AclConnectionHandler::GetScoAddress(uint16_t handle) const {
200 ASSERT_LOG(HasScoHandle(handle), "Unknown SCO handle %hd", handle);
201 return sco_connections_.at(handle).GetAddress();
202 }
203
GetOwnAddress(uint16_t handle) const204 AddressWithType AclConnectionHandler::GetOwnAddress(uint16_t handle) const {
205 ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle);
206 return acl_connections_.at(handle).GetOwnAddress();
207 }
208
GetResolvedAddress(uint16_t handle) const209 AddressWithType AclConnectionHandler::GetResolvedAddress(
210 uint16_t handle) const {
211 ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle);
212 return acl_connections_.at(handle).GetResolvedAddress();
213 }
214
Encrypt(uint16_t handle)215 void AclConnectionHandler::Encrypt(uint16_t handle) {
216 if (!HasHandle(handle)) {
217 return;
218 }
219 acl_connections_.at(handle).Encrypt();
220 }
221
IsEncrypted(uint16_t handle) const222 bool AclConnectionHandler::IsEncrypted(uint16_t handle) const {
223 if (!HasHandle(handle)) {
224 return false;
225 }
226 return acl_connections_.at(handle).IsEncrypted();
227 }
228
GetPhyType(uint16_t handle) const229 Phy::Type AclConnectionHandler::GetPhyType(uint16_t handle) const {
230 if (!HasHandle(handle)) {
231 return Phy::Type::BR_EDR;
232 }
233 return acl_connections_.at(handle).GetPhyType();
234 }
235
GetAclLinkPolicySettings(uint16_t handle) const236 uint16_t AclConnectionHandler::GetAclLinkPolicySettings(uint16_t handle) const {
237 return acl_connections_.at(handle).GetLinkPolicySettings();
238 };
239
SetAclLinkPolicySettings(uint16_t handle,uint16_t settings)240 void AclConnectionHandler::SetAclLinkPolicySettings(uint16_t handle,
241 uint16_t settings) {
242 acl_connections_.at(handle).SetLinkPolicySettings(settings);
243 }
244
GetAclRole(uint16_t handle) const245 bluetooth::hci::Role AclConnectionHandler::GetAclRole(uint16_t handle) const {
246 return acl_connections_.at(handle).GetRole();
247 };
248
SetAclRole(uint16_t handle,bluetooth::hci::Role role)249 void AclConnectionHandler::SetAclRole(uint16_t handle,
250 bluetooth::hci::Role role) {
251 acl_connections_.at(handle).SetRole(role);
252 }
253
254 std::unique_ptr<bluetooth::hci::LeSetCigParametersCompleteBuilder>
SetCigParameters(uint8_t id,uint32_t sdu_interval_m_to_s,uint32_t sdu_interval_s_to_m,bluetooth::hci::ClockAccuracy,bluetooth::hci::Packing packing,bluetooth::hci::Enable framed,uint16_t max_transport_latency_m_to_s_,uint16_t max_transport_latency_s_to_m_,std::vector<bluetooth::hci::CisParametersConfig> & streams)255 AclConnectionHandler::SetCigParameters(
256 uint8_t id, uint32_t sdu_interval_m_to_s, uint32_t sdu_interval_s_to_m,
257 bluetooth::hci::ClockAccuracy /* accuracy */,
258 bluetooth::hci::Packing packing, bluetooth::hci::Enable framed,
259 uint16_t max_transport_latency_m_to_s_,
260 uint16_t max_transport_latency_s_to_m_,
261 std::vector<bluetooth::hci::CisParametersConfig>& streams) {
262 std::vector<uint16_t> handles;
263 GroupParameters group_parameters{
264 .id = id,
265 .sdu_interval_m_to_s = sdu_interval_m_to_s,
266 .sdu_interval_s_to_m = sdu_interval_s_to_m,
267 .interleaved = packing == bluetooth::hci::Packing::INTERLEAVED,
268 .framed = framed == bluetooth::hci::Enable::ENABLED,
269 .max_transport_latency_m_to_s = max_transport_latency_m_to_s_,
270 .max_transport_latency_s_to_m = max_transport_latency_s_to_m_};
271 std::vector<StreamParameters> stream_parameters;
272 for (size_t i = 0; i < streams.size(); i++) {
273 auto handle = GetUnusedHandle();
274 StreamParameters a{.group_id = group_parameters.id,
275 .stream_id = streams[i].cis_id_,
276 .max_sdu_m_to_s = streams[i].max_sdu_m_to_s_,
277 .max_sdu_s_to_m = streams[i].max_sdu_s_to_m_,
278 .rtn_m_to_s = streams[i].rtn_m_to_s_,
279 .rtn_s_to_m = streams[i].rtn_s_to_m_,
280 .handle = handle};
281 handles.push_back(handle);
282 stream_parameters.push_back(std::move(a));
283 }
284
285 return isochronous_connection_handler_.SetCigParameters(
286 group_parameters, stream_parameters, std::move(handles));
287 }
288
CreatePendingCis(bluetooth::hci::CreateCisConfig config)289 void AclConnectionHandler::CreatePendingCis(
290 bluetooth::hci::CreateCisConfig config) {
291 CisHandles handles;
292 handles.cis_handle_ = config.cis_connection_handle_;
293 handles.acl_handle_ = config.acl_connection_handle_;
294 handles.remote_cis_handle_ = kReservedHandle;
295 pending_streams_.emplace_back(std::move(handles));
296 }
297
ConnectCis(uint16_t handle)298 bool AclConnectionHandler::ConnectCis(uint16_t handle) {
299 size_t position;
300 CisHandles connection;
301 for (position = 0; position < pending_streams_.size(); position++) {
302 if (handle == pending_streams_[position].cis_handle_) {
303 LOG_INFO("Found handle 0x%04hx", handle);
304 connection = pending_streams_[position];
305 pending_streams_.erase(pending_streams_.begin() + position);
306 connected_streams_.push_back(connection);
307 ASSERT(connection.cis_handle_ != kReservedHandle);
308 ASSERT(connection.acl_handle_ != kReservedHandle);
309 ASSERT(connection.remote_cis_handle_ != kReservedHandle);
310 return true;
311 }
312 }
313
314 LOG_INFO("No pending CIS connection with handle 0x%04hx", handle);
315 return false;
316 }
317
SetRemoteCisHandle(uint16_t handle,uint16_t remote_handle)318 void AclConnectionHandler::SetRemoteCisHandle(uint16_t handle,
319 uint16_t remote_handle) {
320 for (size_t position = 0; position < pending_streams_.size(); position++) {
321 if (handle == pending_streams_[position].cis_handle_) {
322 LOG_INFO("Added remote handle 0x%04hx to handle 0x%04hx", remote_handle,
323 pending_streams_[position].cis_handle_);
324 pending_streams_[position].remote_cis_handle_ = remote_handle;
325 return;
326 }
327 }
328 LOG_INFO("Couldn't find CIS connection with handle 0x%04hx", handle);
329 }
330
RejectCis(uint16_t handle)331 bool AclConnectionHandler::RejectCis(uint16_t handle) {
332 size_t position;
333 for (position = 0; position < pending_streams_.size(); position++) {
334 if (handle == pending_streams_[position].cis_handle_) {
335 pending_streams_.erase(pending_streams_.begin() + position);
336 break;
337 }
338 }
339 if (position == pending_streams_.size()) {
340 LOG_INFO("No pending connection with handle 0x%hx", handle);
341 return false;
342 }
343 return true;
344 }
345
GetPendingAclHandle(uint16_t cis_handle) const346 uint16_t AclConnectionHandler::GetPendingAclHandle(uint16_t cis_handle) const {
347 size_t position;
348 uint16_t handle = 0xffff;
349 for (position = 0; position < pending_streams_.size(); position++) {
350 if (cis_handle == pending_streams_[position].cis_handle_) {
351 handle = pending_streams_[position].acl_handle_;
352 break;
353 }
354 }
355 if (position == pending_streams_.size()) {
356 LOG_INFO("No pending connection with handle 0x%hx", cis_handle);
357 }
358 return handle;
359 }
360
DisconnectCis(uint16_t cis_handle)361 bool AclConnectionHandler::DisconnectCis(uint16_t cis_handle) {
362 size_t position;
363 for (position = 0; position < connected_streams_.size(); position++) {
364 if (cis_handle == connected_streams_[position].cis_handle_) {
365 connected_streams_.erase(connected_streams_.begin() + position);
366 break;
367 }
368 }
369 if (position == connected_streams_.size()) {
370 LOG_INFO("No connected stream 0x%hx", cis_handle);
371 return false;
372 }
373 return true;
374 }
375
RemoveCig(uint8_t cig_id)376 bluetooth::hci::ErrorCode AclConnectionHandler::RemoveCig(uint8_t cig_id) {
377 for (const auto& stream : connected_streams_) {
378 if (isochronous_connection_handler_.GetGroupId(stream.cis_handle_) ==
379 cig_id) {
380 return bluetooth::hci::ErrorCode::COMMAND_DISALLOWED;
381 }
382 }
383 for (const auto& stream : pending_streams_) {
384 if (isochronous_connection_handler_.GetGroupId(stream.cis_handle_) ==
385 cig_id) {
386 return bluetooth::hci::ErrorCode::COMMAND_DISALLOWED;
387 }
388 }
389 auto status = isochronous_connection_handler_.RemoveCig(cig_id);
390 if (status == bluetooth::hci::ErrorCode::SUCCESS) {
391 // Clean up?
392 }
393 return status;
394 }
395
HasPendingCisConnection(uint16_t handle) const396 bool AclConnectionHandler::HasPendingCisConnection(uint16_t handle) const {
397 for (const auto& config : pending_streams_) {
398 if (config.cis_handle_ == handle) {
399 return true;
400 }
401 }
402 return false;
403 }
404
HasPendingCis() const405 bool AclConnectionHandler::HasPendingCis() const {
406 return !pending_streams_.empty();
407 }
408
HasConnectedCis(uint16_t handle) const409 bool AclConnectionHandler::HasConnectedCis(uint16_t handle) const {
410 for (const auto& cs : connected_streams_) {
411 if (handle == cs.cis_handle_) {
412 return true;
413 }
414 }
415 return false;
416 }
417
HasCisHandle(uint16_t handle) const418 bool AclConnectionHandler::HasCisHandle(uint16_t handle) const {
419 for (const auto& cs : pending_streams_) {
420 if (handle == cs.cis_handle_) {
421 return true;
422 }
423 }
424 for (const auto& cs : connected_streams_) {
425 if (handle == cs.cis_handle_) {
426 return true;
427 }
428 }
429 return isochronous_connection_handler_.HasHandle(handle);
430 }
431
GetAclHandleForCisHandle(uint16_t cis_handle) const432 uint16_t AclConnectionHandler::GetAclHandleForCisHandle(
433 uint16_t cis_handle) const {
434 for (const auto& cs : connected_streams_) {
435 if (cis_handle == cs.cis_handle_) {
436 return cs.acl_handle_;
437 }
438 }
439 return kReservedHandle;
440 }
441
GetRemoteCisHandleForCisHandle(uint16_t cis_handle) const442 uint16_t AclConnectionHandler::GetRemoteCisHandleForCisHandle(
443 uint16_t cis_handle) const {
444 for (const auto& cs : connected_streams_) {
445 if (cis_handle == cs.cis_handle_) {
446 return cs.remote_cis_handle_;
447 }
448 }
449 return kReservedHandle;
450 }
451
GetGroupParameters(uint8_t id) const452 GroupParameters AclConnectionHandler::GetGroupParameters(uint8_t id) const {
453 return isochronous_connection_handler_.GetGroupParameters(id);
454 }
455
GetStreamParameters(uint16_t handle) const456 StreamParameters AclConnectionHandler::GetStreamParameters(
457 uint16_t handle) const {
458 return isochronous_connection_handler_.GetStreamParameters(handle);
459 }
460
CreateScoConnection(bluetooth::hci::Address addr,ScoConnectionParameters const & parameters,ScoState state,ScoDatapath datapath,bool legacy)461 void AclConnectionHandler::CreateScoConnection(
462 bluetooth::hci::Address addr, ScoConnectionParameters const& parameters,
463 ScoState state, ScoDatapath datapath, bool legacy) {
464 uint16_t sco_handle = GetUnusedHandle();
465 sco_connections_.emplace(
466 sco_handle, ScoConnection(addr, parameters, state, datapath, legacy));
467 }
468
HasPendingScoConnection(bluetooth::hci::Address addr) const469 bool AclConnectionHandler::HasPendingScoConnection(
470 bluetooth::hci::Address addr) const {
471 for (const auto& pair : sco_connections_) {
472 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
473 ScoState state = std::get<ScoConnection>(pair).GetState();
474 return state == SCO_STATE_PENDING ||
475 state == SCO_STATE_SENT_ESCO_CONNECTION_REQUEST ||
476 state == SCO_STATE_SENT_SCO_CONNECTION_REQUEST;
477 }
478 }
479 return false;
480 }
481
GetScoConnectionState(bluetooth::hci::Address addr) const482 ScoState AclConnectionHandler::GetScoConnectionState(
483 bluetooth::hci::Address addr) const {
484 for (const auto& pair : sco_connections_) {
485 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
486 return std::get<ScoConnection>(pair).GetState();
487 }
488 }
489 return SCO_STATE_CLOSED;
490 }
491
IsLegacyScoConnection(bluetooth::hci::Address addr) const492 bool AclConnectionHandler::IsLegacyScoConnection(
493 bluetooth::hci::Address addr) const {
494 for (const auto& pair : sco_connections_) {
495 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
496 return std::get<ScoConnection>(pair).IsLegacy();
497 }
498 }
499 return false;
500 }
501
CancelPendingScoConnection(bluetooth::hci::Address addr)502 void AclConnectionHandler::CancelPendingScoConnection(
503 bluetooth::hci::Address addr) {
504 for (auto it = sco_connections_.begin(); it != sco_connections_.end(); it++) {
505 if (std::get<ScoConnection>(*it).GetAddress() == addr) {
506 sco_connections_.erase(it);
507 return;
508 }
509 }
510 }
511
AcceptPendingScoConnection(bluetooth::hci::Address addr,ScoLinkParameters const & parameters,std::function<AsyncTaskId ()> startStream)512 bool AclConnectionHandler::AcceptPendingScoConnection(
513 bluetooth::hci::Address addr, ScoLinkParameters const& parameters,
514 std::function<AsyncTaskId()> startStream) {
515 for (auto& pair : sco_connections_) {
516 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
517 std::get<ScoConnection>(pair).SetLinkParameters(parameters);
518 std::get<ScoConnection>(pair).SetState(ScoState::SCO_STATE_OPENED);
519 std::get<ScoConnection>(pair).StartStream(std::move(startStream));
520 return true;
521 }
522 }
523 return false;
524 }
525
AcceptPendingScoConnection(bluetooth::hci::Address addr,ScoConnectionParameters const & parameters,std::function<AsyncTaskId ()> startStream)526 bool AclConnectionHandler::AcceptPendingScoConnection(
527 bluetooth::hci::Address addr, ScoConnectionParameters const& parameters,
528 std::function<AsyncTaskId()> startStream) {
529 for (auto& pair : sco_connections_) {
530 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
531 bool ok =
532 std::get<ScoConnection>(pair).NegotiateLinkParameters(parameters);
533 std::get<ScoConnection>(pair).SetState(ok ? ScoState::SCO_STATE_OPENED
534 : ScoState::SCO_STATE_CLOSED);
535 if (ok) {
536 std::get<ScoConnection>(pair).StartStream(std::move(startStream));
537 }
538 return ok;
539 }
540 }
541 return false;
542 }
543
GetScoHandle(bluetooth::hci::Address addr) const544 uint16_t AclConnectionHandler::GetScoHandle(
545 bluetooth::hci::Address addr) const {
546 for (const auto& pair : sco_connections_) {
547 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
548 return std::get<0>(pair);
549 }
550 }
551 return kReservedHandle;
552 }
553
GetScoConnectionParameters(bluetooth::hci::Address addr) const554 ScoConnectionParameters AclConnectionHandler::GetScoConnectionParameters(
555 bluetooth::hci::Address addr) const {
556 for (const auto& pair : sco_connections_) {
557 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
558 return std::get<ScoConnection>(pair).GetConnectionParameters();
559 }
560 }
561 return {};
562 }
563
GetScoLinkParameters(bluetooth::hci::Address addr) const564 ScoLinkParameters AclConnectionHandler::GetScoLinkParameters(
565 bluetooth::hci::Address addr) const {
566 for (const auto& pair : sco_connections_) {
567 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
568 return std::get<ScoConnection>(pair).GetLinkParameters();
569 }
570 }
571 return {};
572 }
573
GetAclHandles() const574 std::vector<uint16_t> AclConnectionHandler::GetAclHandles() const {
575 std::vector<uint16_t> keys;
576
577 for (const auto& pair : acl_connections_) {
578 keys.push_back(pair.first);
579 }
580 return keys;
581 }
582
ResetLinkTimer(uint16_t handle)583 void AclConnectionHandler::ResetLinkTimer(uint16_t handle) {
584 acl_connections_.at(handle).ResetLinkTimer();
585 }
586
587 std::chrono::steady_clock::duration
TimeUntilLinkNearExpiring(uint16_t handle) const588 AclConnectionHandler::TimeUntilLinkNearExpiring(uint16_t handle) const {
589 return acl_connections_.at(handle).TimeUntilNearExpiring();
590 }
591
IsLinkNearExpiring(uint16_t handle) const592 bool AclConnectionHandler::IsLinkNearExpiring(uint16_t handle) const {
593 return acl_connections_.at(handle).IsNearExpiring();
594 }
595
TimeUntilLinkExpired(uint16_t handle) const596 std::chrono::steady_clock::duration AclConnectionHandler::TimeUntilLinkExpired(
597 uint16_t handle) const {
598 return acl_connections_.at(handle).TimeUntilExpired();
599 }
600
HasLinkExpired(uint16_t handle) const601 bool AclConnectionHandler::HasLinkExpired(uint16_t handle) const {
602 return acl_connections_.at(handle).HasExpired();
603 }
604
605 } // namespace rootcanal
606