• 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 <flatbuffers/flatbuffers.h>
20 #include <chrono>
21 #include <functional>
22 #include <future>
23 #include <map>
24 #include <string>
25 #include <utility>
26 #include <vector>
27 
28 #include "common/bind.h"
29 #include "dumpsys_data_generated.h"
30 #include "os/handler.h"
31 #include "os/log.h"
32 #include "os/thread.h"
33 
34 namespace bluetooth {
35 
36 class Module;
37 class ModuleDumper;
38 class ModuleRegistry;
39 class TestModuleRegistry;
40 class FuzzTestModuleRegistry;
41 
42 class ModuleFactory {
43  friend ModuleRegistry;
44  friend FuzzTestModuleRegistry;
45 
46 public:
47  ModuleFactory(std::function<Module*()> ctor);
48 
49 private:
50  std::function<Module*()> ctor_;
51 };
52 
53 class ModuleList {
54  friend Module;
55  friend ModuleRegistry;
56 
57 public:
58  template <class T>
add()59  void add() {
60    list_.push_back(&T::Factory);
61  }
62 
63  private:
64   std::vector<const ModuleFactory*> list_;
65 };
66 
67 using DumpsysDataFinisher = std::function<void(DumpsysDataBuilder* dumpsys_data_builder)>;
68 
69 // Each leaf node module must have a factory like so:
70 //
71 // static const ModuleFactory Factory;
72 //
73 // which will provide a constructor for the module registry to call.
74 // The module registry will also use the factory as the identifier
75 // for that module.
76 class Module {
77   friend ModuleDumper;
78   friend ModuleRegistry;
79   friend TestModuleRegistry;
80 
81  public:
82   virtual ~Module() = default;
83  protected:
84   // Populate the provided list with modules that must start before yours
85   virtual void ListDependencies(ModuleList* list) const = 0;
86 
87   // You can grab your started dependencies during or after this call
88   // using GetDependency(), or access the module registry via GetModuleRegistry()
89   virtual void Start() = 0;
90 
91   // Release all resources, you're about to be deleted
92   virtual void Stop() = 0;
93 
94   // Get relevant state data from the module
95   virtual DumpsysDataFinisher GetDumpsysData(flatbuffers::FlatBufferBuilder* builder) const;
96 
97   virtual std::string ToString() const = 0;
98 
99   ::bluetooth::os::Handler* GetHandler() const;
100 
101   const ModuleRegistry* GetModuleRegistry() const;
102 
103   template <class T>
GetDependency()104   T* GetDependency() const {
105     return static_cast<T*>(GetDependency(&T::Factory));
106   }
107 
108   template <typename Functor, typename... Args>
Call(Functor && functor,Args &&...args)109   void Call(Functor&& functor, Args&&... args) {
110     GetHandler()->Call(std::forward<Functor>(functor), std::forward<Args>(args)...);
111   }
112 
113   template <typename T, typename Functor, typename... Args>
CallOn(T * obj,Functor && functor,Args &&...args)114   void CallOn(T* obj, Functor&& functor, Args&&... args) {
115     GetHandler()->CallOn(obj, std::forward<Functor>(functor), std::forward<Args>(args)...);
116   }
117 
118  private:
119   Module* GetDependency(const ModuleFactory* module) const;
120 
121   ::bluetooth::os::Handler* handler_ = nullptr;
122   ModuleList dependencies_;
123   const ModuleRegistry* registry_;
124 };
125 
126 class ModuleRegistry {
127  friend Module;
128  friend ModuleDumper;
129  friend class StackManager;
130  public:
131   template <class T>
IsStarted()132   bool IsStarted() const {
133     return IsStarted(&T::Factory);
134   }
135 
136   bool IsStarted(const ModuleFactory* factory) const;
137 
138   // Start all the modules on this list and their dependencies
139   // in dependency order
140   void Start(ModuleList* modules, ::bluetooth::os::Thread* thread);
141 
142   template <class T>
Start(::bluetooth::os::Thread * thread)143   T* Start(::bluetooth::os::Thread* thread) {
144     return static_cast<T*>(Start(&T::Factory, thread));
145   }
146 
147   Module* Start(const ModuleFactory* id, ::bluetooth::os::Thread* thread);
148 
149   // Stop all running modules in reverse order of start
150   void StopAll();
151 
152  protected:
153   Module* Get(const ModuleFactory* module) const;
154 
155   void set_registry_and_handler(Module* instance, ::bluetooth::os::Thread* thread) const;
156 
157   os::Handler* GetModuleHandler(const ModuleFactory* module) const;
158 
159   std::map<const ModuleFactory*, Module*> started_modules_;
160   std::vector<const ModuleFactory*> start_order_;
161   std::string last_instance_;
162 };
163 
164 class ModuleDumper {
165  public:
ModuleDumper(const ModuleRegistry & module_registry,const char * title)166   ModuleDumper(const ModuleRegistry& module_registry, const char* title)
167       : module_registry_(module_registry), title_(title) {}
168   void DumpState(std::string* output) const;
169 
170  private:
171   const ModuleRegistry& module_registry_;
172   const std::string title_;
173 };
174 
175 class TestModuleRegistry : public ModuleRegistry {
176  public:
InjectTestModule(const ModuleFactory * module,Module * instance)177   void InjectTestModule(const ModuleFactory* module, Module* instance) {
178     start_order_.push_back(module);
179     started_modules_[module] = instance;
180     set_registry_and_handler(instance, &test_thread);
181     instance->Start();
182   }
183 
GetModuleUnderTest(const ModuleFactory * module)184   Module* GetModuleUnderTest(const ModuleFactory* module) const {
185     return Get(module);
186   }
187 
188   template <class T>
GetModuleUnderTest()189   T* GetModuleUnderTest() const {
190     return static_cast<T*>(GetModuleUnderTest(&T::Factory));
191   }
192 
GetTestModuleHandler(const ModuleFactory * module)193   os::Handler* GetTestModuleHandler(const ModuleFactory* module) const {
194     return GetModuleHandler(module);
195   }
196 
GetTestThread()197   os::Thread& GetTestThread() {
198     return test_thread;
199   }
200 
SynchronizeModuleHandler(const ModuleFactory * module,std::chrono::milliseconds timeout)201   bool SynchronizeModuleHandler(const ModuleFactory* module, std::chrono::milliseconds timeout) const {
202     return SynchronizeHandler(GetTestModuleHandler(module), timeout);
203   }
204 
SynchronizeHandler(os::Handler * handler,std::chrono::milliseconds timeout)205   bool SynchronizeHandler(os::Handler* handler, std::chrono::milliseconds timeout) const {
206     std::promise<void> promise;
207     auto future = promise.get_future();
208     handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise)));
209     return future.wait_for(timeout) == std::future_status::ready;
210   }
211 
212  private:
213   os::Thread test_thread{"test_thread", os::Thread::Priority::NORMAL};
214 };
215 
216 class FuzzTestModuleRegistry : public TestModuleRegistry {
217  public:
218   template <class T>
Inject(const ModuleFactory * overriding)219   T* Inject(const ModuleFactory* overriding) {
220     Module* instance = T::Factory.ctor_();
221     InjectTestModule(overriding, instance);
222     return static_cast<T*>(instance);
223   }
224 
225   template <class T>
Start()226   T* Start() {
227     return ModuleRegistry::Start<T>(&GetTestThread());
228   }
229 
WaitForIdleAndStopAll()230   void WaitForIdleAndStopAll() {
231     if (!GetTestThread().GetReactor()->WaitForIdle(std::chrono::milliseconds(100))) {
232       LOG_ERROR("idle timed out");
233     }
234     StopAll();
235   }
236 };
237 
238 }  // namespace bluetooth
239