/*
 * Copyright (c) 2022-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 <dlfcn.h>
#include <limits.h>
#include <unistd.h>
#include "hdf_base.h"
#include "hdf_types.h"
#include "osal_mem.h"
#include "securec.h"
#include "stub_collector.h"
#include "audio_adapter_info_common.h"
#include "audio_common.h"
#include "audio_uhdf_log.h"
#include "audio_internal.h"

#define HDF_LOG_TAG HDF_AUDIO_PRIMARY_IMPL

BindServiceRenderPassthrough g_bindServiceRender = NULL;
InterfaceLibModeRenderPassthrough g_interfaceLibModeRender = NULL;
CloseServiceRenderPassthrough g_closeServiceRender = NULL;

BindServiceCapturePassthrough g_bindServiceCapture = NULL;
InterfaceLibModeCapturePassthrough g_interfaceLibModeCapture = NULL;
CloseServiceCapturePassthrough g_closeServiceCapture = NULL;

InterfaceLibModeGetAllCardInfo g_getAllCardInfo = NULL;

#ifndef AUDIO_HAL_NOTSUPPORT_PATHSELECT
PathSelGetConfToJsonObj g_pathSelGetConfToJsonObj = NULL;
PathSelAnalysisJson g_pathSelAnalysisJson = NULL;
#endif

static const char *CAPTURE_PASSTHTOUGH_PATH = HDF_LIBRARY_FULL_PATH("libaudio_capture_adapter");
static const char *RENDER_PASSTHTOUGH_PATH = HDF_LIBRARY_FULL_PATH("libaudio_render_adapter");

#ifndef AUDIO_HAL_NOTSUPPORT_PATHSELECT
static const char *PATH_SELECT_PASSTHROUGH_PATH = HDF_LIBRARY_FULL_PATH("libaudio_path_select");
#endif

static void *g_ptrCaptureHandle = NULL;
static void *g_ptrRenderHandle = NULL;

#ifndef AUDIO_HAL_NOTSUPPORT_PATHSELECT
static void *g_ptrPathSelHandle = NULL;
#endif

BindServiceRenderPassthrough *AudioPassthroughGetBindServiceRender(void)
{
    return &g_bindServiceRender;
}

InterfaceLibModeRenderPassthrough *AudioPassthroughGetInterfaceLibModeRender(void)
{
    return &g_interfaceLibModeRender;
}

CloseServiceRenderPassthrough *AudioPassthroughGetCloseServiceRender(void)
{
    return &g_closeServiceRender;
}

BindServiceCapturePassthrough *AudioPassthroughGetBindServiceCapture(void)
{
    return &g_bindServiceCapture;
}

InterfaceLibModeCapturePassthrough *AudioPassthroughGetInterfaceLibModeCapture(void)
{
    return &g_interfaceLibModeCapture;
}

CloseServiceCapturePassthrough *AudioPassthroughGetCloseServiceCapture(void)
{
    return &g_closeServiceCapture;
}

#ifndef AUDIO_HAL_NOTSUPPORT_PATHSELECT
PathSelGetConfToJsonObj *AudioPassthroughGetPathSelGetConfToJsonObj(void)
{
    return &g_pathSelGetConfToJsonObj;
}

PathSelAnalysisJson *AudioPassthroughGetPathSelAnalysisJson(void)
{
    return &g_pathSelAnalysisJson;
}
#endif

static int32_t InitCapturePassthroughHandle(const char *capturePassthroughPath)
{
    if (capturePassthroughPath == NULL) {
        AUDIO_FUNC_LOGE("capturePassthroughPath is NULL");
        return HDF_FAILURE;
    }
    char pathBuf[PATH_MAX] = {'\0'};
    if (realpath(capturePassthroughPath, pathBuf) == NULL) {
        return HDF_FAILURE;
    }
    if (g_ptrCaptureHandle == NULL) {
        g_ptrCaptureHandle = dlopen(pathBuf, RTLD_LAZY);
        if (g_ptrCaptureHandle == NULL) {
            AUDIO_FUNC_LOGE("open lib capture so fail, reason:%{public}s", dlerror());
            return HDF_FAILURE;
        }
        g_bindServiceCapture = dlsym(g_ptrCaptureHandle, "AudioBindService");
        g_interfaceLibModeCapture = dlsym(g_ptrCaptureHandle, "AudioInterfaceLibModeCapture");
        g_closeServiceCapture = dlsym(g_ptrCaptureHandle, "AudioCloseService");
        if (g_getAllCardInfo == NULL) {
            g_getAllCardInfo = dlsym(g_ptrCaptureHandle, "AudioGetAllCardInfo");
        }
        if (g_bindServiceCapture == NULL || g_interfaceLibModeCapture == NULL || g_closeServiceCapture == NULL) {
            AUDIO_FUNC_LOGE("lib capture so func not found!");
            AudioDlClose(&g_ptrCaptureHandle);
            return HDF_FAILURE;
        }
    }
    return HDF_SUCCESS;
}

static int32_t InitRenderPassthroughHandle(const char *renderPassthroughPath)
{
    if (renderPassthroughPath == NULL) {
        AUDIO_FUNC_LOGE("renderPassthroughPath is NULL");
        return HDF_FAILURE;
    }
    char pathBuf[PATH_MAX] = {'\0'};
    if (realpath(renderPassthroughPath, pathBuf) == NULL) {
        return HDF_FAILURE;
    }
    if (g_ptrRenderHandle == NULL) {
        g_ptrRenderHandle = dlopen(pathBuf, RTLD_LAZY);
        if (g_ptrRenderHandle == NULL) {
            AUDIO_FUNC_LOGE("open lib render so fail, reason:%{public}s", dlerror());
            return HDF_FAILURE;
        }
        g_bindServiceRender = dlsym(g_ptrRenderHandle, "AudioBindService");
        g_interfaceLibModeRender = dlsym(g_ptrRenderHandle, "AudioInterfaceLibModeRender");
        g_closeServiceRender = dlsym(g_ptrRenderHandle, "AudioCloseService");
        if (g_getAllCardInfo == NULL) {
            g_getAllCardInfo = dlsym(g_ptrRenderHandle, "AudioGetAllCardInfo");
        }
        if (g_bindServiceRender == NULL || g_interfaceLibModeRender == NULL || g_closeServiceRender == NULL) {
            AUDIO_FUNC_LOGE("lib render so func not found!");
            AudioDlClose(&g_ptrRenderHandle);
            return HDF_FAILURE;
        }
    }
    return HDF_SUCCESS;
}

#ifndef AUDIO_HAL_NOTSUPPORT_PATHSELECT
static int32_t InitPathSelectPassthroughHandle(const char *pathSelectPassthroughPath)
{
    if (pathSelectPassthroughPath == NULL) {
        AUDIO_FUNC_LOGE("pathSelectPassthroughPath is NULL");
        return HDF_FAILURE;
    }
    char pathBuf[PATH_MAX] = {'\0'};
    if (realpath(pathSelectPassthroughPath, pathBuf) == NULL) {
        return HDF_FAILURE;
    }
    if (g_ptrPathSelHandle == NULL) {
        g_ptrPathSelHandle = dlopen(pathBuf, RTLD_LAZY);
        if (g_ptrPathSelHandle == NULL) {
            AUDIO_FUNC_LOGE("open lib PathSelct so fail, reason:%{public}s", dlerror());
            return HDF_FAILURE;
        }
        g_pathSelGetConfToJsonObj = dlsym(g_ptrPathSelHandle, "AudioPathSelGetConfToJsonObj");
        g_pathSelAnalysisJson = dlsym(g_ptrPathSelHandle, "AudioPathSelAnalysisJson");
        if (g_pathSelGetConfToJsonObj == NULL || g_pathSelAnalysisJson == NULL) {
            AUDIO_FUNC_LOGE("lib PathSelct so func not found!");
            AudioDlClose(&g_ptrPathSelHandle);
            return HDF_FAILURE;
        }
    }
    return HDF_SUCCESS;
}
#endif

static int32_t AudioManagerServiceGetFreeAdapterPos(struct IAudioManager *manager, const char *adapterName)
{
    int32_t i;
    if (manager == NULL || adapterName == NULL || strlen(adapterName) == 0) {
        AUDIO_FUNC_LOGE("Invalid input param!");
        return SUPPORT_ADAPTER_NUM_MAX;
    }

    struct AudioHwManager *audioManagerSer = (struct AudioHwManager *)manager;
    for (i = 0; i < SUPPORT_ADAPTER_NUM_MAX; i++) {
        if (!strncmp(adapterName, audioManagerSer->adapterInfos[i].adapterName, ADAPTER_NAME_LEN)) {
            AUDIO_FUNC_LOGE("adapterName(%{public}s) already load!", adapterName);
            return SUPPORT_ADAPTER_NUM_MAX;
        }
    }

    for (i = 0; i < SUPPORT_ADAPTER_NUM_MAX; i++) {
        if (strlen(audioManagerSer->adapterInfos[i].adapterName) == 0 &&
            audioManagerSer->adapterInfos[i].adapterServicePtr == NULL) {
            return i;
        }
    }

    AUDIO_FUNC_LOGE("no free pos!");
    return SUPPORT_ADAPTER_NUM_MAX;
}

static int32_t AudioManagerServiceAddAdapter(
    struct IAudioManager *manager, struct IAudioAdapter *adapter, int32_t pos)
{
    struct AudioHwManager *hwManager = (struct AudioHwManager *)manager;
    struct AudioHwAdapter *hwAdapter = (struct AudioHwAdapter *)adapter;

    if (hwManager == NULL) {
        AUDIO_FUNC_LOGE("audioManagerSer is null!");
        return AUDIO_ERR_INVALID_PARAM;
    }
    if (hwAdapter == NULL) {
        AUDIO_FUNC_LOGE("adapterName is null!");
        return AUDIO_ERR_INVALID_PARAM;
    }
    if (pos >= SUPPORT_ADAPTER_NUM_MAX) {
        AUDIO_FUNC_LOGE("pos out of range!");
        return AUDIO_ERR_INVALID_PARAM;
    }
    int32_t ret = strncpy_s(hwManager->adapterInfos[pos].adapterName, ADAPTER_NAME_LEN,
        hwAdapter->adapterDescriptor.adapterName, strlen(hwAdapter->adapterDescriptor.adapterName));
    if (ret != 0) {
        AUDIO_FUNC_LOGE("strncpy_s for adapterName failed!");
        return AUDIO_ERR_INTERNAL;
    }

    hwManager->adapterInfos[pos].refCnt = 1; // first init set 1
    hwManager->adapterInfos[pos].adapterServicePtr = hwAdapter;
    AUDIO_FUNC_LOGI("load adaptername[%{public}s], refCount[1]", hwManager->adapterInfos[pos].adapterName);

    return AUDIO_SUCCESS;
}

static uint32_t AudioManagerServiceFindAdapterPos(struct IAudioManager *manager, const char *adapterName)
{
    uint32_t i;

    struct AudioHwManager *audioManagerSer = (struct AudioHwManager *)manager;
    for (i = 0; i < SUPPORT_ADAPTER_NUM_MAX; i++) {
        if (strncmp(adapterName, audioManagerSer->adapterInfos[i].adapterName, ADAPTER_NAME_LEN) == 0 &&
            audioManagerSer->adapterInfos[i].adapterServicePtr != NULL) {
            return i;
        }
    }

    AUDIO_FUNC_LOGI("can not find adapterName(%{public}s), malloc new pos", adapterName);
    return SUPPORT_ADAPTER_NUM_MAX;
}

static int32_t AudioInitDynamicLib(void)
{
    if (CAPTURE_PASSTHTOUGH_PATH == NULL || RENDER_PASSTHTOUGH_PATH == NULL) {
        AUDIO_FUNC_LOGE("sopath is error");
        return AUDIO_ERR_INTERNAL;
    }

    int32_t ret = InitCapturePassthroughHandle(CAPTURE_PASSTHTOUGH_PATH);
    if (ret < 0) {
        AUDIO_FUNC_LOGE("InitCapturePassthroughHandle FAIL!");
        return AUDIO_ERR_INTERNAL;
    }

    ret = InitRenderPassthroughHandle(RENDER_PASSTHTOUGH_PATH);
    if (ret < 0) {
        AUDIO_FUNC_LOGE("InitRenderPassthroughHandle FAIL!");
        AudioDlClose(&g_ptrCaptureHandle);
        return AUDIO_ERR_INTERNAL;
    }
#ifndef AUDIO_HAL_NOTSUPPORT_PATHSELECT
    ret = InitPathSelectPassthroughHandle(PATH_SELECT_PASSTHROUGH_PATH);
    if (ret < 0 || g_pathSelGetConfToJsonObj == NULL) {
        AUDIO_FUNC_LOGE("InitPathSelectPassthroughHandle FAIL!");
        AudioDlClose(&g_ptrRenderHandle);
        AudioDlClose(&g_ptrCaptureHandle);
        return AUDIO_ERR_INTERNAL;
    }

    ret = g_pathSelGetConfToJsonObj();
    if (ret < 0) {
        AUDIO_FUNC_LOGE("g_pathSelGetConfToJsonObj FAIL!");
        AudioDlClose(&g_ptrRenderHandle);
        AudioDlClose(&g_ptrCaptureHandle);
        AudioDlClose(&g_ptrPathSelHandle);
        return AUDIO_ERR_INTERNAL;
    }
#endif
    return AUDIO_SUCCESS;
}

int32_t AudioManagerGetAllAdapters(struct IAudioManager *manager,
    struct AudioAdapterDescriptor *descs, uint32_t *size)
{
    AUDIO_FUNC_LOGI("enter!");
    if (manager == NULL || descs == NULL || size == NULL) {
        return AUDIO_ERR_INVALID_PARAM;
    }

    int32_t ret = AudioInitDynamicLib();
    if (ret != AUDIO_SUCCESS) {
        AUDIO_FUNC_LOGE("AudioInitDynamicLib FAIL! ret = %{public}d", ret);
        return ret;
    }

    ret = AudioAdaptersForUser(g_getAllCardInfo, descs, size);
    if (ret < 0) {
        AUDIO_FUNC_LOGE("AudioAdaptersForUser FAIL!");
        return AUDIO_ERR_NOTREADY;
    }

    return AUDIO_SUCCESS;
}

static int32_t LoadAdapterImpl(const struct AudioAdapterDescriptor *desc, struct IAudioAdapter **adapter)
{
    if (desc == NULL || adapter == NULL) {
        return AUDIO_ERR_INVALID_PARAM;
    }
    struct AudioHwAdapter *hwAdapter = (struct AudioHwAdapter *)OsalMemCalloc(sizeof(struct AudioHwAdapter));
    if (hwAdapter == NULL) {
        AUDIO_FUNC_LOGE("OsalMemCalloc AudioHwAdapter failed");
        return AUDIO_ERR_MALLOC_FAIL;
    }

    (void)memset_s(hwAdapter, sizeof(struct AudioHwAdapter), 0, sizeof(struct AudioHwAdapter));
    hwAdapter->common.InitAllPorts = AudioAdapterInitAllPorts;
    hwAdapter->common.CreateRender = AudioAdapterCreateRender;
    hwAdapter->common.DestroyRender = AudioAdapterDestroyRender;
    hwAdapter->common.CreateCapture = AudioAdapterCreateCapture;
    hwAdapter->common.DestroyCapture = AudioAdapterDestroyCapture;
    hwAdapter->common.GetPortCapability = AudioAdapterGetPortCapability;
    hwAdapter->common.SetPassthroughMode = AudioAdapterSetPassthroughMode;
    hwAdapter->common.GetPassthroughMode = AudioAdapterGetPassthroughMode;
    hwAdapter->common.GetDeviceStatus = AudioAdapterGetDeviceStatus;
    hwAdapter->common.CreateCallTransfer = NULL;
    hwAdapter->common.SetPhoneCallScene = NULL;
    hwAdapter->adapterDescriptor = *desc;

    *adapter = &(hwAdapter->common);
    return AUDIO_SUCCESS;
}

static int32_t LoadAdapterPrimary(const struct AudioAdapterDescriptor *desc, struct IAudioAdapter **adapter)
{
    if (desc == NULL || adapter == NULL) {
        AUDIO_FUNC_LOGE("primary desc or adapter is null");
        return AUDIO_ERR_INVALID_PARAM;
    }

    int32_t ret = LoadAdapterImpl(desc, adapter);
    if (ret != AUDIO_SUCCESS) {
        return ret;
    }

    return AUDIO_SUCCESS;
}

static int32_t LoadAdapterUsb(const struct AudioAdapterDescriptor *desc, struct IAudioAdapter **adapter)
{
    if (desc == NULL || adapter == NULL) {
        AUDIO_FUNC_LOGE("usb desc or adapter is null");
        return AUDIO_ERR_INVALID_PARAM;
    }

    int32_t ret = LoadAdapterImpl(desc, adapter);
    if (ret != AUDIO_SUCCESS) {
        return ret;
    }

    return AUDIO_SUCCESS;
}

static int32_t LoadAdapterA2dp(const struct AudioAdapterDescriptor *desc, struct IAudioAdapter **adapter)
{
    if (desc == NULL || adapter == NULL) {
        return AUDIO_ERR_INVALID_PARAM;
    }

    return AUDIO_ERR_NOT_SUPPORT;
}

static int32_t SelectAppropriateAdapter(
    enum AudioAdapterType adapterType, const struct AudioAdapterDescriptor *desc, struct IAudioAdapter **adapter)
{
    int32_t ret;

    if (desc == NULL || adapter == NULL) {
        return AUDIO_ERR_INVALID_PARAM;
    }
    switch (adapterType) {
        case AUDIO_ADAPTER_PRIMARY:
        case AUDIO_ADAPTER_PRIMARY_EXT:
        case AUDIO_ADAPTER_HDMI:
            ret = LoadAdapterPrimary(desc, adapter);
            if (ret != AUDIO_SUCCESS) {
                AUDIO_FUNC_LOGE("LoadAdapterPrimary failed.");
                return ret;
            }
            break;
        case AUDIO_ADAPTER_USB:
            ret = LoadAdapterUsb(desc, adapter);
            if (ret != AUDIO_SUCCESS) {
                AUDIO_FUNC_LOGE("LoadAdapterUsb failed.");
                return ret;
            }
            break;
        case AUDIO_ADAPTER_A2DP:
            ret = LoadAdapterA2dp(desc, adapter);
            if (ret != AUDIO_SUCCESS) {
                AUDIO_FUNC_LOGE("LoadAdapterA2dp failed.");
                return ret;
            }
            break;
        default:
            AUDIO_FUNC_LOGE("An unsupported Adapter.");
            return AUDIO_ERR_NOT_SUPPORT;
    }

    return AUDIO_SUCCESS;
}

static int32_t AudioManagerIncreaseAdapterRef(struct IAudioManager *manager, uint32_t infoIndex,
    struct IAudioAdapter **adapter)
{
    struct AudioHwManager *audioManagerSer = (struct AudioHwManager *)manager;

    if (audioManagerSer->adapterInfos[infoIndex].adapterServicePtr == NULL) {
        AUDIO_FUNC_LOGE("Invalid adapterServicePtr param!");
        return AUDIO_ERR_INVALID_PARAM;
    }

    audioManagerSer->adapterInfos[infoIndex].refCnt++;
    *adapter = &(audioManagerSer->adapterInfos[infoIndex].adapterServicePtr->common);

    AUDIO_FUNC_LOGI("load adaptername[%{public}s], refCount[%{public}d] increase",
        audioManagerSer->adapterInfos[infoIndex].adapterName, audioManagerSer->adapterInfos[infoIndex].refCnt);
    return AUDIO_SUCCESS;
}

static int32_t AudioManagerDecreaseAdapterRef(struct IAudioManager *manager, uint32_t infoIndex)
{
    struct AudioHwManager *audioManagerSer = (struct AudioHwManager *)manager;

    if (audioManagerSer->adapterInfos[infoIndex].refCnt == 0) {
        AUDIO_FUNC_LOGE("Invalid adapterInfos[%{public}d] had released", infoIndex);
        return AUDIO_ERR_INVALID_PARAM;
    }

    audioManagerSer->adapterInfos[infoIndex].refCnt--;
    AUDIO_FUNC_LOGI("unload adaptername[%{public}s], refCount[%{public}d] decrease",
        audioManagerSer->adapterInfos[infoIndex].adapterName, audioManagerSer->adapterInfos[infoIndex].refCnt);
    return AUDIO_SUCCESS;
}

static void AudioManagerEnforceClearRef(struct IAudioManager *manager, uint32_t infoIndex)
{
    struct AudioHwManager *audioManagerSer = (struct AudioHwManager *)manager;
    audioManagerSer->adapterInfos[infoIndex].refCnt = 0;
}

static int32_t AudioManagerServiceRemvAdapter(struct IAudioManager *manager, uint32_t pos)
{
    if (manager == NULL || pos >= SUPPORT_ADAPTER_NUM_MAX) {
        AUDIO_FUNC_LOGE("Invalid input param!");
        return AUDIO_ERR_INVALID_PARAM;
    }

    struct AudioHwManager *audioManagerSer = (struct AudioHwManager *)manager;
    struct AudioHwAdapter *hwAdapter = (struct AudioHwAdapter *)audioManagerSer->adapterInfos[pos].adapterServicePtr;

    if (audioManagerSer->adapterInfos[pos].refCnt != 0) {
        return AudioManagerDecreaseAdapterRef(manager, pos);
    }

    StubCollectorRemoveObject(IAUDIOADAPTER_INTERFACE_DESC, hwAdapter);

    if (hwAdapter == NULL) {
        AUDIO_FUNC_LOGE("manager == NULL || hwAdapter == NULL");
        return AUDIO_ERR_INVALID_PARAM;
    }
    if (hwAdapter->portCapabilitys != NULL) {
        uint32_t portsLen = hwAdapter->adapterDescriptor.portsLen;
        uint32_t i = 0;
        while (i < portsLen) {
            if (&hwAdapter->portCapabilitys[i] != NULL) {
                AudioMemFree((void **)&hwAdapter->portCapabilitys[i].capability.subPorts);
            }
            i++;
        }
        AudioMemFree((void **)&hwAdapter->portCapabilitys);
    }

    AudioMemFree((void **)&hwAdapter);
    audioManagerSer->adapterInfos[pos].adapterServicePtr = NULL;
    AUDIO_FUNC_LOGI("audio unload adapterName[%{public}s] success", audioManagerSer->adapterInfos[pos].adapterName);

    (void)memset_s(audioManagerSer->adapterInfos[pos].adapterName, ADAPTER_NAME_LEN, 0, ADAPTER_NAME_LEN);

    return AUDIO_SUCCESS;
}

int32_t AudioManagerLoadAdapter(
    struct IAudioManager *manager, const struct AudioAdapterDescriptor *desc, struct IAudioAdapter **adapter)
{
    AUDIO_FUNC_LOGD("Enter.");
    if (manager == NULL || desc == NULL || desc->adapterName == NULL || desc->ports == NULL || adapter == NULL) {
        AUDIO_FUNC_LOGE("Invalid input param!");
        return AUDIO_ERR_INVALID_PARAM;
    }

    AUDIO_FUNC_LOGI("adapter name %{public}s", desc->adapterName);
    int32_t index = AudioAdapterExist(desc->adapterName);
    if (index < 0) {
        AUDIO_FUNC_LOGE("not supported this adapter %{public}s", desc->adapterName);
        return AUDIO_ERR_INVALID_PARAM;
    }

    uint32_t pos = AudioManagerServiceFindAdapterPos(manager, desc->adapterName);
    if (pos < SUPPORT_ADAPTER_NUM_MAX) {
        return AudioManagerIncreaseAdapterRef(manager, pos, adapter);
    }

    int32_t freePos = AudioManagerServiceGetFreeAdapterPos(manager, desc->adapterName);
    if (freePos < 0 || freePos >= SUPPORT_ADAPTER_NUM_MAX) {
        AUDIO_FUNC_LOGE("AudioManagerServiceGetFreeAdapterPos failed!");
        return HDF_FAILURE;
    }

    enum AudioAdapterType sndCardType = MatchAdapterType(desc->adapterName, desc->ports[0].portId);
    int32_t ret = SelectAppropriateAdapter(sndCardType, &(AudioAdapterGetConfigDescs()[index]), adapter);
    if (ret != AUDIO_SUCCESS) {
        AUDIO_FUNC_LOGE("Load adapter failed.");
        return ret;
    }

    ret = AudioManagerServiceAddAdapter(manager, *adapter, freePos);
    if (ret != AUDIO_SUCCESS) {
        AUDIO_FUNC_LOGE("Add adapter to list failed.");
        AudioManagerEnforceClearRef(manager, (uint32_t)freePos);
        AudioManagerServiceRemvAdapter(manager, (uint32_t)freePos);
        return ret;
    }

    return AUDIO_SUCCESS;
}

int32_t AudioManagerUnloadAdapter(struct IAudioManager *manager, const char *adapterName)
{
    AUDIO_FUNC_LOGD("Enter.");
    if (manager == NULL || adapterName == NULL || strlen(adapterName) == 0) {
        AUDIO_FUNC_LOGE("Invalid input param!");
        return AUDIO_ERR_INVALID_PARAM;
    }

    uint32_t pos = AudioManagerServiceFindAdapterPos(manager, adapterName);
    if (pos >= SUPPORT_ADAPTER_NUM_MAX) {
        AUDIO_FUNC_LOGE("AudioManagerServiceUnloadAdapter failed!");
        return AUDIO_ERR_INVALID_PARAM;
    }

    int ret = AudioManagerServiceRemvAdapter(manager, pos);
    if (ret != AUDIO_SUCCESS) {
        AUDIO_FUNC_LOGE("AudioManagerServiceRemvAdapter failed!");
        return ret;
    }

    AUDIO_FUNC_LOGI("AudioManagerUnloadAdapter success!");
    return AUDIO_SUCCESS;
}

int32_t ReleaseAudioManagerObject(struct IAudioManager *manager)
{
    AUDIO_FUNC_LOGD("Enter.");
    struct AudioHwManager *service = (struct AudioHwManager *)manager;
    if (ReleaseAudioManagerObjectComm(manager)) {
        OsalMemFree(service);
        service = NULL;
    }

    return AUDIO_SUCCESS;
}

struct IAudioManager *AudioManagerCreateIfInstance(void)
{
    AUDIO_FUNC_LOGI("audio manager create if instance");
    struct AudioHwManager *service = (struct AudioHwManager *)OsalMemCalloc(sizeof(struct AudioHwManager));
    if (service == NULL) {
        AUDIO_FUNC_LOGE("OsalMemCalloc service failed!");
        return NULL;
    }

    service->interface.GetAllAdapters = AudioManagerGetAllAdapters;
    service->interface.LoadAdapter = AudioManagerLoadAdapter;
    service->interface.UnloadAdapter = AudioManagerUnloadAdapter;
    service->interface.ReleaseAudioManagerObject = ReleaseAudioManagerObject;

    return &(service->interface);
}

int32_t AudioManagerDestroyIfInstance(struct IAudioManager *manager)
{
    return ReleaseAudioManagerObject(manager);
}