1 /* 2 * Copyright (C) 2017 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 #ifndef ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_ 18 #define ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_ 19 20 #include <dirent.h> 21 #include <dlfcn.h> 22 #include "SharedLibrary.h" 23 #include <utils/KeyedVector.h> 24 #include <utils/Mutex.h> 25 #include <media/cas/CasAPI.h> 26 27 using namespace std; 28 29 namespace android { 30 namespace hardware { 31 namespace cas { 32 namespace V1_0 { 33 namespace implementation { 34 35 template <class T> 36 class FactoryLoader { 37 public: 38 FactoryLoader(const char *name) : 39 mFactory(NULL), mCreateFactoryFuncName(name) {} 40 41 virtual ~FactoryLoader() { closeFactory(); } 42 43 bool findFactoryForScheme( 44 int32_t CA_system_id, 45 sp<SharedLibrary> *library = NULL, 46 T** factory = NULL); 47 48 bool enumeratePlugins(vector<HidlCasPluginDescriptor>* results); 49 50 private: 51 typedef T*(*CreateFactoryFunc)(); 52 53 Mutex mMapLock; 54 T* mFactory; 55 const char *mCreateFactoryFuncName; 56 sp<SharedLibrary> mLibrary; 57 KeyedVector<int32_t, String8> mCASystemIdToLibraryPathMap; 58 KeyedVector<String8, wp<SharedLibrary> > mLibraryPathToOpenLibraryMap; 59 60 bool loadFactoryForSchemeFromPath( 61 const String8 &path, 62 int32_t CA_system_id, 63 sp<SharedLibrary> *library, 64 T** factory); 65 66 bool queryPluginsFromPath( 67 const String8 &path, 68 vector<HidlCasPluginDescriptor>* results); 69 70 bool openFactory(const String8 &path); 71 void closeFactory(); 72 }; 73 74 template <class T> 75 bool FactoryLoader<T>::findFactoryForScheme( 76 int32_t CA_system_id, sp<SharedLibrary> *library, T** factory) { 77 if (library != NULL) { 78 library->clear(); 79 } 80 if (factory != NULL) { 81 *factory = NULL; 82 } 83 84 Mutex::Autolock autoLock(mMapLock); 85 86 // first check cache 87 ssize_t index = mCASystemIdToLibraryPathMap.indexOfKey(CA_system_id); 88 if (index >= 0) { 89 return loadFactoryForSchemeFromPath( 90 mCASystemIdToLibraryPathMap[index], 91 CA_system_id, library, factory); 92 } 93 94 // no luck, have to search 95 String8 dirPath("/vendor/lib/mediacas"); 96 DIR* pDir = opendir(dirPath.string()); 97 98 if (pDir == NULL) { 99 ALOGE("Failed to open plugin directory %s", dirPath.string()); 100 return false; 101 } 102 103 struct dirent* pEntry; 104 while ((pEntry = readdir(pDir))) { 105 String8 pluginPath = dirPath + "/" + pEntry->d_name; 106 if (pluginPath.getPathExtension() == ".so") { 107 if (loadFactoryForSchemeFromPath( 108 pluginPath, CA_system_id, library, factory)) { 109 mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath); 110 closedir(pDir); 111 112 return true; 113 } 114 } 115 } 116 117 closedir(pDir); 118 119 ALOGE("Failed to find plugin"); 120 return false; 121 } 122 123 template <class T> 124 bool FactoryLoader<T>::enumeratePlugins( 125 vector<HidlCasPluginDescriptor>* results) { 126 ALOGI("enumeratePlugins"); 127 128 results->clear(); 129 130 String8 dirPath("/vendor/lib/mediacas"); 131 DIR* pDir = opendir(dirPath.string()); 132 133 if (pDir == NULL) { 134 ALOGE("Failed to open plugin directory %s", dirPath.string()); 135 return false; 136 } 137 138 Mutex::Autolock autoLock(mMapLock); 139 140 struct dirent* pEntry; 141 while ((pEntry = readdir(pDir))) { 142 String8 pluginPath = dirPath + "/" + pEntry->d_name; 143 if (pluginPath.getPathExtension() == ".so") { 144 queryPluginsFromPath(pluginPath, results); 145 } 146 } 147 return true; 148 } 149 150 template <class T> 151 bool FactoryLoader<T>::loadFactoryForSchemeFromPath( 152 const String8 &path, int32_t CA_system_id, 153 sp<SharedLibrary> *library, T** factory) { 154 closeFactory(); 155 156 if (!openFactory(path) || !mFactory->isSystemIdSupported(CA_system_id)) { 157 closeFactory(); 158 return false; 159 } 160 161 if (library != NULL) { 162 *library = mLibrary; 163 } 164 if (factory != NULL) { 165 *factory = mFactory; 166 } 167 return true; 168 } 169 170 template <class T> 171 bool FactoryLoader<T>::queryPluginsFromPath( 172 const String8 &path, vector<HidlCasPluginDescriptor>* results) { 173 closeFactory(); 174 175 vector<CasPluginDescriptor> descriptors; 176 if (!openFactory(path) || mFactory->queryPlugins(&descriptors) != OK) { 177 closeFactory(); 178 return false; 179 } 180 181 for (auto it = descriptors.begin(); it != descriptors.end(); it++) { 182 results->push_back( HidlCasPluginDescriptor { 183 .caSystemId = it->CA_system_id, 184 .name = it->name.c_str()}); 185 } 186 return true; 187 } 188 189 template <class T> 190 bool FactoryLoader<T>::openFactory(const String8 &path) { 191 // get strong pointer to open shared library 192 ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path); 193 if (index >= 0) { 194 mLibrary = mLibraryPathToOpenLibraryMap[index].promote(); 195 } else { 196 index = mLibraryPathToOpenLibraryMap.add(path, NULL); 197 } 198 199 if (!mLibrary.get()) { 200 mLibrary = new SharedLibrary(path); 201 if (!*mLibrary) { 202 return false; 203 } 204 205 mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary); 206 } 207 208 CreateFactoryFunc createFactory = 209 (CreateFactoryFunc)mLibrary->lookup(mCreateFactoryFuncName); 210 if (createFactory == NULL || (mFactory = createFactory()) == NULL) { 211 return false; 212 } 213 return true; 214 } 215 216 template <class T> 217 void FactoryLoader<T>::closeFactory() { 218 delete mFactory; 219 mFactory = NULL; 220 mLibrary.clear(); 221 } 222 223 } // namespace implementation 224 } // namespace V1_0 225 } // namespace cas 226 } // namespace hardware 227 } // namespace android 228 229 #endif // ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_ 230