blob: 0767607da51abf88460e2bd5b6fa22e2d095bc6d [file] [log] [blame]
Shraddha Basantwani6545b4e2022-09-21 16:26:19 +05301/*
2 * Copyright (C) 2022 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#include <dirent.h>
18#include <dlfcn.h>
19#include <media/cas/CasAPI.h>
20#include <utils/KeyedVector.h>
21#include <utils/Mutex.h>
22#include "SharedLibrary.h"
23
24using namespace std;
25
26namespace aidl {
27namespace android {
28namespace hardware {
29namespace cas {
30
31using namespace ::android;
32
33template <class T>
34class FactoryLoader {
35 public:
36 FactoryLoader(const char* name) : mFactory(NULL), mCreateFactoryFuncName(name) {}
37
38 virtual ~FactoryLoader() { closeFactory(); }
39
40 bool findFactoryForScheme(int32_t CA_system_id, shared_ptr<SharedLibrary>* library = NULL,
41 T** factory = NULL);
42
43 bool enumeratePlugins(vector<AidlCasPluginDescriptor>* results);
44
45 private:
46 typedef T* (*CreateFactoryFunc)();
47
48 Mutex mMapLock;
49 T* mFactory;
50 const char* mCreateFactoryFuncName;
51 shared_ptr<SharedLibrary> mLibrary;
52 KeyedVector<int32_t, String8> mCASystemIdToLibraryPathMap;
53 KeyedVector<String8, shared_ptr<SharedLibrary>> mLibraryPathToOpenLibraryMap;
54
55 bool loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id,
56 shared_ptr<SharedLibrary>* library, T** factory);
57
58 bool queryPluginsFromPath(const String8& path, vector<AidlCasPluginDescriptor>* results);
59
60 bool openFactory(const String8& path);
61 void closeFactory();
62};
63
64template <class T>
65bool FactoryLoader<T>::findFactoryForScheme(int32_t CA_system_id,
66 shared_ptr<SharedLibrary>* library, T** factory) {
67 if (library != NULL) {
68 library->reset();
69 }
70 if (factory != NULL) {
71 *factory = NULL;
72 }
73
74 Mutex::Autolock autoLock(mMapLock);
75
76 // first check cache
77 ssize_t index = mCASystemIdToLibraryPathMap.indexOfKey(CA_system_id);
78 if (index >= 0) {
79 return loadFactoryForSchemeFromPath(mCASystemIdToLibraryPathMap[index], CA_system_id,
80 library, factory);
81 }
82
83 // no luck, have to search
84#ifdef __LP64__
85 String8 dirPath("/vendor/lib64/mediacas");
86#else
87 String8 dirPath("/vendor/lib/mediacas");
88#endif
Tomasz Wasilczyk3e74f0b2023-08-11 16:04:23 +000089 DIR* pDir = opendir(dirPath.c_str());
Shraddha Basantwani6545b4e2022-09-21 16:26:19 +053090
91 if (pDir == NULL) {
Tomasz Wasilczyk3e74f0b2023-08-11 16:04:23 +000092 ALOGE("Failed to open plugin directory %s", dirPath.c_str());
Shraddha Basantwani6545b4e2022-09-21 16:26:19 +053093 return false;
94 }
95
96 struct dirent* pEntry;
97 while ((pEntry = readdir(pDir))) {
98 String8 pluginPath = dirPath + "/" + pEntry->d_name;
99 if (pluginPath.getPathExtension() == ".so") {
100 if (loadFactoryForSchemeFromPath(pluginPath, CA_system_id, library, factory)) {
101 mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath);
102 closedir(pDir);
103
104 return true;
105 }
106 }
107 }
108
109 closedir(pDir);
110
111 ALOGE("Failed to find plugin");
112 return false;
113}
114
115template <class T>
116bool FactoryLoader<T>::enumeratePlugins(vector<AidlCasPluginDescriptor>* results) {
117 ALOGI("enumeratePlugins");
118
119 results->clear();
120
121#ifdef __LP64__
122 String8 dirPath("/vendor/lib64/mediacas");
123#else
124 String8 dirPath("/vendor/lib/mediacas");
125#endif
Tomasz Wasilczyk3e74f0b2023-08-11 16:04:23 +0000126 DIR* pDir = opendir(dirPath.c_str());
Shraddha Basantwani6545b4e2022-09-21 16:26:19 +0530127
128 if (pDir == NULL) {
Tomasz Wasilczyk3e74f0b2023-08-11 16:04:23 +0000129 ALOGE("Failed to open plugin directory %s", dirPath.c_str());
Shraddha Basantwani6545b4e2022-09-21 16:26:19 +0530130 return false;
131 }
132
133 Mutex::Autolock autoLock(mMapLock);
134
135 struct dirent* pEntry;
136 while ((pEntry = readdir(pDir))) {
137 String8 pluginPath = dirPath + "/" + pEntry->d_name;
138 if (pluginPath.getPathExtension() == ".so") {
139 queryPluginsFromPath(pluginPath, results);
140 }
141 }
Shraddha Basantwani09edb572023-01-31 14:03:08 +0530142 closedir(pDir);
Shraddha Basantwani6545b4e2022-09-21 16:26:19 +0530143 return true;
144}
145
146template <class T>
147bool FactoryLoader<T>::loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id,
148 shared_ptr<SharedLibrary>* library,
149 T** factory) {
150 closeFactory();
151
152 if (!openFactory(path) || !mFactory->isSystemIdSupported(CA_system_id)) {
153 closeFactory();
154 return false;
155 }
156
157 if (library != NULL) {
158 *library = mLibrary;
159 }
160 if (factory != NULL) {
161 *factory = mFactory;
162 }
163 return true;
164}
165
166template <class T>
167bool FactoryLoader<T>::queryPluginsFromPath(const String8& path,
168 vector<AidlCasPluginDescriptor>* results) {
169 closeFactory();
170
171 vector<CasPluginDescriptor> descriptors;
172 if (!openFactory(path) || mFactory->queryPlugins(&descriptors) != OK) {
173 closeFactory();
174 return false;
175 }
176
177 for (auto it = descriptors.begin(); it != descriptors.end(); it++) {
178 results->push_back(
179 AidlCasPluginDescriptor{.caSystemId = it->CA_system_id, .name = it->name.c_str()});
180 }
181 return true;
182}
183
184template <class T>
185bool FactoryLoader<T>::openFactory(const String8& path) {
186 // get strong pointer to open shared library
187 ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path);
188 if (index >= 0) {
189 mLibrary = mLibraryPathToOpenLibraryMap[index];
190 } else {
191 index = mLibraryPathToOpenLibraryMap.add(path, NULL);
192 }
193
194 if (!mLibrary.get()) {
195 mLibrary = ::ndk::SharedRefBase::make<SharedLibrary>(path);
196 if (!*mLibrary) {
197 return false;
198 }
199
200 mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary);
201 }
202
203 CreateFactoryFunc createFactory = (CreateFactoryFunc)mLibrary->lookup(mCreateFactoryFuncName);
204 if (createFactory == NULL || (mFactory = createFactory()) == NULL) {
205 return false;
206 }
207 return true;
208}
209
210template <class T>
211void FactoryLoader<T>::closeFactory() {
212 delete mFactory;
213 mFactory = NULL;
214 mLibrary.reset();
215}
216
217} // namespace cas
218} // namespace hardware
219} // namespace android
220} // namespace aidl