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