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