1 /* Copyright (C) 2020 The Android Open Source Project 2 ** 3 ** This software is licensed under the terms of the GNU General Public 4 ** License version 2, as published by the Free Software Foundation, and 5 ** may be copied, distributed, and modified under those terms. 6 ** 7 ** This program is distributed in the hope that it will be useful, 8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 ** GNU General Public License for more details. 11 */ 12 13 #pragma once 14 15 #include <map> 16 #include <mutex> 17 18 #include <C2Component.h> 19 #include <C2ComponentFactory.h> 20 #include <android-base/thread_annotations.h> 21 #include <util/C2InterfaceHelper.h> 22 23 namespace android { 24 25 class GoldfishComponentStore : public C2ComponentStore { 26 public: 27 static std::shared_ptr<C2ComponentStore> Create(); 28 29 virtual std::vector<std::shared_ptr<const C2Component::Traits>> 30 listComponents() override; 31 virtual std::shared_ptr<C2ParamReflector> 32 getParamReflector() const override; 33 virtual C2String getName() const override; 34 virtual c2_status_t querySupportedValues_sm( 35 std::vector<C2FieldSupportedValuesQuery> &fields) const override; 36 virtual c2_status_t querySupportedParams_nb( 37 std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) 38 const override; 39 virtual c2_status_t query_sm( 40 const std::vector<C2Param *> &stackParams, 41 const std::vector<C2Param::Index> &heapParamIndices, 42 std::vector<std::unique_ptr<C2Param>> *const heapParams) const override; 43 virtual c2_status_t createInterface( 44 C2String name, 45 std::shared_ptr<C2ComponentInterface> *const interface) override; 46 virtual c2_status_t 47 createComponent(C2String name, 48 std::shared_ptr<C2Component> *const component) override; 49 virtual c2_status_t 50 copyBuffer(std::shared_ptr<C2GraphicBuffer> src, 51 std::shared_ptr<C2GraphicBuffer> dst) override; 52 virtual c2_status_t config_sm( 53 const std::vector<C2Param *> ¶ms, 54 std::vector<std::unique_ptr<C2SettingResult>> *const failures) override; 55 GoldfishComponentStore(); 56 57 virtual ~GoldfishComponentStore() override = default; 58 59 private: 60 /** 61 * An object encapsulating a loaded component module. 62 * 63 * \todo provide a way to add traits to known components here to avoid 64 * loading the .so-s for listComponents 65 */ 66 struct ComponentModule 67 : public C2ComponentFactory, 68 public std::enable_shared_from_this<ComponentModule> { 69 virtual c2_status_t 70 createComponent(c2_node_id_t id, 71 std::shared_ptr<C2Component> *component, 72 ComponentDeleter deleter = 73 std::default_delete<C2Component>()) override; 74 virtual c2_status_t createInterface( 75 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface, 76 InterfaceDeleter deleter = 77 std::default_delete<C2ComponentInterface>()) override; 78 79 /** 80 * \returns the traits of the component in this module. 81 */ 82 std::shared_ptr<const C2Component::Traits> getTraits(); 83 84 /** 85 * Creates an uninitialized component module. 86 * 87 * \param name[in] component name. 88 * 89 * \note Only used by ComponentLoader. 90 */ ComponentModuleComponentModule91 ComponentModule() 92 : mInit(C2_NO_INIT), mLibHandle(nullptr), createFactory(nullptr), 93 destroyFactory(nullptr), mComponentFactory(nullptr) {} 94 95 /** 96 * Initializes a component module with a given library path. Must be 97 * called exactly once. 98 * 99 * \note Only used by ComponentLoader. 100 * 101 * \param libPath[in] library path 102 * 103 * \retval C2_OK the component module has been successfully 104 * loaded \retval C2_NO_MEMORY not enough memory to loading the 105 * component module \retval C2_NOT_FOUND could not locate the component 106 * module \retval C2_CORRUPTED the component module could not be loaded 107 * (unexpected) \retval C2_REFUSED permission denied to load the 108 * component module (unexpected) \retval C2_TIMED_OUT could not load the 109 * module within the time limit (unexpected) 110 */ 111 c2_status_t init(std::string libPath); 112 113 virtual ~ComponentModule() override; 114 115 protected: 116 std::recursive_mutex mLock; ///< lock protecting mTraits 117 std::shared_ptr<C2Component::Traits> 118 mTraits; ///< cached component traits 119 120 c2_status_t mInit; ///< initialization result 121 122 void *mLibHandle; ///< loaded library handle 123 C2ComponentFactory::CreateCodec2FactoryFunc 124 createFactory; ///< loaded create function 125 C2ComponentFactory::DestroyCodec2FactoryFunc 126 destroyFactory; ///< loaded destroy function 127 C2ComponentFactory 128 *mComponentFactory; ///< loaded/created component factory 129 }; 130 131 /** 132 * An object encapsulating a loadable component module. 133 * 134 * \todo make this also work for enumerations 135 */ 136 struct ComponentLoader { 137 /** 138 * Load the component module. 139 * 140 * This method simply returns the component module if it is already 141 * currently loaded, or attempts to load it if it is not. 142 * 143 * \param module[out] pointer to the shared pointer where the loaded 144 * module shall be stored. This will be nullptr on error. 145 * 146 * \retval C2_OK the component module has been successfully 147 * loaded \retval C2_NO_MEMORY not enough memory to loading the 148 * component module \retval C2_NOT_FOUND could not locate the component 149 * module \retval C2_CORRUPTED the component module could not be loaded 150 * \retval C2_REFUSED permission denied to load the component module 151 */ fetchModuleComponentLoader152 c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) { 153 c2_status_t res = C2_OK; 154 std::lock_guard<std::mutex> lock(mMutex); 155 std::shared_ptr<ComponentModule> localModule = mModule.lock(); 156 if (localModule == nullptr) { 157 localModule = std::make_shared<ComponentModule>(); 158 res = localModule->init(mLibPath); 159 if (res == C2_OK) { 160 mModule = localModule; 161 } 162 } 163 *module = localModule; 164 return res; 165 } 166 167 /** 168 * Creates a component loader for a specific library path (or name). 169 */ ComponentLoaderComponentLoader170 ComponentLoader(std::string libPath) : mLibPath(libPath) {} 171 172 private: 173 std::mutex mMutex; ///< mutex guarding the module 174 std::weak_ptr<ComponentModule> 175 mModule; ///< weak reference to the loaded module 176 std::string mLibPath; ///< library path 177 }; 178 179 /** 180 * Retrieves the component module for a component. 181 * 182 * \param module pointer to a shared_pointer where the component module will 183 * be stored on success. 184 * 185 * \retval C2_OK the component loader has been successfully retrieved 186 * \retval C2_NO_MEMORY not enough memory to locate the component loader 187 * \retval C2_NOT_FOUND could not locate the component to be loaded 188 * \retval C2_CORRUPTED the component loader could not be identified due to 189 * some modules being corrupted (this can happen if the name does not refer 190 * to an already identified component but some components could not be 191 * loaded due to bad library) \retval C2_REFUSED permission denied to find 192 * the component loader for the named component (this can happen if the name 193 * does not refer to an already identified component but some components 194 * could not be loaded due to lack of permissions) 195 */ 196 c2_status_t findComponent(C2String name, 197 std::shared_ptr<ComponentModule> *module); 198 199 /** 200 * Loads each component module and discover its contents. 201 */ 202 void visitComponents(); 203 204 std::mutex 205 mMutex; ///< mutex guarding the component lists during construction 206 bool mVisited; ///< component modules visited 207 std::map<C2String, ComponentLoader> 208 mComponents; ///< path -> component module 209 std::map<C2String, C2String> mComponentNameToPath; ///< name -> path 210 std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList; 211 212 std::shared_ptr<C2ReflectorHelper> mReflector; 213 }; 214 } // namespace android 215