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