026dab9f创建于 1月23日历史提交
/*

 * 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;

    // free after send reply

    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;

    }



    /* call the lib destroy method,then free controller manager */

    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;

}