[go: nahoru, domu]

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