PlugInManager.h revision 27ed8ad2db653f6ac07dcf8bcc05e2409c8bb024
1/* 2 * Copyright (C) 2010 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 __PLUGIN_MANAGER_H__ 18#define __PLUGIN_MANAGER_H__ 19 20#include <dlfcn.h> 21#include <sys/types.h> 22#include <dirent.h> 23 24#include <utils/String8.h> 25#include <utils/Vector.h> 26#include <utils/KeyedVector.h> 27 28namespace android { 29 30const char* const PLUGIN_MANAGER_CREATE = "create"; 31const char* const PLUGIN_MANAGER_DESTROY = "destroy"; 32const char* const PLUGIN_EXTENSION = ".so"; 33 34/** 35 * This is the template class for Plugin manager. 36 * 37 * The DrmManager uses this class to handle the plugins. 38 * 39 */ 40template<typename Type> 41class TPlugInManager { 42private: 43 typedef void* HANDLE; 44 typedef Type* create_t(void); 45 typedef void destroy_t(Type*); 46 typedef create_t* FPCREATE; 47 typedef destroy_t* FPDESTORY; 48 49 typedef struct _PlugInContainer { 50 String8 sPath; 51 HANDLE hHandle; 52 FPCREATE fpCreate; 53 FPDESTORY fpDestory; 54 Type* pInstance; 55 56 _PlugInContainer(): 57 sPath("") 58 ,hHandle(NULL) 59 ,fpCreate(NULL) 60 ,fpDestory(NULL) 61 ,pInstance(NULL) 62 {} 63 } PlugInContainer; 64 65 typedef KeyedVector<String8, PlugInContainer*> PlugInMap; 66 PlugInMap m_plugInMap; 67 68 typedef Vector<String8> PlugInIdList; 69 PlugInIdList m_plugInIdList; 70 71public: 72 /** 73 * Load all the plug-ins in the specified directory 74 * 75 * @param[in] rsPlugInDirPath 76 * Directory path which plug-ins (dynamic library) are stored 77 * @note Plug-ins should be implemented according to the specification 78 */ 79 void loadPlugIns(const String8& rsPlugInDirPath) { 80 Vector<String8> plugInFileList = getPlugInPathList(rsPlugInDirPath); 81 82 if (!plugInFileList.isEmpty()) { 83 for (unsigned int i = 0; i < plugInFileList.size(); ++i) { 84 loadPlugIn(plugInFileList[i]); 85 } 86 } 87 } 88 89 /** 90 * Unload all the plug-ins 91 * 92 */ 93 void unloadPlugIns() { 94 for (unsigned int i = 0; i < m_plugInIdList.size(); ++i) { 95 unloadPlugIn(m_plugInIdList[i]); 96 } 97 m_plugInIdList.clear(); 98 } 99 100 /** 101 * Get all the IDs of available plug-ins 102 * 103 * @return[in] plugInIdList 104 * String type Vector in which all plug-in IDs are stored 105 */ 106 Vector<String8> getPlugInIdList() const { 107 return m_plugInIdList; 108 } 109 110 /** 111 * Get a plug-in reference of specified ID 112 * 113 * @param[in] rsPlugInId 114 * Plug-in ID to be used 115 * @return plugIn 116 * Reference of specified plug-in instance 117 */ 118 Type& getPlugIn(const String8& rsPlugInId) { 119 if (!contains(rsPlugInId)) { 120 // This error case never happens 121 } 122 return *(m_plugInMap.valueFor(rsPlugInId)->pInstance); 123 } 124 125public: 126 /** 127 * Load a plug-in stored in the specified path 128 * 129 * @param[in] rsPlugInPath 130 * Plug-in (dynamic library) file path 131 * @note Plug-in should be implemented according to the specification 132 */ 133 void loadPlugIn(const String8& rsPlugInPath) { 134 if (contains(rsPlugInPath)) { 135 return; 136 } 137 138 PlugInContainer* pPlugInContainer = new PlugInContainer(); 139 140 pPlugInContainer->hHandle = dlopen(rsPlugInPath.string(), RTLD_LAZY); 141 142 if (NULL == pPlugInContainer->hHandle) { 143 delete pPlugInContainer; 144 pPlugInContainer = NULL; 145 return; 146 } 147 148 pPlugInContainer->sPath = rsPlugInPath; 149 pPlugInContainer->fpCreate 150 = (FPCREATE)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_CREATE); 151 pPlugInContainer->fpDestory 152 = (FPDESTORY)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_DESTROY); 153 154 if (NULL != pPlugInContainer->fpCreate && NULL != pPlugInContainer->fpDestory) { 155 pPlugInContainer->pInstance = (Type*)pPlugInContainer->fpCreate(); 156 m_plugInIdList.add(rsPlugInPath); 157 m_plugInMap.add(rsPlugInPath, pPlugInContainer); 158 } else { 159 dlclose(pPlugInContainer->hHandle); 160 delete pPlugInContainer; 161 pPlugInContainer = NULL; 162 return; 163 } 164 } 165 166 /** 167 * Unload a plug-in stored in the specified path 168 * 169 * @param[in] rsPlugInPath 170 * Plug-in (dynamic library) file path 171 */ 172 void unloadPlugIn(const String8& rsPlugInPath) { 173 if (!contains(rsPlugInPath)) { 174 return; 175 } 176 177 PlugInContainer* pPlugInContainer = m_plugInMap.valueFor(rsPlugInPath); 178 pPlugInContainer->fpDestory(pPlugInContainer->pInstance); 179 dlclose(pPlugInContainer->hHandle); 180 181 m_plugInMap.removeItem(rsPlugInPath); 182 delete pPlugInContainer; 183 pPlugInContainer = NULL; 184 } 185 186private: 187 /** 188 * True if TPlugInManager contains rsPlugInId 189 */ 190 bool contains(const String8& rsPlugInId) { 191 return m_plugInMap.indexOfKey(rsPlugInId) != NAME_NOT_FOUND; 192 } 193 194 /** 195 * Return file path list of plug-ins stored in the specified directory 196 * 197 * @param[in] rsDirPath 198 * Directory path in which plug-ins are stored 199 * @return plugInFileList 200 * String type Vector in which file path of plug-ins are stored 201 */ 202 Vector<String8> getPlugInPathList(const String8& rsDirPath) { 203 Vector<String8> fileList; 204 DIR* pDir = opendir(rsDirPath.string()); 205 struct dirent* pEntry = new dirent(); 206 207 while (NULL != pDir && NULL != (pEntry = readdir(pDir))) { 208 if (!isPlugIn(pEntry)) { 209 continue; 210 } 211 String8 plugInPath; 212 plugInPath += rsDirPath; 213 plugInPath += "/"; 214 plugInPath += pEntry->d_name; 215 216 fileList.add(plugInPath); 217 } 218 219 if (NULL != pDir) { 220 closedir(pDir); 221 } 222 delete pEntry; 223 pEntry = NULL; 224 225 return fileList; 226 } 227 228 /** 229 * True if the input name denotes plug-in 230 */ 231 bool isPlugIn(const struct dirent* pEntry) const { 232 String8 sName(pEntry->d_name); 233 int extentionPos = sName.size() - String8(PLUGIN_EXTENSION).size(); 234 if (extentionPos < 0) { 235 return false; 236 } 237 return extentionPos == (int)sName.find(PLUGIN_EXTENSION); 238 } 239 240 /** 241 * True if the input entry is "." or ".." 242 */ 243 bool isDotOrDDot(const struct dirent* pEntry) const { 244 String8 sName(pEntry->d_name); 245 return "." == sName || ".." == sName; 246 } 247 248 /** 249 * True if input entry is directory 250 */ 251 bool isDirectory(const struct dirent* pEntry) const { 252 return DT_DIR == pEntry->d_type; 253 } 254 255 /** 256 * True if input entry is regular file 257 */ 258 bool isRegularFile(const struct dirent* pEntry) const { 259 return DT_REG == pEntry->d_type; 260 } 261 262 /** 263 * True if input entry is link 264 */ 265 bool isLink(const struct dirent* pEntry) const { 266 return DT_LNK == pEntry->d_type; 267 } 268}; 269 270}; 271 272#endif /* __PLUGIN_MANAGER_H__ */ 273 274