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