Loading system/gd/l2cap/Android.bp +4 −2 Original line number Diff line number Diff line Loading @@ -6,8 +6,9 @@ filegroup { "classic_fixed_channel.cc", "classic_fixed_channel_manager.cc", "classic_fixed_channel_service.cc", "internal/classic_fixed_channel_service_manager_impl.cc", "internal/classic_fixed_channel_allocator.cc", "internal/classic_fixed_channel_impl.cc", "internal/classic_fixed_channel_service_manager_impl.cc", "internal/classic_link_manager.cc", "internal/scheduler_fifo.cc", ], Loading @@ -17,8 +18,9 @@ filegroup { name: "BluetoothL2capTestSources", srcs: [ "l2cap_packet_test.cc", "internal/classic_fixed_channel_service_manager_test.cc", "internal/classic_fixed_channel_allocator_test.cc", "internal/classic_fixed_channel_impl_test.cc", "internal/classic_fixed_channel_service_manager_test.cc", "internal/classic_link_manager_test.cc", "internal/scheduler_fifo_test.cc", "signal_id_test.cc", Loading system/gd/l2cap/classic_fixed_channel.cc +21 −3 Original line number Diff line number Diff line Loading @@ -15,12 +15,30 @@ */ #include "l2cap/classic_fixed_channel.h" #include "common/bind.h" #include "l2cap/internal/classic_fixed_channel_impl.h" namespace bluetooth { namespace l2cap { void ClassicFixedChannel::RegisterOnCloseCallback(os::Handler* handler, OnCloseCallback callback) {} void ClassicFixedChannel::Acquire() {} void ClassicFixedChannel::Release() {} hci::Address ClassicFixedChannel::GetDevice() const { return impl_->GetDevice(); } void ClassicFixedChannel::RegisterOnCloseCallback(os::Handler* user_handler, ClassicFixedChannel::OnCloseCallback on_close_callback) { l2cap_handler_->Post(common::BindOnce(&internal::ClassicFixedChannelImpl::RegisterOnCloseCallback, impl_, user_handler, std::move(on_close_callback))); } void ClassicFixedChannel::Acquire() { l2cap_handler_->Post(common::BindOnce(&internal::ClassicFixedChannelImpl::Acquire, impl_)); } void ClassicFixedChannel::Release() { l2cap_handler_->Post(common::BindOnce(&internal::ClassicFixedChannelImpl::Release, impl_)); } common::BidiQueueEnd<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder>* ClassicFixedChannel::GetQueueUpEnd() const { return nullptr; Loading system/gd/l2cap/classic_fixed_channel.h +20 −16 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #include "common/bidi_queue.h" #include "common/callback.h" #include "hci/acl_manager.h" #include "l2cap/cid.h" #include "os/handler.h" #include "packet/base_packet_builder.h" #include "packet/packet_view.h" Loading @@ -31,33 +33,40 @@ class ClassicFixedChannelImpl; /** * L2CAP fixed channel object. When a new object is created, it must be * acquired through calling {@link FixedChannel#Acquire()} within X seconds. * Otherwise, {@link FixeChannel#Release()} will be called automatically. * Otherwise, {@link FixedChannel#Release()} will be called automatically. * */ class ClassicFixedChannel { public: using OnCloseCallback = common::Callback<void()>; // Should only be constructed by modules that have access to ClassicLinkManager ClassicFixedChannel(std::shared_ptr<internal::ClassicFixedChannelImpl> impl, os::Handler* l2cap_handler) : impl_(std::move(impl)), l2cap_handler_(l2cap_handler) { ASSERT(impl_ != nullptr); ASSERT(l2cap_handler_ != nullptr); } hci::Address GetDevice() const; /** * Register close callback. If close callback is registered, when a channel is closed, the channel's resource will * only be freed after on_close callback is invoked. Otherwise, if no on_close callback is registered, the channel's * resource will be freed immediately after closing. * * @param on_close The callback invoked upon channel closing. * @param user_handler The handler used to invoke the callback on * @param on_close_callback The callback invoked upon channel closing. */ void RegisterOnCloseCallback(os::Handler* handler, OnCloseCallback on_close); using OnCloseCallback = common::OnceCallback<void(hci::ErrorCode)>; void RegisterOnCloseCallback(os::Handler* user_handler, OnCloseCallback on_close_callback); /** * Indicate that this Fixed Channel is being used. This will prevent ACL * connection from being disconnected. * Indicate that this Fixed Channel is being used. This will prevent ACL connection from being disconnected. */ void Acquire(); /** * Indicate that this Fixed Channel is no longer being used. ACL connection * will be disconnected after X seconds if no other DynamicChannel is connected * or no other Fixed Channel is using this ACL connection. However a module can * still receive data on this channel as long as it remains open. * Indicate that this Fixed Channel is no longer being used. ACL connection will be disconnected after * kClassicLinkIdleDisconnectTimeout if no other DynamicChannel is connected or no other Fixed Channel is using this * ACL connection. However a module can still receive data on this channel as long as it remains open. */ void Release(); Loading @@ -70,14 +79,9 @@ class ClassicFixedChannel { */ common::BidiQueueEnd<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder>* GetQueueUpEnd() const; friend class internal::ClassicFixedChannelImpl; private: ClassicFixedChannel(os::Handler* l2cap_handler, internal::ClassicFixedChannelImpl* classic_fixed_channel_impl) : l2cap_handler_(l2cap_handler), classic_fixed_channel_impl_(classic_fixed_channel_impl) {} std::shared_ptr<internal::ClassicFixedChannelImpl> impl_; os::Handler* l2cap_handler_; internal::ClassicFixedChannelImpl* classic_fixed_channel_impl_; DISALLOW_COPY_AND_ASSIGN(ClassicFixedChannel); }; } // namespace l2cap Loading system/gd/l2cap/internal/classic_fixed_channel_allocator.cc +36 −11 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "classic_fixed_channel_allocator.h" #include "l2cap/cid.h" #include "l2cap/internal/classic_fixed_channel_allocator.h" #include "l2cap/internal/classic_link.h" #include "l2cap/security_policy.h" #include "os/handler.h" #include "os/log.h" Loading @@ -27,30 +28,54 @@ namespace bluetooth { namespace l2cap { namespace internal { ClassicFixedChannelImpl* ClassicFixedChannelAllocator::AllocateChannel(Cid cid, SecurityPolicy security_policy) { ASSERT_LOG(!IsChannelInUse((cid)), "Cid %d is already in use", cid); std::shared_ptr<ClassicFixedChannelImpl> ClassicFixedChannelAllocator::AllocateChannel(Cid cid, SecurityPolicy security_policy) { ASSERT_LOG(!IsChannelAllocated((cid)), "Cid 0x%x for device %s is already in use", cid, link_->GetDevice().ToString().c_str()); ASSERT_LOG(cid >= kFirstFixedChannel && cid <= kLastFixedChannel, "Cid %d out of bound", cid); channels_.try_emplace(cid, cid, handler_); return &channels_.find(cid)->second; auto elem = channels_.try_emplace(cid, std::make_shared<ClassicFixedChannelImpl>(cid, link_, l2cap_handler_)); ASSERT_LOG(elem.second, "Failed to create channel for cid 0x%x device %s", cid, link_->GetDevice().ToString().c_str()); ASSERT(elem.first->second != nullptr); return elem.first->second; } bool ClassicFixedChannelAllocator::FreeChannel(Cid cid) { ASSERT_LOG(IsChannelInUse(cid), "Channel is not in use: cid %d", cid); void ClassicFixedChannelAllocator::FreeChannel(Cid cid) { ASSERT_LOG(IsChannelAllocated(cid), "Channel is not in use: cid %d, device %s", cid, link_->GetDevice().ToString().c_str()); channels_.erase(cid); return true; } bool ClassicFixedChannelAllocator::IsChannelInUse(Cid cid) const { bool ClassicFixedChannelAllocator::IsChannelAllocated(Cid cid) const { return channels_.find(cid) != channels_.end(); } ClassicFixedChannelImpl* ClassicFixedChannelAllocator::FindChannel(Cid cid) { ASSERT_LOG(IsChannelInUse(cid), "Channel is not in use: cid %d", cid); return &channels_.find(cid)->second; std::shared_ptr<ClassicFixedChannelImpl> ClassicFixedChannelAllocator::FindChannel(Cid cid) { ASSERT_LOG(IsChannelAllocated(cid), "Channel is not in use: cid %d, device %s", cid, link_->GetDevice().ToString().c_str()); return channels_.find(cid)->second; } size_t ClassicFixedChannelAllocator::NumberOfChannels() const { return channels_.size(); } void ClassicFixedChannelAllocator::OnAclDisconnected(hci::ErrorCode reason) { for (auto& elem : channels_) { elem.second->OnClosed(reason); } } int ClassicFixedChannelAllocator::GetRefCount() { int ref_count = 0; for (auto& elem : channels_) { if (elem.second->IsAcquired()) { ref_count++; } } return ref_count; } } // namespace internal } // namespace l2cap } // namespace bluetooth system/gd/l2cap/internal/classic_fixed_channel_allocator.h +20 −10 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include <hci/hci_packets.h> #include <unordered_map> #include "l2cap/cid.h" Loading @@ -28,30 +29,39 @@ namespace bluetooth { namespace l2cap { namespace internal { class ClassicLink; // Helper class for keeping channels in a Link. It allocates and frees Channel object, and supports querying whether a // channel is in use class ClassicFixedChannelAllocator { public: explicit ClassicFixedChannelAllocator(os::Handler* handler) : handler_(handler) { ASSERT(handler_ != nullptr); ClassicFixedChannelAllocator(ClassicLink* link, os::Handler* l2cap_handler) : link_(link), l2cap_handler_(l2cap_handler) { ASSERT(link_ != nullptr); ASSERT(l2cap_handler_ != nullptr); } // Allocates a channel. If cid is used, return nullptr. NOTE: The returned ClassicFixedChannelImpl object is still // owned by the channel cllocator, NOT the client. ClassicFixedChannelImpl* AllocateChannel(Cid cid, SecurityPolicy security_policy); // owned by the channel allocator, NOT the client. std::shared_ptr<ClassicFixedChannelImpl> AllocateChannel(Cid cid, SecurityPolicy security_policy); // Frees a channel. If cid doesn't exist, return false bool FreeChannel(Cid cid); // Frees a channel. If cid doesn't exist, it will crash void FreeChannel(Cid cid); bool IsChannelInUse(Cid cid) const; bool IsChannelAllocated(Cid cid) const; ClassicFixedChannelImpl* FindChannel(Cid cid); std::shared_ptr<ClassicFixedChannelImpl> FindChannel(Cid cid); size_t NumberOfChannels() const; void OnAclDisconnected(hci::ErrorCode hci_status); int GetRefCount(); private: os::Handler* handler_ = nullptr; std::unordered_map<Cid, ClassicFixedChannelImpl> channels_; ClassicLink* link_; os::Handler* l2cap_handler_; std::unordered_map<Cid, std::shared_ptr<ClassicFixedChannelImpl>> channels_; }; } // namespace internal Loading Loading
system/gd/l2cap/Android.bp +4 −2 Original line number Diff line number Diff line Loading @@ -6,8 +6,9 @@ filegroup { "classic_fixed_channel.cc", "classic_fixed_channel_manager.cc", "classic_fixed_channel_service.cc", "internal/classic_fixed_channel_service_manager_impl.cc", "internal/classic_fixed_channel_allocator.cc", "internal/classic_fixed_channel_impl.cc", "internal/classic_fixed_channel_service_manager_impl.cc", "internal/classic_link_manager.cc", "internal/scheduler_fifo.cc", ], Loading @@ -17,8 +18,9 @@ filegroup { name: "BluetoothL2capTestSources", srcs: [ "l2cap_packet_test.cc", "internal/classic_fixed_channel_service_manager_test.cc", "internal/classic_fixed_channel_allocator_test.cc", "internal/classic_fixed_channel_impl_test.cc", "internal/classic_fixed_channel_service_manager_test.cc", "internal/classic_link_manager_test.cc", "internal/scheduler_fifo_test.cc", "signal_id_test.cc", Loading
system/gd/l2cap/classic_fixed_channel.cc +21 −3 Original line number Diff line number Diff line Loading @@ -15,12 +15,30 @@ */ #include "l2cap/classic_fixed_channel.h" #include "common/bind.h" #include "l2cap/internal/classic_fixed_channel_impl.h" namespace bluetooth { namespace l2cap { void ClassicFixedChannel::RegisterOnCloseCallback(os::Handler* handler, OnCloseCallback callback) {} void ClassicFixedChannel::Acquire() {} void ClassicFixedChannel::Release() {} hci::Address ClassicFixedChannel::GetDevice() const { return impl_->GetDevice(); } void ClassicFixedChannel::RegisterOnCloseCallback(os::Handler* user_handler, ClassicFixedChannel::OnCloseCallback on_close_callback) { l2cap_handler_->Post(common::BindOnce(&internal::ClassicFixedChannelImpl::RegisterOnCloseCallback, impl_, user_handler, std::move(on_close_callback))); } void ClassicFixedChannel::Acquire() { l2cap_handler_->Post(common::BindOnce(&internal::ClassicFixedChannelImpl::Acquire, impl_)); } void ClassicFixedChannel::Release() { l2cap_handler_->Post(common::BindOnce(&internal::ClassicFixedChannelImpl::Release, impl_)); } common::BidiQueueEnd<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder>* ClassicFixedChannel::GetQueueUpEnd() const { return nullptr; Loading
system/gd/l2cap/classic_fixed_channel.h +20 −16 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #include "common/bidi_queue.h" #include "common/callback.h" #include "hci/acl_manager.h" #include "l2cap/cid.h" #include "os/handler.h" #include "packet/base_packet_builder.h" #include "packet/packet_view.h" Loading @@ -31,33 +33,40 @@ class ClassicFixedChannelImpl; /** * L2CAP fixed channel object. When a new object is created, it must be * acquired through calling {@link FixedChannel#Acquire()} within X seconds. * Otherwise, {@link FixeChannel#Release()} will be called automatically. * Otherwise, {@link FixedChannel#Release()} will be called automatically. * */ class ClassicFixedChannel { public: using OnCloseCallback = common::Callback<void()>; // Should only be constructed by modules that have access to ClassicLinkManager ClassicFixedChannel(std::shared_ptr<internal::ClassicFixedChannelImpl> impl, os::Handler* l2cap_handler) : impl_(std::move(impl)), l2cap_handler_(l2cap_handler) { ASSERT(impl_ != nullptr); ASSERT(l2cap_handler_ != nullptr); } hci::Address GetDevice() const; /** * Register close callback. If close callback is registered, when a channel is closed, the channel's resource will * only be freed after on_close callback is invoked. Otherwise, if no on_close callback is registered, the channel's * resource will be freed immediately after closing. * * @param on_close The callback invoked upon channel closing. * @param user_handler The handler used to invoke the callback on * @param on_close_callback The callback invoked upon channel closing. */ void RegisterOnCloseCallback(os::Handler* handler, OnCloseCallback on_close); using OnCloseCallback = common::OnceCallback<void(hci::ErrorCode)>; void RegisterOnCloseCallback(os::Handler* user_handler, OnCloseCallback on_close_callback); /** * Indicate that this Fixed Channel is being used. This will prevent ACL * connection from being disconnected. * Indicate that this Fixed Channel is being used. This will prevent ACL connection from being disconnected. */ void Acquire(); /** * Indicate that this Fixed Channel is no longer being used. ACL connection * will be disconnected after X seconds if no other DynamicChannel is connected * or no other Fixed Channel is using this ACL connection. However a module can * still receive data on this channel as long as it remains open. * Indicate that this Fixed Channel is no longer being used. ACL connection will be disconnected after * kClassicLinkIdleDisconnectTimeout if no other DynamicChannel is connected or no other Fixed Channel is using this * ACL connection. However a module can still receive data on this channel as long as it remains open. */ void Release(); Loading @@ -70,14 +79,9 @@ class ClassicFixedChannel { */ common::BidiQueueEnd<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder>* GetQueueUpEnd() const; friend class internal::ClassicFixedChannelImpl; private: ClassicFixedChannel(os::Handler* l2cap_handler, internal::ClassicFixedChannelImpl* classic_fixed_channel_impl) : l2cap_handler_(l2cap_handler), classic_fixed_channel_impl_(classic_fixed_channel_impl) {} std::shared_ptr<internal::ClassicFixedChannelImpl> impl_; os::Handler* l2cap_handler_; internal::ClassicFixedChannelImpl* classic_fixed_channel_impl_; DISALLOW_COPY_AND_ASSIGN(ClassicFixedChannel); }; } // namespace l2cap Loading
system/gd/l2cap/internal/classic_fixed_channel_allocator.cc +36 −11 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "classic_fixed_channel_allocator.h" #include "l2cap/cid.h" #include "l2cap/internal/classic_fixed_channel_allocator.h" #include "l2cap/internal/classic_link.h" #include "l2cap/security_policy.h" #include "os/handler.h" #include "os/log.h" Loading @@ -27,30 +28,54 @@ namespace bluetooth { namespace l2cap { namespace internal { ClassicFixedChannelImpl* ClassicFixedChannelAllocator::AllocateChannel(Cid cid, SecurityPolicy security_policy) { ASSERT_LOG(!IsChannelInUse((cid)), "Cid %d is already in use", cid); std::shared_ptr<ClassicFixedChannelImpl> ClassicFixedChannelAllocator::AllocateChannel(Cid cid, SecurityPolicy security_policy) { ASSERT_LOG(!IsChannelAllocated((cid)), "Cid 0x%x for device %s is already in use", cid, link_->GetDevice().ToString().c_str()); ASSERT_LOG(cid >= kFirstFixedChannel && cid <= kLastFixedChannel, "Cid %d out of bound", cid); channels_.try_emplace(cid, cid, handler_); return &channels_.find(cid)->second; auto elem = channels_.try_emplace(cid, std::make_shared<ClassicFixedChannelImpl>(cid, link_, l2cap_handler_)); ASSERT_LOG(elem.second, "Failed to create channel for cid 0x%x device %s", cid, link_->GetDevice().ToString().c_str()); ASSERT(elem.first->second != nullptr); return elem.first->second; } bool ClassicFixedChannelAllocator::FreeChannel(Cid cid) { ASSERT_LOG(IsChannelInUse(cid), "Channel is not in use: cid %d", cid); void ClassicFixedChannelAllocator::FreeChannel(Cid cid) { ASSERT_LOG(IsChannelAllocated(cid), "Channel is not in use: cid %d, device %s", cid, link_->GetDevice().ToString().c_str()); channels_.erase(cid); return true; } bool ClassicFixedChannelAllocator::IsChannelInUse(Cid cid) const { bool ClassicFixedChannelAllocator::IsChannelAllocated(Cid cid) const { return channels_.find(cid) != channels_.end(); } ClassicFixedChannelImpl* ClassicFixedChannelAllocator::FindChannel(Cid cid) { ASSERT_LOG(IsChannelInUse(cid), "Channel is not in use: cid %d", cid); return &channels_.find(cid)->second; std::shared_ptr<ClassicFixedChannelImpl> ClassicFixedChannelAllocator::FindChannel(Cid cid) { ASSERT_LOG(IsChannelAllocated(cid), "Channel is not in use: cid %d, device %s", cid, link_->GetDevice().ToString().c_str()); return channels_.find(cid)->second; } size_t ClassicFixedChannelAllocator::NumberOfChannels() const { return channels_.size(); } void ClassicFixedChannelAllocator::OnAclDisconnected(hci::ErrorCode reason) { for (auto& elem : channels_) { elem.second->OnClosed(reason); } } int ClassicFixedChannelAllocator::GetRefCount() { int ref_count = 0; for (auto& elem : channels_) { if (elem.second->IsAcquired()) { ref_count++; } } return ref_count; } } // namespace internal } // namespace l2cap } // namespace bluetooth
system/gd/l2cap/internal/classic_fixed_channel_allocator.h +20 −10 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include <hci/hci_packets.h> #include <unordered_map> #include "l2cap/cid.h" Loading @@ -28,30 +29,39 @@ namespace bluetooth { namespace l2cap { namespace internal { class ClassicLink; // Helper class for keeping channels in a Link. It allocates and frees Channel object, and supports querying whether a // channel is in use class ClassicFixedChannelAllocator { public: explicit ClassicFixedChannelAllocator(os::Handler* handler) : handler_(handler) { ASSERT(handler_ != nullptr); ClassicFixedChannelAllocator(ClassicLink* link, os::Handler* l2cap_handler) : link_(link), l2cap_handler_(l2cap_handler) { ASSERT(link_ != nullptr); ASSERT(l2cap_handler_ != nullptr); } // Allocates a channel. If cid is used, return nullptr. NOTE: The returned ClassicFixedChannelImpl object is still // owned by the channel cllocator, NOT the client. ClassicFixedChannelImpl* AllocateChannel(Cid cid, SecurityPolicy security_policy); // owned by the channel allocator, NOT the client. std::shared_ptr<ClassicFixedChannelImpl> AllocateChannel(Cid cid, SecurityPolicy security_policy); // Frees a channel. If cid doesn't exist, return false bool FreeChannel(Cid cid); // Frees a channel. If cid doesn't exist, it will crash void FreeChannel(Cid cid); bool IsChannelInUse(Cid cid) const; bool IsChannelAllocated(Cid cid) const; ClassicFixedChannelImpl* FindChannel(Cid cid); std::shared_ptr<ClassicFixedChannelImpl> FindChannel(Cid cid); size_t NumberOfChannels() const; void OnAclDisconnected(hci::ErrorCode hci_status); int GetRefCount(); private: os::Handler* handler_ = nullptr; std::unordered_map<Cid, ClassicFixedChannelImpl> channels_; ClassicLink* link_; os::Handler* l2cap_handler_; std::unordered_map<Cid, std::shared_ptr<ClassicFixedChannelImpl>> channels_; }; } // namespace internal Loading