1 /*
2  * Copyright 2019 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 #include "l2cap/le/internal/link_manager.h"
17 
18 #include <bluetooth/log.h>
19 
20 #include <memory>
21 #include <unordered_map>
22 
23 #include "hci/acl_manager/le_acl_connection.h"
24 #include "hci/address.h"
25 #include "l2cap/internal/scheduler_fifo.h"
26 #include "l2cap/le/internal/link.h"
27 #include "os/handler.h"
28 #include "os/log.h"
29 
30 namespace bluetooth {
31 namespace l2cap {
32 namespace le {
33 namespace internal {
34 
ConnectFixedChannelServices(hci::AddressWithType address_with_type,PendingFixedChannelConnection pending_fixed_channel_connection)35 void LinkManager::ConnectFixedChannelServices(hci::AddressWithType address_with_type,
36                                               PendingFixedChannelConnection pending_fixed_channel_connection) {
37   // Check if there is any service registered
38   auto fixed_channel_services = fixed_channel_service_manager_->GetRegisteredServices();
39   if (fixed_channel_services.empty()) {
40     // If so, return error
41     pending_fixed_channel_connection.handler_->Post(common::BindOnce(
42         std::move(pending_fixed_channel_connection.on_fail_callback_),
43         FixedChannelManager::ConnectionResult{
44             .connection_result_code = FixedChannelManager::ConnectionResultCode::FAIL_NO_SERVICE_REGISTERED}));
45     return;
46   }
47   // Otherwise, check if device has an ACL connection
48   auto* link = GetLink(address_with_type);
49   if (link != nullptr) {
50     // If device already have an ACL connection
51     // Check if all registered services have an allocated channel and allocate one if not already allocated
52     int num_new_channels = 0;
53     for (auto& fixed_channel_service : fixed_channel_services) {
54       if (link->IsFixedChannelAllocated(fixed_channel_service.first)) {
55         // This channel is already allocated for this link, do not allocated twice
56         continue;
57       }
58       // Allocate channel for newly registered fixed channels
59       auto fixed_channel_impl = link->AllocateFixedChannel(
60           fixed_channel_service.first, SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK);
61       fixed_channel_service.second->NotifyChannelCreation(
62           std::make_unique<FixedChannel>(fixed_channel_impl, l2cap_handler_));
63       num_new_channels++;
64     }
65     // Declare connection failure if no new channels are created
66     if (num_new_channels == 0) {
67       pending_fixed_channel_connection.handler_->Post(common::BindOnce(
68           std::move(pending_fixed_channel_connection.on_fail_callback_),
69           FixedChannelManager::ConnectionResult{
70               .connection_result_code = FixedChannelManager::ConnectionResultCode::FAIL_ALL_SERVICES_HAVE_CHANNEL}));
71     }
72     // No need to create ACL connection, return without saving any pending connections
73     return;
74   }
75   // If not, create new ACL connection
76   // Add request to pending link list first
77   auto pending_link = pending_links_.find(address_with_type);
78   if (pending_link == pending_links_.end()) {
79     // Create pending link if not exist
80     pending_links_.try_emplace(address_with_type);
81     pending_link = pending_links_.find(address_with_type);
82   }
83   pending_link->second.pending_fixed_channel_connections_.push_back(std::move(pending_fixed_channel_connection));
84   // Then create new ACL connection
85   acl_manager_->CreateLeConnection(address_with_type, /* is_direct */ true);
86 }
87 
ConnectDynamicChannelServices(hci::AddressWithType device,Link::PendingDynamicChannelConnection pending_dynamic_channel_connection,Psm psm)88 void LinkManager::ConnectDynamicChannelServices(
89     hci::AddressWithType device, Link::PendingDynamicChannelConnection pending_dynamic_channel_connection, Psm psm) {
90   auto* link = GetLink(device);
91   if (link == nullptr) {
92     acl_manager_->CreateLeConnection(device, /* is_direct */ true);
93     pending_dynamic_channels_[device].push_back(std::make_pair(psm, std::move(pending_dynamic_channel_connection)));
94     return;
95   }
96   link->SendConnectionRequest(psm, std::move(pending_dynamic_channel_connection));
97 }
98 
GetLink(hci::AddressWithType address_with_type)99 Link* LinkManager::GetLink(hci::AddressWithType address_with_type) {
100   if (links_.find(address_with_type) == links_.end()) {
101     return nullptr;
102   }
103   return &links_.find(address_with_type)->second;
104 }
105 
OnLeConnectSuccess(hci::AddressWithType connecting_address_with_type,std::unique_ptr<hci::acl_manager::LeAclConnection> acl_connection)106 void LinkManager::OnLeConnectSuccess(hci::AddressWithType connecting_address_with_type,
107                                      std::unique_ptr<hci::acl_manager::LeAclConnection> acl_connection) {
108   // Same link should not be connected twice
109   hci::AddressWithType connected_address_with_type = acl_connection->GetRemoteAddress();
110   uint16_t handle = acl_connection->GetHandle();
111   log::assert_that(
112       GetLink(connected_address_with_type) == nullptr,
113       "{} is connected twice without disconnection",
114       ADDRESS_TO_LOGGABLE_CSTR(acl_connection->GetRemoteAddress()));
115   links_.try_emplace(connected_address_with_type, l2cap_handler_, std::move(acl_connection), parameter_provider_,
116                      dynamic_channel_service_manager_, fixed_channel_service_manager_, this);
117   auto* link = GetLink(connected_address_with_type);
118 
119   if (link_property_callback_handler_ != nullptr) {
120     link_property_callback_handler_->CallOn(
121         link_property_listener_,
122         &LinkPropertyListener::OnLinkConnected,
123         connected_address_with_type,
124         handle,
125         link->GetRole());
126   }
127 
128   // Remove device from pending links list, if any
129   pending_links_.erase(connecting_address_with_type);
130 
131   link->ReadRemoteVersionInformation();
132 }
133 
OnLeConnectFail(hci::AddressWithType address_with_type,hci::ErrorCode reason)134 void LinkManager::OnLeConnectFail(hci::AddressWithType address_with_type, hci::ErrorCode reason) {
135   // Notify all pending links for this device
136   auto pending_link = pending_links_.find(address_with_type);
137   if (pending_link == pending_links_.end()) {
138     // There is no pending link, exit
139     log::info("Connection to {} failed without a pending link", address_with_type);
140     return;
141   }
142   for (auto& pending_fixed_channel_connection : pending_link->second.pending_fixed_channel_connections_) {
143     pending_fixed_channel_connection.handler_->Post(common::BindOnce(
144         std::move(pending_fixed_channel_connection.on_fail_callback_),
145         FixedChannelManager::ConnectionResult{
146             .connection_result_code = FixedChannelManager::ConnectionResultCode::FAIL_HCI_ERROR, .hci_error = reason}));
147   }
148   // Remove entry in pending link list
149   pending_links_.erase(pending_link);
150 }
151 
OnDisconnect(bluetooth::hci::AddressWithType address_with_type)152 void LinkManager::OnDisconnect(bluetooth::hci::AddressWithType address_with_type) {
153   auto* link = GetLink(address_with_type);
154   log::assert_that(
155       link != nullptr,
156       "Device {} is disconnected but not in local database",
157       ADDRESS_TO_LOGGABLE_CSTR(address_with_type));
158   if (links_with_pending_packets_.count(address_with_type) != 0) {
159     disconnected_links_.emplace(address_with_type);
160   } else {
161     links_.erase(address_with_type);
162   }
163 
164   if (link_property_callback_handler_ != nullptr) {
165     link_property_callback_handler_->CallOn(
166         link_property_listener_, &LinkPropertyListener::OnLinkDisconnected, address_with_type);
167   }
168 }
169 
RegisterLinkPropertyListener(os::Handler * handler,LinkPropertyListener * listener)170 void LinkManager::RegisterLinkPropertyListener(os::Handler* handler, LinkPropertyListener* listener) {
171   link_property_callback_handler_ = handler;
172   link_property_listener_ = listener;
173 }
174 
OnReadRemoteVersionInformationComplete(hci::ErrorCode hci_status,hci::AddressWithType address_with_type,uint8_t lmp_version,uint16_t manufacturer_name,uint16_t sub_version)175 void LinkManager::OnReadRemoteVersionInformationComplete(
176     hci::ErrorCode hci_status,
177     hci::AddressWithType address_with_type,
178     uint8_t lmp_version,
179     uint16_t manufacturer_name,
180     uint16_t sub_version) {
181   if (link_property_callback_handler_ != nullptr) {
182     link_property_callback_handler_->CallOn(
183         link_property_listener_,
184         &LinkPropertyListener::OnReadRemoteVersionInformation,
185         hci_status,
186         address_with_type,
187         lmp_version,
188         manufacturer_name,
189         sub_version);
190   }
191 
192   auto* link = GetLink(address_with_type);
193   // Allocate and distribute channels for all registered fixed channel services
194   auto fixed_channel_services = fixed_channel_service_manager_->GetRegisteredServices();
195   for (auto& fixed_channel_service : fixed_channel_services) {
196     auto fixed_channel_impl = link->AllocateFixedChannel(
197         fixed_channel_service.first, SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK);
198     fixed_channel_service.second->NotifyChannelCreation(
199         std::make_unique<FixedChannel>(fixed_channel_impl, l2cap_handler_));
200   }
201   if (pending_dynamic_channels_.find(address_with_type) != pending_dynamic_channels_.end()) {
202     for (auto& psm_callback : pending_dynamic_channels_[address_with_type]) {
203       link->SendConnectionRequest(psm_callback.first, std::move(psm_callback.second));
204     }
205     pending_dynamic_channels_.erase(address_with_type);
206   }
207 }
208 
OnPendingPacketChange(hci::AddressWithType remote,int num_packets)209 void LinkManager::OnPendingPacketChange(hci::AddressWithType remote, int num_packets) {
210   if (disconnected_links_.count(remote) != 0 && num_packets == 0) {
211     links_.erase(remote);
212     links_with_pending_packets_.erase(remote);
213   } else if (num_packets != 0) {
214     links_with_pending_packets_.emplace(remote);
215   } else {
216     links_with_pending_packets_.erase(remote);
217   }
218 }
219 
220 }  // namespace internal
221 }  // namespace le
222 }  // namespace l2cap
223 }  // namespace bluetooth
224