/* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "facade/grpc_root_server.h" #include #include "blueberry/facade/rootservice.grpc.pb.h" #include "facade/read_only_property_server.h" #include "grpc/grpc_module.h" #include "hal/facade.h" #include "hci/facade/acl_manager_facade.h" #include "hci/facade/controller_facade.h" #include "hci/facade/facade.h" #include "hci/facade/le_acl_manager_facade.h" #include "hci/facade/le_advertising_manager_facade.h" #include "hci/facade/le_initiator_address_facade.h" #include "hci/facade/le_scanning_manager_facade.h" #include "l2cap/classic/facade.h" #include "l2cap/le/facade.h" #include "neighbor/facade/facade.h" #include "os/log.h" #include "os/thread.h" #include "security/facade.h" #include "stack_manager.h" namespace bluetooth { namespace facade { using ::blueberry::facade::BluetoothModule; using ::bluetooth::grpc::GrpcModule; using ::bluetooth::os::Thread; class RootFacadeService : public ::blueberry::facade::RootFacade::Service { public: explicit RootFacadeService(int grpc_port) : grpc_port_(grpc_port) {} ::grpc::Status StartStack( ::grpc::ServerContext* /* context */, const ::blueberry::facade::StartStackRequest* request, ::blueberry::facade::StartStackResponse* /* response */) override { if (is_running_) { return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "stack is running"); } ModuleList modules; modules.add<::bluetooth::grpc::GrpcModule>(); BluetoothModule module_under_test = request->module_under_test(); switch (module_under_test) { case BluetoothModule::HAL: modules.add<::bluetooth::hal::HciHalFacadeModule>(); break; case BluetoothModule::HCI: modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>(); modules.add<::bluetooth::hci::facade::HciFacadeModule>(); break; case BluetoothModule::HCI_INTERFACES: modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>(); modules.add<::bluetooth::hci::facade::HciFacadeModule>(); modules.add<::bluetooth::hci::facade::AclManagerFacadeModule>(); modules.add<::bluetooth::hci::facade::ControllerFacadeModule>(); modules.add<::bluetooth::hci::facade::LeAclManagerFacadeModule>(); modules.add<::bluetooth::hci::facade::LeAdvertisingManagerFacadeModule>(); modules.add<::bluetooth::hci::facade::LeInitiatorAddressFacadeModule>(); modules.add<::bluetooth::hci::facade::LeScanningManagerFacadeModule>(); modules.add<::bluetooth::neighbor::facade::NeighborFacadeModule>(); break; case BluetoothModule::L2CAP: modules.add<::bluetooth::hci::facade::ControllerFacadeModule>(); modules.add<::bluetooth::hci::facade::LeAdvertisingManagerFacadeModule>(); modules.add<::bluetooth::hci::facade::LeInitiatorAddressFacadeModule>(); modules.add<::bluetooth::neighbor::facade::NeighborFacadeModule>(); modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>(); modules.add<::bluetooth::l2cap::classic::L2capClassicModuleFacadeModule>(); modules.add<::bluetooth::l2cap::le::L2capLeModuleFacadeModule>(); modules.add<::bluetooth::hci::facade::HciFacadeModule>(); break; case BluetoothModule::SECURITY: modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>(); modules.add<::bluetooth::hci::facade::ControllerFacadeModule>(); modules.add<::bluetooth::security::SecurityModuleFacadeModule>(); modules.add<::bluetooth::neighbor::facade::NeighborFacadeModule>(); modules.add<::bluetooth::l2cap::classic::L2capClassicModuleFacadeModule>(); modules.add<::bluetooth::hci::facade::HciFacadeModule>(); modules.add<::bluetooth::hci::facade::ControllerFacadeModule>(); modules.add<::bluetooth::hci::facade::LeAdvertisingManagerFacadeModule>(); modules.add<::bluetooth::hci::facade::LeScanningManagerFacadeModule>(); break; default: return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "invalid module under test"); } stack_thread_ = std::make_unique("stack_thread", Thread::Priority::NORMAL); stack_manager_.StartUp(&modules, stack_thread_.get()); GrpcModule* grpc_module = stack_manager_.GetInstance(); grpc_module->StartServer("0.0.0.0", grpc_port_); grpc_loop_thread_ = std::make_unique([grpc_module] { grpc_module->RunGrpcLoop(); }); is_running_ = true; return ::grpc::Status::OK; } ::grpc::Status StopStack( ::grpc::ServerContext* /* context */, const ::blueberry::facade::StopStackRequest* /* request */, ::blueberry::facade::StopStackResponse* /* response */) override { if (!is_running_) { return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "stack is not running"); } stack_manager_.GetInstance()->StopServer(); grpc_loop_thread_->join(); grpc_loop_thread_.reset(); stack_manager_.ShutDown(); stack_thread_.reset(); is_running_ = false; return ::grpc::Status::OK; } private: std::unique_ptr stack_thread_ = nullptr; bool is_running_ = false; std::unique_ptr grpc_loop_thread_ = nullptr; StackManager stack_manager_; int grpc_port_ = 8898; }; struct GrpcRootServer::impl { bool started_ = false; std::unique_ptr root_facade_service_ = nullptr; std::unique_ptr<::grpc::Server> server_ = nullptr; }; GrpcRootServer::GrpcRootServer() : pimpl_(new impl()) {} GrpcRootServer::~GrpcRootServer() = default; void GrpcRootServer::StartServer(const std::string& address, int grpc_root_server_port, int grpc_port) { log::assert_that(!pimpl_->started_, "assert failed: !pimpl_->started_"); pimpl_->started_ = true; std::string listening_port = address + ":" + std::to_string(grpc_root_server_port); ::grpc::ServerBuilder builder; pimpl_->root_facade_service_ = std::make_unique(grpc_port); builder.RegisterService(pimpl_->root_facade_service_.get()); builder.AddListeningPort(listening_port, ::grpc::InsecureServerCredentials()); pimpl_->server_ = builder.BuildAndStart(); log::assert_that(pimpl_->server_ != nullptr, "assert failed: pimpl_->server_ != nullptr"); } void GrpcRootServer::StopServer() { log::assert_that(pimpl_->started_, "assert failed: pimpl_->started_"); pimpl_->server_->Shutdown(); pimpl_->started_ = false; } void GrpcRootServer::RunGrpcLoop() { log::assert_that(pimpl_->started_, "assert failed: pimpl_->started_"); pimpl_->server_->Wait(); } } // namespace facade } // namespace bluetooth