blob: e67ced83406056910e988c6c213c598daa49711b [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>
20#include <vector>
21#include <map>
22
23#include "os/log.h"
Zach Johnson7ea20682019-04-29 14:48:42 -070024#include "os/handler.h"
25#include "os/thread.h"
Zach Johnson429c94b2019-04-25 22:24:54 -070026
27namespace bluetooth {
28
29class Module;
30class ModuleRegistry;
31
32class ModuleFactory {
33 friend ModuleRegistry;
34 public:
35 ModuleFactory(std::function<Module*()> ctor);
36
37 private:
38 std::function<Module*()> ctor_;
39};
40
41class ModuleList {
42 friend ModuleRegistry;
Zach Johnson84b448b2019-04-29 15:34:55 -070043 friend Module;
Zach Johnson429c94b2019-04-25 22:24:54 -070044 public:
45 template <class T>
46 void add() {
47 list_.push_back(&T::Factory);
48 }
49
50 private:
51 std::vector<const ModuleFactory*> list_;
52};
53
54// Each leaf node module must have a factory like so:
55//
56// static const ModuleFactory Factory;
57//
58// which will provide a constructor for the module registry to call.
Zach Johnson7ea20682019-04-29 14:48:42 -070059// The module registry will also use the factory as the identifier
Zach Johnson429c94b2019-04-25 22:24:54 -070060// for that module.
61class Module {
62 friend ModuleRegistry;
63 public:
64 virtual ~Module() = default;
65 protected:
66 // Populate the provided list with modules that must start before yours
67 virtual void ListDependencies(ModuleList* list) = 0;
68
Zach Johnson84b448b2019-04-29 15:34:55 -070069 // You can grab your started dependencies during or after this call
70 // using GetDependency(), or access the module registry via GetModuleRegistry()
71 virtual void Start() = 0;
Zach Johnson429c94b2019-04-25 22:24:54 -070072
73 // Release all resources, you're about to be deleted
Zach Johnson84b448b2019-04-29 15:34:55 -070074 virtual void Stop() = 0;
Zach Johnson7ea20682019-04-29 14:48:42 -070075
76 ::bluetooth::os::Handler* GetHandler();
77
Zach Johnson84b448b2019-04-29 15:34:55 -070078 ModuleRegistry* GetModuleRegistry();
79
80 template <class T>
81 T* GetDependency() const {
82 return static_cast<T*>(GetDependency(&T::Factory));
83 }
84
Zach Johnson7ea20682019-04-29 14:48:42 -070085 private:
Zach Johnson84b448b2019-04-29 15:34:55 -070086 Module* GetDependency(const ModuleFactory* module) const;
87
Zach Johnson7ea20682019-04-29 14:48:42 -070088 ::bluetooth::os::Handler* handler_;
Zach Johnson84b448b2019-04-29 15:34:55 -070089 ModuleList dependencies_;
90 ModuleRegistry* registry_;
Zach Johnson429c94b2019-04-25 22:24:54 -070091};
92
93class ModuleRegistry {
Zach Johnson84b448b2019-04-29 15:34:55 -070094 friend Module;
95 friend class StackManager;
Zach Johnson429c94b2019-04-25 22:24:54 -070096 public:
97 template <class T>
Zach Johnson429c94b2019-04-25 22:24:54 -070098 bool IsStarted() const {
99 return IsStarted(&T::Factory);
100 }
101
102 bool IsStarted(const ModuleFactory* factory) const;
103
104 // Start all the modules on this list and their dependencies
105 // in dependency order
Zach Johnson7ea20682019-04-29 14:48:42 -0700106 void Start(ModuleList* modules, ::bluetooth::os::Thread* thread);
Zach Johnson429c94b2019-04-25 22:24:54 -0700107
Zach Johnsone0e158c2019-04-26 11:57:05 -0700108 template <class T>
Zach Johnson84b448b2019-04-29 15:34:55 -0700109 T* Start(::bluetooth::os::Thread* thread) {
110 return static_cast<T*>(Start(&T::Factory, thread));
Zach Johnsone0e158c2019-04-26 11:57:05 -0700111 }
112
Zach Johnson84b448b2019-04-29 15:34:55 -0700113 Module* Start(const ModuleFactory* id, ::bluetooth::os::Thread* thread);
Zach Johnsone0e158c2019-04-26 11:57:05 -0700114
Zach Johnson429c94b2019-04-25 22:24:54 -0700115 // Stop all running modules in reverse order of start
116 void StopAll();
117
Myles Watsonec3dcbf2019-05-15 07:31:57 -0700118 protected:
Hansong Zhang30fa2582019-05-07 16:40:45 -0700119 Module* Get(const ModuleFactory* module) const;
Myles Watsonec3dcbf2019-05-15 07:31:57 -0700120
Zach Johnson429c94b2019-04-25 22:24:54 -0700121 std::map<const ModuleFactory*, Module*> started_modules_;
122 std::vector<const ModuleFactory*> start_order_;
123};
124
Myles Watsonec3dcbf2019-05-15 07:31:57 -0700125class TestModuleRegistry : public ModuleRegistry {
126 public:
127 void InjectTestModule(const ModuleFactory* module, Module* instance) {
128 start_order_.push_back(module);
129 started_modules_[module] = instance;
130 }
131
132 Module* GetModuleUnderTest(const ModuleFactory* module) const {
133 return Get(module);
134 }
135
136 os::Handler* GetTestModuleHandler() {
137 return new os::Handler(&test_thread);
138 }
139
140 os::Thread& GetTestThread() {
141 return test_thread;
142 }
143
144 template <class T>
145 T* StartTestModule() {
146 return Start<T>(&test_thread);
147 }
148
149 os::Thread test_thread{"test_thread", os::Thread::Priority::NORMAL};
150};
151
Zach Johnson429c94b2019-04-25 22:24:54 -0700152} // namespace bluetooth