blob: 466844d8eee4512c9da26fb9f3dd391dc68c61ea [file] [log] [blame]
aimitakeshi27ed8ad2010-07-29 10:12:27 +09001/*
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()) {
Mark Salyzyn3ab368e2014-04-15 14:55:53 -070083 for (size_t i = 0; i < plugInFileList.size(); ++i) {
aimitakeshi27ed8ad2010-07-29 10:12:27 +090084 loadPlugIn(plugInFileList[i]);
85 }
86 }
87 }
88
89 /**
90 * Unload all the plug-ins
91 *
92 */
93 void unloadPlugIns() {
Mark Salyzyn3ab368e2014-04-15 14:55:53 -070094 for (size_t i = 0; i < m_plugInIdList.size(); ++i) {
aimitakeshi27ed8ad2010-07-29 10:12:27 +090095 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());
Gloria Wangc10ce332011-06-15 10:27:52 -0700205 struct dirent* pEntry;
aimitakeshi27ed8ad2010-07-29 10:12:27 +0900206
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 }
aimitakeshi27ed8ad2010-07-29 10:12:27 +0900222
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);
Glenn Kasten41b3d3b2011-03-14 11:32:29 -0700231 String8 extension(sName.getPathExtension());
232 // Note that the plug-in extension must exactly match case
233 return extension == String8(PLUGIN_EXTENSION);
aimitakeshi27ed8ad2010-07-29 10:12:27 +0900234 }
235
236 /**
aimitakeshi27ed8ad2010-07-29 10:12:27 +0900237 * 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