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