* Copyright (c) 2023 Huawei Device Co., Ltd.
* 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 <securec.h>
#include <string.h>
#include <pthread.h>
#include "effect_core.h"
#include "effect_host_common.h"
#include "v1_0/effect_types_vdi.h"
#include "v1_0/effect_factory.h"
#include "osal_mem.h"
#include "parse_effect_config.h"
#include "audio_uhdf_log.h"
#include "stub_collector.h"
#define AUDIO_EFFECT_PLAFORM_CONFIG HDF_CONFIG_DIR"/audio_effect.json"
#define AUDIO_EFFECT_PRODUCT_CONFIG HDF_CHIP_PROD_CONFIG_DIR"/audio_effect.json"
#define HDF_LOG_TAG HDF_AUDIO_EFFECT
#define AUDIO_EFFECT_NUM_MAX 10
pthread_rwlock_t g_rwEffectLock = PTHREAD_RWLOCK_INITIALIZER;
struct ConfigDescriptor *g_cfgDescs = NULL;
struct AudioEffectLibInfo {
char *libName;
uint8_t *libHandle;
struct EffectFactory *libEffect;
struct ControllerManager *ctrlMgr;
int32_t effectCnt;
};
struct AudioEffectLibInfo *g_libInfos[AUDIO_EFFECT_NUM_MAX] = { NULL };
static struct AudioEffectLibInfo* GetEffectLibInfoByName(const char *libName)
{
if (libName == NULL) {
HDF_LOGE("%{public}s: invailid input params", __func__);
return NULL;
}
struct AudioEffectLibInfo *libInfo = NULL;
for (int i = 0; i <= AUDIO_EFFECT_NUM_MAX; i++) {
if (i == AUDIO_EFFECT_NUM_MAX) {
HDF_LOGE("%{public}s: can not find %{public}s", __func__, libName);
return NULL;
}
if (g_libInfos[i] == NULL || g_libInfos[i]->libName == NULL || strcmp(g_libInfos[i]->libName, libName) != 0) {
continue;
}
libInfo = g_libInfos[i];
break;
}
return libInfo;
}
static int32_t LoadLibraryByName(const char *libName, uint8_t **libHandle, struct EffectFactory **factLib)
{
if (libName == NULL || factLib == NULL || libHandle == NULL) {
HDF_LOGE("%{public}s: invailid input params", __func__);
return HDF_ERR_INVALID_PARAM;
}
int32_t ret = 0;
struct EffectFactory *(*getFactoryLib)(void);
char path[PATH_MAX];
char pathBuf[PATH_MAX];
#if (defined(__aarch64__) || defined(__x86_64__))
ret = snprintf_s(path, PATH_MAX, PATH_MAX, "/vendor/lib64/%s.z.so", libName);
#else
ret = snprintf_s(path, PATH_MAX, PATH_MAX, "/vendor/lib/%s.z.so", libName);
#endif
if (ret < 0) {
HDF_LOGE("%{public}s: get libPath failed", __func__);
return HDF_FAILURE;
}
if (realpath(path, pathBuf) == NULL) {
HDF_LOGE("%{public}s: realpath is null! [%{public}d]", __func__, errno);
return HDF_FAILURE;
}
if (strncmp(HDF_LIBRARY_DIR, pathBuf, strlen(HDF_LIBRARY_DIR)) != 0) {
HDF_LOGE("%{public}s: The file path is incorrect", __func__);
return HDF_FAILURE;
}
void *handle = dlopen(pathBuf, RTLD_LAZY);
if (handle == NULL) {
HDF_LOGE("%{public}s: open so failed, reason:%{public}s", __func__, dlerror());
return HDF_FAILURE;
}
getFactoryLib = dlsym(handle, "GetEffectoyFactoryLib");
if (getFactoryLib == NULL) {
HDF_LOGE("%{public}s: dlsym failed %{public}s", __func__, dlerror());
dlclose(handle);
return HDF_FAILURE;
}
*factLib = getFactoryLib();
if (*factLib == NULL) {
HDF_LOGE("%{public}s: get fact lib failed %{public}s", __func__, dlerror());
dlclose(handle);
return HDF_FAILURE;
}
*libHandle = handle;
return HDF_SUCCESS;
}
static struct AudioEffectLibInfo* AddEffectLibInfo(const char *libName, uint8_t *libHandle,
struct EffectFactory *factLib)
{
if (libName == NULL || factLib == NULL || libHandle == NULL) {
HDF_LOGE("%{public}s: invailid input params", __func__);
return NULL;
}
struct AudioEffectLibInfo *libInfo = NULL;
libInfo = (struct AudioEffectLibInfo *)OsalMemCalloc(sizeof(struct AudioEffectLibInfo));
if (libInfo == NULL) {
HDF_LOGE("%{public}s: OsalMemCalloc fail", __func__);
return NULL;
}
libInfo->libName = strdup(libName);
if (libInfo->libName == NULL) {
HDF_LOGE("%{public}s: strdup fail", __func__);
OsalMemFree(libInfo);
libInfo = NULL;
return NULL;
}
libInfo->libHandle = libHandle;
libInfo->libEffect = factLib;
libInfo->ctrlMgr = NULL;
libInfo->effectCnt = 1;
return libInfo;
}
static int32_t LoadEffectLibrary(const char *libName, struct EffectFactory **factLib,
struct ControllerManager** ctrlMgr)
{
if (libName == NULL || factLib == NULL || ctrlMgr == NULL) {
HDF_LOGE("%{public}s: invailid input params", __func__);
return HDF_ERR_INVALID_PARAM;
}
uint8_t *libHandle = NULL;
int32_t index = 0;
for (int i = 0; i <= AUDIO_EFFECT_NUM_MAX; i++) {
if (i == AUDIO_EFFECT_NUM_MAX) {
HDF_LOGE("%{public}s: over effect max num", __func__);
return HDF_FAILURE;
}
if (g_libInfos[i] == NULL) {
index = i;
break;
}
if (g_libInfos[i]->libName == NULL) {
HDF_LOGE("%{public}s: libName is null", __func__);
continue;
}
if (strcmp(g_libInfos[i]->libName, libName) != 0) {
continue;
}
g_libInfos[i]->effectCnt++;
*factLib = g_libInfos[i]->libEffect;
*ctrlMgr = g_libInfos[i]->ctrlMgr;
HDF_LOGI("%{public}s: %{public}s increase, cnt=[%{public}d]", __func__, libName, g_libInfos[i]->effectCnt);
return HDF_SUCCESS;
}
int32_t ret = LoadLibraryByName(libName, &libHandle, factLib);
if (ret != HDF_SUCCESS || libHandle == NULL || *factLib == NULL) {
HDF_LOGE("%{public}s: load lib fail, libName:[%{public}s]", __func__, libName);
return HDF_FAILURE;
}
g_libInfos[index] = AddEffectLibInfo(libName, libHandle, *factLib);
if (g_libInfos[index] == NULL) {
HDF_LOGE("%{public}s: AddEffectLibInfo fail", __func__);
dlclose((void *)libHandle);
return HDF_FAILURE;
}
HDF_LOGI("%{public}s: %{public}s create, cnt=[%{public}d]", __func__, libName, g_libInfos[index]->effectCnt);
return HDF_SUCCESS;
}
static int32_t DeleteEffectLibrary(const char *libName)
{
if (libName == NULL) {
HDF_LOGE("%{public}s: invailid input params", __func__);
return HDF_ERR_INVALID_PARAM;
}
for (int i = 0; i <= AUDIO_EFFECT_NUM_MAX; i++) {
if (i == AUDIO_EFFECT_NUM_MAX) {
HDF_LOGE("%{public}s: fail to destroy effect, can not find %{public}s", __func__, libName);
return HDF_FAILURE;
}
if (g_libInfos[i] == NULL || g_libInfos[i]->libName == NULL || strcmp(g_libInfos[i]->libName, libName) != 0) {
continue;
}
if (g_libInfos[i]->effectCnt > 1) {
g_libInfos[i]->effectCnt--;
HDF_LOGI("%{public}s: %{public}s decrease, cnt=[%{public}d]", __func__, libName, g_libInfos[i]->effectCnt);
return HDF_SUCCESS;
}
dlclose((void*)g_libInfos[i]->libHandle);
OsalMemFree(g_libInfos[i]->libName);
OsalMemFree(g_libInfos[i]->ctrlMgr);
OsalMemFree(g_libInfos[i]);
g_libInfos[i] = NULL;
break;
}
HDF_LOGI("%{public}s: %{public}s delete", __func__, libName);
return HDF_SUCCESS;
}
static int32_t IsSupplyEffect(const char *libName)
{
if (g_cfgDescs == NULL) {
HDF_LOGE("%{public}s: point is null!", __func__);
return HDF_FAILURE;
}
if (libName == NULL) {
HDF_LOGE("%{public}s: libName is null!", __func__);
return HDF_FAILURE;
}
for (uint32_t i = 0; i < g_cfgDescs->effectNum; i++) {
if (g_cfgDescs->effectCfgDescs[i].library == NULL) {
HDF_LOGE("%{public}s: library is null!", __func__);
continue;
}
if (strcmp(g_cfgDescs->effectCfgDescs[i].library, libName) == 0) {
return HDF_SUCCESS;
}
}
return HDF_FAILURE;
}
static int32_t EffectModelIsSupplyEffectLibs(struct IEffectModel *self, bool *supply)
{
if (self == NULL || supply == NULL) {
HDF_LOGE("%{public}s: invailid input params", __func__);
return HDF_ERR_INVALID_PARAM;
}
*supply = IsEffectLibExist();
return HDF_SUCCESS;
}
static int32_t EffectModelGetAllEffectDescriptors(struct IEffectModel *self,
struct EffectControllerDescriptor *descs, uint32_t *descsLen)
{
HDF_LOGD("enter to %{public}s", __func__);
uint32_t descNum = 0;
struct EffectFactory *factLib = NULL;
struct ControllerManager *ctrlMgr = NULL;
if (self == NULL || descs == NULL || descsLen == NULL) {
HDF_LOGE("%{public}s: invailid input params", __func__);
return HDF_ERR_INVALID_PARAM;
}
if (g_cfgDescs == NULL) {
HDF_LOGE("%{public}s: point is null!", __func__);
return HDF_FAILURE;
}
struct EffectControllerDescriptorVdi *descsVdi = (struct EffectControllerDescriptorVdi *)descs;
pthread_rwlock_wrlock(&g_rwEffectLock);
for (uint32_t i = 0; i < g_cfgDescs->effectNum; i++) {
int32_t ret = LoadEffectLibrary(g_cfgDescs->effectCfgDescs[i].library, &factLib, &ctrlMgr);
if (ret != HDF_SUCCESS || factLib == NULL) {
HDF_LOGE("%{public}s: GetEffectLibFromList fail!", __func__);
continue;
}
if (ConstructDescriptor(&descsVdi[descNum]) != HDF_SUCCESS) {
HDF_LOGE("%{public}s: ConstructDescriptor fail!", __func__);
continue;
}
ret = factLib->GetDescriptor(factLib, g_cfgDescs->effectCfgDescs[i].effectId, &descsVdi[descNum]);
if (ret != HDF_SUCCESS) {
descNum++;
DeleteEffectLibrary(g_cfgDescs->effectCfgDescs[i].library);
HDF_LOGE("%{public}s: GetDescriptor fail!", __func__);
continue;
}
DeleteEffectLibrary(g_cfgDescs->effectCfgDescs[i].library);
factLib = NULL;
descNum++;
}
*descsLen = descNum;
descs = (struct EffectControllerDescriptor *)descsVdi;
pthread_rwlock_unlock(&g_rwEffectLock);
HDF_LOGD("%{public}s success", __func__);
return HDF_SUCCESS;
}
static int32_t EffectModelGetEffectDescriptor(struct IEffectModel *self, const char *uuid,
struct EffectControllerDescriptor *desc)
{
HDF_LOGD("enter to %{public}s", __func__);
uint32_t i;
struct EffectFactory *factLib = NULL;
struct ControllerManager *ctrlMgr = NULL;
if (self == NULL || uuid == NULL || desc == NULL || g_cfgDescs == NULL) {
HDF_LOGE("%{public}s: invailid input params", __func__);
return HDF_ERR_INVALID_PARAM;
}
struct EffectControllerDescriptorVdi *descVdi = (struct EffectControllerDescriptorVdi *)desc;
for (i = 0; i < g_cfgDescs->effectNum; i++) {
if (g_cfgDescs->effectCfgDescs[i].effectId == NULL) {
HDF_LOGE("%{public}s: effectId is null", __func__);
continue;
}
if (strcmp(uuid, g_cfgDescs->effectCfgDescs[i].effectId) != 0) {
continue;
}
pthread_rwlock_wrlock(&g_rwEffectLock);
LoadEffectLibrary(g_cfgDescs->effectCfgDescs[i].library, &factLib, &ctrlMgr);
if (factLib == NULL) {
HDF_LOGE("%{public}s: GetEffectLibFromList fail!", __func__);
pthread_rwlock_unlock(&g_rwEffectLock);
return HDF_FAILURE;
}
if (ConstructDescriptor(descVdi) != HDF_SUCCESS) {
HDF_LOGE("%{public}s: ConstructDescriptor fail!", __func__);
pthread_rwlock_unlock(&g_rwEffectLock);
return HDF_FAILURE;
}
if (factLib->GetDescriptor(factLib, uuid, descVdi) != HDF_SUCCESS) {
DeleteEffectLibrary(g_cfgDescs->effectCfgDescs[i].library);
HDF_LOGE("%{public}s: GetDescriptor fail!", __func__);
pthread_rwlock_unlock(&g_rwEffectLock);
return HDF_FAILURE;
}
DeleteEffectLibrary(g_cfgDescs->effectCfgDescs[i].library);
HDF_LOGD("%{public}s success", __func__);
pthread_rwlock_unlock(&g_rwEffectLock);
return HDF_SUCCESS;
}
desc = (struct EffectControllerDescriptor *)descVdi;
HDF_LOGE("%{public}s fail!", __func__);
return HDF_FAILURE;
}
static int32_t CreateEffectController(const struct EffectInfo *info, struct IEffectControl **contoller,
struct ControllerId *contollerId, struct IEffectControlVdi *ctrlOps)
{
if (info == NULL || contoller == NULL || contollerId == NULL || ctrlOps == NULL) {
HDF_LOGE("%{public}s: invailid input params", __func__);
return HDF_ERR_INVALID_PARAM;
}
struct ControllerManager *ctrlMgr = (struct ControllerManager *)OsalMemCalloc(sizeof(struct ControllerManager));
CHECK_NULL_PTR_RETURN_VALUE(ctrlMgr, HDF_FAILURE);
struct AudioEffectLibInfo *libInfo = GetEffectLibInfoByName(info->libName);
if (libInfo == NULL) {
HDF_LOGE("%{public}s: GetEffectLibInfoByName failed", __func__);
OsalMemFree(ctrlMgr);
return HDF_FAILURE;
}
libInfo->ctrlMgr = ctrlMgr;
ctrlMgr->ctrlOps = ctrlOps;
ctrlMgr->libName = strdup(info->libName);
if (ctrlMgr->libName == NULL) {
HDF_LOGE("%{public}s: strdup failed, info->effectId = %{public}s", __func__, info->effectId);
OsalMemFree(ctrlMgr);
return HDF_FAILURE;
}
ctrlMgr->ctrlImpls.EffectProcess = EffectControlEffectProcess;
ctrlMgr->ctrlImpls.SendCommand = EffectControlSendCommand;
ctrlMgr->ctrlImpls.GetEffectDescriptor = EffectGetOwnDescriptor;
ctrlMgr->ctrlImpls.EffectReverse = EffectControlEffectReverse;
*contoller = &ctrlMgr->ctrlImpls;
contollerId->libName = strdup(info->libName);
contollerId->effectId = strdup(info->effectId);
if (contollerId->libName == NULL || contollerId->effectId == NULL) {
HDF_LOGE("%{public}s: strdup failed, info->libName = %{public}s", __func__, info->libName);
OsalMemFree(ctrlMgr->libName);
OsalMemFree(ctrlMgr);
*contoller = NULL;
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int32_t EffectModelCreateEffectController(struct IEffectModel *self, const struct EffectInfo *info,
struct IEffectControl **contoller, struct ControllerId *contollerId)
{
if (self == NULL || info == NULL || contoller == NULL || contollerId == NULL) {
HDF_LOGE("%{public}s: invailid input params", __func__);
return HDF_ERR_INVALID_PARAM;
}
if (IsSupplyEffect(info->libName) != HDF_SUCCESS) {
HDF_LOGE("%{public}s: not support effect [%{public}s]", __func__, info->libName);
return HDF_FAILURE;
}
struct EffectFactory *lib = NULL;
struct ControllerManager *ctrlMgr = NULL;
struct IEffectControlVdi *ctrlOps = NULL;
pthread_rwlock_wrlock(&g_rwEffectLock);
int32_t ret = LoadEffectLibrary(info->libName, &lib, &ctrlMgr);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%{public}s: LoadEffectLibrary fail", __func__);
goto EXIT;
}
if (ctrlMgr != NULL) {
contollerId->libName = strdup(info->libName);
contollerId->effectId = strdup(info->effectId);
if (contollerId->libName == NULL || contollerId->effectId == NULL) {
HDF_LOGE("%{public}s: strdup failed", __func__);
goto EXIT;
}
*contoller = &ctrlMgr->ctrlImpls;
pthread_rwlock_unlock(&g_rwEffectLock);
return HDF_SUCCESS;
}
if (lib == NULL || lib->CreateController == NULL) {
HDF_LOGE("%{public}s: lib or lib->CreateController is null", __func__);
goto EXIT;
}
struct EffectInfoVdi *infoVdi = (struct EffectInfoVdi *)info;
lib->CreateController(lib, infoVdi, &ctrlOps);
if (ctrlOps == NULL) {
HDF_LOGE("%{public}s: ctrlOps is null", __func__);
goto EXIT;
}
if (CreateEffectController(info, contoller, contollerId, ctrlOps) != HDF_SUCCESS) {
DeleteEffectLibrary(info->libName);
goto EXIT;
}
pthread_rwlock_unlock(&g_rwEffectLock);
HDF_LOGI("%{public}s: create effect succeed, libName = %{public}s", __func__, info->libName);
return HDF_SUCCESS;
EXIT:
pthread_rwlock_unlock(&g_rwEffectLock);
return HDF_FAILURE;
}
int32_t EffectModelDestroyEffectController(struct IEffectModel *self, const struct ControllerId *contollerId)
{
if (self == NULL || contollerId == NULL) {
HDF_LOGE("%{public}s: invailid input params", __func__);
return HDF_ERR_INVALID_PARAM;
}
pthread_rwlock_wrlock(&g_rwEffectLock);
struct AudioEffectLibInfo *libInfo = GetEffectLibInfoByName(contollerId->libName);
if (libInfo == NULL) {
HDF_LOGE("%{public}s: GetEffectLibInfoByName failed", __func__);
pthread_rwlock_unlock(&g_rwEffectLock);
return HDF_FAILURE;
}
if (libInfo->effectCnt > 1) {
libInfo->effectCnt--;
pthread_rwlock_unlock(&g_rwEffectLock);
return HDF_SUCCESS;
}
struct EffectFactory *lib = libInfo->libEffect;
if (lib == NULL) {
HDF_LOGE("%{public}s: lib is null", __func__);
pthread_rwlock_unlock(&g_rwEffectLock);
return HDF_FAILURE;
}
struct ControllerManager *ctrlMgr = libInfo->ctrlMgr;
if (ctrlMgr == NULL) {
HDF_LOGE("%{public}s: ctrlMgr is null", __func__);
pthread_rwlock_unlock(&g_rwEffectLock);
return HDF_FAILURE;
}
if (ctrlMgr->libName != NULL) {
OsalMemFree(ctrlMgr->libName);
ctrlMgr->libName = NULL;
}
if (ctrlMgr->ctrlOps == NULL) {
HDF_LOGE("%{public}s: controller has no options", __func__);
pthread_rwlock_unlock(&g_rwEffectLock);
return HDF_FAILURE;
}
StubCollectorRemoveObject(IEFFECTCONTROL_INTERFACE_DESC, &ctrlMgr->ctrlImpls);
lib->DestroyController(lib, ctrlMgr->ctrlOps);
DeleteEffectLibrary(contollerId->libName);
pthread_rwlock_unlock(&g_rwEffectLock);
HDF_LOGI("%{public}s: destroy effect succeed, libName = %{public}s", __func__, contollerId->libName);
return HDF_SUCCESS;
}
void ModelInit(void)
{
FILE *file;
struct ConfigDescriptor *cfgDesc = NULL;
int32_t ret;
file = fopen(AUDIO_EFFECT_PRODUCT_CONFIG, "r");
if (file == NULL) {
ret = AudioEffectGetConfigDescriptor(AUDIO_EFFECT_PLAFORM_CONFIG, &cfgDesc);
HDF_LOGI("%{public}s: %{public}s!", __func__, AUDIO_EFFECT_PLAFORM_CONFIG);
} else {
ret = AudioEffectGetConfigDescriptor(AUDIO_EFFECT_PRODUCT_CONFIG, &cfgDesc);
HDF_LOGI("%{public}s: %{public}s!", __func__, AUDIO_EFFECT_PRODUCT_CONFIG);
(void)fclose(file);
}
if (ret != HDF_SUCCESS) {
HDF_LOGE("%{public}s: AudioEffectGetConfigDescriptor fail!", __func__);
return;
}
if (g_cfgDescs != NULL) {
AudioEffectReleaseCfgDesc(g_cfgDescs);
}
g_cfgDescs = cfgDesc;
HDF_LOGD("%{public}s end!", __func__);
}
struct IEffectModel *EffectModelImplGetInstance(void)
{
struct EffectModelService *service = (struct EffectModelService *)OsalMemCalloc(sizeof(struct EffectModelService));
if (service == NULL) {
HDF_LOGE("%{public}s: malloc EffectModelService obj failed!", __func__);
return NULL;
}
ModelInit();
service->interface.IsSupplyEffectLibs = EffectModelIsSupplyEffectLibs;
service->interface.GetAllEffectDescriptors = EffectModelGetAllEffectDescriptors;
service->interface.CreateEffectController = EffectModelCreateEffectController;
service->interface.DestroyEffectController = EffectModelDestroyEffectController;
service->interface.GetEffectDescriptor = EffectModelGetEffectDescriptor;
return &service->interface;
}
void EffectModelImplRelease(struct IEffectModel *instance)
{
if (instance == NULL) {
return;
}
AudioEffectReleaseCfgDesc(g_cfgDescs);
struct EffectModelService *service = CONTAINER_OF(instance, struct EffectModelService, interface);
if (service == NULL) {
return;
}
StubCollectorRemoveObject(IEFFECTMODEL_INTERFACE_DESC, instance);
OsalMemFree(service);
service = NULL;
}