blob: ed58bdac83dfd09df03301e9f16fc9d95869a735 [file] [log] [blame]
Hansong Zhang6c14ebc2019-12-03 11:17:37 -08001/*
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
17#include <chrono>
18#include <memory>
19
20#include "hci/acl_manager.h"
21#include "l2cap/internal/dynamic_channel_impl.h"
22#include "l2cap/internal/parameter_provider.h"
23#include "l2cap/le/dynamic_channel_manager.h"
24#include "l2cap/le/internal/fixed_channel_impl.h"
25#include "l2cap/le/internal/link.h"
26#include "os/alarm.h"
27
28namespace bluetooth {
29namespace l2cap {
30namespace le {
31namespace internal {
32
33Link::Link(os::Handler* l2cap_handler, std::unique_ptr<hci::AclConnection> acl_connection,
34 l2cap::internal::ParameterProvider* parameter_provider,
35 DynamicChannelServiceManagerImpl* dynamic_service_manager,
36 FixedChannelServiceManagerImpl* fixed_service_manager)
37 : l2cap_handler_(l2cap_handler), acl_connection_(std::move(acl_connection)),
38 data_pipeline_manager_(l2cap_handler, this, acl_connection_->GetAclQueueEnd()),
39 parameter_provider_(parameter_provider), dynamic_service_manager_(dynamic_service_manager),
Hansong Zhangfc1e67b2019-11-26 10:55:51 -080040 signalling_manager_(l2cap_handler_, this, &data_pipeline_manager_, dynamic_service_manager_,
41 &dynamic_channel_allocator_) {
Hansong Zhang6c14ebc2019-12-03 11:17:37 -080042 ASSERT(l2cap_handler_ != nullptr);
43 ASSERT(acl_connection_ != nullptr);
44 ASSERT(parameter_provider_ != nullptr);
45 link_idle_disconnect_alarm_.Schedule(common::BindOnce(&Link::Disconnect, common::Unretained(this)),
46 parameter_provider_->GetLeLinkIdleDisconnectTimeout());
47}
48
49void Link::OnAclDisconnected(hci::ErrorCode status) {
50 fixed_channel_allocator_.OnAclDisconnected(status);
51 dynamic_channel_allocator_.OnAclDisconnected(status);
52}
53
54void Link::Disconnect() {
55 acl_connection_->Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION);
56}
57
58std::shared_ptr<FixedChannelImpl> Link::AllocateFixedChannel(Cid cid, SecurityPolicy security_policy) {
59 auto channel = fixed_channel_allocator_.AllocateChannel(cid, security_policy);
Hansong Zhangfc1e67b2019-11-26 10:55:51 -080060 data_pipeline_manager_.AttachChannel(cid, channel,
61 l2cap::internal::DataPipelineManager::ChannelMode::LE_CREDIT_BASED);
Hansong Zhang6c14ebc2019-12-03 11:17:37 -080062 return channel;
63}
64
65bool Link::IsFixedChannelAllocated(Cid cid) {
66 return fixed_channel_allocator_.IsChannelAllocated(cid);
67}
68
69Cid Link::ReserveDynamicChannel() {
70 return dynamic_channel_allocator_.ReserveChannel();
71}
72
73void Link::SendConnectionRequest(Psm psm, PendingDynamicChannelConnection pending_dynamic_channel_connection) {
74 if (dynamic_channel_allocator_.IsPsmUsed(psm)) {
75 LOG_INFO("Psm %d is already connected", psm);
76 return;
77 }
Hansong Zhangfc1e67b2019-11-26 10:55:51 -080078 auto reserved_cid = ReserveDynamicChannel();
79 signalling_manager_.SendConnectionRequest(psm, reserved_cid, pending_dynamic_channel_connection.configuration_.mtu);
Hansong Zhang6c14ebc2019-12-03 11:17:37 -080080}
81
82void Link::SendDisconnectionRequest(Cid local_cid, Cid remote_cid) {
Hansong Zhangfc1e67b2019-11-26 10:55:51 -080083 auto channel = dynamic_channel_allocator_.FindChannelByCid(local_cid);
84 if (channel == nullptr || channel->GetRemoteCid() != remote_cid) {
85 LOG_ERROR("Invalid cid");
86 }
87 signalling_manager_.SendDisconnectRequest(local_cid, remote_cid);
Hansong Zhang6c14ebc2019-12-03 11:17:37 -080088}
89
90std::shared_ptr<l2cap::internal::DynamicChannelImpl> Link::AllocateDynamicChannel(Psm psm, Cid remote_cid,
91 SecurityPolicy security_policy) {
92 auto channel = dynamic_channel_allocator_.AllocateChannel(psm, remote_cid, security_policy);
93 if (channel != nullptr) {
Hansong Zhangfc1e67b2019-11-26 10:55:51 -080094 data_pipeline_manager_.AttachChannel(channel->GetCid(), channel,
95 l2cap::internal::DataPipelineManager::ChannelMode::LE_CREDIT_BASED);
Hansong Zhang6c14ebc2019-12-03 11:17:37 -080096 RefreshRefCount();
Hansong Zhangfc1e67b2019-11-26 10:55:51 -080097 channel->local_initiated_ = false;
Hansong Zhang6c14ebc2019-12-03 11:17:37 -080098 }
Hansong Zhang6c14ebc2019-12-03 11:17:37 -080099 return channel;
100}
101
102std::shared_ptr<l2cap::internal::DynamicChannelImpl> Link::AllocateReservedDynamicChannel(
103 Cid reserved_cid, Psm psm, Cid remote_cid, SecurityPolicy security_policy) {
104 auto channel = dynamic_channel_allocator_.AllocateReservedChannel(reserved_cid, psm, remote_cid, security_policy);
105 if (channel != nullptr) {
Hansong Zhangfc1e67b2019-11-26 10:55:51 -0800106 data_pipeline_manager_.AttachChannel(channel->GetCid(), channel,
107 l2cap::internal::DataPipelineManager::ChannelMode::LE_CREDIT_BASED);
Hansong Zhang6c14ebc2019-12-03 11:17:37 -0800108 RefreshRefCount();
Hansong Zhangfc1e67b2019-11-26 10:55:51 -0800109 channel->local_initiated_ = true;
Hansong Zhang6c14ebc2019-12-03 11:17:37 -0800110 }
Hansong Zhang6c14ebc2019-12-03 11:17:37 -0800111 return channel;
112}
113
114DynamicChannelConfigurationOption Link::GetConfigurationForInitialConfiguration(Cid cid) {
115 ASSERT(local_cid_to_pending_dynamic_channel_connection_map_.find(cid) !=
116 local_cid_to_pending_dynamic_channel_connection_map_.end());
117 return local_cid_to_pending_dynamic_channel_connection_map_[cid].configuration_;
118}
119
120void Link::FreeDynamicChannel(Cid cid) {
121 if (dynamic_channel_allocator_.FindChannelByCid(cid) == nullptr) {
122 return;
123 }
124 data_pipeline_manager_.DetachChannel(cid);
125 dynamic_channel_allocator_.FreeChannel(cid);
126 RefreshRefCount();
127}
128
129void Link::RefreshRefCount() {
130 int ref_count = 0;
131 ref_count += fixed_channel_allocator_.GetRefCount();
132 ref_count += dynamic_channel_allocator_.NumberOfChannels();
133 ASSERT_LOG(ref_count >= 0, "ref_count %d is less than 0", ref_count);
134 if (ref_count > 0) {
135 link_idle_disconnect_alarm_.Cancel();
136 } else {
137 link_idle_disconnect_alarm_.Schedule(common::BindOnce(&Link::Disconnect, common::Unretained(this)),
138 parameter_provider_->GetLeLinkIdleDisconnectTimeout());
139 }
140}
141
142void Link::NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> user_channel) {
143 ASSERT(local_cid_to_pending_dynamic_channel_connection_map_.find(cid) !=
144 local_cid_to_pending_dynamic_channel_connection_map_.end());
145 auto& pending_dynamic_channel_connection = local_cid_to_pending_dynamic_channel_connection_map_[cid];
146 pending_dynamic_channel_connection.handler_->Post(
147 common::BindOnce(std::move(pending_dynamic_channel_connection.on_open_callback_), std::move(user_channel)));
148 local_cid_to_pending_dynamic_channel_connection_map_.erase(cid);
149}
150
151void Link::NotifyChannelFail(Cid cid) {
152 ASSERT(local_cid_to_pending_dynamic_channel_connection_map_.find(cid) !=
153 local_cid_to_pending_dynamic_channel_connection_map_.end());
154 auto& pending_dynamic_channel_connection = local_cid_to_pending_dynamic_channel_connection_map_[cid];
155 // TODO(cmanton) Pass proper connection falure result to user
156 DynamicChannelManager::ConnectionResult result;
157 pending_dynamic_channel_connection.handler_->Post(
158 common::BindOnce(std::move(pending_dynamic_channel_connection.on_fail_callback_), result));
159 local_cid_to_pending_dynamic_channel_connection_map_.erase(cid);
160}
161
Hansong Zhangfc1e67b2019-11-26 10:55:51 -0800162uint16_t Link::GetMps() const {
163 return parameter_provider_->GetLeMps();
164}
165
Hansong Zhang57602a62019-12-04 14:08:40 -0800166uint16_t Link::GetInitialCredit() const {
167 return parameter_provider_->GetLeInitialCredit();
168}
169
170
171void Link::SendLeCredit(Cid local_cid, uint16_t credit) {
172 signalling_manager_.SendCredit(local_cid, credit);
173}
174
Hansong Zhang6c14ebc2019-12-03 11:17:37 -0800175} // namespace internal
176} // namespace le
177} // namespace l2cap
178} // namespace bluetooth