• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <memory>
17 #include <unordered_map>
18 
19 #include "hci/acl_manager.h"
20 #include "hci/address.h"
21 #include "l2cap/internal/scheduler_fifo.h"
22 #include "l2cap/le/internal/link.h"
23 #include "os/handler.h"
24 #include "os/log.h"
25 
26 #include "l2cap/le/internal/link_manager.h"
27 
28 namespace bluetooth {
29 namespace l2cap {
30 namespace le {
31 namespace internal {
32 
ConnectFixedChannelServices(hci::AddressWithType address_with_type,PendingFixedChannelConnection pending_fixed_channel_connection)33 void LinkManager::ConnectFixedChannelServices(hci::AddressWithType address_with_type,
34                                               PendingFixedChannelConnection pending_fixed_channel_connection) {
35   // Check if there is any service registered
36   auto fixed_channel_services = fixed_channel_service_manager_->GetRegisteredServices();
37   if (fixed_channel_services.empty()) {
38     // If so, return error
39     pending_fixed_channel_connection.handler_->Post(common::BindOnce(
40         std::move(pending_fixed_channel_connection.on_fail_callback_),
41         FixedChannelManager::ConnectionResult{
42             .connection_result_code = FixedChannelManager::ConnectionResultCode::FAIL_NO_SERVICE_REGISTERED}));
43     return;
44   }
45   // Otherwise, check if device has an ACL connection
46   auto* link = GetLink(address_with_type);
47   if (link != nullptr) {
48     // If device already have an ACL connection
49     // Check if all registered services have an allocated channel and allocate one if not already allocated
50     int num_new_channels = 0;
51     for (auto& fixed_channel_service : fixed_channel_services) {
52       if (link->IsFixedChannelAllocated(fixed_channel_service.first)) {
53         // This channel is already allocated for this link, do not allocated twice
54         continue;
55       }
56       // Allocate channel for newly registered fixed channels
57       auto fixed_channel_impl = link->AllocateFixedChannel(fixed_channel_service.first, SecurityPolicy());
58       fixed_channel_service.second->NotifyChannelCreation(
59           std::make_unique<FixedChannel>(fixed_channel_impl, l2cap_handler_));
60       num_new_channels++;
61     }
62     // Declare connection failure if no new channels are created
63     if (num_new_channels == 0) {
64       pending_fixed_channel_connection.handler_->Post(common::BindOnce(
65           std::move(pending_fixed_channel_connection.on_fail_callback_),
66           FixedChannelManager::ConnectionResult{
67               .connection_result_code = FixedChannelManager::ConnectionResultCode::FAIL_ALL_SERVICES_HAVE_CHANNEL}));
68     }
69     // No need to create ACL connection, return without saving any pending connections
70     return;
71   }
72   // If not, create new ACL connection
73   // Add request to pending link list first
74   auto pending_link = pending_links_.find(address_with_type);
75   if (pending_link == pending_links_.end()) {
76     // Create pending link if not exist
77     pending_links_.try_emplace(address_with_type);
78     pending_link = pending_links_.find(address_with_type);
79   }
80   pending_link->second.pending_fixed_channel_connections_.push_back(std::move(pending_fixed_channel_connection));
81   // Then create new ACL connection
82   acl_manager_->CreateLeConnection(address_with_type);
83 }
84 
ConnectDynamicChannelServices(hci::AddressWithType device,Link::PendingDynamicChannelConnection pending_dynamic_channel_connection,Psm psm)85 void LinkManager::ConnectDynamicChannelServices(
86     hci::AddressWithType device, Link::PendingDynamicChannelConnection pending_dynamic_channel_connection, Psm psm) {
87   auto* link = GetLink(device);
88   if (link == nullptr) {
89     acl_manager_->CreateLeConnection(device);
90     pending_dynamic_channels_[device].push_back(std::make_pair(psm, std::move(pending_dynamic_channel_connection)));
91     return;
92   }
93   link->SendConnectionRequest(psm, std::move(pending_dynamic_channel_connection));
94 }
95 
GetLink(hci::AddressWithType address_with_type)96 Link* LinkManager::GetLink(hci::AddressWithType address_with_type) {
97   if (links_.find(address_with_type) == links_.end()) {
98     return nullptr;
99   }
100   return &links_.find(address_with_type)->second;
101 }
102 
OnLeConnectSuccess(hci::AddressWithType connecting_address_with_type,std::unique_ptr<hci::AclConnection> acl_connection)103 void LinkManager::OnLeConnectSuccess(hci::AddressWithType connecting_address_with_type,
104                                      std::unique_ptr<hci::AclConnection> acl_connection) {
105   // Same link should not be connected twice
106   hci::AddressWithType connected_address_with_type(acl_connection->GetAddress(), acl_connection->GetAddressType());
107   ASSERT_LOG(GetLink(connected_address_with_type) == nullptr, "%s is connected twice without disconnection",
108              acl_connection->GetAddress().ToString().c_str());
109   // Register ACL disconnection callback in LinkManager so that we can clean up link resource properly
110   acl_connection->RegisterDisconnectCallback(
111       common::BindOnce(&LinkManager::OnDisconnect, common::Unretained(this), connected_address_with_type),
112       l2cap_handler_);
113   links_.try_emplace(connected_address_with_type, l2cap_handler_, std::move(acl_connection), parameter_provider_,
114                      dynamic_channel_service_manager_, fixed_channel_service_manager_);
115   auto* link = GetLink(connected_address_with_type);
116   // Allocate and distribute channels for all registered fixed channel services
117   auto fixed_channel_services = fixed_channel_service_manager_->GetRegisteredServices();
118   for (auto& fixed_channel_service : fixed_channel_services) {
119     auto fixed_channel_impl = link->AllocateFixedChannel(fixed_channel_service.first, SecurityPolicy());
120     fixed_channel_service.second->NotifyChannelCreation(
121         std::make_unique<FixedChannel>(fixed_channel_impl, l2cap_handler_));
122   }
123   if (pending_dynamic_channels_.find(connected_address_with_type) != pending_dynamic_channels_.end()) {
124     for (auto& psm_callback : pending_dynamic_channels_[connected_address_with_type]) {
125       link->SendConnectionRequest(psm_callback.first, std::move(psm_callback.second));
126     }
127     pending_dynamic_channels_.erase(connected_address_with_type);
128   }
129 
130   // Remove device from pending links list, if any
131   auto pending_link = pending_links_.find(connecting_address_with_type);
132   if (pending_link == pending_links_.end()) {
133     // This an incoming connection, exit
134     return;
135   }
136   // This is an outgoing connection, remove entry in pending link list
137   pending_links_.erase(pending_link);
138 }
139 
OnLeConnectFail(hci::AddressWithType address_with_type,hci::ErrorCode reason)140 void LinkManager::OnLeConnectFail(hci::AddressWithType address_with_type, hci::ErrorCode reason) {
141   // Notify all pending links for this device
142   auto pending_link = pending_links_.find(address_with_type);
143   if (pending_link == pending_links_.end()) {
144     // There is no pending link, exit
145     LOG_DEBUG("Connection to %s failed without a pending link", address_with_type.ToString().c_str());
146     return;
147   }
148   for (auto& pending_fixed_channel_connection : pending_link->second.pending_fixed_channel_connections_) {
149     pending_fixed_channel_connection.handler_->Post(common::BindOnce(
150         std::move(pending_fixed_channel_connection.on_fail_callback_),
151         FixedChannelManager::ConnectionResult{
152             .connection_result_code = FixedChannelManager::ConnectionResultCode::FAIL_HCI_ERROR, .hci_error = reason}));
153   }
154   // Remove entry in pending link list
155   pending_links_.erase(pending_link);
156 }
157 
OnDisconnect(hci::AddressWithType address_with_type,hci::ErrorCode status)158 void LinkManager::OnDisconnect(hci::AddressWithType address_with_type, hci::ErrorCode status) {
159   auto* link = GetLink(address_with_type);
160   ASSERT_LOG(link != nullptr, "Device %s is disconnected with reason 0x%x, but not in local database",
161              address_with_type.ToString().c_str(), static_cast<uint8_t>(status));
162   link->OnAclDisconnected(status);
163   links_.erase(address_with_type);
164 }
165 
166 }  // namespace internal
167 }  // namespace le
168 }  // namespace l2cap
169 }  // namespace bluetooth
170