116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck/* 216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * Copyright (C) 2010 The Android Open Source Project 316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * 416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * you may not use this file except in compliance with the License. 616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * You may obtain a copy of the License at 716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * 816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * http://www.apache.org/licenses/LICENSE-2.0 916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * 1016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * Unless required by applicable law or agreed to in writing, software 1116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * distributed under the License is distributed on an "AS IS" BASIS, 1216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * See the License for the specific language governing permissions and 1416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * limitations under the License. 1516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck */ 1616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 1716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#ifndef __PLUGIN_MANAGER_H__ 1854fa17f667c285a5c9225e238c8132dfe830ef36Chris Craik#define __PLUGIN_MANAGER_H__ 1916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 2016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include <dlfcn.h> 2116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include <sys/types.h> 2216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include <dirent.h> 2316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 2416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include <utils/String8.h> 2516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include <utils/Vector.h> 2616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include <utils/KeyedVector.h> 2716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 2816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Recknamespace android { 2916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 3016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckconst char* const PLUGIN_MANAGER_CREATE = "create"; 3116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckconst char* const PLUGIN_MANAGER_DESTROY = "destroy"; 3216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckconst char* const PLUGIN_EXTENSION = ".so"; 3354fa17f667c285a5c9225e238c8132dfe830ef36Chris Craik 3454fa17f667c285a5c9225e238c8132dfe830ef36Chris Craik/** 3554fa17f667c285a5c9225e238c8132dfe830ef36Chris Craik * This is the template class for Plugin manager. 3654fa17f667c285a5c9225e238c8132dfe830ef36Chris Craik * 3716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * The DrmManager uses this class to handle the plugins. 3816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * 3916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck */ 4016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Recktemplate<typename Type> 4116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckclass TPlugInManager { 4254fa17f667c285a5c9225e238c8132dfe830ef36Chris Craikprivate: 4316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck typedef void* HANDLE; 4416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck typedef Type* create_t(void); 4516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck typedef void destroy_t(Type*); 4616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck typedef create_t* FPCREATE; 4716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck typedef destroy_t* FPDESTORY; 4816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 4916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck typedef struct _PlugInContainer { 5016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck String8 sPath; 5116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck HANDLE hHandle; 5216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck FPCREATE fpCreate; 5316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck FPDESTORY fpDestory; 5416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck Type* pInstance; 5516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 5616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck _PlugInContainer(): 5716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck sPath("") 5816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck ,hHandle(NULL) 5916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck ,fpCreate(NULL) 6016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck ,fpDestory(NULL) 6116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck ,pInstance(NULL) 6216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck {} 6316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck } PlugInContainer; 6416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 6516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck typedef KeyedVector<String8, PlugInContainer*> PlugInMap; 6616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck PlugInMap m_plugInMap; 6754fa17f667c285a5c9225e238c8132dfe830ef36Chris Craik 6816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck typedef Vector<String8> PlugInIdList; 6916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck PlugInIdList m_plugInIdList; 7016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 7116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckpublic: 7216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck /** 7316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * Load all the plug-ins in the specified directory 7416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * 7516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * @param[in] rsPlugInDirPath 7616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * Directory path which plug-ins (dynamic library) are stored 7716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * @note Plug-ins should be implemented according to the specification 7816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck */ 7954fa17f667c285a5c9225e238c8132dfe830ef36Chris Craik void loadPlugIns(const String8& rsPlugInDirPath) { 8016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck Vector<String8> plugInFileList = getPlugInPathList(rsPlugInDirPath); 8116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 8216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck if (!plugInFileList.isEmpty()) { 8316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck for (size_t i = 0; i < plugInFileList.size(); ++i) { 8416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck loadPlugIn(plugInFileList[i]); 8516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck } 8616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck } 8716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck } 8816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 89 /** 90 * Unload all the plug-ins 91 * 92 */ 93 void unloadPlugIns() { 94 for (size_t 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; 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 223 return fileList; 224 } 225 226 /** 227 * True if the input name denotes plug-in 228 */ 229 bool isPlugIn(const struct dirent* pEntry) const { 230 String8 sName(pEntry->d_name); 231 String8 extension(sName.getPathExtension()); 232 // Note that the plug-in extension must exactly match case 233 return extension == String8(PLUGIN_EXTENSION); 234 } 235 236 /** 237 * True if input entry is directory 238 */ 239 bool isDirectory(const struct dirent* pEntry) const { 240 return DT_DIR == pEntry->d_type; 241 } 242 243 /** 244 * True if input entry is regular file 245 */ 246 bool isRegularFile(const struct dirent* pEntry) const { 247 return DT_REG == pEntry->d_type; 248 } 249 250 /** 251 * True if input entry is link 252 */ 253 bool isLink(const struct dirent* pEntry) const { 254 return DT_LNK == pEntry->d_type; 255 } 256}; 257 258}; 259 260#endif /* __PLUGIN_MANAGER_H__ */ 261 262