blob: 70b7fa7f761fb3d9c81716e82cc60527eb3df99b [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
Tomasz Wasilczyk9e532812023-08-29 15:04:50 +000020#include <android-base/strings.h>
Chong Zhanga4f67512017-04-24 17:18:25 -070021#include <dirent.h>
22#include <dlfcn.h>
23#include "SharedLibrary.h"
24#include <utils/KeyedVector.h>
25#include <utils/Mutex.h>
26#include <media/cas/CasAPI.h>
27
28using namespace std;
29
30namespace android {
31namespace hardware {
32namespace cas {
33namespace V1_0 {
34namespace implementation {
35
36template <class T>
37class FactoryLoader {
38public:
39 FactoryLoader(const char *name) :
40 mFactory(NULL), mCreateFactoryFuncName(name) {}
41
42 virtual ~FactoryLoader() { closeFactory(); }
43
44 bool findFactoryForScheme(
45 int32_t CA_system_id,
46 sp<SharedLibrary> *library = NULL,
47 T** factory = NULL);
48
Steven Moreland9b2e5042019-05-01 01:15:39 +000049 bool enumeratePlugins(vector<HidlCasPluginDescriptor>* results);
Chong Zhanga4f67512017-04-24 17:18:25 -070050
Steven Moreland9b2e5042019-05-01 01:15:39 +000051private:
Chong Zhanga4f67512017-04-24 17:18:25 -070052 typedef T*(*CreateFactoryFunc)();
53
54 Mutex mMapLock;
55 T* mFactory;
56 const char *mCreateFactoryFuncName;
57 sp<SharedLibrary> mLibrary;
58 KeyedVector<int32_t, String8> mCASystemIdToLibraryPathMap;
59 KeyedVector<String8, wp<SharedLibrary> > mLibraryPathToOpenLibraryMap;
60
61 bool loadFactoryForSchemeFromPath(
62 const String8 &path,
63 int32_t CA_system_id,
64 sp<SharedLibrary> *library,
65 T** factory);
66
Steven Moreland9b2e5042019-05-01 01:15:39 +000067 bool queryPluginsFromPath(
68 const String8 &path,
69 vector<HidlCasPluginDescriptor>* results);
Chong Zhanga4f67512017-04-24 17:18:25 -070070
71 bool openFactory(const String8 &path);
72 void closeFactory();
73};
74
75template <class T>
76bool FactoryLoader<T>::findFactoryForScheme(
77 int32_t CA_system_id, sp<SharedLibrary> *library, T** factory) {
78 if (library != NULL) {
79 library->clear();
80 }
81 if (factory != NULL) {
82 *factory = NULL;
83 }
84
85 Mutex::Autolock autoLock(mMapLock);
86
87 // first check cache
88 ssize_t index = mCASystemIdToLibraryPathMap.indexOfKey(CA_system_id);
89 if (index >= 0) {
90 return loadFactoryForSchemeFromPath(
91 mCASystemIdToLibraryPathMap[index],
92 CA_system_id, library, factory);
93 }
94
95 // no luck, have to search
bohub305c802021-01-30 19:14:05 -080096#ifdef __LP64__
97 String8 dirPath("/vendor/lib64/mediacas");
98#else
Chong Zhanga4f67512017-04-24 17:18:25 -070099 String8 dirPath("/vendor/lib/mediacas");
bohub305c802021-01-30 19:14:05 -0800100#endif
101
Chong Zhanga4f67512017-04-24 17:18:25 -0700102 DIR* pDir = opendir(dirPath.string());
103
104 if (pDir == NULL) {
105 ALOGE("Failed to open plugin directory %s", dirPath.string());
106 return false;
107 }
108
109 struct dirent* pEntry;
110 while ((pEntry = readdir(pDir))) {
111 String8 pluginPath = dirPath + "/" + pEntry->d_name;
Tomasz Wasilczyk9e532812023-08-29 15:04:50 +0000112 if (base::EndsWith(pluginPath.c_str(), ".so")) {
Chong Zhanga4f67512017-04-24 17:18:25 -0700113 if (loadFactoryForSchemeFromPath(
114 pluginPath, CA_system_id, library, factory)) {
115 mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath);
116 closedir(pDir);
117
118 return true;
119 }
120 }
121 }
122
123 closedir(pDir);
124
125 ALOGE("Failed to find plugin");
126 return false;
127}
128
129template <class T>
Steven Moreland9b2e5042019-05-01 01:15:39 +0000130bool FactoryLoader<T>::enumeratePlugins(
131 vector<HidlCasPluginDescriptor>* results) {
Chong Zhanga4f67512017-04-24 17:18:25 -0700132 ALOGI("enumeratePlugins");
133
Steven Moreland9b2e5042019-05-01 01:15:39 +0000134 results->clear();
135
bohub305c802021-01-30 19:14:05 -0800136#ifdef __LP64__
137 String8 dirPath("/vendor/lib64/mediacas");
138#else
Chong Zhanga4f67512017-04-24 17:18:25 -0700139 String8 dirPath("/vendor/lib/mediacas");
bohub305c802021-01-30 19:14:05 -0800140#endif
141
Chong Zhanga4f67512017-04-24 17:18:25 -0700142 DIR* pDir = opendir(dirPath.string());
143
144 if (pDir == NULL) {
145 ALOGE("Failed to open plugin directory %s", dirPath.string());
146 return false;
147 }
148
149 Mutex::Autolock autoLock(mMapLock);
150
151 struct dirent* pEntry;
152 while ((pEntry = readdir(pDir))) {
153 String8 pluginPath = dirPath + "/" + pEntry->d_name;
Tomasz Wasilczyk9e532812023-08-29 15:04:50 +0000154 if (base::EndsWith(pluginPath.c_str(), ".so")) {
Chong Zhanga4f67512017-04-24 17:18:25 -0700155 queryPluginsFromPath(pluginPath, results);
156 }
157 }
158 return true;
159}
160
161template <class T>
162bool FactoryLoader<T>::loadFactoryForSchemeFromPath(
163 const String8 &path, int32_t CA_system_id,
164 sp<SharedLibrary> *library, T** factory) {
165 closeFactory();
166
167 if (!openFactory(path) || !mFactory->isSystemIdSupported(CA_system_id)) {
168 closeFactory();
169 return false;
170 }
171
172 if (library != NULL) {
173 *library = mLibrary;
174 }
175 if (factory != NULL) {
176 *factory = mFactory;
177 }
178 return true;
179}
180
181template <class T>
Steven Moreland9b2e5042019-05-01 01:15:39 +0000182bool FactoryLoader<T>::queryPluginsFromPath(
183 const String8 &path, vector<HidlCasPluginDescriptor>* results) {
Chong Zhanga4f67512017-04-24 17:18:25 -0700184 closeFactory();
185
186 vector<CasPluginDescriptor> descriptors;
187 if (!openFactory(path) || mFactory->queryPlugins(&descriptors) != OK) {
188 closeFactory();
189 return false;
190 }
191
Steven Moreland9b2e5042019-05-01 01:15:39 +0000192 for (auto it = descriptors.begin(); it != descriptors.end(); it++) {
193 results->push_back( HidlCasPluginDescriptor {
194 .caSystemId = it->CA_system_id,
195 .name = it->name.c_str()});
Chong Zhanga4f67512017-04-24 17:18:25 -0700196 }
Chong Zhanga4f67512017-04-24 17:18:25 -0700197 return true;
198}
199
200template <class T>
201bool FactoryLoader<T>::openFactory(const String8 &path) {
202 // get strong pointer to open shared library
203 ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path);
204 if (index >= 0) {
205 mLibrary = mLibraryPathToOpenLibraryMap[index].promote();
206 } else {
207 index = mLibraryPathToOpenLibraryMap.add(path, NULL);
208 }
209
210 if (!mLibrary.get()) {
211 mLibrary = new SharedLibrary(path);
212 if (!*mLibrary) {
213 return false;
214 }
215
216 mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary);
217 }
218
219 CreateFactoryFunc createFactory =
220 (CreateFactoryFunc)mLibrary->lookup(mCreateFactoryFuncName);
221 if (createFactory == NULL || (mFactory = createFactory()) == NULL) {
222 return false;
223 }
224 return true;
225}
226
227template <class T>
228void FactoryLoader<T>::closeFactory() {
229 delete mFactory;
230 mFactory = NULL;
231 mLibrary.clear();
232}
233
234} // namespace implementation
235} // namespace V1_0
236} // namespace cas
237} // namespace hardware
238} // namespace android
239
240#endif // ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_