Files
hardware_interfaces/cas/aidl/default/FactoryLoader.h
Garfield Tan 7777a4be12 Unmark executable bits from CAS AIDL HAL impl
None of these files are executable. The .rc and .xml files shouldn't be
installed to the device image as executables either.

Bug: None
Test: Files installed on the device aren't executables anymore.
Change-Id: Id15ecc7febb56ea108155fcbd338efeb8885709a
2023-07-17 14:58:47 -07:00

221 lines
6.2 KiB
C++

/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <dirent.h>
#include <dlfcn.h>
#include <media/cas/CasAPI.h>
#include <utils/KeyedVector.h>
#include <utils/Mutex.h>
#include "SharedLibrary.h"
using namespace std;
namespace aidl {
namespace android {
namespace hardware {
namespace cas {
using namespace ::android;
template <class T>
class FactoryLoader {
public:
FactoryLoader(const char* name) : mFactory(NULL), mCreateFactoryFuncName(name) {}
virtual ~FactoryLoader() { closeFactory(); }
bool findFactoryForScheme(int32_t CA_system_id, shared_ptr<SharedLibrary>* library = NULL,
T** factory = NULL);
bool enumeratePlugins(vector<AidlCasPluginDescriptor>* results);
private:
typedef T* (*CreateFactoryFunc)();
Mutex mMapLock;
T* mFactory;
const char* mCreateFactoryFuncName;
shared_ptr<SharedLibrary> mLibrary;
KeyedVector<int32_t, String8> mCASystemIdToLibraryPathMap;
KeyedVector<String8, shared_ptr<SharedLibrary>> mLibraryPathToOpenLibraryMap;
bool loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id,
shared_ptr<SharedLibrary>* library, T** factory);
bool queryPluginsFromPath(const String8& path, vector<AidlCasPluginDescriptor>* results);
bool openFactory(const String8& path);
void closeFactory();
};
template <class T>
bool FactoryLoader<T>::findFactoryForScheme(int32_t CA_system_id,
shared_ptr<SharedLibrary>* library, T** factory) {
if (library != NULL) {
library->reset();
}
if (factory != NULL) {
*factory = NULL;
}
Mutex::Autolock autoLock(mMapLock);
// first check cache
ssize_t index = mCASystemIdToLibraryPathMap.indexOfKey(CA_system_id);
if (index >= 0) {
return loadFactoryForSchemeFromPath(mCASystemIdToLibraryPathMap[index], CA_system_id,
library, factory);
}
// no luck, have to search
#ifdef __LP64__
String8 dirPath("/vendor/lib64/mediacas");
#else
String8 dirPath("/vendor/lib/mediacas");
#endif
DIR* pDir = opendir(dirPath.string());
if (pDir == NULL) {
ALOGE("Failed to open plugin directory %s", dirPath.string());
return false;
}
struct dirent* pEntry;
while ((pEntry = readdir(pDir))) {
String8 pluginPath = dirPath + "/" + pEntry->d_name;
if (pluginPath.getPathExtension() == ".so") {
if (loadFactoryForSchemeFromPath(pluginPath, CA_system_id, library, factory)) {
mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath);
closedir(pDir);
return true;
}
}
}
closedir(pDir);
ALOGE("Failed to find plugin");
return false;
}
template <class T>
bool FactoryLoader<T>::enumeratePlugins(vector<AidlCasPluginDescriptor>* results) {
ALOGI("enumeratePlugins");
results->clear();
#ifdef __LP64__
String8 dirPath("/vendor/lib64/mediacas");
#else
String8 dirPath("/vendor/lib/mediacas");
#endif
DIR* pDir = opendir(dirPath.string());
if (pDir == NULL) {
ALOGE("Failed to open plugin directory %s", dirPath.string());
return false;
}
Mutex::Autolock autoLock(mMapLock);
struct dirent* pEntry;
while ((pEntry = readdir(pDir))) {
String8 pluginPath = dirPath + "/" + pEntry->d_name;
if (pluginPath.getPathExtension() == ".so") {
queryPluginsFromPath(pluginPath, results);
}
}
closedir(pDir);
return true;
}
template <class T>
bool FactoryLoader<T>::loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id,
shared_ptr<SharedLibrary>* library,
T** factory) {
closeFactory();
if (!openFactory(path) || !mFactory->isSystemIdSupported(CA_system_id)) {
closeFactory();
return false;
}
if (library != NULL) {
*library = mLibrary;
}
if (factory != NULL) {
*factory = mFactory;
}
return true;
}
template <class T>
bool FactoryLoader<T>::queryPluginsFromPath(const String8& path,
vector<AidlCasPluginDescriptor>* results) {
closeFactory();
vector<CasPluginDescriptor> descriptors;
if (!openFactory(path) || mFactory->queryPlugins(&descriptors) != OK) {
closeFactory();
return false;
}
for (auto it = descriptors.begin(); it != descriptors.end(); it++) {
results->push_back(
AidlCasPluginDescriptor{.caSystemId = it->CA_system_id, .name = it->name.c_str()});
}
return true;
}
template <class T>
bool FactoryLoader<T>::openFactory(const String8& path) {
// get strong pointer to open shared library
ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path);
if (index >= 0) {
mLibrary = mLibraryPathToOpenLibraryMap[index];
} else {
index = mLibraryPathToOpenLibraryMap.add(path, NULL);
}
if (!mLibrary.get()) {
mLibrary = ::ndk::SharedRefBase::make<SharedLibrary>(path);
if (!*mLibrary) {
return false;
}
mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary);
}
CreateFactoryFunc createFactory = (CreateFactoryFunc)mLibrary->lookup(mCreateFactoryFuncName);
if (createFactory == NULL || (mFactory = createFactory()) == NULL) {
return false;
}
return true;
}
template <class T>
void FactoryLoader<T>::closeFactory() {
delete mFactory;
mFactory = NULL;
mLibrary.reset();
}
} // namespace cas
} // namespace hardware
} // namespace android
} // namespace aidl