• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 <future>
21 #include <map>
22 #include <string>
23 #include <vector>
24 
25 #include "common/bind.h"
26 #include "os/handler.h"
27 #include "os/log.h"
28 #include "os/thread.h"
29 
30 namespace bluetooth {
31 
32 class Module;
33 class ModuleRegistry;
34 
35 class ModuleFactory {
36  friend ModuleRegistry;
37  public:
38   ModuleFactory(std::function<Module*()> ctor);
39 
40  private:
41   std::function<Module*()> ctor_;
42 };
43 
44 class ModuleList {
45  friend ModuleRegistry;
46  friend Module;
47  public:
48   template <class T>
add()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.
62 // The module registry will also use the factory as the identifier
63 // for that module.
64 class 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 
72   // 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;
75 
76   // Release all resources, you're about to be deleted
77   virtual void Stop() = 0;
78 
79   virtual std::string ToString() const;
80 
81   ::bluetooth::os::Handler* GetHandler() const;
82 
83   const ModuleRegistry* GetModuleRegistry() const;
84 
85   template <class T>
GetDependency()86   T* GetDependency() const {
87     return static_cast<T*>(GetDependency(&T::Factory));
88   }
89 
90  private:
91   Module* GetDependency(const ModuleFactory* module) const;
92 
93   ::bluetooth::os::Handler* handler_ = nullptr;
94   ModuleList dependencies_;
95   const ModuleRegistry* registry_;
96 };
97 
98 class ModuleRegistry {
99  friend Module;
100  friend class StackManager;
101  public:
102   template <class T>
IsStarted()103   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
111   void Start(ModuleList* modules, ::bluetooth::os::Thread* thread);
112 
113   template <class T>
Start(::bluetooth::os::Thread * thread)114   T* Start(::bluetooth::os::Thread* thread) {
115     return static_cast<T*>(Start(&T::Factory, thread));
116   }
117 
118   Module* Start(const ModuleFactory* id, ::bluetooth::os::Thread* thread);
119 
120   // Stop all running modules in reverse order of start
121   void StopAll();
122 
123  protected:
124   Module* Get(const ModuleFactory* module) const;
125 
126   void set_registry_and_handler(Module* instance, ::bluetooth::os::Thread* thread) const;
127 
128   os::Handler* GetModuleHandler(const ModuleFactory* module) const;
129 
130   std::map<const ModuleFactory*, Module*> started_modules_;
131   std::vector<const ModuleFactory*> start_order_;
132 };
133 
134 class TestModuleRegistry : public ModuleRegistry {
135  public:
InjectTestModule(const ModuleFactory * module,Module * instance)136   void InjectTestModule(const ModuleFactory* module, Module* instance) {
137     start_order_.push_back(module);
138     started_modules_[module] = instance;
139     set_registry_and_handler(instance, &test_thread);
140   }
141 
GetModuleUnderTest(const ModuleFactory * module)142   Module* GetModuleUnderTest(const ModuleFactory* module) const {
143     return Get(module);
144   }
145 
GetTestModuleHandler(const ModuleFactory * module)146   os::Handler* GetTestModuleHandler(const ModuleFactory* module) const {
147     return GetModuleHandler(module);
148   }
149 
GetTestThread()150   os::Thread& GetTestThread() {
151     return test_thread;
152   }
153 
SynchronizeModuleHandler(const ModuleFactory * module,std::chrono::milliseconds timeout)154   bool SynchronizeModuleHandler(const ModuleFactory* module, std::chrono::milliseconds timeout) const {
155     std::promise<void> promise;
156     auto future = promise.get_future();
157     os::Handler* handler = GetTestModuleHandler(module);
158     handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise)));
159     return future.wait_for(timeout) == std::future_status::ready;
160   }
161 
162  private:
163   os::Thread test_thread{"test_thread", os::Thread::Priority::NORMAL};
164 };
165 
166 }  // namespace bluetooth
167