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 = 0; 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 std::string last_instance_; 160 }; 161 162 class ModuleDumper { 163 public: ModuleDumper(const ModuleRegistry & module_registry,const char * title)164 ModuleDumper(const ModuleRegistry& module_registry, const char* title) 165 : module_registry_(module_registry), title_(title) {} 166 void DumpState(std::string* output) const; 167 168 private: 169 const ModuleRegistry& module_registry_; 170 const std::string title_; 171 }; 172 173 class TestModuleRegistry : public ModuleRegistry { 174 public: InjectTestModule(const ModuleFactory * module,Module * instance)175 void InjectTestModule(const ModuleFactory* module, Module* instance) { 176 start_order_.push_back(module); 177 started_modules_[module] = instance; 178 set_registry_and_handler(instance, &test_thread); 179 instance->Start(); 180 } 181 GetModuleUnderTest(const ModuleFactory * module)182 Module* GetModuleUnderTest(const ModuleFactory* module) const { 183 return Get(module); 184 } 185 186 template <class T> GetModuleUnderTest()187 T* GetModuleUnderTest() const { 188 return static_cast<T*>(GetModuleUnderTest(&T::Factory)); 189 } 190 GetTestModuleHandler(const ModuleFactory * module)191 os::Handler* GetTestModuleHandler(const ModuleFactory* module) const { 192 return GetModuleHandler(module); 193 } 194 GetTestThread()195 os::Thread& GetTestThread() { 196 return test_thread; 197 } 198 SynchronizeModuleHandler(const ModuleFactory * module,std::chrono::milliseconds timeout)199 bool SynchronizeModuleHandler(const ModuleFactory* module, std::chrono::milliseconds timeout) const { 200 return SynchronizeHandler(GetTestModuleHandler(module), timeout); 201 } 202 SynchronizeHandler(os::Handler * handler,std::chrono::milliseconds timeout)203 bool SynchronizeHandler(os::Handler* handler, std::chrono::milliseconds timeout) const { 204 std::promise<void> promise; 205 auto future = promise.get_future(); 206 handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise))); 207 return future.wait_for(timeout) == std::future_status::ready; 208 } 209 210 private: 211 os::Thread test_thread{"test_thread", os::Thread::Priority::NORMAL}; 212 }; 213 214 class FuzzTestModuleRegistry : public TestModuleRegistry { 215 public: 216 template <class T> Inject(const ModuleFactory * overriding)217 T* Inject(const ModuleFactory* overriding) { 218 Module* instance = T::Factory.ctor_(); 219 InjectTestModule(overriding, instance); 220 return static_cast<T*>(instance); 221 } 222 223 template <class T> Start()224 T* Start() { 225 return ModuleRegistry::Start<T>(&GetTestThread()); 226 } 227 WaitForIdleAndStopAll()228 void WaitForIdleAndStopAll() { 229 if (!GetTestThread().GetReactor()->WaitForIdle(std::chrono::milliseconds(100))) { 230 LOG_ERROR("idle timed out"); 231 } 232 StopAll(); 233 } 234 }; 235 236 } // namespace bluetooth 237