| /* |
| * 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. |
| */ |
| #define LOG_TAG "BtGdModule" |
| |
| #include "module.h" |
| #include "common/init_flags.h" |
| #include "dumpsys/init_flags.h" |
| #include "os/wakelock_manager.h" |
| |
| using ::bluetooth::os::Handler; |
| using ::bluetooth::os::Thread; |
| using ::bluetooth::os::WakelockManager; |
| |
| namespace bluetooth { |
| |
| constexpr std::chrono::milliseconds kModuleStopTimeout = std::chrono::milliseconds(2000); |
| |
| ModuleFactory::ModuleFactory(std::function<Module*()> ctor) : ctor_(ctor) { |
| } |
| |
| Handler* Module::GetHandler() const { |
| ASSERT_LOG(handler_ != nullptr, "Can't get handler when it's not started"); |
| return handler_; |
| } |
| |
| DumpsysDataFinisher EmptyDumpsysDataFinisher = [](DumpsysDataBuilder* dumpsys_data_builder) {}; |
| DumpsysDataFinisher Module::GetDumpsysData(flatbuffers::FlatBufferBuilder* builder) const { |
| return EmptyDumpsysDataFinisher; |
| } |
| |
| const ModuleRegistry* Module::GetModuleRegistry() const { |
| return registry_; |
| } |
| |
| Module* Module::GetDependency(const ModuleFactory* module) const { |
| for (auto& dependency : dependencies_.list_) { |
| if (dependency == module) { |
| return registry_->Get(module); |
| } |
| } |
| |
| ASSERT_LOG(false, "Module was not listed as a dependency in ListDependencies"); |
| } |
| |
| Module* ModuleRegistry::Get(const ModuleFactory* module) const { |
| auto instance = started_modules_.find(module); |
| ASSERT_LOG(instance != started_modules_.end(), "Request for module not started up, maybe not in Start(ModuleList)?"); |
| return instance->second; |
| } |
| |
| bool ModuleRegistry::IsStarted(const ModuleFactory* module) const { |
| return started_modules_.find(module) != started_modules_.end(); |
| } |
| |
| void ModuleRegistry::Start(ModuleList* modules, Thread* thread) { |
| for (auto it = modules->list_.begin(); it != modules->list_.end(); it++) { |
| Start(*it, thread); |
| } |
| } |
| |
| void ModuleRegistry::set_registry_and_handler(Module* instance, Thread* thread) const { |
| instance->registry_ = this; |
| instance->handler_ = new Handler(thread); |
| } |
| |
| Module* ModuleRegistry::Start(const ModuleFactory* module, Thread* thread) { |
| auto started_instance = started_modules_.find(module); |
| if (started_instance != started_modules_.end()) { |
| return started_instance->second; |
| } |
| |
| LOG_DEBUG("Constructing next module"); |
| Module* instance = module->ctor_(); |
| last_instance_ = "starting " + instance->ToString(); |
| set_registry_and_handler(instance, thread); |
| |
| LOG_DEBUG("Starting dependencies of %s", instance->ToString().c_str()); |
| instance->ListDependencies(&instance->dependencies_); |
| Start(&instance->dependencies_, thread); |
| |
| LOG_DEBUG("Finished starting dependencies and calling Start() of %s", instance->ToString().c_str()); |
| |
| instance->Start(); |
| start_order_.push_back(module); |
| started_modules_[module] = instance; |
| LOG_DEBUG("Started %s", instance->ToString().c_str()); |
| return instance; |
| } |
| |
| void ModuleRegistry::StopAll() { |
| // Since modules were brought up in dependency order, it is safe to tear down by going in reverse order. |
| for (auto it = start_order_.rbegin(); it != start_order_.rend(); it++) { |
| auto instance = started_modules_.find(*it); |
| ASSERT(instance != started_modules_.end()); |
| last_instance_ = "stopping " + instance->second->ToString(); |
| |
| // Clear the handler before stopping the module to allow it to shut down gracefully. |
| LOG_INFO("Stopping Handler of Module %s", instance->second->ToString().c_str()); |
| instance->second->handler_->Clear(); |
| instance->second->handler_->WaitUntilStopped(kModuleStopTimeout); |
| LOG_INFO("Stopping Module %s", instance->second->ToString().c_str()); |
| instance->second->Stop(); |
| } |
| for (auto it = start_order_.rbegin(); it != start_order_.rend(); it++) { |
| auto instance = started_modules_.find(*it); |
| ASSERT(instance != started_modules_.end()); |
| delete instance->second->handler_; |
| delete instance->second; |
| started_modules_.erase(instance); |
| } |
| |
| ASSERT(started_modules_.empty()); |
| start_order_.clear(); |
| } |
| |
| os::Handler* ModuleRegistry::GetModuleHandler(const ModuleFactory* module) const { |
| auto started_instance = started_modules_.find(module); |
| if (started_instance != started_modules_.end()) { |
| return started_instance->second->GetHandler(); |
| } |
| return nullptr; |
| } |
| |
| void ModuleDumper::DumpState(std::string* output) const { |
| ASSERT(output != nullptr); |
| |
| flatbuffers::FlatBufferBuilder builder(1024); |
| auto title = builder.CreateString(title_); |
| |
| auto init_flags_offset = dumpsys::InitFlags::Dump(&builder); |
| auto wakelock_offset = WakelockManager::Get().GetDumpsysData(&builder); |
| |
| std::queue<DumpsysDataFinisher> queue; |
| for (auto it = module_registry_.start_order_.rbegin(); it != module_registry_.start_order_.rend(); it++) { |
| auto instance = module_registry_.started_modules_.find(*it); |
| ASSERT(instance != module_registry_.started_modules_.end()); |
| queue.push(instance->second->GetDumpsysData(&builder)); |
| } |
| |
| DumpsysDataBuilder data_builder(builder); |
| data_builder.add_title(title); |
| data_builder.add_init_flags(init_flags_offset); |
| data_builder.add_wakelock_manager_data(wakelock_offset); |
| |
| while (!queue.empty()) { |
| queue.front()(&data_builder); |
| queue.pop(); |
| } |
| |
| builder.Finish(data_builder.Finish()); |
| *output = std::string(builder.GetBufferPointer(), builder.GetBufferPointer() + builder.GetSize()); |
| } |
| |
| } // namespace bluetooth |