/*

 * Copyright (c) 2024 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 "fast_audio_render.h"

#include "audio_adapter_info_common.h"

#include "audio_bluetooth_manager.h"

#include "audio_internal.h"

#include "hdf_log.h"

#include <string>



namespace OHOS::HDI::Audio_Bluetooth {

#ifdef A2DP_HDI_SERVICE

const uint32_t MIN_TIME_INTERVAL = 30;

const uint32_t MAX_TIME_INTERVAL = 80;

const int32_t MAX_ASHMEM_LEN = 100000;

const int32_t MIN_ASHMEM_LEN = 10;

const int32_t RENDER_TIME_INTERVAL = 5;

const int32_t PER_MS_SECOND = 1000;



static int32_t CalculateSampleNum(uint32_t sampleRate, uint32_t timeMs)

{

    return (sampleRate * timeMs) / PER_MS_SECOND;

}

#endif



int32_t FastRenderStart(AudioHandle handle)

{

    HDF_LOGI("%{public}s enter", __func__);

#ifdef A2DP_HDI_SERVICE

    AudioHwRender *hwRender = reinterpret_cast<struct AudioHwRender>(handle);

    if (hwRender == nullptr) {

        return AUDIO_HAL_ERR_INVALID_PARAM;

    }

    AudioSampleAttributes *attr = &hwRender->RenderParam.frameRenderMode.attrs;

    uint32_t format = static_cast<uint32_t>(attrs->format);

    return OHOS::Bluetooth::FastStartPlaying(attrs->sampleRate, attrs->channelCount, format);

#endif

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderStop(AudioHandle handle)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

#ifdef A2DP_HDI_SERVICE

    return OHOS::Bluetooth::FastStopPlaying();

#endif

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderPause(AudioHandle handle)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

#ifdef A2DP_HDI_SERVICE

    return OHOS::Bluetooth::FastSuspendPlaying();

#endif

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderResume(AudioHandle handle)

{

    HDF_LOGI("%{public}s enter", __func__);

#ifdef A2DP_HDI_SERVICE

    AudioHwRender *hwRender = reinterpret_cast<struct AudioHwRender>(handle);

    if (hwRender == nullptr) {

        return AUDIO_HAL_ERR_INVALID_PARAM;

    }

    AudioSampleAttributes *attr = &hwRender->RenderParam.frameRenderMode.attrs;

    uint32_t format = static_cast<uint32_t>(attrs->format);

    return OHOS::Bluetooth::FastStartPlaying(attrs->sampleRate, attrs->channelCount, format);

#endif

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderFlush(AudioHandle handle)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderGetFrameSize(AudioHandle handle, uint64_t *size)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)size;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderGetFrameCount(AudioHandle handle, uint64_t *count)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)count;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderSetSampleAttributes(AudioHandle handle, const struct AudioSampleAttributes *attrs)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)attrs;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderGetSampleAttributes(AudioHandle handle, struct AudioSampleAttributes *attrs)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)attrs;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderGetCurrentChannelId(AudioHandle handle, uint32_t *channelId)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)channelId;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderCheckSceneCapability(AudioHandle handle, const struct AudioSceneDescriptor *scene, bool *supported)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)scene;

    (void)supported;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderSelectScene(AudioHandle handle, const struct AudioSceneDescriptor *scene)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)scene;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderSetMute(AudioHandle handle, bool mute)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)mute;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderGetMute(AudioHandle handle, bool *mute)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)mute;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderSetVolume(AudioHandle handle, float volume)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)volume;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderGetVolume(AudioHandle handle, float *volume)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)volume;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderGetGainThreshold(AudioHandle handle, float *min, float *max)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)min;

    (void)max;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderGetGain(AudioHandle handle, float *gain)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)gain;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderSetGain(AudioHandle handle, float gain)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)gain;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderGetLatency(struct AudioRender *render, uint32_t *ms)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)render;

    (void)ms;

#ifdef A2DP_HDI_SERVICE

    uint32_t latency = 0;

    OHOS::Bluetooth::FastGetLatency(latency);

    *ms = latency;

    return AUDIO_HAL_SUCCESS;

#endif

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderRenderFrame(

    struct AudioRender *render, const void *frame, uint64_t requestBytes, uint64_t *replyBytes)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)render;

    (void)frame;

    (void)requestBytes;

    (void)replyBytes;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderGetRenderPosition(struct AudioRender *render, uint64_t *frames, struct AudioTimeStamp *time)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)render;

    (void)frames;

    (void)time;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderSetRenderSpeed(struct AudioRender *render, float speed)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)render;

    (void)speed;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderGetRenderSpeed(struct AudioRender *render, float *speed)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)render;

    (void)speed;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderSetChannelMode(struct AudioRender *render, AudioChannelMode mode)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)render;

    (void)mode;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderGetChannelMode(struct AudioRender *render, AudioChannelMode *mode)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)render;

    (void)mode;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderSetExtraParams(AudioHandle handle, const char *keyValueList)

{

    HDF_LOGI("%{public}s enter", __func__);

    struct AudioHwRender *render = reinterpret_cast<struct AudioHwRender *>(handle);

    if (render == nullptr || keyValueList == nullptr) {

        return AUDIO_HAL_ERR_INVALID_PARAM;

    }

    int32_t count = 0;

    int32_t sumOk = 0;

    struct ExtraParams mExtraParams;

    if (AudioSetExtraParams(keyValueList, &count, &mExtraParams, &sumOk) < 0) {

        return AUDIO_HAL_ERR_INTERNAL;

    }

    if (count != 0 && sumOk == count) {

#ifdef A2DP_HDI_SERVICE

        if (mExtraParams.audioStreamCtl == 1) {

            HDF_LOGI("SetValue, try to fastSuspendPlaying=1");

            OHOS::Bluetooth::FastSuspendPlayingFromParam();

        } else if (mExtraParams.audioStreamCtl == 0) {

            HDF_LOGI("SetValue, try to fastSuspendPlaying=0");

            OHOS::Bluetooth::UnBlockStart();

        }

#endif

        return AUDIO_HAL_SUCCESS;

    } else {

        return AUDIO_HAL_ERR_INTERNAL;

    }

}



int32_t FastRenderGetExtraParams(AudioHandle handle, char *keyValueList, int32_t listLength)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)keyValueList;

    (void)listLength;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderReqMmapBuffer(AudioHandle handle, int32_t reqSize, struct AudioMmapBufferDescriptor *desc)

{

    HDF_LOGI("%{public}s enter", __func__);

#ifdef A2DP_HDI_SERVICE

    AudioHwRender *render = reinterpret_cast<AudioHwRender *>(handle);

    if (render == nullptr) {

        return AUDIO_HAL_ERR_INVALID_PARAM;

    }

    AudioSampleAttributes attr = render->renderParam.frameRenderMode.attrs;



    int32_t minSize = CalculateSampleNum(attr.sampleRate, MIN_TIME_INTERVAL);

    int32_t maxSize = CalculateSampleNum(attr.sampleRate, MAX_TIME_INTERVAL);

    int32_t realSize = reqSize;

    if (reqSize < minSize) {

        realSize = minSize;

    } else if (reqSize > maxSize) {

        realSize = maxSize;

    }

    int32_t ashmemLength = realSize * static_cast<int32_t>(attr.channelCount) * attr.format;

    if (ashmemLength < MIN_ASHMEM_LEN || ashmemLength > MAX_ASHMEM_LEN) {

        HDF_LOGE("reqMmapBuffer failed, length is illegal %{public}d", ashmemLength);

        return AUDIO_HAL_ERR_INVALID_PARAM;

    }

    int32_t fd = OHOS::Bluetooth::FastReqMmapBuffer(ashmemLength);

    if (fd < 0) {

        HDF_LOGE("reqMmapBuffer failed");

        return HDF_FAILURE;

    }

    desc->memoryFd = fd;

    desc->transferFrameSize = static_cast<int32_t>(CalculateSampleNum(attr.sampleRate, RENDER_TIME_INTERVAL));

    desc->totalBufferFrames = realSize;

    desc->isShareable = false;

    HDF_LOGI("%{public}s, fd=%{public}d, length=%{public}d, transferFrameSize=%{public}d, totalBufferFrames=%{public}d",

        __func__, desc->memoryFd, desc->transferFrameSize, desc->totalBufferFrames);

#endif

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderGetMmapPosition(AudioHandle handle, uint64_t *frames, struct AudioTimeStamp *time)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

#ifdef A2DP_HDI_SERVICE

    int64_t sec = 0;

    int64_t nSec = 0;

    uint64_t readFrames = 0;

    OHOS::Bluetooth::FastReadMmapPosition(sec, nSec, readFrames);

    *frames = readFrames;

    time->tvSec = sec;

    time->tvNSec = nSec;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

#endif

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderTurnStandbyMode(AudioHandle handle)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderAudioDevDump(AudioHandle handle, int32_t range, int32_t fd)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)handle;

    (void)range;

    (void)fd;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderRegCallback(struct AudioRender *render, RenderCallback callback, void *cookie)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)render;

    (void)callback;

    (void)cookie;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}



int32_t FastRenderDrainBuffer(struct AudioRender *render, AudioDrainNotifyType *type)

{

    HDF_LOGI("%{public}s enter", __func__);

    (void)render;

    (void)type;

    return AUDIO_HAL_ERR_NOT_SUPPORT;

}

} // namespace OHOS::HDI::Audio_Bluetooth