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 "model/controller/acl_connection_handler.h"
18
19 #include <chrono>
20 #include <cstdint>
21 #include <functional>
22 #include <optional>
23 #include <utility>
24 #include <vector>
25
26 #include "hci/address.h"
27 #include "hci/address_with_type.h"
28 #include "log.h"
29 #include "model/controller/acl_connection.h"
30 #include "model/controller/sco_connection.h"
31 #include "packets/hci_packets.h"
32 #include "phy.h"
33
34 namespace rootcanal {
35
36 using ::bluetooth::hci::Address;
37 using ::bluetooth::hci::AddressType;
38 using ::bluetooth::hci::AddressWithType;
39
Reset(std::function<void (TaskId)> stopStream)40 void AclConnectionHandler::Reset(std::function<void(TaskId)> stopStream) {
41 // Leave no dangling periodic task.
42 for (auto& [_, sco_connection] : sco_connections_) {
43 sco_connection.StopStream(stopStream);
44 }
45
46 sco_connections_.clear();
47 acl_connections_.clear();
48 }
49
HasHandle(uint16_t handle) const50 bool AclConnectionHandler::HasHandle(uint16_t handle) const {
51 return acl_connections_.count(handle) != 0;
52 }
53
HasScoHandle(uint16_t handle) const54 bool AclConnectionHandler::HasScoHandle(uint16_t handle) const {
55 return sco_connections_.count(handle) != 0;
56 }
57
GetUnusedHandle()58 uint16_t AclConnectionHandler::GetUnusedHandle() {
59 // Keep a reserved range of handles for CIS connections implemented
60 // in the rust module.
61 while (HasHandle(last_handle_) || HasScoHandle(last_handle_) ||
62 (last_handle_ >= kCisHandleRangeStart &&
63 last_handle_ < kCisHandleRangeEnd)) {
64 last_handle_ = (last_handle_ + 1) % kReservedHandle;
65 }
66 uint16_t unused_handle = last_handle_;
67 last_handle_ = (last_handle_ + 1) % kReservedHandle;
68 return unused_handle;
69 }
70
CreatePendingConnection(Address addr,bool authenticate_on_connect,bool allow_role_switch)71 bool AclConnectionHandler::CreatePendingConnection(Address addr,
72 bool authenticate_on_connect,
73 bool allow_role_switch) {
74 if (classic_connection_pending_ || GetAclConnectionHandle(addr).has_value()) {
75 return false;
76 }
77 classic_connection_pending_ = true;
78 pending_connection_address_ = addr;
79 authenticate_pending_classic_connection_ = authenticate_on_connect;
80 pending_classic_connection_allow_role_switch_ = allow_role_switch;
81 return true;
82 }
83
HasPendingConnection(Address addr) const84 bool AclConnectionHandler::HasPendingConnection(Address addr) const {
85 return classic_connection_pending_ && pending_connection_address_ == addr;
86 }
87
AuthenticatePendingConnection() const88 bool AclConnectionHandler::AuthenticatePendingConnection() const {
89 return authenticate_pending_classic_connection_;
90 }
91
CancelPendingConnection(Address addr)92 bool AclConnectionHandler::CancelPendingConnection(Address addr) {
93 if (!classic_connection_pending_ || pending_connection_address_ != addr) {
94 return false;
95 }
96 classic_connection_pending_ = false;
97 pending_connection_address_ = Address::kEmpty;
98 pending_le_connection_resolved_address_ = AddressWithType();
99 return true;
100 }
101
CreatePendingLeConnection(AddressWithType peer,AddressWithType resolved_peer,AddressWithType local_address)102 bool AclConnectionHandler::CreatePendingLeConnection(
103 AddressWithType peer, AddressWithType resolved_peer,
104 AddressWithType local_address) {
105 for (auto pair : acl_connections_) {
106 auto connection = std::get<AclConnection>(pair);
107 if (connection.GetAddress() == peer ||
108 connection.GetResolvedAddress() == resolved_peer) {
109 INFO("{}: {} is already connected", __func__, peer);
110 if (connection.GetResolvedAddress() == resolved_peer) {
111 INFO("{}: allowing a second connection with {}", __func__,
112 resolved_peer);
113 } else {
114 return false;
115 }
116 }
117 }
118 if (le_connection_pending_) {
119 INFO("{}: connection already pending", __func__);
120 return false;
121 }
122 le_connection_pending_ = true;
123 pending_le_connection_address_ = peer;
124 pending_le_connection_own_address_ = local_address;
125 pending_le_connection_resolved_address_ = resolved_peer;
126 return true;
127 }
128
HasPendingLeConnection(AddressWithType addr) const129 bool AclConnectionHandler::HasPendingLeConnection(AddressWithType addr) const {
130 return le_connection_pending_ && pending_le_connection_address_ == addr;
131 }
132
CancelPendingLeConnection(AddressWithType addr)133 bool AclConnectionHandler::CancelPendingLeConnection(AddressWithType addr) {
134 if (!le_connection_pending_ || pending_le_connection_address_ != addr) {
135 return false;
136 }
137 le_connection_pending_ = false;
138 pending_le_connection_address_ =
139 AddressWithType{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
140 pending_le_connection_resolved_address_ =
141 AddressWithType{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
142 return true;
143 }
144
CreateConnection(Address addr,Address own_addr,bool pending)145 uint16_t AclConnectionHandler::CreateConnection(Address addr, Address own_addr,
146 bool pending) {
147 if (!pending || CancelPendingConnection(addr)) {
148 uint16_t handle = GetUnusedHandle();
149 acl_connections_.emplace(
150 handle,
151 AclConnection{
152 AddressWithType{addr, AddressType::PUBLIC_DEVICE_ADDRESS},
153 AddressWithType{own_addr, AddressType::PUBLIC_DEVICE_ADDRESS},
154 AddressWithType(), Phy::Type::BR_EDR,
155 bluetooth::hci::Role::CENTRAL});
156 return handle;
157 }
158 return kReservedHandle;
159 }
160
CreateLeConnection(AddressWithType addr,AddressWithType own_addr,bluetooth::hci::Role role)161 uint16_t AclConnectionHandler::CreateLeConnection(AddressWithType addr,
162 AddressWithType own_addr,
163 bluetooth::hci::Role role) {
164 AddressWithType resolved_peer = pending_le_connection_resolved_address_;
165 if (CancelPendingLeConnection(addr)) {
166 uint16_t handle = GetUnusedHandle();
167 acl_connections_.emplace(handle,
168 AclConnection{addr, own_addr, resolved_peer,
169 Phy::Type::LOW_ENERGY, role});
170 return handle;
171 }
172 return kReservedHandle;
173 }
174
Disconnect(uint16_t handle,std::function<void (TaskId)> stopStream)175 bool AclConnectionHandler::Disconnect(uint16_t handle,
176 std::function<void(TaskId)> stopStream) {
177 if (HasScoHandle(handle)) {
178 sco_connections_.at(handle).StopStream(std::move(stopStream));
179 sco_connections_.erase(handle);
180 return true;
181 }
182 if (HasHandle(handle)) {
183 // It is the responsibility of the caller to remove SCO connections
184 // with connected peer first.
185 uint16_t sco_handle = GetScoHandle(GetAddress(handle).GetAddress());
186 ASSERT(!HasScoHandle(sco_handle));
187 acl_connections_.erase(handle);
188 return true;
189 }
190 return false;
191 }
192
GetHandle(AddressWithType addr) const193 uint16_t AclConnectionHandler::GetHandle(AddressWithType addr) const {
194 for (auto pair : acl_connections_) {
195 if (std::get<AclConnection>(pair).GetAddress() == addr) {
196 return std::get<0>(pair);
197 }
198 }
199 return kReservedHandle;
200 }
201
GetHandleOnlyAddress(bluetooth::hci::Address addr) const202 uint16_t AclConnectionHandler::GetHandleOnlyAddress(
203 bluetooth::hci::Address addr) const {
204 for (auto pair : acl_connections_) {
205 if (std::get<AclConnection>(pair).GetAddress().GetAddress() == addr) {
206 return std::get<0>(pair);
207 }
208 }
209 return kReservedHandle;
210 }
211
GetAclConnectionHandle(bluetooth::hci::Address bd_addr) const212 std::optional<uint16_t> AclConnectionHandler::GetAclConnectionHandle(
213 bluetooth::hci::Address bd_addr) const {
214 for (auto const& [handle, connection] : acl_connections_) {
215 if (connection.GetAddress().GetAddress() == bd_addr &&
216 connection.GetPhyType() == Phy::Type::BR_EDR) {
217 return handle;
218 }
219 }
220 return {};
221 }
222
GetAclConnection(uint16_t handle)223 AclConnection& AclConnectionHandler::GetAclConnection(uint16_t handle) {
224 ASSERT_LOG(HasHandle(handle), "Unknown handle %d", handle);
225 return acl_connections_.at(handle);
226 }
227
GetAddress(uint16_t handle) const228 AddressWithType AclConnectionHandler::GetAddress(uint16_t handle) const {
229 ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle);
230 return acl_connections_.at(handle).GetAddress();
231 }
232
GetAddressSafe(uint16_t handle) const233 std::optional<AddressWithType> AclConnectionHandler::GetAddressSafe(
234 uint16_t handle) const {
235 return HasHandle(handle) ? acl_connections_.at(handle).GetAddress()
236 : std::optional<AddressWithType>();
237 }
238
GetScoAddress(uint16_t handle) const239 Address AclConnectionHandler::GetScoAddress(uint16_t handle) const {
240 ASSERT_LOG(HasScoHandle(handle), "Unknown SCO handle %hd", handle);
241 return sco_connections_.at(handle).GetAddress();
242 }
243
GetOwnAddress(uint16_t handle) const244 AddressWithType AclConnectionHandler::GetOwnAddress(uint16_t handle) const {
245 ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle);
246 return acl_connections_.at(handle).GetOwnAddress();
247 }
248
GetResolvedAddress(uint16_t handle) const249 AddressWithType AclConnectionHandler::GetResolvedAddress(
250 uint16_t handle) const {
251 ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle);
252 return acl_connections_.at(handle).GetResolvedAddress();
253 }
254
Encrypt(uint16_t handle)255 void AclConnectionHandler::Encrypt(uint16_t handle) {
256 if (!HasHandle(handle)) {
257 return;
258 }
259 acl_connections_.at(handle).Encrypt();
260 }
261
IsEncrypted(uint16_t handle) const262 bool AclConnectionHandler::IsEncrypted(uint16_t handle) const {
263 if (!HasHandle(handle)) {
264 return false;
265 }
266 return acl_connections_.at(handle).IsEncrypted();
267 }
268
SetRssi(uint16_t handle,int8_t rssi)269 void AclConnectionHandler::SetRssi(uint16_t handle, int8_t rssi) {
270 if (HasHandle(handle)) {
271 acl_connections_.at(handle).SetRssi(rssi);
272 }
273 }
274
GetRssi(uint16_t handle) const275 int8_t AclConnectionHandler::GetRssi(uint16_t handle) const {
276 return HasHandle(handle) ? acl_connections_.at(handle).GetRssi() : 0;
277 }
278
GetPhyType(uint16_t handle) const279 Phy::Type AclConnectionHandler::GetPhyType(uint16_t handle) const {
280 if (!HasHandle(handle)) {
281 return Phy::Type::BR_EDR;
282 }
283 return acl_connections_.at(handle).GetPhyType();
284 }
285
GetAclLinkPolicySettings(uint16_t handle) const286 uint16_t AclConnectionHandler::GetAclLinkPolicySettings(uint16_t handle) const {
287 return acl_connections_.at(handle).GetLinkPolicySettings();
288 }
289
SetAclLinkPolicySettings(uint16_t handle,uint16_t settings)290 void AclConnectionHandler::SetAclLinkPolicySettings(uint16_t handle,
291 uint16_t settings) {
292 acl_connections_.at(handle).SetLinkPolicySettings(settings);
293 }
294
GetAclRole(uint16_t handle) const295 bluetooth::hci::Role AclConnectionHandler::GetAclRole(uint16_t handle) const {
296 return acl_connections_.at(handle).GetRole();
297 }
298
SetAclRole(uint16_t handle,bluetooth::hci::Role role)299 void AclConnectionHandler::SetAclRole(uint16_t handle,
300 bluetooth::hci::Role role) {
301 acl_connections_.at(handle).SetRole(role);
302 }
303
CreateScoConnection(bluetooth::hci::Address addr,ScoConnectionParameters const & parameters,ScoState state,ScoDatapath datapath,bool legacy)304 void AclConnectionHandler::CreateScoConnection(
305 bluetooth::hci::Address addr, ScoConnectionParameters const& parameters,
306 ScoState state, ScoDatapath datapath, bool legacy) {
307 uint16_t sco_handle = GetUnusedHandle();
308 sco_connections_.emplace(
309 sco_handle, ScoConnection(addr, parameters, state, datapath, legacy));
310 }
311
HasPendingScoConnection(bluetooth::hci::Address addr) const312 bool AclConnectionHandler::HasPendingScoConnection(
313 bluetooth::hci::Address addr) const {
314 for (const auto& pair : sco_connections_) {
315 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
316 ScoState state = std::get<ScoConnection>(pair).GetState();
317 return state == SCO_STATE_PENDING ||
318 state == SCO_STATE_SENT_ESCO_CONNECTION_REQUEST ||
319 state == SCO_STATE_SENT_SCO_CONNECTION_REQUEST;
320 }
321 }
322 return false;
323 }
324
GetScoConnectionState(bluetooth::hci::Address addr) const325 ScoState AclConnectionHandler::GetScoConnectionState(
326 bluetooth::hci::Address addr) const {
327 for (const auto& pair : sco_connections_) {
328 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
329 return std::get<ScoConnection>(pair).GetState();
330 }
331 }
332 return SCO_STATE_CLOSED;
333 }
334
IsLegacyScoConnection(bluetooth::hci::Address addr) const335 bool AclConnectionHandler::IsLegacyScoConnection(
336 bluetooth::hci::Address addr) const {
337 for (const auto& pair : sco_connections_) {
338 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
339 return std::get<ScoConnection>(pair).IsLegacy();
340 }
341 }
342 return false;
343 }
344
CancelPendingScoConnection(bluetooth::hci::Address addr)345 void AclConnectionHandler::CancelPendingScoConnection(
346 bluetooth::hci::Address addr) {
347 for (auto it = sco_connections_.begin(); it != sco_connections_.end(); it++) {
348 if (std::get<ScoConnection>(*it).GetAddress() == addr) {
349 sco_connections_.erase(it);
350 return;
351 }
352 }
353 }
354
AcceptPendingScoConnection(bluetooth::hci::Address addr,ScoLinkParameters const & parameters,std::function<TaskId ()> startStream)355 bool AclConnectionHandler::AcceptPendingScoConnection(
356 bluetooth::hci::Address addr, ScoLinkParameters const& parameters,
357 std::function<TaskId()> startStream) {
358 for (auto& pair : sco_connections_) {
359 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
360 std::get<ScoConnection>(pair).SetLinkParameters(parameters);
361 std::get<ScoConnection>(pair).SetState(ScoState::SCO_STATE_OPENED);
362 std::get<ScoConnection>(pair).StartStream(std::move(startStream));
363 return true;
364 }
365 }
366 return false;
367 }
368
AcceptPendingScoConnection(bluetooth::hci::Address addr,ScoConnectionParameters const & parameters,std::function<TaskId ()> startStream)369 bool AclConnectionHandler::AcceptPendingScoConnection(
370 bluetooth::hci::Address addr, ScoConnectionParameters const& parameters,
371 std::function<TaskId()> startStream) {
372 for (auto& pair : sco_connections_) {
373 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
374 bool ok =
375 std::get<ScoConnection>(pair).NegotiateLinkParameters(parameters);
376 std::get<ScoConnection>(pair).SetState(ok ? ScoState::SCO_STATE_OPENED
377 : ScoState::SCO_STATE_CLOSED);
378 if (ok) {
379 std::get<ScoConnection>(pair).StartStream(std::move(startStream));
380 }
381 return ok;
382 }
383 }
384 return false;
385 }
386
GetScoHandle(bluetooth::hci::Address addr) const387 uint16_t AclConnectionHandler::GetScoHandle(
388 bluetooth::hci::Address addr) const {
389 for (const auto& pair : sco_connections_) {
390 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
391 return std::get<0>(pair);
392 }
393 }
394 return kReservedHandle;
395 }
396
GetScoConnectionParameters(bluetooth::hci::Address addr) const397 ScoConnectionParameters AclConnectionHandler::GetScoConnectionParameters(
398 bluetooth::hci::Address addr) const {
399 for (const auto& pair : sco_connections_) {
400 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
401 return std::get<ScoConnection>(pair).GetConnectionParameters();
402 }
403 }
404 return {};
405 }
406
GetScoLinkParameters(bluetooth::hci::Address addr) const407 ScoLinkParameters AclConnectionHandler::GetScoLinkParameters(
408 bluetooth::hci::Address addr) const {
409 for (const auto& pair : sco_connections_) {
410 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
411 return std::get<ScoConnection>(pair).GetLinkParameters();
412 }
413 }
414 return {};
415 }
416
GetAclHandles() const417 std::vector<uint16_t> AclConnectionHandler::GetAclHandles() const {
418 std::vector<uint16_t> keys(acl_connections_.size());
419
420 for (const auto& pair : acl_connections_) {
421 keys.push_back(pair.first);
422 }
423 return keys;
424 }
425
ResetLinkTimer(uint16_t handle)426 void AclConnectionHandler::ResetLinkTimer(uint16_t handle) {
427 acl_connections_.at(handle).ResetLinkTimer();
428 }
429
430 std::chrono::steady_clock::duration
TimeUntilLinkNearExpiring(uint16_t handle) const431 AclConnectionHandler::TimeUntilLinkNearExpiring(uint16_t handle) const {
432 return acl_connections_.at(handle).TimeUntilNearExpiring();
433 }
434
IsLinkNearExpiring(uint16_t handle) const435 bool AclConnectionHandler::IsLinkNearExpiring(uint16_t handle) const {
436 return acl_connections_.at(handle).IsNearExpiring();
437 }
438
TimeUntilLinkExpired(uint16_t handle) const439 std::chrono::steady_clock::duration AclConnectionHandler::TimeUntilLinkExpired(
440 uint16_t handle) const {
441 return acl_connections_.at(handle).TimeUntilExpired();
442 }
443
HasLinkExpired(uint16_t handle) const444 bool AclConnectionHandler::HasLinkExpired(uint16_t handle) const {
445 return acl_connections_.at(handle).HasExpired();
446 }
447
IsRoleSwitchAllowedForPendingConnection() const448 bool AclConnectionHandler::IsRoleSwitchAllowedForPendingConnection() const {
449 return pending_classic_connection_allow_role_switch_;
450 }
451
452 } // namespace rootcanal
453