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