Loading system/gd/l2cap/classic/internal/link.cc +12 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,15 @@ void Link::ReadClockOffset() { acl_connection_->ReadClockOffset(); } void Link::AcquireSecurityHold() { used_by_security_module_ = true; RefreshRefCount(); } void Link::ReleaseSecurityHold() { used_by_security_module_ = false; RefreshRefCount(); } std::shared_ptr<FixedChannelImpl> Link::AllocateFixedChannel(Cid cid) { auto channel = fixed_channel_allocator_.AllocateChannel(cid); data_pipeline_manager_.AttachChannel(cid, channel, l2cap::internal::DataPipelineManager::ChannelMode::BASIC); Loading Loading @@ -235,6 +244,9 @@ void Link::RefreshRefCount() { int ref_count = 0; ref_count += fixed_channel_allocator_.GetRefCount(); ref_count += dynamic_channel_allocator_.NumberOfChannels(); if (used_by_security_module_) { ref_count += 1; } ASSERT_LOG(ref_count >= 0, "ref_count %d is less than 0", ref_count); if (ref_count > 0) { link_idle_disconnect_alarm_.Cancel(); Loading system/gd/l2cap/classic/internal/link.h +7 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,12 @@ class Link : public l2cap::internal::ILink, public hci::acl_manager::ConnectionM virtual void ReadClockOffset(); // Increase the link usage refcount to ensure the link won't be disconnected when SecurityModule needs it virtual void AcquireSecurityHold(); // Decrease the link usage refcount when SecurityModule no longer needs it virtual void ReleaseSecurityHold(); // FixedChannel methods std::shared_ptr<FixedChannelImpl> AllocateFixedChannel(Cid cid); Loading Loading @@ -195,6 +201,7 @@ class Link : public l2cap::internal::ILink, public hci::acl_manager::ConnectionM std::list<Psm> pending_dynamic_psm_list_; std::list<Link::PendingDynamicChannelConnection> pending_dynamic_channel_callback_list_; std::list<uint16_t> pending_outgoing_configuration_request_list_; bool used_by_security_module_ = false; DISALLOW_COPY_AND_ASSIGN(Link); }; Loading system/gd/l2cap/classic/internal/link_manager.cc +95 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,19 @@ void LinkManager::ConnectDynamicChannelServices( link->SendConnectionRequest(psm, link->ReserveDynamicChannel(), std::move(pending_dynamic_channel_connection)); } void LinkManager::InitiateConnectionForSecurity(hci::Address remote) { auto* link = GetLink(remote); if (link != nullptr) { LOG_ERROR("Link already exists for %s", remote.ToString().c_str()); } acl_manager_->CreateConnection(remote); } void LinkManager::RegisterLinkSecurityInterfaceListener(os::Handler* handler, LinkSecurityInterfaceListener* listener) { link_security_interface_listener_handler_ = handler; link_security_interface_listener_ = listener; } Link* LinkManager::GetLink(const hci::Address device) { if (links_.find(device) == links_.end()) { return nullptr; Loading @@ -126,6 +139,76 @@ void LinkManager::TriggerPairing(Link* link) { link->ReadClockOffset(); } /** * The implementation for LinkSecurityInterface, which allows the SecurityModule to access some link functionalities. * Note: All public methods implementing this interface are invoked from external context. */ struct LinkSecurityInterfaceImpl : public LinkSecurityInterface { public: LinkSecurityInterfaceImpl(os::Handler* handler, LinkManager* link_manager, Link* link) : handler_(handler), link_manager_(link_manager), link_(link), remote_(link_->GetDevice().GetAddress()) {} hci::Address GetRemoteAddress() override { return remote_; } void Hold() override { handler_->CallOn(this, &LinkSecurityInterfaceImpl::handle_hold); } void handle_hold() { if (link_manager_->GetLink(remote_) == nullptr) { LOG_WARN("Remote is disconnected"); return; } link_->AcquireSecurityHold(); } void Release() override { handler_->CallOn(this, &LinkSecurityInterfaceImpl::handle_release); } void handle_release() { if (link_manager_->GetLink(remote_) == nullptr) { LOG_WARN("Remote is disconnected"); return; } link_->ReleaseSecurityHold(); } void Disconnect() override { handler_->CallOn(this, &LinkSecurityInterfaceImpl::handle_disconnect); } void handle_disconnect() { if (link_manager_->GetLink(remote_) == nullptr) { LOG_WARN("Remote is disconnected"); return; } link_->Disconnect(); } void EnsureAuthenticated() override { handler_->CallOn(this, &LinkSecurityInterfaceImpl::handle_ensure_authenticated); } void handle_ensure_authenticated() { if (link_manager_->GetLink(remote_) == nullptr) { LOG_WARN("Remote is disconnected"); return; } if (!link_->IsAuthenticated()) { link_->Authenticate(); } } os::Handler* handler_; LinkManager* link_manager_; Link* link_; hci::Address remote_; }; void LinkManager::OnConnectSuccess(std::unique_ptr<hci::acl_manager::ClassicAclConnection> acl_connection) { // Same link should not be connected twice hci::Address device = acl_connection->GetAddress(); Loading Loading @@ -155,6 +238,14 @@ void LinkManager::OnConnectSuccess(std::unique_ptr<hci::acl_manager::ClassicAclC pending_dynamic_channels_.erase(device); pending_dynamic_channels_callbacks_.erase(device); } // Notify security manager if (link_security_interface_listener_handler_ != nullptr) { link_security_interface_listener_handler_->CallOn( link_security_interface_listener_, &LinkSecurityInterfaceListener::OnLinkConnected, std::make_unique<LinkSecurityInterfaceImpl>(l2cap_handler_, this, link)); } // Remove device from pending links list, if any pending_links_.erase(device); } Loading Loading @@ -194,6 +285,10 @@ void LinkManager::OnDisconnect(hci::Address device, hci::ErrorCode status) { device.ToString().c_str(), static_cast<uint8_t>(status)); link->OnAclDisconnected(status); links_.erase(device); if (link_security_interface_listener_handler_ != nullptr) { link_security_interface_listener_handler_->CallOn( link_security_interface_listener_, &LinkSecurityInterfaceListener::OnLinkDisconnected, device); } } } // namespace internal Loading system/gd/l2cap/classic/internal/link_manager.h +9 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "l2cap/classic/internal/dynamic_channel_service_manager_impl.h" #include "l2cap/classic/internal/fixed_channel_service_manager_impl.h" #include "l2cap/classic/internal/link.h" #include "l2cap/classic/link_security_interface.h" #include "l2cap/internal/parameter_provider.h" #include "l2cap/internal/scheduler.h" #include "os/handler.h" Loading Loading @@ -72,6 +73,12 @@ class LinkManager : public hci::acl_manager::ConnectionCallbacks { void ConnectDynamicChannelServices(hci::Address device, Link::PendingDynamicChannelConnection pending_dynamic_channel_connection, Psm psm); // For SecurityModule to initiate an ACL link void InitiateConnectionForSecurity(hci::Address remote); // LinkManager will handle sending OnLinkConnected() callback and construct a LinkSecurityInterface proxy. void RegisterLinkSecurityInterfaceListener(os::Handler* handler, LinkSecurityInterfaceListener* listener); private: void TriggerPairing(Link* link); Loading @@ -88,6 +95,8 @@ class LinkManager : public hci::acl_manager::ConnectionCallbacks { std::unordered_map<hci::Address, std::list<Psm>> pending_dynamic_channels_; std::unordered_map<hci::Address, std::list<Link::PendingDynamicChannelConnection>> pending_dynamic_channels_callbacks_; os::Handler* link_security_interface_listener_handler_ = nullptr; LinkSecurityInterfaceListener* link_security_interface_listener_ = nullptr; DISALLOW_COPY_AND_ASSIGN(LinkManager); }; Loading system/gd/l2cap/classic/l2cap_classic_module.cc +27 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,27 @@ struct L2capClassicModule::impl { internal::DynamicChannelServiceManagerImpl dynamic_channel_service_manager_impl_{l2cap_handler_}; internal::LinkManager link_manager_{l2cap_handler_, acl_manager_, &fixed_channel_service_manager_impl_, &dynamic_channel_service_manager_impl_, ¶meter_provider_}; struct SecurityInterfaceImpl : public SecurityInterface { SecurityInterfaceImpl(impl* module_impl) : module_impl_(module_impl) {} void RegisterLinkSecurityInterfaceListener(os::Handler* handler, LinkSecurityInterfaceListener* listener) { ASSERT(!registered_); module_impl_->link_manager_.RegisterLinkSecurityInterfaceListener(handler, listener); } void InitiateConnectionForSecurity(hci::Address remote) override { ASSERT(registered_); module_impl_->link_manager_.InitiateConnectionForSecurity(remote); } void Unregister() override { ASSERT(registered_); module_impl_->link_manager_.RegisterLinkSecurityInterfaceListener(nullptr, nullptr); } impl* module_impl_; bool registered_ = false; } security_interface_impl_{this}; }; L2capClassicModule::L2capClassicModule() {} Loading Loading @@ -93,6 +114,12 @@ void L2capClassicModule::InjectSecurityEnforcementInterface( } } SecurityInterface* L2capClassicModule::GetSecurityInterface( os::Handler* handler, LinkSecurityInterfaceListener* listener) { pimpl_->security_interface_impl_.RegisterLinkSecurityInterfaceListener(handler, listener); return &pimpl_->security_interface_impl_; } } // namespace classic } // namespace l2cap } // namespace bluetooth Loading
system/gd/l2cap/classic/internal/link.cc +12 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,15 @@ void Link::ReadClockOffset() { acl_connection_->ReadClockOffset(); } void Link::AcquireSecurityHold() { used_by_security_module_ = true; RefreshRefCount(); } void Link::ReleaseSecurityHold() { used_by_security_module_ = false; RefreshRefCount(); } std::shared_ptr<FixedChannelImpl> Link::AllocateFixedChannel(Cid cid) { auto channel = fixed_channel_allocator_.AllocateChannel(cid); data_pipeline_manager_.AttachChannel(cid, channel, l2cap::internal::DataPipelineManager::ChannelMode::BASIC); Loading Loading @@ -235,6 +244,9 @@ void Link::RefreshRefCount() { int ref_count = 0; ref_count += fixed_channel_allocator_.GetRefCount(); ref_count += dynamic_channel_allocator_.NumberOfChannels(); if (used_by_security_module_) { ref_count += 1; } ASSERT_LOG(ref_count >= 0, "ref_count %d is less than 0", ref_count); if (ref_count > 0) { link_idle_disconnect_alarm_.Cancel(); Loading
system/gd/l2cap/classic/internal/link.h +7 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,12 @@ class Link : public l2cap::internal::ILink, public hci::acl_manager::ConnectionM virtual void ReadClockOffset(); // Increase the link usage refcount to ensure the link won't be disconnected when SecurityModule needs it virtual void AcquireSecurityHold(); // Decrease the link usage refcount when SecurityModule no longer needs it virtual void ReleaseSecurityHold(); // FixedChannel methods std::shared_ptr<FixedChannelImpl> AllocateFixedChannel(Cid cid); Loading Loading @@ -195,6 +201,7 @@ class Link : public l2cap::internal::ILink, public hci::acl_manager::ConnectionM std::list<Psm> pending_dynamic_psm_list_; std::list<Link::PendingDynamicChannelConnection> pending_dynamic_channel_callback_list_; std::list<uint16_t> pending_outgoing_configuration_request_list_; bool used_by_security_module_ = false; DISALLOW_COPY_AND_ASSIGN(Link); }; Loading
system/gd/l2cap/classic/internal/link_manager.cc +95 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,19 @@ void LinkManager::ConnectDynamicChannelServices( link->SendConnectionRequest(psm, link->ReserveDynamicChannel(), std::move(pending_dynamic_channel_connection)); } void LinkManager::InitiateConnectionForSecurity(hci::Address remote) { auto* link = GetLink(remote); if (link != nullptr) { LOG_ERROR("Link already exists for %s", remote.ToString().c_str()); } acl_manager_->CreateConnection(remote); } void LinkManager::RegisterLinkSecurityInterfaceListener(os::Handler* handler, LinkSecurityInterfaceListener* listener) { link_security_interface_listener_handler_ = handler; link_security_interface_listener_ = listener; } Link* LinkManager::GetLink(const hci::Address device) { if (links_.find(device) == links_.end()) { return nullptr; Loading @@ -126,6 +139,76 @@ void LinkManager::TriggerPairing(Link* link) { link->ReadClockOffset(); } /** * The implementation for LinkSecurityInterface, which allows the SecurityModule to access some link functionalities. * Note: All public methods implementing this interface are invoked from external context. */ struct LinkSecurityInterfaceImpl : public LinkSecurityInterface { public: LinkSecurityInterfaceImpl(os::Handler* handler, LinkManager* link_manager, Link* link) : handler_(handler), link_manager_(link_manager), link_(link), remote_(link_->GetDevice().GetAddress()) {} hci::Address GetRemoteAddress() override { return remote_; } void Hold() override { handler_->CallOn(this, &LinkSecurityInterfaceImpl::handle_hold); } void handle_hold() { if (link_manager_->GetLink(remote_) == nullptr) { LOG_WARN("Remote is disconnected"); return; } link_->AcquireSecurityHold(); } void Release() override { handler_->CallOn(this, &LinkSecurityInterfaceImpl::handle_release); } void handle_release() { if (link_manager_->GetLink(remote_) == nullptr) { LOG_WARN("Remote is disconnected"); return; } link_->ReleaseSecurityHold(); } void Disconnect() override { handler_->CallOn(this, &LinkSecurityInterfaceImpl::handle_disconnect); } void handle_disconnect() { if (link_manager_->GetLink(remote_) == nullptr) { LOG_WARN("Remote is disconnected"); return; } link_->Disconnect(); } void EnsureAuthenticated() override { handler_->CallOn(this, &LinkSecurityInterfaceImpl::handle_ensure_authenticated); } void handle_ensure_authenticated() { if (link_manager_->GetLink(remote_) == nullptr) { LOG_WARN("Remote is disconnected"); return; } if (!link_->IsAuthenticated()) { link_->Authenticate(); } } os::Handler* handler_; LinkManager* link_manager_; Link* link_; hci::Address remote_; }; void LinkManager::OnConnectSuccess(std::unique_ptr<hci::acl_manager::ClassicAclConnection> acl_connection) { // Same link should not be connected twice hci::Address device = acl_connection->GetAddress(); Loading Loading @@ -155,6 +238,14 @@ void LinkManager::OnConnectSuccess(std::unique_ptr<hci::acl_manager::ClassicAclC pending_dynamic_channels_.erase(device); pending_dynamic_channels_callbacks_.erase(device); } // Notify security manager if (link_security_interface_listener_handler_ != nullptr) { link_security_interface_listener_handler_->CallOn( link_security_interface_listener_, &LinkSecurityInterfaceListener::OnLinkConnected, std::make_unique<LinkSecurityInterfaceImpl>(l2cap_handler_, this, link)); } // Remove device from pending links list, if any pending_links_.erase(device); } Loading Loading @@ -194,6 +285,10 @@ void LinkManager::OnDisconnect(hci::Address device, hci::ErrorCode status) { device.ToString().c_str(), static_cast<uint8_t>(status)); link->OnAclDisconnected(status); links_.erase(device); if (link_security_interface_listener_handler_ != nullptr) { link_security_interface_listener_handler_->CallOn( link_security_interface_listener_, &LinkSecurityInterfaceListener::OnLinkDisconnected, device); } } } // namespace internal Loading
system/gd/l2cap/classic/internal/link_manager.h +9 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "l2cap/classic/internal/dynamic_channel_service_manager_impl.h" #include "l2cap/classic/internal/fixed_channel_service_manager_impl.h" #include "l2cap/classic/internal/link.h" #include "l2cap/classic/link_security_interface.h" #include "l2cap/internal/parameter_provider.h" #include "l2cap/internal/scheduler.h" #include "os/handler.h" Loading Loading @@ -72,6 +73,12 @@ class LinkManager : public hci::acl_manager::ConnectionCallbacks { void ConnectDynamicChannelServices(hci::Address device, Link::PendingDynamicChannelConnection pending_dynamic_channel_connection, Psm psm); // For SecurityModule to initiate an ACL link void InitiateConnectionForSecurity(hci::Address remote); // LinkManager will handle sending OnLinkConnected() callback and construct a LinkSecurityInterface proxy. void RegisterLinkSecurityInterfaceListener(os::Handler* handler, LinkSecurityInterfaceListener* listener); private: void TriggerPairing(Link* link); Loading @@ -88,6 +95,8 @@ class LinkManager : public hci::acl_manager::ConnectionCallbacks { std::unordered_map<hci::Address, std::list<Psm>> pending_dynamic_channels_; std::unordered_map<hci::Address, std::list<Link::PendingDynamicChannelConnection>> pending_dynamic_channels_callbacks_; os::Handler* link_security_interface_listener_handler_ = nullptr; LinkSecurityInterfaceListener* link_security_interface_listener_ = nullptr; DISALLOW_COPY_AND_ASSIGN(LinkManager); }; Loading
system/gd/l2cap/classic/l2cap_classic_module.cc +27 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,27 @@ struct L2capClassicModule::impl { internal::DynamicChannelServiceManagerImpl dynamic_channel_service_manager_impl_{l2cap_handler_}; internal::LinkManager link_manager_{l2cap_handler_, acl_manager_, &fixed_channel_service_manager_impl_, &dynamic_channel_service_manager_impl_, ¶meter_provider_}; struct SecurityInterfaceImpl : public SecurityInterface { SecurityInterfaceImpl(impl* module_impl) : module_impl_(module_impl) {} void RegisterLinkSecurityInterfaceListener(os::Handler* handler, LinkSecurityInterfaceListener* listener) { ASSERT(!registered_); module_impl_->link_manager_.RegisterLinkSecurityInterfaceListener(handler, listener); } void InitiateConnectionForSecurity(hci::Address remote) override { ASSERT(registered_); module_impl_->link_manager_.InitiateConnectionForSecurity(remote); } void Unregister() override { ASSERT(registered_); module_impl_->link_manager_.RegisterLinkSecurityInterfaceListener(nullptr, nullptr); } impl* module_impl_; bool registered_ = false; } security_interface_impl_{this}; }; L2capClassicModule::L2capClassicModule() {} Loading Loading @@ -93,6 +114,12 @@ void L2capClassicModule::InjectSecurityEnforcementInterface( } } SecurityInterface* L2capClassicModule::GetSecurityInterface( os::Handler* handler, LinkSecurityInterfaceListener* listener) { pimpl_->security_interface_impl_.RegisterLinkSecurityInterfaceListener(handler, listener); return &pimpl_->security_interface_impl_; } } // namespace classic } // namespace l2cap } // namespace bluetooth