1*ec779b8eSAndroid Build Coastguard Worker /* 2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2010 The Android Open Source Project 3*ec779b8eSAndroid Build Coastguard Worker * 4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*ec779b8eSAndroid Build Coastguard Worker * 8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*ec779b8eSAndroid Build Coastguard Worker * 10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License. 15*ec779b8eSAndroid Build Coastguard Worker */ 16*ec779b8eSAndroid Build Coastguard Worker 17*ec779b8eSAndroid Build Coastguard Worker #ifndef __PLUGIN_MANAGER_H__ 18*ec779b8eSAndroid Build Coastguard Worker #define __PLUGIN_MANAGER_H__ 19*ec779b8eSAndroid Build Coastguard Worker 20*ec779b8eSAndroid Build Coastguard Worker #include <dlfcn.h> 21*ec779b8eSAndroid Build Coastguard Worker #include <sys/types.h> 22*ec779b8eSAndroid Build Coastguard Worker #include <dirent.h> 23*ec779b8eSAndroid Build Coastguard Worker 24*ec779b8eSAndroid Build Coastguard Worker #include <utils/String8.h> 25*ec779b8eSAndroid Build Coastguard Worker #include <utils/Vector.h> 26*ec779b8eSAndroid Build Coastguard Worker #include <utils/KeyedVector.h> 27*ec779b8eSAndroid Build Coastguard Worker 28*ec779b8eSAndroid Build Coastguard Worker #include <filesystem> 29*ec779b8eSAndroid Build Coastguard Worker 30*ec779b8eSAndroid Build Coastguard Worker namespace android { 31*ec779b8eSAndroid Build Coastguard Worker 32*ec779b8eSAndroid Build Coastguard Worker const char* const PLUGIN_MANAGER_CREATE = "create"; 33*ec779b8eSAndroid Build Coastguard Worker const char* const PLUGIN_MANAGER_DESTROY = "destroy"; 34*ec779b8eSAndroid Build Coastguard Worker const char* const PLUGIN_EXTENSION = ".so"; 35*ec779b8eSAndroid Build Coastguard Worker 36*ec779b8eSAndroid Build Coastguard Worker /** 37*ec779b8eSAndroid Build Coastguard Worker * This is the template class for Plugin manager. 38*ec779b8eSAndroid Build Coastguard Worker * 39*ec779b8eSAndroid Build Coastguard Worker * The DrmManager uses this class to handle the plugins. 40*ec779b8eSAndroid Build Coastguard Worker * 41*ec779b8eSAndroid Build Coastguard Worker */ 42*ec779b8eSAndroid Build Coastguard Worker template<typename Type> 43*ec779b8eSAndroid Build Coastguard Worker class TPlugInManager { 44*ec779b8eSAndroid Build Coastguard Worker private: 45*ec779b8eSAndroid Build Coastguard Worker typedef void* HANDLE; 46*ec779b8eSAndroid Build Coastguard Worker typedef Type* create_t(void); 47*ec779b8eSAndroid Build Coastguard Worker typedef void destroy_t(Type*); 48*ec779b8eSAndroid Build Coastguard Worker typedef create_t* FPCREATE; 49*ec779b8eSAndroid Build Coastguard Worker typedef destroy_t* FPDESTORY; 50*ec779b8eSAndroid Build Coastguard Worker 51*ec779b8eSAndroid Build Coastguard Worker typedef struct _PlugInContainer { 52*ec779b8eSAndroid Build Coastguard Worker String8 sPath; 53*ec779b8eSAndroid Build Coastguard Worker HANDLE hHandle; 54*ec779b8eSAndroid Build Coastguard Worker FPCREATE fpCreate; 55*ec779b8eSAndroid Build Coastguard Worker FPDESTORY fpDestory; 56*ec779b8eSAndroid Build Coastguard Worker Type* pInstance; 57*ec779b8eSAndroid Build Coastguard Worker _PlugInContainer_PlugInContainer58*ec779b8eSAndroid Build Coastguard Worker _PlugInContainer(): 59*ec779b8eSAndroid Build Coastguard Worker sPath("") 60*ec779b8eSAndroid Build Coastguard Worker ,hHandle(NULL) 61*ec779b8eSAndroid Build Coastguard Worker ,fpCreate(NULL) 62*ec779b8eSAndroid Build Coastguard Worker ,fpDestory(NULL) 63*ec779b8eSAndroid Build Coastguard Worker ,pInstance(NULL) 64*ec779b8eSAndroid Build Coastguard Worker {} 65*ec779b8eSAndroid Build Coastguard Worker } PlugInContainer; 66*ec779b8eSAndroid Build Coastguard Worker 67*ec779b8eSAndroid Build Coastguard Worker typedef KeyedVector<String8, PlugInContainer*> PlugInMap; 68*ec779b8eSAndroid Build Coastguard Worker PlugInMap m_plugInMap; 69*ec779b8eSAndroid Build Coastguard Worker 70*ec779b8eSAndroid Build Coastguard Worker typedef Vector<String8> PlugInIdList; 71*ec779b8eSAndroid Build Coastguard Worker PlugInIdList m_plugInIdList; 72*ec779b8eSAndroid Build Coastguard Worker 73*ec779b8eSAndroid Build Coastguard Worker public: 74*ec779b8eSAndroid Build Coastguard Worker /** 75*ec779b8eSAndroid Build Coastguard Worker * Load all the plug-ins in the specified directory 76*ec779b8eSAndroid Build Coastguard Worker * 77*ec779b8eSAndroid Build Coastguard Worker * @param[in] rsPlugInDirPath 78*ec779b8eSAndroid Build Coastguard Worker * Directory path which plug-ins (dynamic library) are stored 79*ec779b8eSAndroid Build Coastguard Worker * @note Plug-ins should be implemented according to the specification 80*ec779b8eSAndroid Build Coastguard Worker */ loadPlugIns(const String8 & rsPlugInDirPath)81*ec779b8eSAndroid Build Coastguard Worker void loadPlugIns(const String8& rsPlugInDirPath) { 82*ec779b8eSAndroid Build Coastguard Worker Vector<String8> plugInFileList = getPlugInPathList(rsPlugInDirPath); 83*ec779b8eSAndroid Build Coastguard Worker 84*ec779b8eSAndroid Build Coastguard Worker if (!plugInFileList.isEmpty()) { 85*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < plugInFileList.size(); ++i) { 86*ec779b8eSAndroid Build Coastguard Worker loadPlugIn(plugInFileList[i]); 87*ec779b8eSAndroid Build Coastguard Worker } 88*ec779b8eSAndroid Build Coastguard Worker } 89*ec779b8eSAndroid Build Coastguard Worker } 90*ec779b8eSAndroid Build Coastguard Worker 91*ec779b8eSAndroid Build Coastguard Worker /** 92*ec779b8eSAndroid Build Coastguard Worker * Unload all the plug-ins 93*ec779b8eSAndroid Build Coastguard Worker * 94*ec779b8eSAndroid Build Coastguard Worker */ unloadPlugIns()95*ec779b8eSAndroid Build Coastguard Worker void unloadPlugIns() { 96*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < m_plugInIdList.size(); ++i) { 97*ec779b8eSAndroid Build Coastguard Worker unloadPlugIn(m_plugInIdList[i]); 98*ec779b8eSAndroid Build Coastguard Worker } 99*ec779b8eSAndroid Build Coastguard Worker m_plugInIdList.clear(); 100*ec779b8eSAndroid Build Coastguard Worker } 101*ec779b8eSAndroid Build Coastguard Worker 102*ec779b8eSAndroid Build Coastguard Worker /** 103*ec779b8eSAndroid Build Coastguard Worker * Get all the IDs of available plug-ins 104*ec779b8eSAndroid Build Coastguard Worker * 105*ec779b8eSAndroid Build Coastguard Worker * @return[in] plugInIdList 106*ec779b8eSAndroid Build Coastguard Worker * String type Vector in which all plug-in IDs are stored 107*ec779b8eSAndroid Build Coastguard Worker */ getPlugInIdList()108*ec779b8eSAndroid Build Coastguard Worker Vector<String8> getPlugInIdList() const { 109*ec779b8eSAndroid Build Coastguard Worker return m_plugInIdList; 110*ec779b8eSAndroid Build Coastguard Worker } 111*ec779b8eSAndroid Build Coastguard Worker 112*ec779b8eSAndroid Build Coastguard Worker /** 113*ec779b8eSAndroid Build Coastguard Worker * Get a plug-in reference of specified ID 114*ec779b8eSAndroid Build Coastguard Worker * 115*ec779b8eSAndroid Build Coastguard Worker * @param[in] rsPlugInId 116*ec779b8eSAndroid Build Coastguard Worker * Plug-in ID to be used 117*ec779b8eSAndroid Build Coastguard Worker * @return plugIn 118*ec779b8eSAndroid Build Coastguard Worker * Reference of specified plug-in instance 119*ec779b8eSAndroid Build Coastguard Worker */ getPlugIn(const String8 & rsPlugInId)120*ec779b8eSAndroid Build Coastguard Worker Type& getPlugIn(const String8& rsPlugInId) { 121*ec779b8eSAndroid Build Coastguard Worker if (!contains(rsPlugInId)) { 122*ec779b8eSAndroid Build Coastguard Worker // This error case never happens 123*ec779b8eSAndroid Build Coastguard Worker } 124*ec779b8eSAndroid Build Coastguard Worker return *(m_plugInMap.valueFor(rsPlugInId)->pInstance); 125*ec779b8eSAndroid Build Coastguard Worker } 126*ec779b8eSAndroid Build Coastguard Worker 127*ec779b8eSAndroid Build Coastguard Worker public: 128*ec779b8eSAndroid Build Coastguard Worker /** 129*ec779b8eSAndroid Build Coastguard Worker * Load a plug-in stored in the specified path 130*ec779b8eSAndroid Build Coastguard Worker * 131*ec779b8eSAndroid Build Coastguard Worker * @param[in] rsPlugInPath 132*ec779b8eSAndroid Build Coastguard Worker * Plug-in (dynamic library) file path 133*ec779b8eSAndroid Build Coastguard Worker * @note Plug-in should be implemented according to the specification 134*ec779b8eSAndroid Build Coastguard Worker */ loadPlugIn(const String8 & rsPlugInPath)135*ec779b8eSAndroid Build Coastguard Worker void loadPlugIn(const String8& rsPlugInPath) { 136*ec779b8eSAndroid Build Coastguard Worker if (contains(rsPlugInPath)) { 137*ec779b8eSAndroid Build Coastguard Worker return; 138*ec779b8eSAndroid Build Coastguard Worker } 139*ec779b8eSAndroid Build Coastguard Worker 140*ec779b8eSAndroid Build Coastguard Worker PlugInContainer* pPlugInContainer = new PlugInContainer(); 141*ec779b8eSAndroid Build Coastguard Worker 142*ec779b8eSAndroid Build Coastguard Worker pPlugInContainer->hHandle = dlopen(rsPlugInPath.c_str(), RTLD_LAZY); 143*ec779b8eSAndroid Build Coastguard Worker 144*ec779b8eSAndroid Build Coastguard Worker if (NULL == pPlugInContainer->hHandle) { 145*ec779b8eSAndroid Build Coastguard Worker delete pPlugInContainer; 146*ec779b8eSAndroid Build Coastguard Worker pPlugInContainer = NULL; 147*ec779b8eSAndroid Build Coastguard Worker return; 148*ec779b8eSAndroid Build Coastguard Worker } 149*ec779b8eSAndroid Build Coastguard Worker 150*ec779b8eSAndroid Build Coastguard Worker pPlugInContainer->sPath = rsPlugInPath; 151*ec779b8eSAndroid Build Coastguard Worker pPlugInContainer->fpCreate 152*ec779b8eSAndroid Build Coastguard Worker = (FPCREATE)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_CREATE); 153*ec779b8eSAndroid Build Coastguard Worker pPlugInContainer->fpDestory 154*ec779b8eSAndroid Build Coastguard Worker = (FPDESTORY)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_DESTROY); 155*ec779b8eSAndroid Build Coastguard Worker 156*ec779b8eSAndroid Build Coastguard Worker if (NULL != pPlugInContainer->fpCreate && NULL != pPlugInContainer->fpDestory) { 157*ec779b8eSAndroid Build Coastguard Worker pPlugInContainer->pInstance = (Type*)pPlugInContainer->fpCreate(); 158*ec779b8eSAndroid Build Coastguard Worker m_plugInIdList.add(rsPlugInPath); 159*ec779b8eSAndroid Build Coastguard Worker m_plugInMap.add(rsPlugInPath, pPlugInContainer); 160*ec779b8eSAndroid Build Coastguard Worker } else { 161*ec779b8eSAndroid Build Coastguard Worker dlclose(pPlugInContainer->hHandle); 162*ec779b8eSAndroid Build Coastguard Worker delete pPlugInContainer; 163*ec779b8eSAndroid Build Coastguard Worker pPlugInContainer = NULL; 164*ec779b8eSAndroid Build Coastguard Worker return; 165*ec779b8eSAndroid Build Coastguard Worker } 166*ec779b8eSAndroid Build Coastguard Worker } 167*ec779b8eSAndroid Build Coastguard Worker 168*ec779b8eSAndroid Build Coastguard Worker /** 169*ec779b8eSAndroid Build Coastguard Worker * Unload a plug-in stored in the specified path 170*ec779b8eSAndroid Build Coastguard Worker * 171*ec779b8eSAndroid Build Coastguard Worker * @param[in] rsPlugInPath 172*ec779b8eSAndroid Build Coastguard Worker * Plug-in (dynamic library) file path 173*ec779b8eSAndroid Build Coastguard Worker */ unloadPlugIn(const String8 & rsPlugInPath)174*ec779b8eSAndroid Build Coastguard Worker void unloadPlugIn(const String8& rsPlugInPath) { 175*ec779b8eSAndroid Build Coastguard Worker if (!contains(rsPlugInPath)) { 176*ec779b8eSAndroid Build Coastguard Worker return; 177*ec779b8eSAndroid Build Coastguard Worker } 178*ec779b8eSAndroid Build Coastguard Worker 179*ec779b8eSAndroid Build Coastguard Worker PlugInContainer* pPlugInContainer = m_plugInMap.valueFor(rsPlugInPath); 180*ec779b8eSAndroid Build Coastguard Worker pPlugInContainer->fpDestory(pPlugInContainer->pInstance); 181*ec779b8eSAndroid Build Coastguard Worker dlclose(pPlugInContainer->hHandle); 182*ec779b8eSAndroid Build Coastguard Worker 183*ec779b8eSAndroid Build Coastguard Worker m_plugInMap.removeItem(rsPlugInPath); 184*ec779b8eSAndroid Build Coastguard Worker delete pPlugInContainer; 185*ec779b8eSAndroid Build Coastguard Worker pPlugInContainer = NULL; 186*ec779b8eSAndroid Build Coastguard Worker } 187*ec779b8eSAndroid Build Coastguard Worker 188*ec779b8eSAndroid Build Coastguard Worker private: 189*ec779b8eSAndroid Build Coastguard Worker /** 190*ec779b8eSAndroid Build Coastguard Worker * True if TPlugInManager contains rsPlugInId 191*ec779b8eSAndroid Build Coastguard Worker */ contains(const String8 & rsPlugInId)192*ec779b8eSAndroid Build Coastguard Worker bool contains(const String8& rsPlugInId) { 193*ec779b8eSAndroid Build Coastguard Worker return m_plugInMap.indexOfKey(rsPlugInId) != NAME_NOT_FOUND; 194*ec779b8eSAndroid Build Coastguard Worker } 195*ec779b8eSAndroid Build Coastguard Worker 196*ec779b8eSAndroid Build Coastguard Worker /** 197*ec779b8eSAndroid Build Coastguard Worker * Return file path list of plug-ins stored in the specified directory 198*ec779b8eSAndroid Build Coastguard Worker * 199*ec779b8eSAndroid Build Coastguard Worker * @param[in] rsDirPath 200*ec779b8eSAndroid Build Coastguard Worker * Directory path in which plug-ins are stored 201*ec779b8eSAndroid Build Coastguard Worker * @return plugInFileList 202*ec779b8eSAndroid Build Coastguard Worker * String type Vector in which file path of plug-ins are stored 203*ec779b8eSAndroid Build Coastguard Worker */ getPlugInPathList(const String8 & rsDirPath)204*ec779b8eSAndroid Build Coastguard Worker Vector<String8> getPlugInPathList(const String8& rsDirPath) { 205*ec779b8eSAndroid Build Coastguard Worker Vector<String8> fileList; 206*ec779b8eSAndroid Build Coastguard Worker DIR* pDir = opendir(rsDirPath.c_str()); 207*ec779b8eSAndroid Build Coastguard Worker struct dirent* pEntry; 208*ec779b8eSAndroid Build Coastguard Worker 209*ec779b8eSAndroid Build Coastguard Worker while (NULL != pDir && NULL != (pEntry = readdir(pDir))) { 210*ec779b8eSAndroid Build Coastguard Worker if (!isPlugIn(pEntry)) { 211*ec779b8eSAndroid Build Coastguard Worker continue; 212*ec779b8eSAndroid Build Coastguard Worker } 213*ec779b8eSAndroid Build Coastguard Worker String8 plugInPath; 214*ec779b8eSAndroid Build Coastguard Worker plugInPath += rsDirPath; 215*ec779b8eSAndroid Build Coastguard Worker plugInPath += "/"; 216*ec779b8eSAndroid Build Coastguard Worker plugInPath += pEntry->d_name; 217*ec779b8eSAndroid Build Coastguard Worker 218*ec779b8eSAndroid Build Coastguard Worker fileList.add(plugInPath); 219*ec779b8eSAndroid Build Coastguard Worker } 220*ec779b8eSAndroid Build Coastguard Worker 221*ec779b8eSAndroid Build Coastguard Worker if (NULL != pDir) { 222*ec779b8eSAndroid Build Coastguard Worker closedir(pDir); 223*ec779b8eSAndroid Build Coastguard Worker } 224*ec779b8eSAndroid Build Coastguard Worker 225*ec779b8eSAndroid Build Coastguard Worker return fileList; 226*ec779b8eSAndroid Build Coastguard Worker } 227*ec779b8eSAndroid Build Coastguard Worker 228*ec779b8eSAndroid Build Coastguard Worker /** 229*ec779b8eSAndroid Build Coastguard Worker * True if the input name denotes plug-in 230*ec779b8eSAndroid Build Coastguard Worker */ isPlugIn(const struct dirent * pEntry)231*ec779b8eSAndroid Build Coastguard Worker bool isPlugIn(const struct dirent* pEntry) const { 232*ec779b8eSAndroid Build Coastguard Worker const auto extension = std::filesystem::path(pEntry->d_name).extension(); 233*ec779b8eSAndroid Build Coastguard Worker // Note that the plug-in extension must exactly match case 234*ec779b8eSAndroid Build Coastguard Worker return extension.string() == PLUGIN_EXTENSION; 235*ec779b8eSAndroid Build Coastguard Worker } 236*ec779b8eSAndroid Build Coastguard Worker 237*ec779b8eSAndroid Build Coastguard Worker /** 238*ec779b8eSAndroid Build Coastguard Worker * True if input entry is directory 239*ec779b8eSAndroid Build Coastguard Worker */ isDirectory(const struct dirent * pEntry)240*ec779b8eSAndroid Build Coastguard Worker bool isDirectory(const struct dirent* pEntry) const { 241*ec779b8eSAndroid Build Coastguard Worker return DT_DIR == pEntry->d_type; 242*ec779b8eSAndroid Build Coastguard Worker } 243*ec779b8eSAndroid Build Coastguard Worker 244*ec779b8eSAndroid Build Coastguard Worker /** 245*ec779b8eSAndroid Build Coastguard Worker * True if input entry is regular file 246*ec779b8eSAndroid Build Coastguard Worker */ isRegularFile(const struct dirent * pEntry)247*ec779b8eSAndroid Build Coastguard Worker bool isRegularFile(const struct dirent* pEntry) const { 248*ec779b8eSAndroid Build Coastguard Worker return DT_REG == pEntry->d_type; 249*ec779b8eSAndroid Build Coastguard Worker } 250*ec779b8eSAndroid Build Coastguard Worker 251*ec779b8eSAndroid Build Coastguard Worker /** 252*ec779b8eSAndroid Build Coastguard Worker * True if input entry is link 253*ec779b8eSAndroid Build Coastguard Worker */ isLink(const struct dirent * pEntry)254*ec779b8eSAndroid Build Coastguard Worker bool isLink(const struct dirent* pEntry) const { 255*ec779b8eSAndroid Build Coastguard Worker return DT_LNK == pEntry->d_type; 256*ec779b8eSAndroid Build Coastguard Worker } 257*ec779b8eSAndroid Build Coastguard Worker }; 258*ec779b8eSAndroid Build Coastguard Worker 259*ec779b8eSAndroid Build Coastguard Worker }; 260*ec779b8eSAndroid Build Coastguard Worker 261*ec779b8eSAndroid Build Coastguard Worker #endif /* __PLUGIN_MANAGER_H__ */ 262*ec779b8eSAndroid Build Coastguard Worker 263