blob: 45e515afbfcae9453a85baf275f02e7879c26884 [file] [log] [blame]
Chong Zhanga4f67512017-04-24 17:18:25 -07001/*
2 * Copyright (C) 2017 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 ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_
18#define ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_
19
20#include <dirent.h>
21#include <dlfcn.h>
22#include "SharedLibrary.h"
23#include <utils/KeyedVector.h>
24#include <utils/Mutex.h>
25#include <media/cas/CasAPI.h>
26
27using namespace std;
28
29namespace android {
30namespace hardware {
31namespace cas {
32namespace V1_0 {
33namespace implementation {
34
35template <class T>
36class FactoryLoader {
37public:
38 FactoryLoader(const char *name) :
39 mFactory(NULL), mCreateFactoryFuncName(name) {}
40
41 virtual ~FactoryLoader() { closeFactory(); }
42
43 bool findFactoryForScheme(
44 int32_t CA_system_id,
45 sp<SharedLibrary> *library = NULL,
46 T** factory = NULL);
47
Steven Moreland9b2e5042019-05-01 01:15:39 +000048 bool enumeratePlugins(vector<HidlCasPluginDescriptor>* results);
Chong Zhanga4f67512017-04-24 17:18:25 -070049
Steven Moreland9b2e5042019-05-01 01:15:39 +000050private:
Chong Zhanga4f67512017-04-24 17:18:25 -070051 typedef T*(*CreateFactoryFunc)();
52
53 Mutex mMapLock;
54 T* mFactory;
55 const char *mCreateFactoryFuncName;
56 sp<SharedLibrary> mLibrary;
57 KeyedVector<int32_t, String8> mCASystemIdToLibraryPathMap;
58 KeyedVector<String8, wp<SharedLibrary> > mLibraryPathToOpenLibraryMap;
59
60 bool loadFactoryForSchemeFromPath(
61 const String8 &path,
62 int32_t CA_system_id,
63 sp<SharedLibrary> *library,
64 T** factory);
65
Steven Moreland9b2e5042019-05-01 01:15:39 +000066 bool queryPluginsFromPath(
67 const String8 &path,
68 vector<HidlCasPluginDescriptor>* results);
Chong Zhanga4f67512017-04-24 17:18:25 -070069
70 bool openFactory(const String8 &path);
71 void closeFactory();
72};
73
74template <class T>
75bool FactoryLoader<T>::findFactoryForScheme(
76 int32_t CA_system_id, sp<SharedLibrary> *library, T** factory) {
77 if (library != NULL) {
78 library->clear();
79 }
80 if (factory != NULL) {
81 *factory = NULL;
82 }
83
84 Mutex::Autolock autoLock(mMapLock);
85
86 // first check cache
87 ssize_t index = mCASystemIdToLibraryPathMap.indexOfKey(CA_system_id);
88 if (index >= 0) {
89 return loadFactoryForSchemeFromPath(
90 mCASystemIdToLibraryPathMap[index],
91 CA_system_id, library, factory);
92 }
93
94 // no luck, have to search
bohub305c802021-01-30 19:14:05 -080095#ifdef __LP64__
96 String8 dirPath("/vendor/lib64/mediacas");
97#else
Chong Zhanga4f67512017-04-24 17:18:25 -070098 String8 dirPath("/vendor/lib/mediacas");
bohub305c802021-01-30 19:14:05 -080099#endif
100
Chong Zhanga4f67512017-04-24 17:18:25 -0700101 DIR* pDir = opendir(dirPath.string());
102
103 if (pDir == NULL) {
104 ALOGE("Failed to open plugin directory %s", dirPath.string());
105 return false;
106 }
107
108 struct dirent* pEntry;
109 while ((pEntry = readdir(pDir))) {
110 String8 pluginPath = dirPath + "/" + pEntry->d_name;
111 if (pluginPath.getPathExtension() == ".so") {
112 if (loadFactoryForSchemeFromPath(
113 pluginPath, CA_system_id, library, factory)) {
114 mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath);
115 closedir(pDir);
116
117 return true;
118 }
119 }
120 }
121
122 closedir(pDir);
123
124 ALOGE("Failed to find plugin");
125 return false;
126}
127
128template <class T>
Steven Moreland9b2e5042019-05-01 01:15:39 +0000129bool FactoryLoader<T>::enumeratePlugins(
130 vector<HidlCasPluginDescriptor>* results) {
Chong Zhanga4f67512017-04-24 17:18:25 -0700131 ALOGI("enumeratePlugins");
132
Steven Moreland9b2e5042019-05-01 01:15:39 +0000133 results->clear();
134
bohub305c802021-01-30 19:14:05 -0800135#ifdef __LP64__
136 String8 dirPath("/vendor/lib64/mediacas");
137#else
Chong Zhanga4f67512017-04-24 17:18:25 -0700138 String8 dirPath("/vendor/lib/mediacas");
bohub305c802021-01-30 19:14:05 -0800139#endif
140
Chong Zhanga4f67512017-04-24 17:18:25 -0700141 DIR* pDir = opendir(dirPath.string());
142
143 if (pDir == NULL) {
144 ALOGE("Failed to open plugin directory %s", dirPath.string());
145 return false;
146 }
147
148 Mutex::Autolock autoLock(mMapLock);
149
150 struct dirent* pEntry;
151 while ((pEntry = readdir(pDir))) {
152 String8 pluginPath = dirPath + "/" + pEntry->d_name;
153 if (pluginPath.getPathExtension() == ".so") {
154 queryPluginsFromPath(pluginPath, results);
155 }
156 }
157 return true;
158}
159
160template <class T>
161bool FactoryLoader<T>::loadFactoryForSchemeFromPath(
162 const String8 &path, int32_t CA_system_id,
163 sp<SharedLibrary> *library, T** factory) {
164 closeFactory();
165
166 if (!openFactory(path) || !mFactory->isSystemIdSupported(CA_system_id)) {
167 closeFactory();
168 return false;
169 }
170
171 if (library != NULL) {
172 *library = mLibrary;
173 }
174 if (factory != NULL) {
175 *factory = mFactory;
176 }
177 return true;
178}
179
180template <class T>
Steven Moreland9b2e5042019-05-01 01:15:39 +0000181bool FactoryLoader<T>::queryPluginsFromPath(
182 const String8 &path, vector<HidlCasPluginDescriptor>* results) {
Chong Zhanga4f67512017-04-24 17:18:25 -0700183 closeFactory();
184
185 vector<CasPluginDescriptor> descriptors;
186 if (!openFactory(path) || mFactory->queryPlugins(&descriptors) != OK) {
187 closeFactory();
188 return false;
189 }
190
Steven Moreland9b2e5042019-05-01 01:15:39 +0000191 for (auto it = descriptors.begin(); it != descriptors.end(); it++) {
192 results->push_back( HidlCasPluginDescriptor {
193 .caSystemId = it->CA_system_id,
194 .name = it->name.c_str()});
Chong Zhanga4f67512017-04-24 17:18:25 -0700195 }
Chong Zhanga4f67512017-04-24 17:18:25 -0700196 return true;
197}
198
199template <class T>
200bool FactoryLoader<T>::openFactory(const String8 &path) {
201 // get strong pointer to open shared library
202 ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path);
203 if (index >= 0) {
204 mLibrary = mLibraryPathToOpenLibraryMap[index].promote();
205 } else {
206 index = mLibraryPathToOpenLibraryMap.add(path, NULL);
207 }
208
209 if (!mLibrary.get()) {
210 mLibrary = new SharedLibrary(path);
211 if (!*mLibrary) {
212 return false;
213 }
214
215 mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary);
216 }
217
218 CreateFactoryFunc createFactory =
219 (CreateFactoryFunc)mLibrary->lookup(mCreateFactoryFuncName);
220 if (createFactory == NULL || (mFactory = createFactory()) == NULL) {
221 return false;
222 }
223 return true;
224}
225
226template <class T>
227void FactoryLoader<T>::closeFactory() {
228 delete mFactory;
229 mFactory = NULL;
230 mLibrary.clear();
231}
232
233} // namespace implementation
234} // namespace V1_0
235} // namespace cas
236} // namespace hardware
237} // namespace android
238
239#endif // ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_