blob: f05a607db133a02e864cbfc25c464cd176eb5145 [file] [log] [blame]
Jack He492dcf72019-09-26 18:27:41 -07001/*
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"
Jack He492dcf72019-09-26 18:27:41 -070021#include "l2cap/internal/scheduler_fifo.h"
Jack Heff38d892019-10-03 17:11:07 -070022#include "l2cap/le/internal/link.h"
Jack He492dcf72019-09-26 18:27:41 -070023#include "os/handler.h"
24#include "os/log.h"
25
Jack Heff38d892019-10-03 17:11:07 -070026#include "l2cap/le/internal/link_manager.h"
Jack He492dcf72019-09-26 18:27:41 -070027
28namespace bluetooth {
29namespace l2cap {
Jack Heff38d892019-10-03 17:11:07 -070030namespace le {
Jack He492dcf72019-09-26 18:27:41 -070031namespace internal {
32
Jack He423b6be2019-10-21 15:03:11 -070033void LinkManager::ConnectFixedChannelServices(hci::AddressWithType address_with_type,
Jack Heff38d892019-10-03 17:11:07 -070034 PendingFixedChannelConnection pending_fixed_channel_connection) {
Jack He492dcf72019-09-26 18:27:41 -070035 // Check if there is any service registered
36 auto fixed_channel_services = 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_),
Jack Heff38d892019-10-03 17:11:07 -070041 FixedChannelManager::ConnectionResult{
42 .connection_result_code = FixedChannelManager::ConnectionResultCode::FAIL_NO_SERVICE_REGISTERED}));
Jack He492dcf72019-09-26 18:27:41 -070043 return;
44 }
45 // Otherwise, check if device has an ACL connection
Jack He423b6be2019-10-21 15:03:11 -070046 auto* link = GetLink(address_with_type);
Jack He492dcf72019-09-26 18:27:41 -070047 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(
Jack Heff38d892019-10-03 17:11:07 -070059 std::make_unique<FixedChannel>(fixed_channel_impl, l2cap_handler_));
Jack He492dcf72019-09-26 18:27:41 -070060 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_),
Jack Heff38d892019-10-03 17:11:07 -070066 FixedChannelManager::ConnectionResult{
67 .connection_result_code = FixedChannelManager::ConnectionResultCode::FAIL_ALL_SERVICES_HAVE_CHANNEL}));
Jack He492dcf72019-09-26 18:27:41 -070068 }
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
Jack He423b6be2019-10-21 15:03:11 -070074 auto pending_link = pending_links_.find(address_with_type);
Jack He492dcf72019-09-26 18:27:41 -070075 if (pending_link == pending_links_.end()) {
76 // Create pending link if not exist
Jack He423b6be2019-10-21 15:03:11 -070077 pending_links_.try_emplace(address_with_type);
78 pending_link = pending_links_.find(address_with_type);
Jack He492dcf72019-09-26 18:27:41 -070079 }
80 pending_link->second.pending_fixed_channel_connections_.push_back(std::move(pending_fixed_channel_connection));
81 // Then create new ACL connection
Jack He1d4c6df2019-10-21 17:03:18 -070082 acl_manager_->CreateLeConnection(address_with_type);
Jack He492dcf72019-09-26 18:27:41 -070083}
84
Jack He423b6be2019-10-21 15:03:11 -070085Link* LinkManager::GetLink(hci::AddressWithType address_with_type) {
86 if (links_.find(address_with_type) == links_.end()) {
Jack He492dcf72019-09-26 18:27:41 -070087 return nullptr;
88 }
Jack He423b6be2019-10-21 15:03:11 -070089 return &links_.find(address_with_type)->second;
Jack He492dcf72019-09-26 18:27:41 -070090}
91
Jack He1d4c6df2019-10-21 17:03:18 -070092void LinkManager::OnLeConnectSuccess(hci::AddressWithType connecting_address_with_type,
93 std::unique_ptr<hci::AclConnection> acl_connection) {
Jack He492dcf72019-09-26 18:27:41 -070094 // Same link should not be connected twice
Jack He1d4c6df2019-10-21 17:03:18 -070095 hci::AddressWithType connected_address_with_type(acl_connection->GetAddress(), acl_connection->GetAddressType());
96 ASSERT_LOG(GetLink(connected_address_with_type) == nullptr, "%s is connected twice without disconnection",
Jack He492dcf72019-09-26 18:27:41 -070097 acl_connection->GetAddress().ToString().c_str());
98 auto* link_queue_up_end = acl_connection->GetAclQueueEnd();
Jack He1d4c6df2019-10-21 17:03:18 -070099 links_.try_emplace(connected_address_with_type, l2cap_handler_, std::move(acl_connection),
Jack Heff38d892019-10-03 17:11:07 -0700100 std::make_unique<l2cap::internal::Fifo>(link_queue_up_end, l2cap_handler_), parameter_provider_);
Jack He1d4c6df2019-10-21 17:03:18 -0700101 auto* link = GetLink(connected_address_with_type);
Jack He492dcf72019-09-26 18:27:41 -0700102 // Allocate and distribute channels for all registered fixed channel services
103 auto fixed_channel_services = service_manager_->GetRegisteredServices();
104 for (auto& fixed_channel_service : fixed_channel_services) {
105 auto fixed_channel_impl = link->AllocateFixedChannel(fixed_channel_service.first, SecurityPolicy());
106 fixed_channel_service.second->NotifyChannelCreation(
Jack Heff38d892019-10-03 17:11:07 -0700107 std::make_unique<FixedChannel>(fixed_channel_impl, l2cap_handler_));
Jack He492dcf72019-09-26 18:27:41 -0700108 }
109 // Remove device from pending links list, if any
Jack He1d4c6df2019-10-21 17:03:18 -0700110 auto pending_link = pending_links_.find(connecting_address_with_type);
Jack He492dcf72019-09-26 18:27:41 -0700111 if (pending_link == pending_links_.end()) {
112 // This an incoming connection, exit
113 return;
114 }
115 // This is an outgoing connection, remove entry in pending link list
116 pending_links_.erase(pending_link);
117}
118
Jack He1d4c6df2019-10-21 17:03:18 -0700119void LinkManager::OnLeConnectFail(hci::AddressWithType address_with_type, hci::ErrorCode reason) {
Jack He492dcf72019-09-26 18:27:41 -0700120 // Notify all pending links for this device
Jack He423b6be2019-10-21 15:03:11 -0700121 auto pending_link = pending_links_.find(address_with_type);
Jack He492dcf72019-09-26 18:27:41 -0700122 if (pending_link == pending_links_.end()) {
123 // There is no pending link, exit
Jack He423b6be2019-10-21 15:03:11 -0700124 LOG_DEBUG("Connection to %s failed without a pending link", address_with_type.ToString().c_str());
Jack He492dcf72019-09-26 18:27:41 -0700125 return;
126 }
127 for (auto& pending_fixed_channel_connection : pending_link->second.pending_fixed_channel_connections_) {
Jack Heff38d892019-10-03 17:11:07 -0700128 pending_fixed_channel_connection.handler_->Post(common::BindOnce(
129 std::move(pending_fixed_channel_connection.on_fail_callback_),
130 FixedChannelManager::ConnectionResult{
131 .connection_result_code = FixedChannelManager::ConnectionResultCode::FAIL_HCI_ERROR, .hci_error = reason}));
Jack He492dcf72019-09-26 18:27:41 -0700132 }
133 // Remove entry in pending link list
134 pending_links_.erase(pending_link);
135}
136
Jack He423b6be2019-10-21 15:03:11 -0700137void LinkManager::OnDisconnect(hci::AddressWithType address_with_type, hci::ErrorCode status) {
138 auto* link = GetLink(address_with_type);
Jack He492dcf72019-09-26 18:27:41 -0700139 ASSERT_LOG(link != nullptr, "Device %s is disconnected with reason 0x%x, but not in local database",
Jack He423b6be2019-10-21 15:03:11 -0700140 address_with_type.ToString().c_str(), static_cast<uint8_t>(status));
Jack He492dcf72019-09-26 18:27:41 -0700141 link->OnAclDisconnected(status);
Jack He423b6be2019-10-21 15:03:11 -0700142 links_.erase(address_with_type);
Jack He492dcf72019-09-26 18:27:41 -0700143}
144
145} // namespace internal
Jack Heff38d892019-10-03 17:11:07 -0700146} // namespace le
Jack He492dcf72019-09-26 18:27:41 -0700147} // namespace l2cap
148} // namespace bluetooth