blob: 6b2ed181e48f6325a2101aec471f34e46fe5beef [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>
Hansong Zhang70799832019-05-09 16:40:37 -070022#include <vector>
Zach Johnson429c94b2019-04-25 22:24:54 -070023
24#include "os/log.h"
Zach Johnson7ea20682019-04-29 14:48:42 -070025#include "os/handler.h"
26#include "os/thread.h"
Zach Johnson429c94b2019-04-25 22:24:54 -070027
28namespace bluetooth {
29
30class Module;
31class ModuleRegistry;
32
33class ModuleFactory {
34 friend ModuleRegistry;
35 public:
36 ModuleFactory(std::function<Module*()> ctor);
37
38 private:
39 std::function<Module*()> ctor_;
40};
41
42class ModuleList {
43 friend ModuleRegistry;
Zach Johnson84b448b2019-04-29 15:34:55 -070044 friend Module;
Zach Johnson429c94b2019-04-25 22:24:54 -070045 public:
46 template <class T>
47 void add() {
48 list_.push_back(&T::Factory);
49 }
50
51 private:
52 std::vector<const ModuleFactory*> list_;
53};
54
55// Each leaf node module must have a factory like so:
56//
57// static const ModuleFactory Factory;
58//
59// which will provide a constructor for the module registry to call.
Zach Johnson7ea20682019-04-29 14:48:42 -070060// The module registry will also use the factory as the identifier
Zach Johnson429c94b2019-04-25 22:24:54 -070061// for that module.
62class Module {
63 friend ModuleRegistry;
64 public:
65 virtual ~Module() = default;
66 protected:
67 // Populate the provided list with modules that must start before yours
68 virtual void ListDependencies(ModuleList* list) = 0;
69
Zach Johnson84b448b2019-04-29 15:34:55 -070070 // You can grab your started dependencies during or after this call
71 // using GetDependency(), or access the module registry via GetModuleRegistry()
72 virtual void Start() = 0;
Zach Johnson429c94b2019-04-25 22:24:54 -070073
74 // Release all resources, you're about to be deleted
Zach Johnson84b448b2019-04-29 15:34:55 -070075 virtual void Stop() = 0;
Zach Johnson7ea20682019-04-29 14:48:42 -070076
77 ::bluetooth::os::Handler* GetHandler();
78
Zach Johnson84b448b2019-04-29 15:34:55 -070079 ModuleRegistry* GetModuleRegistry();
80
81 template <class T>
82 T* GetDependency() const {
83 return static_cast<T*>(GetDependency(&T::Factory));
84 }
85
Zach Johnson7ea20682019-04-29 14:48:42 -070086 private:
Zach Johnson84b448b2019-04-29 15:34:55 -070087 Module* GetDependency(const ModuleFactory* module) const;
88
Hansong Zhang712e9e22019-05-29 17:52:24 -070089 ::bluetooth::os::Handler* handler_ = nullptr;
Zach Johnson84b448b2019-04-29 15:34:55 -070090 ModuleList dependencies_;
91 ModuleRegistry* registry_;
Zach Johnson429c94b2019-04-25 22:24:54 -070092};
93
94class ModuleRegistry {
Zach Johnson84b448b2019-04-29 15:34:55 -070095 friend Module;
96 friend class StackManager;
Zach Johnson429c94b2019-04-25 22:24:54 -070097 public:
98 template <class T>
Zach Johnson429c94b2019-04-25 22:24:54 -070099 bool IsStarted() const {
100 return IsStarted(&T::Factory);
101 }
102
103 bool IsStarted(const ModuleFactory* factory) const;
104
105 // Start all the modules on this list and their dependencies
106 // in dependency order
Zach Johnson7ea20682019-04-29 14:48:42 -0700107 void Start(ModuleList* modules, ::bluetooth::os::Thread* thread);
Zach Johnson429c94b2019-04-25 22:24:54 -0700108
Zach Johnsone0e158c2019-04-26 11:57:05 -0700109 template <class T>
Zach Johnson84b448b2019-04-29 15:34:55 -0700110 T* Start(::bluetooth::os::Thread* thread) {
111 return static_cast<T*>(Start(&T::Factory, thread));
Zach Johnsone0e158c2019-04-26 11:57:05 -0700112 }
113
Zach Johnson84b448b2019-04-29 15:34:55 -0700114 Module* Start(const ModuleFactory* id, ::bluetooth::os::Thread* thread);
Zach Johnsone0e158c2019-04-26 11:57:05 -0700115
Zach Johnson429c94b2019-04-25 22:24:54 -0700116 // Stop all running modules in reverse order of start
117 void StopAll();
118
Myles Watsonec3dcbf2019-05-15 07:31:57 -0700119 protected:
Hansong Zhang30fa2582019-05-07 16:40:45 -0700120 Module* Get(const ModuleFactory* module) const;
Myles Watsonec3dcbf2019-05-15 07:31:57 -0700121
Hansong Zhang70799832019-05-09 16:40:37 -0700122 os::Handler* GetModuleHandler(const ModuleFactory* module) const;
123
Zach Johnson429c94b2019-04-25 22:24:54 -0700124 std::map<const ModuleFactory*, Module*> started_modules_;
125 std::vector<const ModuleFactory*> start_order_;
126};
127
Myles Watsonec3dcbf2019-05-15 07:31:57 -0700128class TestModuleRegistry : public ModuleRegistry {
129 public:
130 void InjectTestModule(const ModuleFactory* module, Module* instance) {
131 start_order_.push_back(module);
132 started_modules_[module] = instance;
133 }
134
135 Module* GetModuleUnderTest(const ModuleFactory* module) const {
136 return Get(module);
137 }
138
Hansong Zhang70799832019-05-09 16:40:37 -0700139 os::Handler* GetTestModuleHandler(const ModuleFactory* module) const {
140 return GetModuleHandler(module);
Myles Watsonec3dcbf2019-05-15 07:31:57 -0700141 }
142
143 os::Thread& GetTestThread() {
144 return test_thread;
145 }
146
147 template <class T>
148 T* StartTestModule() {
149 return Start<T>(&test_thread);
150 }
151
Hansong Zhang70799832019-05-09 16:40:37 -0700152 bool SynchronizeModuleHandler(const ModuleFactory* module, std::chrono::milliseconds timeout) const {
153 std::promise<void> promise;
154 os::Handler* handler = GetTestModuleHandler(module);
155 handler->Post([&promise] { promise.set_value(); });
156 return promise.get_future().wait_for(timeout) == std::future_status::ready;
157 }
158
Myles Watsonec3dcbf2019-05-15 07:31:57 -0700159 os::Thread test_thread{"test_thread", os::Thread::Priority::NORMAL};
160};
161
Zach Johnson429c94b2019-04-25 22:24:54 -0700162} // namespace bluetooth