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 
17 #include "facade/grpc_root_server.h"
18 
19 #include <string>
20 
21 #include "blueberry/facade/rootservice.grpc.pb.h"
22 #include "facade/read_only_property_server.h"
23 #include "grpc/grpc_module.h"
24 #include "hal/facade.h"
25 #include "hci/facade/acl_manager_facade.h"
26 #include "hci/facade/controller_facade.h"
27 #include "hci/facade/facade.h"
28 #include "hci/facade/le_acl_manager_facade.h"
29 #include "hci/facade/le_advertising_manager_facade.h"
30 #include "hci/facade/le_initiator_address_facade.h"
31 #include "hci/facade/le_scanning_manager_facade.h"
32 #include "neighbor/facade/facade.h"
33 #include "os/thread.h"
34 #include "stack_manager.h"
35 
36 namespace bluetooth {
37 namespace facade {
38 
39 using ::blueberry::facade::BluetoothModule;
40 using ::bluetooth::grpc::GrpcModule;
41 using ::bluetooth::os::Thread;
42 
43 class RootFacadeService : public ::blueberry::facade::RootFacade::Service {
44 public:
RootFacadeService(int grpc_port)45   explicit RootFacadeService(int grpc_port) : grpc_port_(grpc_port) {}
46 
StartStack(::grpc::ServerContext *,const::blueberry::facade::StartStackRequest * request,::blueberry::facade::StartStackResponse *)47   ::grpc::Status StartStack(::grpc::ServerContext* /* context */,
48                             const ::blueberry::facade::StartStackRequest* request,
49                             ::blueberry::facade::StartStackResponse* /* response */) override {
50     if (is_running_) {
51       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "stack is running");
52     }
53 
54     ModuleList modules;
55     modules.add<::bluetooth::grpc::GrpcModule>();
56 
57     BluetoothModule module_under_test = request->module_under_test();
58     switch (module_under_test) {
59       case BluetoothModule::HAL:
60         modules.add<::bluetooth::hal::HciHalFacadeModule>();
61         break;
62       case BluetoothModule::HCI:
63         modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>();
64         modules.add<::bluetooth::hci::facade::HciFacadeModule>();
65         break;
66       case BluetoothModule::HCI_INTERFACES:
67         modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>();
68         modules.add<::bluetooth::hci::facade::HciFacadeModule>();
69         modules.add<::bluetooth::hci::facade::AclManagerFacadeModule>();
70         modules.add<::bluetooth::hci::facade::ControllerFacadeModule>();
71         modules.add<::bluetooth::hci::facade::LeAclManagerFacadeModule>();
72         modules.add<::bluetooth::hci::facade::LeAdvertisingManagerFacadeModule>();
73         modules.add<::bluetooth::hci::facade::LeInitiatorAddressFacadeModule>();
74         modules.add<::bluetooth::hci::facade::LeScanningManagerFacadeModule>();
75         modules.add<::bluetooth::neighbor::facade::NeighborFacadeModule>();
76         break;
77       default:
78         return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "invalid module under test");
79     }
80 
81     stack_thread_ = std::make_unique<Thread>("stack_thread", Thread::Priority::NORMAL);
82     stack_manager_.StartUp(&modules, stack_thread_.get());
83 
84     GrpcModule* grpc_module = stack_manager_.GetInstance<GrpcModule>();
85     grpc_module->StartServer("0.0.0.0", grpc_port_);
86 
87     grpc_loop_thread_ =
88             std::make_unique<std::thread>([grpc_module] { grpc_module->RunGrpcLoop(); });
89     is_running_ = true;
90 
91     return ::grpc::Status::OK;
92   }
93 
StopStack(::grpc::ServerContext *,const::blueberry::facade::StopStackRequest *,::blueberry::facade::StopStackResponse *)94   ::grpc::Status StopStack(::grpc::ServerContext* /* context */,
95                            const ::blueberry::facade::StopStackRequest* /* request */,
96                            ::blueberry::facade::StopStackResponse* /* response */) override {
97     if (!is_running_) {
98       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "stack is not running");
99     }
100 
101     stack_manager_.GetInstance<GrpcModule>()->StopServer();
102     grpc_loop_thread_->join();
103     grpc_loop_thread_.reset();
104 
105     stack_manager_.ShutDown();
106     stack_thread_.reset();
107     is_running_ = false;
108     return ::grpc::Status::OK;
109   }
110 
111 private:
112   std::unique_ptr<Thread> stack_thread_ = nullptr;
113   bool is_running_ = false;
114   std::unique_ptr<std::thread> grpc_loop_thread_ = nullptr;
115   StackManager stack_manager_;
116   int grpc_port_ = 8898;
117 };
118 
119 struct GrpcRootServer::impl {
120   bool started_ = false;
121   std::unique_ptr<RootFacadeService> root_facade_service_ = nullptr;
122   std::unique_ptr<::grpc::Server> server_ = nullptr;
123 };
124 
GrpcRootServer()125 GrpcRootServer::GrpcRootServer() : pimpl_(new impl()) {}
126 
127 GrpcRootServer::~GrpcRootServer() = default;
128 
StartServer(const std::string & address,int grpc_root_server_port,int grpc_port)129 void GrpcRootServer::StartServer(const std::string& address, int grpc_root_server_port,
130                                  int grpc_port) {
131   log::assert_that(!pimpl_->started_, "assert failed: !pimpl_->started_");
132   pimpl_->started_ = true;
133 
134   std::string listening_port = address + ":" + std::to_string(grpc_root_server_port);
135   ::grpc::ServerBuilder builder;
136 
137   pimpl_->root_facade_service_ = std::make_unique<RootFacadeService>(grpc_port);
138   builder.RegisterService(pimpl_->root_facade_service_.get());
139   builder.AddListeningPort(listening_port, ::grpc::InsecureServerCredentials());
140   pimpl_->server_ = builder.BuildAndStart();
141 
142   log::assert_that(pimpl_->server_ != nullptr, "assert failed: pimpl_->server_ != nullptr");
143 }
144 
StopServer()145 void GrpcRootServer::StopServer() {
146   log::assert_that(pimpl_->started_, "assert failed: pimpl_->started_");
147   pimpl_->server_->Shutdown();
148   pimpl_->started_ = false;
149 }
150 
RunGrpcLoop()151 void GrpcRootServer::RunGrpcLoop() {
152   log::assert_that(pimpl_->started_, "assert failed: pimpl_->started_");
153   pimpl_->server_->Wait();
154 }
155 
156 }  // namespace facade
157 }  // namespace bluetooth
158