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 && last_handle_ < kCisHandleRangeEnd)) {
63 last_handle_ = (last_handle_ + 1) % kReservedHandle;
64 }
65 uint16_t unused_handle = last_handle_;
66 last_handle_ = (last_handle_ + 1) % kReservedHandle;
67 return unused_handle;
68 }
69
CreatePendingConnection(Address addr,bool authenticate_on_connect,bool allow_role_switch)70 bool AclConnectionHandler::CreatePendingConnection(Address addr, bool authenticate_on_connect,
71 bool allow_role_switch) {
72 if (classic_connection_pending_ || GetAclConnectionHandle(addr).has_value()) {
73 return false;
74 }
75 classic_connection_pending_ = true;
76 pending_connection_address_ = addr;
77 authenticate_pending_classic_connection_ = authenticate_on_connect;
78 pending_classic_connection_allow_role_switch_ = allow_role_switch;
79 return true;
80 }
81
HasPendingConnection(Address addr) const82 bool AclConnectionHandler::HasPendingConnection(Address addr) const {
83 return classic_connection_pending_ && pending_connection_address_ == addr;
84 }
85
AuthenticatePendingConnection() const86 bool AclConnectionHandler::AuthenticatePendingConnection() const {
87 return authenticate_pending_classic_connection_;
88 }
89
CancelPendingConnection(Address addr)90 bool AclConnectionHandler::CancelPendingConnection(Address addr) {
91 if (!classic_connection_pending_ || pending_connection_address_ != addr) {
92 return false;
93 }
94 classic_connection_pending_ = false;
95 pending_connection_address_ = Address::kEmpty;
96 pending_le_connection_resolved_address_ = AddressWithType();
97 return true;
98 }
99
CreatePendingLeConnection(AddressWithType peer,AddressWithType resolved_peer,AddressWithType local_address)100 bool AclConnectionHandler::CreatePendingLeConnection(AddressWithType peer,
101 AddressWithType resolved_peer,
102 AddressWithType local_address) {
103 for (auto pair : acl_connections_) {
104 auto connection = std::get<AclConnection>(pair);
105 if (connection.GetAddress() == peer || connection.GetResolvedAddress() == resolved_peer) {
106 INFO("{}: {} is already connected", __func__, peer);
107 if (connection.GetResolvedAddress() == resolved_peer) {
108 INFO("{}: allowing a second connection with {}", __func__, resolved_peer);
109 } else {
110 return false;
111 }
112 }
113 }
114 if (le_connection_pending_) {
115 INFO("{}: connection already pending", __func__);
116 return false;
117 }
118 le_connection_pending_ = true;
119 pending_le_connection_address_ = peer;
120 pending_le_connection_own_address_ = local_address;
121 pending_le_connection_resolved_address_ = resolved_peer;
122 return true;
123 }
124
HasPendingLeConnection(AddressWithType addr) const125 bool AclConnectionHandler::HasPendingLeConnection(AddressWithType addr) const {
126 return le_connection_pending_ && pending_le_connection_address_ == addr;
127 }
128
CancelPendingLeConnection(AddressWithType addr)129 bool AclConnectionHandler::CancelPendingLeConnection(AddressWithType addr) {
130 if (!le_connection_pending_ || pending_le_connection_address_ != addr) {
131 return false;
132 }
133 le_connection_pending_ = false;
134 pending_le_connection_address_ =
135 AddressWithType{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
136 pending_le_connection_resolved_address_ =
137 AddressWithType{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
138 return true;
139 }
140
CreateConnection(Address addr,Address own_addr,bool pending)141 uint16_t AclConnectionHandler::CreateConnection(Address addr, Address own_addr, bool pending) {
142 if (!pending || CancelPendingConnection(addr)) {
143 uint16_t handle = GetUnusedHandle();
144 acl_connections_.emplace(
145 handle,
146 AclConnection{AddressWithType{addr, AddressType::PUBLIC_DEVICE_ADDRESS},
147 AddressWithType{own_addr, AddressType::PUBLIC_DEVICE_ADDRESS},
148 AddressWithType(), Phy::Type::BR_EDR, bluetooth::hci::Role::CENTRAL});
149 return handle;
150 }
151 return kReservedHandle;
152 }
153
CreateLeConnection(AddressWithType addr,AddressWithType own_addr,bluetooth::hci::Role role)154 uint16_t AclConnectionHandler::CreateLeConnection(AddressWithType addr, AddressWithType own_addr,
155 bluetooth::hci::Role role) {
156 AddressWithType resolved_peer = pending_le_connection_resolved_address_;
157 if (CancelPendingLeConnection(addr)) {
158 uint16_t handle = GetUnusedHandle();
159 acl_connections_.emplace(
160 handle, AclConnection{addr, own_addr, resolved_peer, Phy::Type::LOW_ENERGY, role});
161 return handle;
162 }
163 return kReservedHandle;
164 }
165
Disconnect(uint16_t handle,std::function<void (TaskId)> stopStream)166 bool AclConnectionHandler::Disconnect(uint16_t handle, std::function<void(TaskId)> stopStream) {
167 if (HasScoHandle(handle)) {
168 sco_connections_.at(handle).StopStream(std::move(stopStream));
169 sco_connections_.erase(handle);
170 return true;
171 }
172 if (HasHandle(handle)) {
173 // It is the responsibility of the caller to remove SCO connections
174 // with connected peer first.
175 uint16_t sco_handle = GetScoHandle(GetAddress(handle).GetAddress());
176 ASSERT(!HasScoHandle(sco_handle));
177 acl_connections_.erase(handle);
178 return true;
179 }
180 return false;
181 }
182
GetHandle(AddressWithType addr) const183 uint16_t AclConnectionHandler::GetHandle(AddressWithType addr) const {
184 for (auto pair : acl_connections_) {
185 if (std::get<AclConnection>(pair).GetAddress() == addr) {
186 return std::get<0>(pair);
187 }
188 }
189 return kReservedHandle;
190 }
191
GetHandleOnlyAddress(bluetooth::hci::Address addr) const192 uint16_t AclConnectionHandler::GetHandleOnlyAddress(bluetooth::hci::Address addr) const {
193 for (auto pair : acl_connections_) {
194 if (std::get<AclConnection>(pair).GetAddress().GetAddress() == addr) {
195 return std::get<0>(pair);
196 }
197 }
198 return kReservedHandle;
199 }
200
GetAclConnectionHandle(bluetooth::hci::Address bd_addr) const201 std::optional<uint16_t> AclConnectionHandler::GetAclConnectionHandle(
202 bluetooth::hci::Address bd_addr) const {
203 for (auto const& [handle, connection] : acl_connections_) {
204 if (connection.GetAddress().GetAddress() == bd_addr &&
205 connection.GetPhyType() == Phy::Type::BR_EDR) {
206 return handle;
207 }
208 }
209 return {};
210 }
211
GetAclConnection(uint16_t handle)212 AclConnection& AclConnectionHandler::GetAclConnection(uint16_t handle) {
213 ASSERT_LOG(HasHandle(handle), "Unknown handle %d", handle);
214 return acl_connections_.at(handle);
215 }
216
GetAddress(uint16_t handle) const217 AddressWithType AclConnectionHandler::GetAddress(uint16_t handle) const {
218 ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle);
219 return acl_connections_.at(handle).GetAddress();
220 }
221
GetAddressSafe(uint16_t handle) const222 std::optional<AddressWithType> AclConnectionHandler::GetAddressSafe(uint16_t handle) const {
223 return HasHandle(handle) ? acl_connections_.at(handle).GetAddress()
224 : std::optional<AddressWithType>();
225 }
226
GetScoAddress(uint16_t handle) const227 Address AclConnectionHandler::GetScoAddress(uint16_t handle) const {
228 ASSERT_LOG(HasScoHandle(handle), "Unknown SCO handle %hd", handle);
229 return sco_connections_.at(handle).GetAddress();
230 }
231
GetOwnAddress(uint16_t handle) const232 AddressWithType AclConnectionHandler::GetOwnAddress(uint16_t handle) const {
233 ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle);
234 return acl_connections_.at(handle).GetOwnAddress();
235 }
236
GetResolvedAddress(uint16_t handle) const237 AddressWithType AclConnectionHandler::GetResolvedAddress(uint16_t handle) const {
238 ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle);
239 return acl_connections_.at(handle).GetResolvedAddress();
240 }
241
Encrypt(uint16_t handle)242 void AclConnectionHandler::Encrypt(uint16_t handle) {
243 if (!HasHandle(handle)) {
244 return;
245 }
246 acl_connections_.at(handle).Encrypt();
247 }
248
IsEncrypted(uint16_t handle) const249 bool AclConnectionHandler::IsEncrypted(uint16_t handle) const {
250 if (!HasHandle(handle)) {
251 return false;
252 }
253 return acl_connections_.at(handle).IsEncrypted();
254 }
255
SetRssi(uint16_t handle,int8_t rssi)256 void AclConnectionHandler::SetRssi(uint16_t handle, int8_t rssi) {
257 if (HasHandle(handle)) {
258 acl_connections_.at(handle).SetRssi(rssi);
259 }
260 }
261
GetRssi(uint16_t handle) const262 int8_t AclConnectionHandler::GetRssi(uint16_t handle) const {
263 return HasHandle(handle) ? acl_connections_.at(handle).GetRssi() : 0;
264 }
265
GetPhyType(uint16_t handle) const266 Phy::Type AclConnectionHandler::GetPhyType(uint16_t handle) const {
267 if (!HasHandle(handle)) {
268 return Phy::Type::BR_EDR;
269 }
270 return acl_connections_.at(handle).GetPhyType();
271 }
272
GetAclLinkPolicySettings(uint16_t handle) const273 uint16_t AclConnectionHandler::GetAclLinkPolicySettings(uint16_t handle) const {
274 return acl_connections_.at(handle).GetLinkPolicySettings();
275 }
276
SetAclLinkPolicySettings(uint16_t handle,uint16_t settings)277 void AclConnectionHandler::SetAclLinkPolicySettings(uint16_t handle, uint16_t settings) {
278 acl_connections_.at(handle).SetLinkPolicySettings(settings);
279 }
280
GetAclRole(uint16_t handle) const281 bluetooth::hci::Role AclConnectionHandler::GetAclRole(uint16_t handle) const {
282 return acl_connections_.at(handle).GetRole();
283 }
284
SetAclRole(uint16_t handle,bluetooth::hci::Role role)285 void AclConnectionHandler::SetAclRole(uint16_t handle, bluetooth::hci::Role role) {
286 acl_connections_.at(handle).SetRole(role);
287 }
288
CreateScoConnection(bluetooth::hci::Address addr,ScoConnectionParameters const & parameters,ScoState state,ScoDatapath datapath,bool legacy)289 void AclConnectionHandler::CreateScoConnection(bluetooth::hci::Address addr,
290 ScoConnectionParameters const& parameters,
291 ScoState state, ScoDatapath datapath, bool legacy) {
292 uint16_t sco_handle = GetUnusedHandle();
293 sco_connections_.emplace(sco_handle, ScoConnection(addr, parameters, state, datapath, legacy));
294 }
295
HasPendingScoConnection(bluetooth::hci::Address addr) const296 bool AclConnectionHandler::HasPendingScoConnection(bluetooth::hci::Address addr) const {
297 for (const auto& pair : sco_connections_) {
298 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
299 ScoState state = std::get<ScoConnection>(pair).GetState();
300 return state == SCO_STATE_PENDING || state == SCO_STATE_SENT_ESCO_CONNECTION_REQUEST ||
301 state == SCO_STATE_SENT_SCO_CONNECTION_REQUEST;
302 }
303 }
304 return false;
305 }
306
GetScoConnectionState(bluetooth::hci::Address addr) const307 ScoState AclConnectionHandler::GetScoConnectionState(bluetooth::hci::Address addr) const {
308 for (const auto& pair : sco_connections_) {
309 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
310 return std::get<ScoConnection>(pair).GetState();
311 }
312 }
313 return SCO_STATE_CLOSED;
314 }
315
IsLegacyScoConnection(bluetooth::hci::Address addr) const316 bool AclConnectionHandler::IsLegacyScoConnection(bluetooth::hci::Address addr) const {
317 for (const auto& pair : sco_connections_) {
318 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
319 return std::get<ScoConnection>(pair).IsLegacy();
320 }
321 }
322 return false;
323 }
324
CancelPendingScoConnection(bluetooth::hci::Address addr)325 void AclConnectionHandler::CancelPendingScoConnection(bluetooth::hci::Address addr) {
326 for (auto it = sco_connections_.begin(); it != sco_connections_.end(); it++) {
327 if (std::get<ScoConnection>(*it).GetAddress() == addr) {
328 sco_connections_.erase(it);
329 return;
330 }
331 }
332 }
333
AcceptPendingScoConnection(bluetooth::hci::Address addr,ScoLinkParameters const & parameters,std::function<TaskId ()> startStream)334 bool AclConnectionHandler::AcceptPendingScoConnection(bluetooth::hci::Address addr,
335 ScoLinkParameters const& parameters,
336 std::function<TaskId()> startStream) {
337 for (auto& pair : sco_connections_) {
338 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
339 std::get<ScoConnection>(pair).SetLinkParameters(parameters);
340 std::get<ScoConnection>(pair).SetState(ScoState::SCO_STATE_OPENED);
341 std::get<ScoConnection>(pair).StartStream(std::move(startStream));
342 return true;
343 }
344 }
345 return false;
346 }
347
AcceptPendingScoConnection(bluetooth::hci::Address addr,ScoConnectionParameters const & parameters,std::function<TaskId ()> startStream)348 bool AclConnectionHandler::AcceptPendingScoConnection(bluetooth::hci::Address addr,
349 ScoConnectionParameters const& parameters,
350 std::function<TaskId()> startStream) {
351 for (auto& pair : sco_connections_) {
352 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
353 bool ok = std::get<ScoConnection>(pair).NegotiateLinkParameters(parameters);
354 std::get<ScoConnection>(pair).SetState(ok ? ScoState::SCO_STATE_OPENED
355 : ScoState::SCO_STATE_CLOSED);
356 if (ok) {
357 std::get<ScoConnection>(pair).StartStream(std::move(startStream));
358 }
359 return ok;
360 }
361 }
362 return false;
363 }
364
GetScoHandle(bluetooth::hci::Address addr) const365 uint16_t AclConnectionHandler::GetScoHandle(bluetooth::hci::Address addr) const {
366 for (const auto& pair : sco_connections_) {
367 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
368 return std::get<0>(pair);
369 }
370 }
371 return kReservedHandle;
372 }
373
GetScoConnectionParameters(bluetooth::hci::Address addr) const374 ScoConnectionParameters AclConnectionHandler::GetScoConnectionParameters(
375 bluetooth::hci::Address addr) const {
376 for (const auto& pair : sco_connections_) {
377 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
378 return std::get<ScoConnection>(pair).GetConnectionParameters();
379 }
380 }
381 return {};
382 }
383
GetScoLinkParameters(bluetooth::hci::Address addr) const384 ScoLinkParameters AclConnectionHandler::GetScoLinkParameters(bluetooth::hci::Address addr) const {
385 for (const auto& pair : sco_connections_) {
386 if (std::get<ScoConnection>(pair).GetAddress() == addr) {
387 return std::get<ScoConnection>(pair).GetLinkParameters();
388 }
389 }
390 return {};
391 }
392
GetAclHandles() const393 std::vector<uint16_t> AclConnectionHandler::GetAclHandles() const {
394 std::vector<uint16_t> keys(acl_connections_.size());
395
396 for (const auto& pair : acl_connections_) {
397 keys.push_back(pair.first);
398 }
399 return keys;
400 }
401
ResetLinkTimer(uint16_t handle)402 void AclConnectionHandler::ResetLinkTimer(uint16_t handle) {
403 acl_connections_.at(handle).ResetLinkTimer();
404 }
405
TimeUntilLinkNearExpiring(uint16_t handle) const406 std::chrono::steady_clock::duration AclConnectionHandler::TimeUntilLinkNearExpiring(
407 uint16_t handle) const {
408 return acl_connections_.at(handle).TimeUntilNearExpiring();
409 }
410
IsLinkNearExpiring(uint16_t handle) const411 bool AclConnectionHandler::IsLinkNearExpiring(uint16_t handle) const {
412 return acl_connections_.at(handle).IsNearExpiring();
413 }
414
TimeUntilLinkExpired(uint16_t handle) const415 std::chrono::steady_clock::duration AclConnectionHandler::TimeUntilLinkExpired(
416 uint16_t handle) const {
417 return acl_connections_.at(handle).TimeUntilExpired();
418 }
419
HasLinkExpired(uint16_t handle) const420 bool AclConnectionHandler::HasLinkExpired(uint16_t handle) const {
421 return acl_connections_.at(handle).HasExpired();
422 }
423
IsRoleSwitchAllowedForPendingConnection() const424 bool AclConnectionHandler::IsRoleSwitchAllowedForPendingConnection() const {
425 return pending_classic_connection_allow_role_switch_;
426 }
427
428 } // namespace rootcanal
429