Migrate GD code to module
Test: atest --host bluetooth_test_gd
Change-Id: Ibcb219666ff5552efc602bf063e69a6e6b7e4bd8
diff --git a/gd/Android.bp b/gd/Android.bp
index 572eebc..da660ab 100644
--- a/gd/Android.bp
+++ b/gd/Android.bp
@@ -24,6 +24,9 @@
"-fvisibility=hidden",
"-DLOG_NDEBUG=1",
"-DGOOGLE_PROTOBUF_NO_RTTI",
+ "-Wno-unused-parameter",
+ "-Wno-implicit-fallthrough",
+ "-Wno-unused-result",
],
conlyflags: [
"-std=c99",
@@ -116,9 +119,8 @@
],
host_supported: true,
srcs: [
- "stack_manager.cc",
"facade/stack_with_grpc_main.cc",
- "facade/facade_manager.cc",
+ "grpc/grpc_module.cc",
":BluetoothCertFacade_hci_hal",
],
generated_headers: [
@@ -146,11 +148,6 @@
],
},
},
- cflags: [
- "-Wno-unused-parameter",
- "-Wno-implicit-fallthrough",
- "-Wno-unused-result",
- ],
sanitize: {
address: true,
},
@@ -182,11 +179,6 @@
sanitize: {
address: true,
},
- cflags: [
- "-Wno-unused-parameter",
- "-Wno-implicit-fallthrough",
- "-Wno-unused-result",
- ],
}
cc_test {
@@ -228,11 +220,6 @@
":BluetoothL2capTestSources",
":BluetoothPacketTestSources",
],
- cflags: [
- "-Wno-unused-parameter",
- "-Wno-implicit-fallthrough",
- "-Wno-unused-result",
- ],
generated_headers : [
"BluetoothGeneratedPackets_h",
],
diff --git a/gd/facade/facade_manager.cc b/gd/facade/facade_manager.cc
deleted file mode 100644
index 95decb0..0000000
--- a/gd/facade/facade_manager.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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/facade_manager.h"
-
-#include "grpc/async_grpc.h"
-#include "hal/facade/facade.h"
-#include "os/log.h"
-#include "stack_manager.h"
-
-using ::bluetooth::hal::HciPacket;
-
-using ::grpc::Server;
-using ::grpc::ServerBuilder;
-
-namespace {
-
-::bluetooth::facade::CertFacade* module_enum_to_module(const ::bluetooth::facade::FacadeManager::Module& module) {
- switch (module) {
- case ::bluetooth::facade::FacadeManager::Module::HciHal:
- return ::bluetooth::hal::facade::GetFacadeModule();
- }
- return nullptr;
-}
-} // namespace
-
-namespace bluetooth {
-namespace facade {
-
-void FacadeManager::EnableModule(Module module) {
- enabled_modules_.push_back(module);
-}
-
-void FacadeManager::StartUp() {
- StackManager::Get()->StartUp();
- LOG_INFO("%d", FacadeConfig::Get()->GetGrpcPort());
- start_server("0.0.0.0", FacadeConfig::Get()->GetGrpcPort());
-
- for (const auto& enabled_module : enabled_modules_) {
- auto* module = module_enum_to_module(enabled_module);
- module->StartUp(get_grpc_completion_queue());
- }
-}
-
-void FacadeManager::start_server(const std::string& address, int port) {
- std::string listening_port = address + ":" + std::to_string(port);
- ServerBuilder builder;
- builder.AddListeningPort(listening_port, ::grpc::InsecureServerCredentials());
-
- grpc_completion_queue_ = builder.AddCompletionQueue();
- for (const auto& enabled_module : enabled_modules_) {
- auto* module = module_enum_to_module(enabled_module);
- builder.RegisterService(module->GetModuleGrpcService());
- }
-
- server_ = builder.BuildAndStart();
-}
-
-void FacadeManager::ShutDown() {
- stop_server();
-
- for (const auto& enabled_module : enabled_modules_) {
- auto* module = module_enum_to_module(enabled_module);
- module->ShutDown();
- }
-
- StackManager::Get()->ShutDown();
-}
-
-void FacadeManager::stop_server() {
- server_->Shutdown();
- grpc_completion_queue_->Shutdown();
-}
-
-::grpc::ServerCompletionQueue* FacadeManager::get_grpc_completion_queue() {
- auto* queue = grpc_completion_queue_.get();
- ASSERT(queue != nullptr);
- return queue;
-}
-
-void FacadeManager::GrpcMainLoop() {
- void* tag;
- bool ok;
- while (true) {
- if (!grpc_completion_queue_->Next(&tag, &ok)) {
- LOG_INFO("gRPC is shutdown");
- break;
- }
- auto* data = static_cast<grpc::GrpcAsyncEventCallback*>(tag);
- (*data)(ok);
- }
-}
-
-} // namespace facade
-} // namespace bluetooth
diff --git a/gd/facade/facade_manager.h b/gd/facade/facade_manager.h
deleted file mode 100644
index 969ba6a..0000000
--- a/gd/facade/facade_manager.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <functional>
-#include <list>
-
-#include <grpc++/grpc++.h>
-
-#include "hal/hci_hal.h"
-
-namespace bluetooth {
-namespace facade {
-
-class FacadeConfig {
- public:
- static FacadeConfig* Get() {
- static FacadeConfig instance;
- return &instance;
- }
-
- void SetGrpcPort(int port) {
- grpc_port_ = port;
- }
-
- int GetGrpcPort() {
- return grpc_port_;
- }
-
- private:
- FacadeConfig() = default;
- int grpc_port_ = 8899;
-};
-
-class FacadeManager {
- public:
- enum class Module {
- HciHal,
- };
-
- static FacadeManager* Get() {
- static FacadeManager instance;
- return &instance;
- }
-
- void EnableModule(Module module);
-
- void StartUp();
-
- void ShutDown();
-
- // Blocks for incoming gRPC requests
- void GrpcMainLoop();
-
- private:
- std::unique_ptr<::grpc::Server> server_ = nullptr;
- std::unique_ptr<::grpc::ServerCompletionQueue> grpc_completion_queue_ = nullptr;
- std::list<Module> enabled_modules_;
- void start_server(const std::string& address, int port);
- void stop_server();
- ::grpc::ServerCompletionQueue* get_grpc_completion_queue();
-};
-
-// Cert facade for each layer
-class CertFacade {
- public:
- virtual ~CertFacade() = default;
-
- // Initialize gRPC service, asynchronous request handlers, and other resources here.
- // This should be invoked after CompletionQueue is started.
- virtual void StartUp(::grpc::ServerCompletionQueue* cq) {}
-
- // Do the clean up here
- // This should be invoked before CompletionQueue is shutdown.
- virtual void ShutDown() {}
-
- // Each facade has a gRPC service that implements stubs from its api proto. The service instance should exist all
- // the time, so static storage is recommended.
- virtual ::grpc::Service* GetModuleGrpcService() const = 0;
-};
-
-} // namespace facade
-} // namespace bluetooth
diff --git a/gd/facade/stack_with_grpc_main.cc b/gd/facade/stack_with_grpc_main.cc
index 054b44b..67b618d 100644
--- a/gd/facade/stack_with_grpc_main.cc
+++ b/gd/facade/stack_with_grpc_main.cc
@@ -14,26 +14,33 @@
* limitations under the License.
*/
-#include "facade/facade_manager.h"
+#include "grpc/grpc_module.h"
#include "hal/hci_hal_host_rootcanal.h"
+#include "hal/facade/facade.h"
#include <csignal>
#include <string>
#include <thread>
-using ::bluetooth::facade::FacadeConfig;
-using ::bluetooth::facade::FacadeManager;
+#include "stack_manager.h"
+
using ::bluetooth::hal::HciHalHostRootcanalConfig;
+using ::bluetooth::StackManager;
+using ::bluetooth::grpc::GrpcModule;
+using ::bluetooth::ModuleList;
namespace {
+static StackManager* stack;
+
void interrupt_handler(int) {
- FacadeManager::Get()->ShutDown();
+ stack->GetInstance<GrpcModule>()->StopServer();
}
} // namespace
// The entry point for the binary with libbluetooth + facades
int main(int argc, const char** argv) {
- signal(SIGINT, interrupt_handler);
+
+ int port = 8899;
const std::string arg_grpc_port = "--port=";
const std::string arg_rootcanal_port = "--rootcanal-port=";
@@ -41,7 +48,7 @@
std::string arg = argv[i];
if (arg.find(arg_grpc_port) == 0) {
auto port_number = arg.substr(arg_grpc_port.size());
- FacadeConfig::Get()->SetGrpcPort(std::stoi(port_number));
+ port = std::stoi(port_number);
}
if (arg.find(arg_rootcanal_port) == 0) {
auto port_number = arg.substr(arg_rootcanal_port.size());
@@ -49,13 +56,22 @@
}
}
- // TODO: This should be run-time configurable
- FacadeManager::Get()->EnableModule(FacadeManager::Module::HciHal);
+ ModuleList modules;
+ modules.add<::bluetooth::hal::facade::HalFacadeModule>();
- FacadeManager::Get()->StartUp();
- auto wait_thread = std::thread([] { FacadeManager::Get()->GrpcMainLoop(); });
+ stack = new StackManager();
+ stack->StartUp(&modules);
+
+ GrpcModule* grpc_module = stack->GetInstance<GrpcModule>();
+ grpc_module->StartServer("0.0.0.0", port);
+
+ signal(SIGINT, interrupt_handler);
+ auto wait_thread = std::thread([grpc_module] { grpc_module->RunGrpcLoop(); });
wait_thread.join();
- FacadeManager::Get()->ShutDown();
+
+ grpc_module->StopServer();
+ stack->ShutDown();
+ delete stack;
return 0;
}
diff --git a/gd/grpc/grpc_module.cc b/gd/grpc/grpc_module.cc
new file mode 100644
index 0000000..60099a8
--- /dev/null
+++ b/gd/grpc/grpc_module.cc
@@ -0,0 +1,122 @@
+/*
+ * 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 "grpc/grpc_module.h"
+
+#include "os/log.h"
+#include "grpc/async_grpc.h"
+
+using ::grpc::Server;
+using ::grpc::ServerBuilder;
+
+namespace bluetooth {
+namespace grpc {
+
+void GrpcModule::ListDependencies(ModuleList* list) {
+}
+
+void GrpcModule::Start(const ModuleRegistry* registry) {
+ ASSERT(!started_);
+}
+
+void GrpcModule::Stop(const ModuleRegistry* registry) {
+ ASSERT(!started_);
+}
+
+void GrpcModule::StartServer(const std::string& address, int port) {
+ ASSERT(!started_);
+ started_ = true;
+
+ std::string listening_port = address + ":" + std::to_string(port);
+ ServerBuilder builder;
+
+ for (const auto& facade : facades_) {
+ builder.RegisterService(facade->GetService());
+ }
+
+ builder.AddListeningPort(listening_port, ::grpc::InsecureServerCredentials());
+ completion_queue_ = builder.AddCompletionQueue();
+ server_ = builder.BuildAndStart();
+
+ for (const auto& facade : facades_) {
+ facade->OnServerStarted(completion_queue_.get());
+ }
+}
+
+void GrpcModule::StopServer() {
+ ASSERT(started_);
+
+ server_->Shutdown();
+ completion_queue_->Shutdown();
+
+ for (const auto& facade : facades_) {
+ facade->OnServerStopped();
+ }
+
+ started_ = false;
+}
+
+void GrpcModule::Register(GrpcFacadeModule* facade) {
+ ASSERT(!started_);
+
+ facades_.push_back(facade);
+}
+
+void GrpcModule::Unregister(GrpcFacadeModule* facade) {
+ ASSERT(!started_);
+
+ for (auto it = facades_.begin(); it != facades_.end(); it++) {
+ if (*it == facade) {
+ facades_.erase(it);
+ return;
+ }
+ }
+
+ ASSERT(false);
+}
+
+void GrpcModule::RunGrpcLoop() {
+ void* tag;
+ bool ok;
+ while (true) {
+ if (!completion_queue_->Next(&tag, &ok)) {
+ LOG_INFO("gRPC is shutdown");
+ break;
+ }
+ auto* data = static_cast<GrpcAsyncEventCallback*>(tag);
+ (*data)(ok);
+ }
+}
+
+const ::bluetooth::ModuleFactory GrpcModule::Factory = ::bluetooth::ModuleFactory([]() {
+ return new GrpcModule();
+});
+
+
+void GrpcFacadeModule::ListDependencies(ModuleList* list) {
+ list->add<GrpcModule>();
+}
+
+void GrpcFacadeModule::Start(const ModuleRegistry* registry) {
+ registry->GetInstance<GrpcModule>()->Register(this);
+}
+
+void GrpcFacadeModule::Stop(const ModuleRegistry* registry) {
+ registry->GetInstance<GrpcModule>()->Unregister(this);
+}
+
+} // namespace grpc
+} // namespace bluetooth
diff --git a/gd/grpc/grpc_module.h b/gd/grpc/grpc_module.h
new file mode 100644
index 0000000..f059a69
--- /dev/null
+++ b/gd/grpc/grpc_module.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <functional>
+#include <vector>
+
+#include <grpc++/grpc++.h>
+#include <module.h>
+
+namespace bluetooth {
+namespace grpc {
+
+class GrpcFacadeModule;
+
+class GrpcModule : public ::bluetooth::Module {
+ public:
+ static const ModuleFactory Factory;
+
+ void StartServer(const std::string& address, int port);
+
+ void StopServer();
+
+ void Register(GrpcFacadeModule* facade);
+
+ void Unregister(GrpcFacadeModule* facade);
+
+ // Blocks for incoming gRPC requests
+ void RunGrpcLoop();
+
+ protected:
+ void ListDependencies(ModuleList* list) override;
+
+ void Start(const ModuleRegistry* registry) override;
+
+ void Stop(const ModuleRegistry* registry) override;
+
+ private:
+ bool started_;
+ std::unique_ptr<::grpc::Server> server_ = nullptr;
+ std::unique_ptr<::grpc::ServerCompletionQueue> completion_queue_ = nullptr;
+ std::vector<GrpcFacadeModule*> facades_;
+};
+
+class GrpcFacadeModule : public ::bluetooth::Module {
+ friend GrpcModule;
+ protected:
+ void ListDependencies(ModuleList* list) override;
+
+ void Start(const ModuleRegistry* registry) override;
+
+ void Stop(const ModuleRegistry* registry) override;
+
+ virtual ::grpc::Service* GetService() const = 0;
+
+ virtual void OnServerStarted(::grpc::ServerCompletionQueue* cq) {}
+
+ virtual void OnServerStopped() {}
+};
+
+} // namespace grpc
+} // namespace bluetooth
diff --git a/gd/hal/cert/simple_hal_test.cc b/gd/hal/cert/simple_hal_test.cc
index b5879a2..8804a23 100644
--- a/gd/hal/cert/simple_hal_test.cc
+++ b/gd/hal/cert/simple_hal_test.cc
@@ -21,7 +21,6 @@
#include <string>
#include <thread>
-#include "facade/facade_manager.h"
#include "hal/facade/api.grpc.pb.h"
#include "hci/hci_packets.h"
#include "os/log.h"
@@ -40,7 +39,7 @@
class HalAdapterCertTest : public ::testing::Test {
protected:
void SetUp() override {
- int port = ::bluetooth::facade::FacadeConfig::Get()->GetGrpcPort();
+ int port = 8899;
std::string channel = "localhost:" + std::to_string(port);
stub_ = HciTransportation::NewStub(grpc::CreateChannel(channel, grpc::InsecureChannelCredentials()));
}
diff --git a/gd/hal/facade/facade.cc b/gd/hal/facade/facade.cc
index 9163fb3..7542931 100644
--- a/gd/hal/facade/facade.cc
+++ b/gd/hal/facade/facade.cc
@@ -35,16 +35,13 @@
namespace hal {
namespace facade {
-namespace {
-
-HalFacadeModule hci_cert_module_instance_;
-
-void stop_stream_hci_evt();
-void stop_stream_hci_acl();
-void stop_stream_hci_sco();
-
-class HciTransportationSyncService : public HciTransportation::Service {
+class HciTransportationService
+ : public HciTransportation::Service,
+ public ::bluetooth::hal::BluetoothHciHalCallbacks {
public:
+ HciTransportationService(BluetoothHciHal* hal) : hal_(hal) {
+ }
+
::grpc::Status SetLoopbackMode(::grpc::ServerContext* context,
const ::bluetooth::hal::facade::LoopbackModeSettings* request,
::google::protobuf::Empty* response) override {
@@ -54,277 +51,70 @@
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
hci::BitInserter it(*packet_bytes);
packet->Serialize(it);
- GetBluetoothHciHal()->sendHciCommand(*packet_bytes);
+ hal_->sendHciCommand(*packet_bytes);
return ::grpc::Status::OK;
}
::grpc::Status SendHciCmd(::grpc::ServerContext* context, const ::bluetooth::hal::facade::HciCmdPacket* request,
::google::protobuf::Empty* response) override {
std::string req_string = request->payload();
- ::bluetooth::hal::GetBluetoothHciHal()->sendHciCommand(std::vector<uint8_t>(req_string.begin(), req_string.end()));
+ hal_->sendHciCommand(std::vector<uint8_t>(req_string.begin(), req_string.end()));
return ::grpc::Status::OK;
}
::grpc::Status SendHciAcl(::grpc::ServerContext* context, const ::bluetooth::hal::facade::HciAclPacket* request,
::google::protobuf::Empty* response) override {
std::string req_string = request->payload();
- ::bluetooth::hal::GetBluetoothHciHal()->sendAclData(std::vector<uint8_t>(req_string.begin(), req_string.end()));
+ hal_->sendAclData(std::vector<uint8_t>(req_string.begin(), req_string.end()));
return ::grpc::Status::OK;
}
::grpc::Status SendHciSco(::grpc::ServerContext* context, const ::bluetooth::hal::facade::HciScoPacket* request,
::google::protobuf::Empty* response) override {
std::string req_string = request->payload();
- ::bluetooth::hal::GetBluetoothHciHal()->sendScoData(std::vector<uint8_t>(req_string.begin(), req_string.end()));
+ hal_->sendScoData(std::vector<uint8_t>(req_string.begin(), req_string.end()));
return ::grpc::Status::OK;
}
- ::grpc::Status UnregisterHciEvt(::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
- ::google::protobuf::Empty* response) override {
- stop_stream_hci_evt();
- return ::grpc::Status::OK;
- }
- ::grpc::Status UnregisterHciAcl(::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
- ::google::protobuf::Empty* response) override {
- stop_stream_hci_acl();
- return ::grpc::Status::OK;
- }
-
- ::grpc::Status UnregisterHciSco(::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
- ::google::protobuf::Empty* response) override {
- stop_stream_hci_sco();
- return ::grpc::Status::OK;
- }
-};
-
-using HciTransportationAsyncService =
- HciTransportation::WithAsyncMethod_RegisterHciEvt<HciTransportation::WithAsyncMethod_RegisterHciAcl<
- HciTransportation::WithAsyncMethod_RegisterHciSco<HciTransportationSyncService>>>;
-
-HciTransportationAsyncService async_service_;
-
-class RegisterHciEvtImpl : public grpc::GrpcAsyncServerStreamingHandler<::google::protobuf::Empty, HciEvtPacket>,
- public HalFacadeModule::HciEvtListener {
- public:
- explicit RegisterHciEvtImpl(HciTransportationAsyncService* service, ::grpc::ServerCompletionQueue* cq)
- : service_(service), streaming_control_box_(this, cq) {
- streaming_control_box_.RequestNewRpc();
- }
-
- void OnReadyForNextRequest(::grpc::ServerContext* context, google::protobuf::Empty* req,
- ServerAsyncWriter<HciEvtPacket>* res, ::grpc::CompletionQueue* new_call_cq,
- ServerCompletionQueue* notification_cq, void* tag) override {
- service_->RequestRegisterHciEvt(context, req, res, new_call_cq, notification_cq, tag);
- }
-
- void OnRpcRequestReceived(google::protobuf::Empty) override {
- hci_cert_module_instance_.RegisterHciEvtListener(this);
- }
-
- void OnRpcFinished() override {
- streaming_control_box_.RequestNewRpc();
- }
-
- void operator()(const hal::HciPacket& hciPacket) override {
- HciEvtPacket packet;
- packet.set_payload(std::string(hciPacket.begin(), hciPacket.end()));
- streaming_control_box_.Write(packet);
- }
-
- void StopStream() {
- hci_cert_module_instance_.UnregisterHciEvtListener(this);
- streaming_control_box_.StopStreaming();
- }
-
- private:
- HciTransportationAsyncService* service_;
- grpc::GrpcAsyncServerStreamingControlBox<::google::protobuf::Empty, HciEvtPacket> streaming_control_box_;
-};
-
-class RegisterHciAclImpl : public grpc::GrpcAsyncServerStreamingHandler<::google::protobuf::Empty, HciAclPacket>,
- public HalFacadeModule::HciAclListener {
- public:
- explicit RegisterHciAclImpl(HciTransportationAsyncService* service, ::grpc::ServerCompletionQueue* cq)
- : service_(service), streaming_control_box_(this, cq) {
- streaming_control_box_.RequestNewRpc();
- }
-
- void OnReadyForNextRequest(::grpc::ServerContext* context, google::protobuf::Empty* req,
- ServerAsyncWriter<HciAclPacket>* res, ::grpc::CompletionQueue* new_call_cq,
- ServerCompletionQueue* notification_cq, void* tag) override {
- service_->RequestRegisterHciAcl(context, req, res, new_call_cq, notification_cq, tag);
- }
-
- void OnRpcRequestReceived(google::protobuf::Empty) override {
- hci_cert_module_instance_.RegisterHciAclListener(this);
- }
-
- void OnRpcFinished() override {
- streaming_control_box_.RequestNewRpc();
- }
-
- void operator()(const hal::HciPacket& hciPacket) override {
- HciAclPacket packet;
- packet.set_payload(std::string(hciPacket.begin(), hciPacket.end()));
- streaming_control_box_.Write(packet);
- }
-
- void StopStream() {
- hci_cert_module_instance_.UnregisterHciAclListener(this);
- streaming_control_box_.StopStreaming();
- }
-
- private:
- HciTransportationAsyncService* service_;
- grpc::GrpcAsyncServerStreamingControlBox<::google::protobuf::Empty, HciAclPacket> streaming_control_box_;
-};
-
-class RegisterHciScoImpl : public grpc::GrpcAsyncServerStreamingHandler<::google::protobuf::Empty, HciScoPacket>,
- public HalFacadeModule::HciScoListener {
- public:
- explicit RegisterHciScoImpl(HciTransportationAsyncService* service, ::grpc::ServerCompletionQueue* cq)
- : service_(service), streaming_control_box_(this, cq) {
- streaming_control_box_.RequestNewRpc();
- }
-
- void OnReadyForNextRequest(::grpc::ServerContext* context, google::protobuf::Empty* req,
- ServerAsyncWriter<HciScoPacket>* res, ::grpc::CompletionQueue* new_call_cq,
- ServerCompletionQueue* notification_cq, void* tag) override {
- service_->RequestRegisterHciSco(context, req, res, new_call_cq, notification_cq, tag);
- }
-
- void OnRpcRequestReceived(google::protobuf::Empty) override {
- hci_cert_module_instance_.RegisterHciScoListener(this);
- }
-
- void OnRpcFinished() override {
- streaming_control_box_.RequestNewRpc();
- }
-
- void operator()(const hal::HciPacket& hciPacket) override {
- HciScoPacket packet;
- packet.set_payload(std::string(hciPacket.begin(), hciPacket.end()));
- streaming_control_box_.Write(packet);
- }
-
- void StopStream() {
- hci_cert_module_instance_.UnregisterHciScoListener(this);
- streaming_control_box_.StopStreaming();
- }
-
- private:
- HciTransportationAsyncService* service_;
- grpc::GrpcAsyncServerStreamingControlBox<::google::protobuf::Empty, HciScoPacket> streaming_control_box_;
-};
-
-struct GrpcHelper {
- explicit GrpcHelper(::grpc::ServerCompletionQueue* cq)
- : hci_evt_impl_(&async_service_, cq), hci_acl_impl_(&async_service_, cq), hci_sco_impl_(&async_service_, cq) {}
-
- RegisterHciEvtImpl hci_evt_impl_;
- RegisterHciAclImpl hci_acl_impl_;
- RegisterHciScoImpl hci_sco_impl_;
-};
-GrpcHelper* grpc_helper_instance_ = nullptr;
-
-void stop_stream_hci_evt() {
- grpc_helper_instance_->hci_evt_impl_.StopStream();
-}
-
-void stop_stream_hci_acl() {
- grpc_helper_instance_->hci_acl_impl_.StopStream();
-}
-
-void stop_stream_hci_sco() {
- grpc_helper_instance_->hci_sco_impl_.StopStream();
-}
-
-} // namespace
-
-class IncomingPacketCallback : public ::bluetooth::hal::BluetoothHciHalCallbacks {
- public:
- explicit IncomingPacketCallback(HalFacadeModule* hal_cert_module) : hal_cert_module_(hal_cert_module) {}
-
void hciEventReceived(bluetooth::hal::HciPacket event) override {
- std::unique_lock<std::mutex> lock(hal_cert_module_->mutex_);
- for (auto* listener : hal_cert_module_->registered_evt_listener_) {
- (*listener)(event);
- }
+ // TODO
}
void aclDataReceived(bluetooth::hal::HciPacket data) override {
- std::unique_lock<std::mutex> lock(hal_cert_module_->mutex_);
- for (auto* listener : hal_cert_module_->registered_acl_listener_) {
- (*listener)(data);
- }
+ // TODO
}
void scoDataReceived(bluetooth::hal::HciPacket data) override {
- std::unique_lock<std::mutex> lock(hal_cert_module_->mutex_);
- for (auto* listener : hal_cert_module_->registered_sco_listener_) {
- (*listener)(data);
- }
+ // TODO
}
-
private:
- HalFacadeModule* hal_cert_module_;
+ BluetoothHciHal* hal_;
};
-static IncomingPacketCallback* incoming_packet_callback_;
-
-void HalFacadeModule::StartUp(::grpc::ServerCompletionQueue* cq) {
- std::unique_lock<std::mutex> lock(mutex_);
- incoming_packet_callback_ = new IncomingPacketCallback(this);
- hal::GetBluetoothHciHal()->registerIncomingPacketCallback(incoming_packet_callback_);
-
- grpc_helper_instance_ = new GrpcHelper(cq);
+void HalFacadeModule::ListDependencies(ModuleList* list) {
+ ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
+ list->add<BluetoothHciHal>();
}
-void HalFacadeModule::ShutDown() {
- std::unique_lock<std::mutex> lock(mutex_);
- delete grpc_helper_instance_;
- grpc_helper_instance_ = nullptr;
- delete incoming_packet_callback_;
- incoming_packet_callback_ = nullptr;
+void HalFacadeModule::Start(const ModuleRegistry* registry) {
+ ::bluetooth::grpc::GrpcFacadeModule::Start(registry);
+ auto hal = registry->GetInstance<BluetoothHciHal>();
+
+ service_ = new HciTransportationService(hal);
+ hal->registerIncomingPacketCallback(service_);
}
-::grpc::Service* HalFacadeModule::GetModuleGrpcService() const {
- return &async_service_;
+void HalFacadeModule::Stop(const ModuleRegistry* registry) {
+ delete service_;
}
-void HalFacadeModule::RegisterHciEvtListener(HciEvtListener* listener) {
- std::unique_lock<std::mutex> lock(mutex_);
- registered_evt_listener_.push_back(listener);
+::grpc::Service* HalFacadeModule::GetService() const {
+ return service_;
}
-void HalFacadeModule::UnregisterHciEvtListener(HciEvtListener* listener) {
- std::unique_lock<std::mutex> lock(mutex_);
- registered_evt_listener_.remove(listener);
-}
-
-void HalFacadeModule::RegisterHciAclListener(HciAclListener* listener) {
- std::unique_lock<std::mutex> lock(mutex_);
- registered_acl_listener_.push_back(listener);
-}
-
-void HalFacadeModule::UnregisterHciAclListener(HciAclListener* listener) {
- std::unique_lock<std::mutex> lock(mutex_);
- registered_acl_listener_.remove(listener);
-}
-
-void HalFacadeModule::RegisterHciScoListener(HciScoListener* listener) {
- std::unique_lock<std::mutex> lock(mutex_);
- registered_sco_listener_.push_back(listener);
-}
-
-void HalFacadeModule::UnregisterHciScoListener(HciScoListener* listener) {
- std::unique_lock<std::mutex> lock(mutex_);
- registered_sco_listener_.remove(listener);
-}
-
-::bluetooth::facade::CertFacade* GetFacadeModule() {
- return &hci_cert_module_instance_;
-}
+const ModuleFactory HalFacadeModule::Factory = ::bluetooth::ModuleFactory([]() {
+ return new HalFacadeModule();
+});
} // namespace facade
} // namespace hal
diff --git a/gd/hal/facade/facade.h b/gd/hal/facade/facade.h
index 45ab919..3a0896c 100644
--- a/gd/hal/facade/facade.h
+++ b/gd/hal/facade/facade.h
@@ -21,52 +21,29 @@
#include <grpc++/grpc++.h>
-#include "facade/facade_manager.h"
+#include "grpc/grpc_module.h"
+#include "hal/hci_hal.h"
namespace bluetooth {
namespace hal {
namespace facade {
-// Get cert facade. This instance has static storage.
-::bluetooth::facade::CertFacade* GetFacadeModule();
-class HalFacadeModule : public ::bluetooth::facade::CertFacade {
+class HciTransportationService;
+
+class HalFacadeModule : public ::bluetooth::grpc::GrpcFacadeModule {
public:
- void StartUp(::grpc::ServerCompletionQueue* cq) override;
+ static const ModuleFactory Factory;
- void ShutDown() override;
+ void ListDependencies(ModuleList* list) override;
- ::grpc::Service* GetModuleGrpcService() const override;
+ void Start(const ModuleRegistry* registry) override;
+ void Stop(const ModuleRegistry* registry) override;
- struct HciEvtListener {
- virtual ~HciEvtListener() = default;
- virtual void operator()(const hal::HciPacket&) {}
- };
-
- void RegisterHciEvtListener(HciEvtListener* listener);
- void UnregisterHciEvtListener(HciEvtListener* listener);
-
- struct HciAclListener {
- virtual ~HciAclListener() = default;
- virtual void operator()(const hal::HciPacket&) {}
- };
-
- void RegisterHciAclListener(HciAclListener* listener);
- void UnregisterHciAclListener(HciAclListener* listener);
-
- struct HciScoListener {
- virtual ~HciScoListener() = default;
- virtual void operator()(const hal::HciPacket&) {}
- };
-
- void RegisterHciScoListener(HciScoListener* listener);
- void UnregisterHciScoListener(HciScoListener* listener);
+ ::grpc::Service* GetService() const override;
private:
- std::mutex mutex_;
+ HciTransportationService* service_;
friend class IncomingPacketCallback;
- std::list<HciEvtListener*> registered_evt_listener_;
- std::list<HciAclListener*> registered_acl_listener_;
- std::list<HciScoListener*> registered_sco_listener_;
};
} // namespace facade
diff --git a/gd/hal/hci_hal.h b/gd/hal/hci_hal.h
index 375af4b..b8d6849 100644
--- a/gd/hal/hci_hal.h
+++ b/gd/hal/hci_hal.h
@@ -18,6 +18,8 @@
#include <vector>
+#include "module.h"
+
namespace bluetooth {
namespace hal {
@@ -47,15 +49,6 @@
virtual void scoDataReceived(HciPacket data) = 0;
};
-// Callback for BluetoothHciHal::initialize()
-class BluetoothInitializationCompleteCallback {
- public:
- virtual ~BluetoothInitializationCompleteCallback() = default;
-
- // Invoked when the Bluetooth controller initialization has been completed
- virtual void initializationComplete(Status status) = 0;
-};
-
// Mirrors hardware/interfaces/bluetooth/1.0/IBluetoothHci.hal in Android
// The Host Controller Interface (HCI) is the layer defined by the Bluetooth
// specification between the software that runs on the host and the Bluetooth
@@ -63,24 +56,11 @@
// Abstraction Layer (HAL). Dealing only in HCI packets and events simplifies
// the stack and abstracts away power management, initialization, and other
// implementation-specific details related to the hardware.
-class BluetoothHciHal {
+class BluetoothHciHal : public ::bluetooth::Module {
public:
- virtual ~BluetoothHciHal() = default;
+ static const ModuleFactory Factory;
- // Initialize the underlying HCI interface.
- //
- // This method should be used to initialize any hardware interfaces
- // required to communicate with the Bluetooth hardware in the
- // device.
- //
- // The |InitializationCompleteCallback| callback must be invoked in response
- // to this function to indicate success before any other function
- // (sendHciCommand, sendAclData, * sendScoData) is invoked on this
- // interface.
- //
- // @param callback implements BluetoothInitializationCompleteCallback which will
- // receive callbacks when incoming HCI initialization is complete
- virtual void initialize(BluetoothInitializationCompleteCallback* callback) = 0;
+ virtual ~BluetoothHciHal() = default;
// Register the callback for incoming packets. All incoming packets are dropped before
// this callback is registered. Callback can only be registered once, but will be reset
@@ -107,12 +87,7 @@
// V4.2, Vol 2, Part 5, Section 5.4.3) to the Bluetooth controller.
// Packets must be processed in order.
virtual void sendScoData(HciPacket data) = 0;
-
- // Close the HCI interface
- virtual void close() = 0;
};
-BluetoothHciHal* GetBluetoothHciHal();
-
} // namespace hal
} // namespace bluetooth
diff --git a/gd/hal/hci_hal_android_hidl.cc b/gd/hal/hci_hal_android_hidl.cc
index 217da9f..0c2b56f 100644
--- a/gd/hal/hci_hal_android_hidl.cc
+++ b/gd/hal/hci_hal_android_hidl.cc
@@ -18,6 +18,7 @@
#include <stdlib.h>
#include <vector>
+#include <future>
#include <android/hardware/bluetooth/1.0/IBluetoothHci.h>
#include <android/hardware/bluetooth/1.0/IBluetoothHciCallbacks.h>
@@ -50,9 +51,10 @@
class HciHalBluetoothHciCallbacks : public IBluetoothHciCallbacks {
public:
- HciHalBluetoothHciCallbacks(BluetoothInitializationCompleteCallback* initialization_callback,
- BluetoothSnoopLogger* btsnoop_logger)
- : initialization_callback_(initialization_callback), btsnoop_logger_(btsnoop_logger) {}
+ HciHalBluetoothHciCallbacks(BluetoothSnoopLogger* btsnoop_logger)
+ : btsnoop_logger_(btsnoop_logger) {
+ init_promise_ = new std::promise<void>();
+ }
void SetCallback(BluetoothHciHalCallbacks* callback) {
ASSERT(callback_ == nullptr && callback != nullptr);
@@ -63,9 +65,13 @@
callback_ = nullptr;
}
+ std::promise<void>* GetInitPromise() {
+ return init_promise_;
+ }
+
Return<void> initializationComplete(HidlStatus status) {
ASSERT(status == HidlStatus::SUCCESS);
- initialization_callback_->initializationComplete(Status::SUCCESS);
+ init_promise_->set_value();
return Void();
}
@@ -100,7 +106,7 @@
}
private:
- BluetoothInitializationCompleteCallback* initialization_callback_ = nullptr;
+ std::promise<void>* init_promise_ = nullptr;
BluetoothHciHalCallbacks* callback_ = nullptr;
BluetoothSnoopLogger* btsnoop_logger_ = nullptr;
};
@@ -109,19 +115,6 @@
class BluetoothHciHalHidl : public BluetoothHciHal {
public:
- void initialize(BluetoothInitializationCompleteCallback* callback) override {
- btsnoop_logger_ = new BluetoothSnoopLogger(kDefaultBtsnoopPath);
- bt_hci_ = IBluetoothHci::getService();
- ASSERT(bt_hci_ != nullptr);
- auto death_link = bt_hci_->linkToDeath(bluetooth_hci_death_recipient_, 0);
- ASSERT_LOG(death_link.isOk(), "Unable to set the death recipient for the Bluetooth HAL");
- // Block allows allocation of a variable that might be bypassed by goto.
- {
- callbacks_ = new HciHalBluetoothHciCallbacks(callback, btsnoop_logger_);
- bt_hci_->initialize(callbacks_);
- }
- }
-
void registerIncomingPacketCallback(BluetoothHciHalCallbacks* callback) override {
callbacks_->SetCallback(callback);
}
@@ -141,7 +134,27 @@
bt_hci_->sendScoData(packet);
}
- void close() override {
+ protected:
+ void ListDependencies(ModuleList* list) override {
+ // We have no dependencies
+ }
+
+ void Start(const ModuleRegistry* registry) override {
+ btsnoop_logger_ = new BluetoothSnoopLogger(kDefaultBtsnoopPath);
+ bt_hci_ = IBluetoothHci::getService();
+ ASSERT(bt_hci_ != nullptr);
+ auto death_link = bt_hci_->linkToDeath(bluetooth_hci_death_recipient_, 0);
+ ASSERT_LOG(death_link.isOk(), "Unable to set the death recipient for the Bluetooth HAL");
+ // Block allows allocation of a variable that might be bypassed by goto.
+ {
+ callbacks_ = new HciHalBluetoothHciCallbacks(btsnoop_logger_);
+ bt_hci_->initialize(callbacks_);
+ // Don't timeout here, time out at a higher layer
+ callbacks_->GetInitPromise()->get_future().wait();
+ }
+ }
+
+ void Stop(const ModuleRegistry* registry) override {
ASSERT(bt_hci_ != nullptr);
auto death_unlink = bt_hci_->unlinkToDeath(bluetooth_hci_death_recipient_);
if (!death_unlink.isOk()) {
@@ -160,10 +173,9 @@
BluetoothSnoopLogger* btsnoop_logger_;
};
-BluetoothHciHal* GetBluetoothHciHal() {
- static auto* instance = new BluetoothHciHalHidl;
- return instance;
-}
+const ModuleFactory BluetoothHciHal::Factory = ModuleFactory([]() {
+ return new BluetoothHciHalHidl();
+});
} // namespace hal
} // namespace bluetooth
diff --git a/gd/hal/hci_hal_android_hidl_test.cc b/gd/hal/hci_hal_android_hidl_test.cc
index 0171fc5..01eaa2d 100644
--- a/gd/hal/hci_hal_android_hidl_test.cc
+++ b/gd/hal/hci_hal_android_hidl_test.cc
@@ -25,38 +25,20 @@
namespace hal {
namespace {
-std::promise<void>* g_promise;
-
-class TestBluetoothInitializationCompleteCallback : public BluetoothInitializationCompleteCallback {
- public:
- void initializationComplete(Status status) override {
- EXPECT_EQ(status, Status::SUCCESS);
- g_promise->set_value();
- }
-};
-
class HciHalHidlTest : public ::testing::Test {
protected:
void SetUp() override {
- g_promise = new std::promise<void>;
- hal_ = GetBluetoothHciHal();
- hal_->initialize(&init_callback_);
}
void TearDown() override {
- hal_->close();
- hal_ = nullptr;
- delete g_promise;
}
- BluetoothHciHal* hal_ = nullptr;
- TestBluetoothInitializationCompleteCallback init_callback_;
+ ModuleRegistry fake_registry_;
};
TEST_F(HciHalHidlTest, init_and_close) {
- // Give a long timeout because this only checks HAL is initialized, not performance
- auto wait_status = g_promise->get_future().wait_for(std::chrono::seconds(30));
- EXPECT_EQ(wait_status, std::future_status::ready);
+ fake_registry_.Start<BluetoothHciHal>();
+ fake_registry_.StopAll();
}
} // namespace
} // namespace hal
diff --git a/gd/hal/hci_hal_host_rootcanal.cc b/gd/hal/hci_hal_host_rootcanal.cc
index 4c8cf9e..94afad7 100644
--- a/gd/hal/hci_hal_host_rootcanal.cc
+++ b/gd/hal/hci_hal_host_rootcanal.cc
@@ -17,6 +17,7 @@
#include "hal/hci_hal_host_rootcanal.h"
#include "hal/hci_hal.h"
+#include <csignal>
#include <fcntl.h>
#include <netdb.h>
#include <unistd.h>
@@ -85,18 +86,6 @@
class BluetoothHciHalHostRootcanal : public BluetoothHciHal {
public:
- void initialize(BluetoothInitializationCompleteCallback* callback) override {
- std::lock_guard<std::mutex> lock(mutex_);
- ASSERT(sock_fd_ == INVALID_FD && callback != nullptr);
- sock_fd_ = ConnectToRootCanal(config_->GetServerAddress(), config_->GetPort());
- ASSERT(sock_fd_ != INVALID_FD);
- reactable_ =
- hci_incoming_thread_.GetReactor()->Register(sock_fd_, [this]() { this->incoming_packet_received(); }, nullptr);
- callback->initializationComplete(Status::SUCCESS);
- btsnoop_logger_ = new BluetoothSnoopLogger(kDefaultBtsnoopPath);
- LOG_INFO("Rootcanal HAL opened successfully");
- }
-
void registerIncomingPacketCallback(BluetoothHciHalCallbacks* callback) override {
std::lock_guard<std::mutex> lock(mutex_);
ASSERT(incoming_packet_callback_ == nullptr && callback != nullptr);
@@ -130,7 +119,23 @@
write_to_rootcanal_fd(packet);
}
- void close() override {
+ protected:
+ void ListDependencies(ModuleList* list) override {
+ // We have no dependencies
+ }
+
+ void Start(const ModuleRegistry* registry) override {
+ std::lock_guard<std::mutex> lock(mutex_);
+ ASSERT(sock_fd_ == INVALID_FD);
+ sock_fd_ = ConnectToRootCanal(config_->GetServerAddress(), config_->GetPort());
+ ASSERT(sock_fd_ != INVALID_FD);
+ reactable_ =
+ hci_incoming_thread_.GetReactor()->Register(sock_fd_, [this]() { this->incoming_packet_received(); }, nullptr);
+ btsnoop_logger_ = new BluetoothSnoopLogger(kDefaultBtsnoopPath);
+ LOG_INFO("Rootcanal HAL opened successfully");
+ }
+
+ void Stop(const ModuleRegistry* registry) override {
std::lock_guard<std::mutex> lock(mutex_);
delete btsnoop_logger_;
btsnoop_logger_ = nullptr;
@@ -187,8 +192,8 @@
RUN_NO_INTR(received_size = recv(sock_fd_, buf, kH4HeaderSize, 0));
ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno));
if (received_size == 0) {
- LOG_WARN("Can't read H4 header. Closing this Rootcanal HAL.");
- close();
+ LOG_WARN("Can't read H4 header.");
+ raise(SIGINT);
return;
}
@@ -247,18 +252,9 @@
}
};
-namespace {
-BluetoothHciHalHostRootcanal* instance = new BluetoothHciHalHostRootcanal;
-}
-
-BluetoothHciHal* GetBluetoothHciHal() {
- return instance;
-}
-
-void ResetRootcanalHal() {
- delete instance;
- instance = new BluetoothHciHalHostRootcanal;
-}
+const ModuleFactory BluetoothHciHal::Factory = ModuleFactory([]() {
+ return new BluetoothHciHalHostRootcanal();
+});
} // namespace hal
} // namespace bluetooth
diff --git a/gd/hal/hci_hal_host_rootcanal.h b/gd/hal/hci_hal_host_rootcanal.h
index a34d741..9b73b15 100644
--- a/gd/hal/hci_hal_host_rootcanal.h
+++ b/gd/hal/hci_hal_host_rootcanal.h
@@ -55,8 +55,5 @@
std::string server_address_ = "127.0.0.1"; // Default server address
};
-// Destroy and construct a new rootcanal HAL to clear all internal states
-void ResetRootcanalHal();
-
} // namespace hal
} // namespace bluetooth
diff --git a/gd/hal/hci_hal_host_rootcanal_test.cc b/gd/hal/hci_hal_host_rootcanal_test.cc
index e26ec95..33b6221 100644
--- a/gd/hal/hci_hal_host_rootcanal_test.cc
+++ b/gd/hal/hci_hal_host_rootcanal_test.cc
@@ -50,13 +50,6 @@
std::queue<std::pair<uint8_t, HciPacket>> incoming_packets_queue_;
-class TestBluetoothInitializationCompleteCallback : public BluetoothInitializationCompleteCallback {
- public:
- void initializationComplete(Status status) override {
- EXPECT_EQ(status, Status::SUCCESS);
- }
-};
-
class TestBluetoothHciHalCallbacks : public BluetoothHciHalCallbacks {
public:
void hciEventReceived(HciPacket packet) override {
@@ -141,8 +134,8 @@
void SetUp() override {
HciHalHostRootcanalConfig::Get()->SetPort(kTestPort);
fake_server_ = new FakeRootcanalDesktopHciServer;
- hal_ = GetBluetoothHciHal();
- hal_->initialize(&init_callback_);
+ fake_registry_.Start<BluetoothHciHal>();
+ hal_ = fake_registry_.GetInstance<BluetoothHciHal>();
hal_->registerIncomingPacketCallback(&callbacks_);
fake_server_socket_ = fake_server_->Accept(); // accept() after client is connected to avoid blocking
std::queue<std::pair<uint8_t, HciPacket>> empty;
@@ -150,7 +143,7 @@
}
void TearDown() override {
- hal_->close();
+ fake_registry_.StopAll();
close(fake_server_socket_);
delete fake_server_;
}
@@ -163,7 +156,7 @@
FakeRootcanalDesktopHciServer* fake_server_ = nullptr;
BluetoothHciHal* hal_ = nullptr;
- TestBluetoothInitializationCompleteCallback init_callback_;
+ ModuleRegistry fake_registry_;
TestBluetoothHciHalCallbacks callbacks_;
int fake_server_socket_ = -1;
};
diff --git a/gd/module.cc b/gd/module.cc
index 95f4d10..cf8b7e9 100644
--- a/gd/module.cc
+++ b/gd/module.cc
@@ -27,21 +27,25 @@
void ModuleRegistry::Start(ModuleList* modules) {
for (auto it = modules->list_.begin(); it != modules->list_.end(); it++) {
- if (IsStarted(*it)) {
- continue;
- }
-
- Module* instance = (*it)->ctor_();
- ModuleList dependencies;
- instance->ListDependencies(&dependencies);
- Start(&dependencies);
-
- instance->Start(this);
- start_order_.push_back(*it);
- started_modules_[*it] = instance;
+ Start(*it);
}
}
+void ModuleRegistry::Start(const ModuleFactory* module) {
+ if (IsStarted(module)) {
+ return;
+ }
+
+ Module* instance = module->ctor_();
+ ModuleList dependencies;
+ instance->ListDependencies(&dependencies);
+ Start(&dependencies);
+
+ instance->Start(this);
+ start_order_.push_back(module);
+ started_modules_[module] = instance;
+}
+
void ModuleRegistry::StopAll() {
// Since modules were brought up in dependency order,
// it is safe to tear down by going in reverse order.
diff --git a/gd/module.h b/gd/module.h
index 2e78bca..a073649 100644
--- a/gd/module.h
+++ b/gd/module.h
@@ -90,6 +90,13 @@
// in dependency order
void Start(ModuleList* modules);
+ template <class T>
+ void Start() {
+ Start(&T::Factory);
+ }
+
+ void Start(const ModuleFactory* id);
+
// Stop all running modules in reverse order of start
void StopAll();
diff --git a/gd/stack_manager.cc b/gd/stack_manager.cc
index 8e859e8..e3749ac 100644
--- a/gd/stack_manager.cc
+++ b/gd/stack_manager.cc
@@ -21,49 +21,47 @@
#include <queue>
#include "hal/hci_hal.h"
+#include "os/thread.h"
#include "os/handler.h"
#include "os/log.h"
+#include "module.h"
-using ::bluetooth::hal::BluetoothHciHalCallbacks;
-using ::bluetooth::hal::BluetoothInitializationCompleteCallback;
-using ::bluetooth::hal::HciPacket;
-using ::bluetooth::hal::Status;
using ::bluetooth::os::Handler;
using ::bluetooth::os::Thread;
namespace bluetooth {
-namespace {
-std::promise<void>* startup_promise;
-class InitCallback : public BluetoothInitializationCompleteCallback {
- public:
- void initializationComplete(Status status) override {
- ASSERT(status == Status::SUCCESS);
- startup_promise->set_value();
- }
-} init_callback;
+void StackManager::StartUp(ModuleList* modules) {
+ management_thread_ = new Thread("management_thread", Thread::Priority::NORMAL);
+ handler_ = new Handler(management_thread_);
-Thread* main_thread_;
+ std::promise<void>* promise = new std::promise<void>();
+ handler_->Post([this, promise, modules]() {
+ registry_.Start(modules);
+ promise->set_value();
+ });
-} // namespace
-
-void StackManager::StartUp() {
- startup_promise = new std::promise<void>;
- ::bluetooth::hal::GetBluetoothHciHal()->initialize(&init_callback);
- auto init_status = startup_promise->get_future().wait_for(std::chrono::seconds(3));
- ASSERT_LOG(init_status == std::future_status::ready, "Can't initialize HCI HAL");
- delete startup_promise;
-
- main_thread_ = new Thread("main_thread", Thread::Priority::NORMAL);
+ auto future = promise->get_future();
+ auto init_status = future.wait_for(std::chrono::seconds(3));
+ ASSERT_LOG(init_status == std::future_status::ready, "Can't start stack");
+ delete promise;
LOG_INFO("init complete");
- // Bring up HCI layer
}
void StackManager::ShutDown() {
- // Delete HCI layer
- delete main_thread_;
- main_thread_ = nullptr;
- ::bluetooth::hal::GetBluetoothHciHal()->close();
+ std::promise<void>* promise = new std::promise<void>();
+ handler_->Post([this, promise]() {
+ registry_.StopAll();
+ promise->set_value();
+ });
+
+ auto future = promise->get_future();
+ auto stop_status = future.wait_for(std::chrono::seconds(3));
+ ASSERT_LOG(stop_status == std::future_status::ready, "Can't stop stack");
+
+ delete promise;
+ delete handler_;
+ delete management_thread_;
}
} // namespace bluetooth
diff --git a/gd/stack_manager.h b/gd/stack_manager.h
index 11d218b..b9fb985 100644
--- a/gd/stack_manager.h
+++ b/gd/stack_manager.h
@@ -16,23 +16,26 @@
#pragma once
+#include "module.h"
+#include "os/thread.h"
+#include "os/handler.h"
+
namespace bluetooth {
class StackManager {
public:
- static StackManager* Get() {
- static StackManager instance;
- return &instance;
- }
-
- // Start up the stack, init HCI HAL
- void StartUp();
-
- // Shut down the stack, close HCI HAL
+ void StartUp(ModuleList *modules);
void ShutDown();
+ template <class T>
+ T* GetInstance() const {
+ return registry_.GetInstance<T>();
+ }
+
private:
- StackManager() = default;
+ os::Thread* management_thread_;
+ os::Handler* handler_;
+ ModuleRegistry registry_;
};
} // namespace bluetooth