xref: /aosp_15_r20/frameworks/av/drm/drmserver/PlugInManager.h (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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