blob: 045865de5aaf179d6966260b891f1d381edfe1b1 [file] [log] [blame]
Zach Johnson429c94b2019-04-25 22:24:54 -07001/*
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#pragma once
18
19#include <functional>
Hansong Zhang70799832019-05-09 16:40:37 -070020#include <future>
Zach Johnson429c94b2019-04-25 22:24:54 -070021#include <map>
Zongheng Wang6fd349a2019-11-12 16:14:01 -080022#include <string>
Hansong Zhang70799832019-05-09 16:40:37 -070023#include <vector>
Zach Johnson429c94b2019-04-25 22:24:54 -070024
Hansong Zhangaa0875c2019-06-06 21:44:55 -070025#include "common/bind.h"
Zach Johnson7ea20682019-04-29 14:48:42 -070026#include "os/handler.h"
Hansong Zhangaa0875c2019-06-06 21:44:55 -070027#include "os/log.h"
Zach Johnson7ea20682019-04-29 14:48:42 -070028#include "os/thread.h"
Zach Johnson429c94b2019-04-25 22:24:54 -070029
30namespace bluetooth {
31
32class Module;
33class ModuleRegistry;
34
35class ModuleFactory {
36 friend ModuleRegistry;
37 public:
38 ModuleFactory(std::function<Module*()> ctor);
39
40 private:
41 std::function<Module*()> ctor_;
42};
43
44class ModuleList {
45 friend ModuleRegistry;
Zach Johnson84b448b2019-04-29 15:34:55 -070046 friend Module;
Zach Johnson429c94b2019-04-25 22:24:54 -070047 public:
48 template <class T>
49 void add() {
50 list_.push_back(&T::Factory);
51 }
52
53 private:
54 std::vector<const ModuleFactory*> list_;
55};
56
57// Each leaf node module must have a factory like so:
58//
59// static const ModuleFactory Factory;
60//
61// which will provide a constructor for the module registry to call.
Zach Johnson7ea20682019-04-29 14:48:42 -070062// The module registry will also use the factory as the identifier
Zach Johnson429c94b2019-04-25 22:24:54 -070063// for that module.
64class Module {
65 friend ModuleRegistry;
66 public:
67 virtual ~Module() = default;
68 protected:
69 // Populate the provided list with modules that must start before yours
70 virtual void ListDependencies(ModuleList* list) = 0;
71
Zach Johnson84b448b2019-04-29 15:34:55 -070072 // You can grab your started dependencies during or after this call
73 // using GetDependency(), or access the module registry via GetModuleRegistry()
74 virtual void Start() = 0;
Zach Johnson429c94b2019-04-25 22:24:54 -070075
76 // Release all resources, you're about to be deleted
Zach Johnson84b448b2019-04-29 15:34:55 -070077 virtual void Stop() = 0;
Zach Johnson7ea20682019-04-29 14:48:42 -070078
Zongheng Wang6fd349a2019-11-12 16:14:01 -080079 virtual std::string ToString() const;
80
Myles Watsona61337d2019-10-18 11:21:47 -070081 ::bluetooth::os::Handler* GetHandler() const;
Zach Johnson7ea20682019-04-29 14:48:42 -070082
Myles Watsona61337d2019-10-18 11:21:47 -070083 const ModuleRegistry* GetModuleRegistry() const;
Zach Johnson84b448b2019-04-29 15:34:55 -070084
85 template <class T>
86 T* GetDependency() const {
87 return static_cast<T*>(GetDependency(&T::Factory));
88 }
89
Zach Johnson7ea20682019-04-29 14:48:42 -070090 private:
Zach Johnson84b448b2019-04-29 15:34:55 -070091 Module* GetDependency(const ModuleFactory* module) const;
92
Hansong Zhang712e9e22019-05-29 17:52:24 -070093 ::bluetooth::os::Handler* handler_ = nullptr;
Zach Johnson84b448b2019-04-29 15:34:55 -070094 ModuleList dependencies_;
Myles Watson879fbfb2019-05-06 17:54:51 -070095 const ModuleRegistry* registry_;
Zach Johnson429c94b2019-04-25 22:24:54 -070096};
97
98class ModuleRegistry {
Zach Johnson84b448b2019-04-29 15:34:55 -070099 friend Module;
100 friend class StackManager;
Zach Johnson429c94b2019-04-25 22:24:54 -0700101 public:
102 template <class T>
Zach Johnson429c94b2019-04-25 22:24:54 -0700103 bool IsStarted() const {
104 return IsStarted(&T::Factory);
105 }
106
107 bool IsStarted(const ModuleFactory* factory) const;
108
109 // Start all the modules on this list and their dependencies
110 // in dependency order
Zach Johnson7ea20682019-04-29 14:48:42 -0700111 void Start(ModuleList* modules, ::bluetooth::os::Thread* thread);
Zach Johnson429c94b2019-04-25 22:24:54 -0700112
Zach Johnsone0e158c2019-04-26 11:57:05 -0700113 template <class T>
Zach Johnson84b448b2019-04-29 15:34:55 -0700114 T* Start(::bluetooth::os::Thread* thread) {
115 return static_cast<T*>(Start(&T::Factory, thread));
Zach Johnsone0e158c2019-04-26 11:57:05 -0700116 }
117
Zach Johnson84b448b2019-04-29 15:34:55 -0700118 Module* Start(const ModuleFactory* id, ::bluetooth::os::Thread* thread);
Zach Johnsone0e158c2019-04-26 11:57:05 -0700119
Zach Johnson429c94b2019-04-25 22:24:54 -0700120 // Stop all running modules in reverse order of start
121 void StopAll();
122
Myles Watsonec3dcbf2019-05-15 07:31:57 -0700123 protected:
Hansong Zhang30fa2582019-05-07 16:40:45 -0700124 Module* Get(const ModuleFactory* module) const;
Myles Watsonec3dcbf2019-05-15 07:31:57 -0700125
Myles Watson879fbfb2019-05-06 17:54:51 -0700126 void set_registry_and_handler(Module* instance, ::bluetooth::os::Thread* thread) const;
127
Hansong Zhang70799832019-05-09 16:40:37 -0700128 os::Handler* GetModuleHandler(const ModuleFactory* module) const;
129
Zach Johnson429c94b2019-04-25 22:24:54 -0700130 std::map<const ModuleFactory*, Module*> started_modules_;
131 std::vector<const ModuleFactory*> start_order_;
132};
133
Myles Watsonec3dcbf2019-05-15 07:31:57 -0700134class TestModuleRegistry : public ModuleRegistry {
135 public:
136 void InjectTestModule(const ModuleFactory* module, Module* instance) {
137 start_order_.push_back(module);
138 started_modules_[module] = instance;
Myles Watson879fbfb2019-05-06 17:54:51 -0700139 set_registry_and_handler(instance, &test_thread);
Myles Watsonec3dcbf2019-05-15 07:31:57 -0700140 }
141
142 Module* GetModuleUnderTest(const ModuleFactory* module) const {
143 return Get(module);
144 }
145
Hansong Zhang70799832019-05-09 16:40:37 -0700146 os::Handler* GetTestModuleHandler(const ModuleFactory* module) const {
147 return GetModuleHandler(module);
Myles Watsonec3dcbf2019-05-15 07:31:57 -0700148 }
149
150 os::Thread& GetTestThread() {
151 return test_thread;
152 }
153
Hansong Zhang70799832019-05-09 16:40:37 -0700154 bool SynchronizeModuleHandler(const ModuleFactory* module, std::chrono::milliseconds timeout) const {
155 std::promise<void> promise;
Hansong Zhangaa0875c2019-06-06 21:44:55 -0700156 auto future = promise.get_future();
Hansong Zhang70799832019-05-09 16:40:37 -0700157 os::Handler* handler = GetTestModuleHandler(module);
Hansong Zhangaa0875c2019-06-06 21:44:55 -0700158 handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise)));
159 return future.wait_for(timeout) == std::future_status::ready;
Hansong Zhang70799832019-05-09 16:40:37 -0700160 }
161
Hansong Zhangaa0875c2019-06-06 21:44:55 -0700162 private:
Myles Watsonec3dcbf2019-05-15 07:31:57 -0700163 os::Thread test_thread{"test_thread", os::Thread::Priority::NORMAL};
164};
165
Zach Johnson429c94b2019-04-25 22:24:54 -0700166} // namespace bluetooth