| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 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 |  | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 17 | #include <chrono> | 
 | 18 | #include <memory> | 
 | 19 |  | 
 | 20 | #include "hci/acl_manager.h" | 
| Chris Manton | 6230a6f | 2019-11-13 18:37:33 -0800 | [diff] [blame] | 21 | #include "l2cap/classic/dynamic_channel_manager.h" | 
| Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 22 | #include "l2cap/classic/internal/fixed_channel_impl.h" | 
 | 23 | #include "l2cap/classic/internal/link.h" | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 24 | #include "l2cap/internal/parameter_provider.h" | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 25 | #include "os/alarm.h" | 
 | 26 |  | 
 | 27 | namespace bluetooth { | 
 | 28 | namespace l2cap { | 
| Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 29 | namespace classic { | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 30 | namespace internal { | 
 | 31 |  | 
| Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 32 | Link::Link(os::Handler* l2cap_handler, std::unique_ptr<hci::AclConnection> acl_connection, | 
| Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 33 |            l2cap::internal::ParameterProvider* parameter_provider, | 
 | 34 |            DynamicChannelServiceManagerImpl* dynamic_service_manager, | 
 | 35 |            FixedChannelServiceManagerImpl* fixed_service_manager) | 
| Hansong Zhang | 90603b3 | 2019-11-22 15:11:12 -0800 | [diff] [blame] | 36 |     : l2cap_handler_(l2cap_handler), acl_connection_(std::move(acl_connection)), | 
 | 37 |       data_pipeline_manager_(l2cap_handler, acl_connection_->GetAclQueueEnd()), parameter_provider_(parameter_provider), | 
 | 38 |       dynamic_service_manager_(dynamic_service_manager), fixed_service_manager_(fixed_service_manager), | 
| Hansong Zhang | f0a1692 | 2019-11-22 21:27:08 -0800 | [diff] [blame] | 39 |       signalling_manager_(l2cap_handler_, this, &data_pipeline_manager_, dynamic_service_manager_, | 
 | 40 |                           &dynamic_channel_allocator_, fixed_service_manager_) { | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 41 |   ASSERT(l2cap_handler_ != nullptr); | 
 | 42 |   ASSERT(acl_connection_ != nullptr); | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 43 |   ASSERT(parameter_provider_ != nullptr); | 
| Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 44 |   link_idle_disconnect_alarm_.Schedule(common::BindOnce(&Link::Disconnect, common::Unretained(this)), | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 45 |                                        parameter_provider_->GetClassicLinkIdleDisconnectTimeout()); | 
 | 46 | } | 
 | 47 |  | 
| Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 48 | void Link::OnAclDisconnected(hci::ErrorCode status) { | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 49 |   fixed_channel_allocator_.OnAclDisconnected(status); | 
| Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 50 |   dynamic_channel_allocator_.OnAclDisconnected(status); | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 51 | } | 
 | 52 |  | 
| Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 53 | void Link::Disconnect() { | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 54 |   acl_connection_->Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION); | 
 | 55 | } | 
 | 56 |  | 
| Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 57 | std::shared_ptr<FixedChannelImpl> Link::AllocateFixedChannel(Cid cid, SecurityPolicy security_policy) { | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 58 |   auto channel = fixed_channel_allocator_.AllocateChannel(cid, security_policy); | 
| Hansong Zhang | 90603b3 | 2019-11-22 15:11:12 -0800 | [diff] [blame] | 59 |   data_pipeline_manager_.AttachChannel(cid, channel); | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 60 |   return channel; | 
 | 61 | } | 
 | 62 |  | 
| Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 63 | bool Link::IsFixedChannelAllocated(Cid cid) { | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 64 |   return fixed_channel_allocator_.IsChannelAllocated(cid); | 
 | 65 | } | 
 | 66 |  | 
| Hansong Zhang | d1b6c9b | 2019-10-22 16:11:53 -0700 | [diff] [blame] | 67 | Cid Link::ReserveDynamicChannel() { | 
 | 68 |   return dynamic_channel_allocator_.ReserveChannel(); | 
 | 69 | } | 
 | 70 |  | 
| Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 71 | void Link::SendConnectionRequest(Psm psm, Cid local_cid) { | 
 | 72 |   signalling_manager_.SendConnectionRequest(psm, local_cid); | 
 | 73 | } | 
 | 74 |  | 
| Chris Manton | 6230a6f | 2019-11-13 18:37:33 -0800 | [diff] [blame] | 75 | void Link::SendConnectionRequest(Psm psm, Cid local_cid, | 
 | 76 |                                  PendingDynamicChannelConnection pending_dynamic_channel_connection) { | 
 | 77 |   local_cid_to_pending_dynamic_channel_connection_map_[local_cid] = std::move(pending_dynamic_channel_connection); | 
 | 78 |   signalling_manager_.SendConnectionRequest(psm, local_cid); | 
 | 79 | } | 
 | 80 |  | 
| Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 81 | void Link::SendDisconnectionRequest(Cid local_cid, Cid remote_cid) { | 
 | 82 |   signalling_manager_.SendDisconnectionRequest(local_cid, remote_cid); | 
 | 83 | } | 
 | 84 |  | 
| Chris Manton | 2480960 | 2019-10-31 14:36:02 -0700 | [diff] [blame] | 85 | void Link::SendInformationRequest(InformationRequestInfoType type) { | 
 | 86 |   signalling_manager_.SendInformationRequest(type); | 
 | 87 | } | 
 | 88 |  | 
| Hansong Zhang | 47dec64 | 2019-11-25 12:01:15 -0800 | [diff] [blame^] | 89 | std::shared_ptr<l2cap::internal::DynamicChannelImpl> Link::AllocateDynamicChannel(Psm psm, Cid remote_cid, | 
 | 90 |                                                                                   SecurityPolicy security_policy) { | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 91 |   auto channel = dynamic_channel_allocator_.AllocateChannel(psm, remote_cid, security_policy); | 
| Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 92 |   if (channel != nullptr) { | 
| Hansong Zhang | 90603b3 | 2019-11-22 15:11:12 -0800 | [diff] [blame] | 93 |     data_pipeline_manager_.AttachChannel(channel->GetCid(), channel); | 
| Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 94 |   } | 
| Chris Manton | 6230a6f | 2019-11-13 18:37:33 -0800 | [diff] [blame] | 95 |   channel->local_initiated_ = false; | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 96 |   return channel; | 
 | 97 | } | 
 | 98 |  | 
| Hansong Zhang | 47dec64 | 2019-11-25 12:01:15 -0800 | [diff] [blame^] | 99 | std::shared_ptr<l2cap::internal::DynamicChannelImpl> Link::AllocateReservedDynamicChannel( | 
 | 100 |     Cid reserved_cid, Psm psm, Cid remote_cid, SecurityPolicy security_policy) { | 
| Hansong Zhang | d1b6c9b | 2019-10-22 16:11:53 -0700 | [diff] [blame] | 101 |   auto channel = dynamic_channel_allocator_.AllocateReservedChannel(reserved_cid, psm, remote_cid, security_policy); | 
 | 102 |   if (channel != nullptr) { | 
| Hansong Zhang | 90603b3 | 2019-11-22 15:11:12 -0800 | [diff] [blame] | 103 |     data_pipeline_manager_.AttachChannel(channel->GetCid(), channel); | 
| Hansong Zhang | d1b6c9b | 2019-10-22 16:11:53 -0700 | [diff] [blame] | 104 |   } | 
| Chris Manton | 6230a6f | 2019-11-13 18:37:33 -0800 | [diff] [blame] | 105 |   channel->local_initiated_ = true; | 
| Hansong Zhang | d1b6c9b | 2019-10-22 16:11:53 -0700 | [diff] [blame] | 106 |   return channel; | 
 | 107 | } | 
 | 108 |  | 
| Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 109 | classic::DynamicChannelConfigurationOption Link::GetConfigurationForInitialConfiguration(Cid cid) { | 
 | 110 |   ASSERT(local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != | 
 | 111 |          local_cid_to_pending_dynamic_channel_connection_map_.end()); | 
 | 112 |   return local_cid_to_pending_dynamic_channel_connection_map_[cid].configuration_; | 
| Hansong Zhang | b096076 | 2019-11-14 17:57:10 -0800 | [diff] [blame] | 113 | } | 
 | 114 |  | 
| Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 115 | void Link::FreeDynamicChannel(Cid cid) { | 
 | 116 |   if (dynamic_channel_allocator_.FindChannelByCid(cid) == nullptr) { | 
 | 117 |     return; | 
 | 118 |   } | 
| Hansong Zhang | 90603b3 | 2019-11-22 15:11:12 -0800 | [diff] [blame] | 119 |   data_pipeline_manager_.DetachChannel(cid); | 
| Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 120 |   dynamic_channel_allocator_.FreeChannel(cid); | 
 | 121 | } | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 122 |  | 
| Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 123 | void Link::RefreshRefCount() { | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 124 |   int ref_count = 0; | 
 | 125 |   ref_count += fixed_channel_allocator_.GetRefCount(); | 
 | 126 |   ref_count += dynamic_channel_allocator_.NumberOfChannels(); | 
 | 127 |   ASSERT_LOG(ref_count >= 0, "ref_count %d is less than 0", ref_count); | 
 | 128 |   if (ref_count > 0) { | 
 | 129 |     link_idle_disconnect_alarm_.Cancel(); | 
 | 130 |   } else { | 
| Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 131 |     link_idle_disconnect_alarm_.Schedule(common::BindOnce(&Link::Disconnect, common::Unretained(this)), | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 132 |                                          parameter_provider_->GetClassicLinkIdleDisconnectTimeout()); | 
 | 133 |   } | 
 | 134 | } | 
 | 135 |  | 
| Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 136 | void Link::NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> user_channel) { | 
| Chris Manton | 6230a6f | 2019-11-13 18:37:33 -0800 | [diff] [blame] | 137 |   ASSERT(local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != | 
 | 138 |          local_cid_to_pending_dynamic_channel_connection_map_.end()); | 
 | 139 |   auto& pending_dynamic_channel_connection = local_cid_to_pending_dynamic_channel_connection_map_[cid]; | 
 | 140 |   pending_dynamic_channel_connection.handler_->Post( | 
| Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 141 |       common::BindOnce(std::move(pending_dynamic_channel_connection.on_open_callback_), std::move(user_channel))); | 
| Chris Manton | 6230a6f | 2019-11-13 18:37:33 -0800 | [diff] [blame] | 142 |   local_cid_to_pending_dynamic_channel_connection_map_.erase(cid); | 
 | 143 | } | 
 | 144 |  | 
 | 145 | void Link::NotifyChannelFail(Cid cid) { | 
 | 146 |   ASSERT(local_cid_to_pending_dynamic_channel_connection_map_.find(cid) != | 
 | 147 |          local_cid_to_pending_dynamic_channel_connection_map_.end()); | 
 | 148 |   auto& pending_dynamic_channel_connection = local_cid_to_pending_dynamic_channel_connection_map_[cid]; | 
 | 149 |   // TODO(cmanton) Pass proper connection falure result to user | 
 | 150 |   DynamicChannelManager::ConnectionResult result; | 
 | 151 |   pending_dynamic_channel_connection.handler_->Post( | 
 | 152 |       common::BindOnce(std::move(pending_dynamic_channel_connection.on_fail_callback_), result)); | 
 | 153 |   local_cid_to_pending_dynamic_channel_connection_map_.erase(cid); | 
 | 154 | } | 
 | 155 |  | 
| Hansong Zhang | 70fb464 | 2019-11-20 17:33:06 -0800 | [diff] [blame] | 156 | void Link::SetRemoteConnectionlessMtu(Mtu mtu) { | 
 | 157 |   remote_mtu_ = mtu; | 
 | 158 | } | 
 | 159 |  | 
 | 160 | Mtu Link::GetRemoteConnectionlessMtu() const { | 
 | 161 |   return remote_mtu_; | 
 | 162 | } | 
 | 163 |  | 
 | 164 | void Link::SetRemoteSupportsErtm(bool supported) { | 
 | 165 |   remote_supports_ertm_ = supported; | 
 | 166 | } | 
 | 167 |  | 
 | 168 | bool Link::GetRemoteSupportsErtm() const { | 
 | 169 |   return remote_supports_ertm_; | 
 | 170 | } | 
 | 171 |  | 
 | 172 | void Link::SetRemoteSupportsFcs(bool supported) { | 
 | 173 |   remote_supports_fcs_ = supported; | 
 | 174 | } | 
 | 175 |  | 
 | 176 | bool Link::GetRemoteSupportsFcs() const { | 
 | 177 |   return remote_supports_fcs_; | 
 | 178 | } | 
 | 179 |  | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 180 | }  // namespace internal | 
| Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 181 | }  // namespace classic | 
| Hansong Zhang | 80bbfc3 | 2019-09-10 16:12:05 -0700 | [diff] [blame] | 182 | }  // namespace l2cap | 
 | 183 | }  // namespace bluetooth |