Loading system/gd/common/callback_list.h +58 −1 Original line number Diff line number Diff line Loading @@ -16,12 +16,69 @@ #pragma once #include <utility> #include "base/callback_list.h" #include "os/handler.h" /* This file contains CallbackList implementation that will execute callback on provided Handler thread Example usage inside your class: private: common::CallbackList<void(int)> callbacks_list_; public: std::unique_ptr<common::CallbackList<void(int)>::Subscription> RegisterCallback( const base::RepeatingCallback<void(int)>& cb, os::Handler* handler) { return callbacks_list_.Add({cb, handler}); } void NotifyAllCallbacks(int value) { callbacks_list_.Notify(value); } */ namespace bluetooth { namespace common { using base::CallbackList; namespace { template <typename CallbackType> struct CallbackWithHandler { CallbackWithHandler(base::RepeatingCallback<CallbackType> callback, os::Handler* handler) : callback(callback), handler(handler) {} bool is_null() const { return callback.is_null(); } void Reset() { callback.Reset(); } base::RepeatingCallback<CallbackType> callback; os::Handler* handler; }; } // namespace template <typename Sig> class CallbackList; template <typename... Args> class CallbackList<void(Args...)> : public base::internal::CallbackListBase<CallbackWithHandler<void(Args...)>> { public: using CallbackType = CallbackWithHandler<void(Args...)>; CallbackList() = default; template <typename... RunArgs> void Notify(RunArgs&&... args) { auto it = this->GetIterator(); CallbackType* cb; while ((cb = it.GetNext()) != nullptr) { cb->handler->Post(base::Bind(cb->callback, args...)); } } private: DISALLOW_COPY_AND_ASSIGN(CallbackList); }; } // namespace common } // namespace bluetooth system/gd/l2cap/classic/cert/api.proto +5 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ service L2capModuleCert { rpc FetchConnectionComplete(facade.EventStreamRequest) returns (stream ConnectionCompleteEvent) {} rpc DisconnectLink(DisconnectLinkRequest) returns (google.protobuf.Empty) {} rpc SendConnectionRequest(ConnectionRequest) returns (google.protobuf.Empty) {} rpc SendConfigurationRequest(ConfigurationRequest) returns (SendConfigurationRequestResult) {} rpc SendDisconnectionRequest(DisconnectionRequest) returns (google.protobuf.Empty) {} } Loading @@ -34,6 +35,10 @@ message ConnectionRequest { uint32 scid = 3; } message ConfigurationRequest {} message SendConfigurationRequestResult {} message DisconnectionRequest { facade.BluetoothAddress remote = 1; uint32 dcid = 2; Loading system/gd/l2cap/classic/cert/cert.cc +13 −0 Original line number Diff line number Diff line Loading @@ -101,6 +101,19 @@ class L2capModuleCertService : public L2capModuleCert::Service { return ::grpc::Status::OK; } ::grpc::Status SendConfigurationRequest( ::grpc::ServerContext* context, const ::bluetooth::l2cap::classic::cert::ConfigurationRequest* request, ::bluetooth::l2cap::classic::cert::SendConfigurationRequestResult* response) override { auto builder = ConfigurationRequestBuilder::Create(1, 0x40, Continuation::END, {}); auto l2cap_builder = BasicFrameBuilder::Create(1, std::move(builder)); outgoing_packet_queue_.push(std::move(l2cap_builder)); if (outgoing_packet_queue_.size() == 1) { acl_connection_->GetAclQueueEnd()->RegisterEnqueue( handler_, common::Bind(&L2capModuleCertService::enqueue_packet_to_acl, common::Unretained(this))); } return ::grpc::Status::OK; } ::grpc::Status SendDisconnectionRequest(::grpc::ServerContext* context, const cert::DisconnectionRequest* request, ::google::protobuf::Empty* response) override { auto builder = DisconnectionRequestBuilder::Create(3, 0x40, 101); Loading system/gd/l2cap/classic/cert/simple_l2cap_test.py +2 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,8 @@ class SimpleL2capTest(GdBaseTestClass): dut_packet_stream.subscribe() cert_packet_stream.subscribe() self.cert_device.l2cap.SendConfigurationRequest(l2cap_cert_pb2.ConfigurationRequest()) self.cert_device.l2cap.SendL2capPacket(l2cap_facade_pb2.L2capPacket(channel=2, payload=b"abc")) dut_packet_stream.assert_event_occurs( lambda packet: b"abc" in packet.payload Loading system/gd/l2cap/classic/internal/signalling_manager.cc +39 −11 Original line number Diff line number Diff line Loading @@ -63,29 +63,39 @@ void ClassicSignallingManager::OnCommandReject(CommandRejectView command_reject_ } void ClassicSignallingManager::SendConnectionRequest(Psm psm, Cid local_cid) { PendingCommand pending_command = {next_signal_id_, CommandCode::CONNECTION_REQUEST, psm, local_cid, {}, {}}; PendingCommand pending_command = {next_signal_id_, CommandCode::CONNECTION_REQUEST, psm, local_cid, {}, {}, {}}; next_signal_id_++; pending_commands_.push(pending_command); pending_commands_.push(std::move(pending_command)); if (pending_commands_.size() == 1) { handle_send_next_command(); } } void ClassicSignallingManager::SendConfigurationRequest() {} void ClassicSignallingManager::SendConfigurationRequest(Cid remote_cid, std::vector<std::unique_ptr<ConfigurationOption>> config) { PendingCommand pending_command = {next_signal_id_, CommandCode::CONFIGURATION_REQUEST, {}, {}, remote_cid, {}, std::move(config)}; next_signal_id_++; pending_commands_.push(std::move(pending_command)); if (pending_commands_.size() == 1) { handle_send_next_command(); } } void ClassicSignallingManager::SendDisconnectionRequest(Cid local_cid, Cid remote_cid) { PendingCommand pending_command = {next_signal_id_, CommandCode::DISCONNECTION_REQUEST, {}, local_cid, remote_cid, {}}; PendingCommand pending_command = { next_signal_id_, CommandCode::DISCONNECTION_REQUEST, {}, local_cid, remote_cid, {}, {}}; next_signal_id_++; pending_commands_.push(pending_command); pending_commands_.push(std::move(pending_command)); if (pending_commands_.size() == 1) { handle_send_next_command(); } } void ClassicSignallingManager::SendInformationRequest(InformationRequestInfoType type) { PendingCommand pending_command = {next_signal_id_, CommandCode::INFORMATION_REQUEST, {}, {}, {}, type}; PendingCommand pending_command = {next_signal_id_, CommandCode::INFORMATION_REQUEST, {}, {}, {}, type, {}}; next_signal_id_++; pending_commands_.push(pending_command); pending_commands_.push(std::move(pending_command)); if (pending_commands_.size() == 1) { handle_send_next_command(); } Loading Loading @@ -131,6 +141,7 @@ void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm, send_connection_response(signal_id, remote_cid, new_channel->GetCid(), ConnectionResponseResult::SUCCESS, ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE); std::unique_ptr<DynamicChannel> channel = std::make_unique<DynamicChannel>(new_channel, handler_); SendConfigurationRequest(remote_cid, {}); dynamic_service_manager_->GetService(psm)->NotifyChannelCreation(std::move(channel)); } Loading Loading @@ -158,11 +169,21 @@ void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid cid, ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE); std::unique_ptr<DynamicChannel> channel = std::make_unique<DynamicChannel>(new_channel, handler_); dynamic_service_manager_->GetService(pending_psm)->NotifyChannelCreation(std::move(channel)); SendConfigurationRequest(remote_cid, {}); alarm_.Cancel(); } void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid cid, Continuation is_continuation, std::vector<std::unique_ptr<ConfigurationOption>> option) {} std::vector<std::unique_ptr<ConfigurationOption>> option) { auto channel = channel_allocator_->FindChannelByCid(cid); if (channel == nullptr) { LOG_WARN("Configuration request for an unknown channel"); return; } auto response = ConfigurationResponseBuilder::Create(signal_id.Value(), cid, is_continuation, ConfigurationResponseResult::SUCCESS, {}); enqueue_buffer_->Enqueue(std::move(response), handler_); } void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid cid, Continuation is_continuation, ConfigurationResponseResult result, Loading Loading @@ -365,14 +386,14 @@ void ClassicSignallingManager::send_connection_response(SignalId signal_id, Cid void ClassicSignallingManager::on_command_timeout() { LOG_WARN("Response time out"); // TODO: drop the link? link_->OnAclDisconnected(hci::ErrorCode::SUCCESS); } void ClassicSignallingManager::handle_send_next_command() { if (pending_commands_.empty()) { return; } pending_command_ = pending_commands_.front(); pending_command_ = std::move(pending_commands_.front()); pending_commands_.pop(); auto signal_id = pending_command_.signal_id_; Loading @@ -380,6 +401,7 @@ void ClassicSignallingManager::handle_send_next_command() { auto source_cid = pending_command_.source_cid_; auto destination_cid = pending_command_.destination_cid_; auto info_type = pending_command_.info_type_; auto config = std::move(pending_command_.config_); switch (pending_command_.command_code_) { case CommandCode::CONNECTION_REQUEST: { auto builder = ConnectionRequestBuilder::Create(signal_id.Value(), psm, source_cid); Loading @@ -388,8 +410,14 @@ void ClassicSignallingManager::handle_send_next_command() { kTimeout); break; } case CommandCode::CONFIGURATION_REQUEST: case CommandCode::CONFIGURATION_REQUEST: { auto builder = ConfigurationRequestBuilder::Create(signal_id.Value(), destination_cid, Continuation::END, std::move(config)); enqueue_buffer_->Enqueue(std::move(builder), handler_); alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)), kTimeout); break; } case CommandCode::DISCONNECTION_REQUEST: { auto builder = DisconnectionRequestBuilder::Create(signal_id.Value(), destination_cid, source_cid); enqueue_buffer_->Enqueue(std::move(builder), handler_); Loading Loading
system/gd/common/callback_list.h +58 −1 Original line number Diff line number Diff line Loading @@ -16,12 +16,69 @@ #pragma once #include <utility> #include "base/callback_list.h" #include "os/handler.h" /* This file contains CallbackList implementation that will execute callback on provided Handler thread Example usage inside your class: private: common::CallbackList<void(int)> callbacks_list_; public: std::unique_ptr<common::CallbackList<void(int)>::Subscription> RegisterCallback( const base::RepeatingCallback<void(int)>& cb, os::Handler* handler) { return callbacks_list_.Add({cb, handler}); } void NotifyAllCallbacks(int value) { callbacks_list_.Notify(value); } */ namespace bluetooth { namespace common { using base::CallbackList; namespace { template <typename CallbackType> struct CallbackWithHandler { CallbackWithHandler(base::RepeatingCallback<CallbackType> callback, os::Handler* handler) : callback(callback), handler(handler) {} bool is_null() const { return callback.is_null(); } void Reset() { callback.Reset(); } base::RepeatingCallback<CallbackType> callback; os::Handler* handler; }; } // namespace template <typename Sig> class CallbackList; template <typename... Args> class CallbackList<void(Args...)> : public base::internal::CallbackListBase<CallbackWithHandler<void(Args...)>> { public: using CallbackType = CallbackWithHandler<void(Args...)>; CallbackList() = default; template <typename... RunArgs> void Notify(RunArgs&&... args) { auto it = this->GetIterator(); CallbackType* cb; while ((cb = it.GetNext()) != nullptr) { cb->handler->Post(base::Bind(cb->callback, args...)); } } private: DISALLOW_COPY_AND_ASSIGN(CallbackList); }; } // namespace common } // namespace bluetooth
system/gd/l2cap/classic/cert/api.proto +5 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ service L2capModuleCert { rpc FetchConnectionComplete(facade.EventStreamRequest) returns (stream ConnectionCompleteEvent) {} rpc DisconnectLink(DisconnectLinkRequest) returns (google.protobuf.Empty) {} rpc SendConnectionRequest(ConnectionRequest) returns (google.protobuf.Empty) {} rpc SendConfigurationRequest(ConfigurationRequest) returns (SendConfigurationRequestResult) {} rpc SendDisconnectionRequest(DisconnectionRequest) returns (google.protobuf.Empty) {} } Loading @@ -34,6 +35,10 @@ message ConnectionRequest { uint32 scid = 3; } message ConfigurationRequest {} message SendConfigurationRequestResult {} message DisconnectionRequest { facade.BluetoothAddress remote = 1; uint32 dcid = 2; Loading
system/gd/l2cap/classic/cert/cert.cc +13 −0 Original line number Diff line number Diff line Loading @@ -101,6 +101,19 @@ class L2capModuleCertService : public L2capModuleCert::Service { return ::grpc::Status::OK; } ::grpc::Status SendConfigurationRequest( ::grpc::ServerContext* context, const ::bluetooth::l2cap::classic::cert::ConfigurationRequest* request, ::bluetooth::l2cap::classic::cert::SendConfigurationRequestResult* response) override { auto builder = ConfigurationRequestBuilder::Create(1, 0x40, Continuation::END, {}); auto l2cap_builder = BasicFrameBuilder::Create(1, std::move(builder)); outgoing_packet_queue_.push(std::move(l2cap_builder)); if (outgoing_packet_queue_.size() == 1) { acl_connection_->GetAclQueueEnd()->RegisterEnqueue( handler_, common::Bind(&L2capModuleCertService::enqueue_packet_to_acl, common::Unretained(this))); } return ::grpc::Status::OK; } ::grpc::Status SendDisconnectionRequest(::grpc::ServerContext* context, const cert::DisconnectionRequest* request, ::google::protobuf::Empty* response) override { auto builder = DisconnectionRequestBuilder::Create(3, 0x40, 101); Loading
system/gd/l2cap/classic/cert/simple_l2cap_test.py +2 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,8 @@ class SimpleL2capTest(GdBaseTestClass): dut_packet_stream.subscribe() cert_packet_stream.subscribe() self.cert_device.l2cap.SendConfigurationRequest(l2cap_cert_pb2.ConfigurationRequest()) self.cert_device.l2cap.SendL2capPacket(l2cap_facade_pb2.L2capPacket(channel=2, payload=b"abc")) dut_packet_stream.assert_event_occurs( lambda packet: b"abc" in packet.payload Loading
system/gd/l2cap/classic/internal/signalling_manager.cc +39 −11 Original line number Diff line number Diff line Loading @@ -63,29 +63,39 @@ void ClassicSignallingManager::OnCommandReject(CommandRejectView command_reject_ } void ClassicSignallingManager::SendConnectionRequest(Psm psm, Cid local_cid) { PendingCommand pending_command = {next_signal_id_, CommandCode::CONNECTION_REQUEST, psm, local_cid, {}, {}}; PendingCommand pending_command = {next_signal_id_, CommandCode::CONNECTION_REQUEST, psm, local_cid, {}, {}, {}}; next_signal_id_++; pending_commands_.push(pending_command); pending_commands_.push(std::move(pending_command)); if (pending_commands_.size() == 1) { handle_send_next_command(); } } void ClassicSignallingManager::SendConfigurationRequest() {} void ClassicSignallingManager::SendConfigurationRequest(Cid remote_cid, std::vector<std::unique_ptr<ConfigurationOption>> config) { PendingCommand pending_command = {next_signal_id_, CommandCode::CONFIGURATION_REQUEST, {}, {}, remote_cid, {}, std::move(config)}; next_signal_id_++; pending_commands_.push(std::move(pending_command)); if (pending_commands_.size() == 1) { handle_send_next_command(); } } void ClassicSignallingManager::SendDisconnectionRequest(Cid local_cid, Cid remote_cid) { PendingCommand pending_command = {next_signal_id_, CommandCode::DISCONNECTION_REQUEST, {}, local_cid, remote_cid, {}}; PendingCommand pending_command = { next_signal_id_, CommandCode::DISCONNECTION_REQUEST, {}, local_cid, remote_cid, {}, {}}; next_signal_id_++; pending_commands_.push(pending_command); pending_commands_.push(std::move(pending_command)); if (pending_commands_.size() == 1) { handle_send_next_command(); } } void ClassicSignallingManager::SendInformationRequest(InformationRequestInfoType type) { PendingCommand pending_command = {next_signal_id_, CommandCode::INFORMATION_REQUEST, {}, {}, {}, type}; PendingCommand pending_command = {next_signal_id_, CommandCode::INFORMATION_REQUEST, {}, {}, {}, type, {}}; next_signal_id_++; pending_commands_.push(pending_command); pending_commands_.push(std::move(pending_command)); if (pending_commands_.size() == 1) { handle_send_next_command(); } Loading Loading @@ -131,6 +141,7 @@ void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm, send_connection_response(signal_id, remote_cid, new_channel->GetCid(), ConnectionResponseResult::SUCCESS, ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE); std::unique_ptr<DynamicChannel> channel = std::make_unique<DynamicChannel>(new_channel, handler_); SendConfigurationRequest(remote_cid, {}); dynamic_service_manager_->GetService(psm)->NotifyChannelCreation(std::move(channel)); } Loading Loading @@ -158,11 +169,21 @@ void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid cid, ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE); std::unique_ptr<DynamicChannel> channel = std::make_unique<DynamicChannel>(new_channel, handler_); dynamic_service_manager_->GetService(pending_psm)->NotifyChannelCreation(std::move(channel)); SendConfigurationRequest(remote_cid, {}); alarm_.Cancel(); } void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid cid, Continuation is_continuation, std::vector<std::unique_ptr<ConfigurationOption>> option) {} std::vector<std::unique_ptr<ConfigurationOption>> option) { auto channel = channel_allocator_->FindChannelByCid(cid); if (channel == nullptr) { LOG_WARN("Configuration request for an unknown channel"); return; } auto response = ConfigurationResponseBuilder::Create(signal_id.Value(), cid, is_continuation, ConfigurationResponseResult::SUCCESS, {}); enqueue_buffer_->Enqueue(std::move(response), handler_); } void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid cid, Continuation is_continuation, ConfigurationResponseResult result, Loading Loading @@ -365,14 +386,14 @@ void ClassicSignallingManager::send_connection_response(SignalId signal_id, Cid void ClassicSignallingManager::on_command_timeout() { LOG_WARN("Response time out"); // TODO: drop the link? link_->OnAclDisconnected(hci::ErrorCode::SUCCESS); } void ClassicSignallingManager::handle_send_next_command() { if (pending_commands_.empty()) { return; } pending_command_ = pending_commands_.front(); pending_command_ = std::move(pending_commands_.front()); pending_commands_.pop(); auto signal_id = pending_command_.signal_id_; Loading @@ -380,6 +401,7 @@ void ClassicSignallingManager::handle_send_next_command() { auto source_cid = pending_command_.source_cid_; auto destination_cid = pending_command_.destination_cid_; auto info_type = pending_command_.info_type_; auto config = std::move(pending_command_.config_); switch (pending_command_.command_code_) { case CommandCode::CONNECTION_REQUEST: { auto builder = ConnectionRequestBuilder::Create(signal_id.Value(), psm, source_cid); Loading @@ -388,8 +410,14 @@ void ClassicSignallingManager::handle_send_next_command() { kTimeout); break; } case CommandCode::CONFIGURATION_REQUEST: case CommandCode::CONFIGURATION_REQUEST: { auto builder = ConfigurationRequestBuilder::Create(signal_id.Value(), destination_cid, Continuation::END, std::move(config)); enqueue_buffer_->Enqueue(std::move(builder), handler_); alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)), kTimeout); break; } case CommandCode::DISCONNECTION_REQUEST: { auto builder = DisconnectionRequestBuilder::Create(signal_id.Value(), destination_cid, source_cid); enqueue_buffer_->Enqueue(std::move(builder), handler_); Loading