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