150a07fd2Sopenharmony_ci/*
250a07fd2Sopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
350a07fd2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
450a07fd2Sopenharmony_ci * you may not use this file except in compliance with the License.
550a07fd2Sopenharmony_ci * You may obtain a copy of the License at
650a07fd2Sopenharmony_ci *
750a07fd2Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
850a07fd2Sopenharmony_ci *
950a07fd2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1050a07fd2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1150a07fd2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1250a07fd2Sopenharmony_ci * See the License for the specific language governing permissions and
1350a07fd2Sopenharmony_ci * limitations under the License.
1450a07fd2Sopenharmony_ci */
1550a07fd2Sopenharmony_ci
1650a07fd2Sopenharmony_ci#include "dspeaker_dev.h"
1750a07fd2Sopenharmony_ci
1850a07fd2Sopenharmony_ci#include <algorithm>
1950a07fd2Sopenharmony_ci#include <condition_variable>
2050a07fd2Sopenharmony_ci#include <mutex>
2150a07fd2Sopenharmony_ci#include <string>
2250a07fd2Sopenharmony_ci#include <thread>
2350a07fd2Sopenharmony_ci#include <securec.h>
2450a07fd2Sopenharmony_ci
2550a07fd2Sopenharmony_ci#include "daudio_constants.h"
2650a07fd2Sopenharmony_ci#include "daudio_errorcode.h"
2750a07fd2Sopenharmony_ci#include "daudio_hidumper.h"
2850a07fd2Sopenharmony_ci#include "daudio_hisysevent.h"
2950a07fd2Sopenharmony_ci#include "daudio_hitrace.h"
3050a07fd2Sopenharmony_ci#include "daudio_log.h"
3150a07fd2Sopenharmony_ci#include "daudio_source_manager.h"
3250a07fd2Sopenharmony_ci#include "daudio_util.h"
3350a07fd2Sopenharmony_ci
3450a07fd2Sopenharmony_ci#undef DH_LOG_TAG
3550a07fd2Sopenharmony_ci#define DH_LOG_TAG "DSpeakerDev"
3650a07fd2Sopenharmony_ci
3750a07fd2Sopenharmony_cinamespace OHOS {
3850a07fd2Sopenharmony_cinamespace DistributedHardware {
3950a07fd2Sopenharmony_ciint32_t DSpeakerDev::EnableDevice(const int32_t dhId, const std::string &capability)
4050a07fd2Sopenharmony_ci{
4150a07fd2Sopenharmony_ci    DHLOGI("Enable IO device, device pin: %{public}d.", dhId);
4250a07fd2Sopenharmony_ci    int32_t ret = DAudioHdiHandler::GetInstance().RegisterAudioDevice(devId_, dhId, capability, shared_from_this());
4350a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
4450a07fd2Sopenharmony_ci        DHLOGE("Register device failed, ret: %{public}d.", ret);
4550a07fd2Sopenharmony_ci        DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_REGISTER_FAIL, devId_, std::to_string(dhId), ret,
4650a07fd2Sopenharmony_ci            "daudio register device failed.");
4750a07fd2Sopenharmony_ci        return ret;
4850a07fd2Sopenharmony_ci    }
4950a07fd2Sopenharmony_ci    dhId_ = dhId;
5050a07fd2Sopenharmony_ci    return DH_SUCCESS;
5150a07fd2Sopenharmony_ci}
5250a07fd2Sopenharmony_ci
5350a07fd2Sopenharmony_ciint32_t DSpeakerDev::DisableDevice(const int32_t dhId)
5450a07fd2Sopenharmony_ci{
5550a07fd2Sopenharmony_ci    DHLOGI("Disable IO device, device pin: %{public}d.", dhId);
5650a07fd2Sopenharmony_ci    int32_t ret = DAudioHdiHandler::GetInstance().UnRegisterAudioDevice(devId_, dhId);
5750a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
5850a07fd2Sopenharmony_ci        DHLOGE("UnRegister failed, ret: %{public}d.", ret);
5950a07fd2Sopenharmony_ci        DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_UNREGISTER_FAIL, devId_, std::to_string(dhId), ret,
6050a07fd2Sopenharmony_ci            "daudio unregister device failed.");
6150a07fd2Sopenharmony_ci        return ret;
6250a07fd2Sopenharmony_ci    }
6350a07fd2Sopenharmony_ci    return DH_SUCCESS;
6450a07fd2Sopenharmony_ci}
6550a07fd2Sopenharmony_ci
6650a07fd2Sopenharmony_ciint32_t DSpeakerDev::InitReceiverEngine(IAVEngineProvider *providerPtr)
6750a07fd2Sopenharmony_ci{
6850a07fd2Sopenharmony_ci    DHLOGI("InitReceiverEngine enter.");
6950a07fd2Sopenharmony_ci    return DH_SUCCESS;
7050a07fd2Sopenharmony_ci}
7150a07fd2Sopenharmony_ci
7250a07fd2Sopenharmony_ciint32_t DSpeakerDev::InitSenderEngine(IAVEngineProvider *providerPtr)
7350a07fd2Sopenharmony_ci{
7450a07fd2Sopenharmony_ci    DHLOGI("InitSenderEngine enter");
7550a07fd2Sopenharmony_ci    if (speakerTrans_ == nullptr) {
7650a07fd2Sopenharmony_ci        speakerTrans_ = std::make_shared<AVTransSenderTransport>(devId_, shared_from_this());
7750a07fd2Sopenharmony_ci    }
7850a07fd2Sopenharmony_ci    int32_t ret = speakerTrans_->InitEngine(providerPtr);
7950a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
8050a07fd2Sopenharmony_ci        DHLOGE("Speaker dev initialize av sender adapter failed.");
8150a07fd2Sopenharmony_ci        return ret;
8250a07fd2Sopenharmony_ci    }
8350a07fd2Sopenharmony_ci    ret = speakerTrans_->CreateCtrl();
8450a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
8550a07fd2Sopenharmony_ci        DHLOGE("Create ctrl channel failed.");
8650a07fd2Sopenharmony_ci    }
8750a07fd2Sopenharmony_ci    return ret;
8850a07fd2Sopenharmony_ci}
8950a07fd2Sopenharmony_ci
9050a07fd2Sopenharmony_civoid DSpeakerDev::OnEngineTransEvent(const AVTransEvent &event)
9150a07fd2Sopenharmony_ci{
9250a07fd2Sopenharmony_ci    if (event.type == EventType::EVENT_START_SUCCESS) {
9350a07fd2Sopenharmony_ci        OnStateChange(DATA_OPENED);
9450a07fd2Sopenharmony_ci    } else if ((event.type == EventType::EVENT_STOP_SUCCESS) ||
9550a07fd2Sopenharmony_ci        (event.type == EventType::EVENT_CHANNEL_CLOSED) ||
9650a07fd2Sopenharmony_ci        (event.type == EventType::EVENT_START_FAIL)) {
9750a07fd2Sopenharmony_ci        OnStateChange(DATA_CLOSED);
9850a07fd2Sopenharmony_ci    }
9950a07fd2Sopenharmony_ci}
10050a07fd2Sopenharmony_ci
10150a07fd2Sopenharmony_civoid DSpeakerDev::OnEngineTransMessage(const std::shared_ptr<AVTransMessage> &message)
10250a07fd2Sopenharmony_ci{
10350a07fd2Sopenharmony_ci    CHECK_NULL_VOID(message);
10450a07fd2Sopenharmony_ci    DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str());
10550a07fd2Sopenharmony_ci    DAudioSourceManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_,
10650a07fd2Sopenharmony_ci        message->type_, message->content_);
10750a07fd2Sopenharmony_ci}
10850a07fd2Sopenharmony_ci
10950a07fd2Sopenharmony_ciint32_t DSpeakerDev::CreateStream(const int32_t streamId)
11050a07fd2Sopenharmony_ci{
11150a07fd2Sopenharmony_ci    DHLOGI("Open stream of speaker device, streamId: %{public}d.", streamId);
11250a07fd2Sopenharmony_ci    std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
11350a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
11450a07fd2Sopenharmony_ci
11550a07fd2Sopenharmony_ci    cJSON *jParam = cJSON_CreateObject();
11650a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR);
11750a07fd2Sopenharmony_ci    cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
11850a07fd2Sopenharmony_ci    char *jsonData = cJSON_PrintUnformatted(jParam);
11950a07fd2Sopenharmony_ci    if (jsonData == nullptr) {
12050a07fd2Sopenharmony_ci        DHLOGE("Failed to create JSON data.");
12150a07fd2Sopenharmony_ci        cJSON_Delete(jParam);
12250a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_NULLPTR;
12350a07fd2Sopenharmony_ci    }
12450a07fd2Sopenharmony_ci    std::string jsonDataStr(jsonData);
12550a07fd2Sopenharmony_ci    AudioEvent event(AudioEventType::OPEN_SPEAKER, jsonDataStr);
12650a07fd2Sopenharmony_ci    cbObj->NotifyEvent(event);
12750a07fd2Sopenharmony_ci    DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_OPEN, devId_, std::to_string(dhId_),
12850a07fd2Sopenharmony_ci        "daudio spk device open success.");
12950a07fd2Sopenharmony_ci    streamId_ = streamId;
13050a07fd2Sopenharmony_ci    cJSON_Delete(jParam);
13150a07fd2Sopenharmony_ci    cJSON_free(jsonData);
13250a07fd2Sopenharmony_ci    return DH_SUCCESS;
13350a07fd2Sopenharmony_ci}
13450a07fd2Sopenharmony_ci
13550a07fd2Sopenharmony_ciint32_t DSpeakerDev::DestroyStream(const int32_t streamId)
13650a07fd2Sopenharmony_ci{
13750a07fd2Sopenharmony_ci    DHLOGI("Close stream of speaker device streamId: %{public}d.",  streamId);
13850a07fd2Sopenharmony_ci    std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
13950a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
14050a07fd2Sopenharmony_ci
14150a07fd2Sopenharmony_ci    cJSON *jParam = cJSON_CreateObject();
14250a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR);
14350a07fd2Sopenharmony_ci    cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
14450a07fd2Sopenharmony_ci    char *jsonData = cJSON_PrintUnformatted(jParam);
14550a07fd2Sopenharmony_ci    if (jsonData == nullptr) {
14650a07fd2Sopenharmony_ci        DHLOGE("Failed to create JSON data.");
14750a07fd2Sopenharmony_ci        cJSON_Delete(jParam);
14850a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_NULLPTR;
14950a07fd2Sopenharmony_ci    }
15050a07fd2Sopenharmony_ci    std::string jsonDataStr(jsonData);
15150a07fd2Sopenharmony_ci    AudioEvent event(AudioEventType::CLOSE_SPEAKER, jsonDataStr);
15250a07fd2Sopenharmony_ci    cbObj->NotifyEvent(event);
15350a07fd2Sopenharmony_ci    DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_CLOSE, devId_, std::to_string(dhId_),
15450a07fd2Sopenharmony_ci        "daudio spk device close success.");
15550a07fd2Sopenharmony_ci    curPort_ = 0;
15650a07fd2Sopenharmony_ci    cJSON_Delete(jParam);
15750a07fd2Sopenharmony_ci    cJSON_free(jsonData);
15850a07fd2Sopenharmony_ci    return DH_SUCCESS;
15950a07fd2Sopenharmony_ci}
16050a07fd2Sopenharmony_ci
16150a07fd2Sopenharmony_ciint32_t DSpeakerDev::SetParameters(const int32_t streamId, const AudioParamHDF &param)
16250a07fd2Sopenharmony_ci{
16350a07fd2Sopenharmony_ci    DHLOGD("Set speaker parameters {samplerate: %{public}d, channelmask: %{public}d, format: %{public}d, "
16450a07fd2Sopenharmony_ci        "streamusage: %{public}d, period: %{public}d, framesize: %{public}d, renderFlags: %{public}d, "
16550a07fd2Sopenharmony_ci        "ext{%{public}s}}.", param.sampleRate, param.channelMask, param.bitFormat, param.streamUsage,
16650a07fd2Sopenharmony_ci        param.period, param.frameSize, param.renderFlags, param.ext.c_str());
16750a07fd2Sopenharmony_ci    curPort_ = dhId_;
16850a07fd2Sopenharmony_ci    paramHDF_ = param;
16950a07fd2Sopenharmony_ci
17050a07fd2Sopenharmony_ci    param_.comParam.sampleRate = paramHDF_.sampleRate;
17150a07fd2Sopenharmony_ci    param_.comParam.channelMask = paramHDF_.channelMask;
17250a07fd2Sopenharmony_ci    param_.comParam.bitFormat = paramHDF_.bitFormat;
17350a07fd2Sopenharmony_ci    param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC;
17450a07fd2Sopenharmony_ci    param_.comParam.frameSize = paramHDF_.frameSize;
17550a07fd2Sopenharmony_ci    param_.renderOpts.contentType = CONTENT_TYPE_MUSIC;
17650a07fd2Sopenharmony_ci    param_.renderOpts.renderFlags = paramHDF_.renderFlags;
17750a07fd2Sopenharmony_ci    param_.renderOpts.streamUsage = paramHDF_.streamUsage;
17850a07fd2Sopenharmony_ci    return DH_SUCCESS;
17950a07fd2Sopenharmony_ci}
18050a07fd2Sopenharmony_ci
18150a07fd2Sopenharmony_ciint32_t DSpeakerDev::NotifyEvent(const int32_t streamId, const AudioEvent &event)
18250a07fd2Sopenharmony_ci{
18350a07fd2Sopenharmony_ci    DHLOGD("Notify speaker event.");
18450a07fd2Sopenharmony_ci    std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
18550a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
18650a07fd2Sopenharmony_ci    AudioEvent audioEvent(event.type, event.content);
18750a07fd2Sopenharmony_ci    cbObj->NotifyEvent(audioEvent);
18850a07fd2Sopenharmony_ci    return DH_SUCCESS;
18950a07fd2Sopenharmony_ci}
19050a07fd2Sopenharmony_ci
19150a07fd2Sopenharmony_ciint32_t DSpeakerDev::SetUp()
19250a07fd2Sopenharmony_ci{
19350a07fd2Sopenharmony_ci    DHLOGI("Set up speaker device.");
19450a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR);
19550a07fd2Sopenharmony_ci
19650a07fd2Sopenharmony_ci    int32_t ret = speakerTrans_->SetUp(param_, param_, shared_from_this(), CAP_SPK);
19750a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
19850a07fd2Sopenharmony_ci        DHLOGE("Speaker trans set up failed. ret:%{public}d", ret);
19950a07fd2Sopenharmony_ci        return ret;
20050a07fd2Sopenharmony_ci    }
20150a07fd2Sopenharmony_ci    DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, SPK_DEV_FILENAME, &dumpFileCommn_);
20250a07fd2Sopenharmony_ci    DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, SPK_LOWLATENCY_FILENAME, &dumpFileFast_);
20350a07fd2Sopenharmony_ci    return DH_SUCCESS;
20450a07fd2Sopenharmony_ci}
20550a07fd2Sopenharmony_ci
20650a07fd2Sopenharmony_ciint32_t DSpeakerDev::Start()
20750a07fd2Sopenharmony_ci{
20850a07fd2Sopenharmony_ci    DHLOGI("Start speaker device.");
20950a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR);
21050a07fd2Sopenharmony_ci    int32_t ret = speakerTrans_->Start();
21150a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
21250a07fd2Sopenharmony_ci        DHLOGE("Speaker trans start failed, ret: %{public}d.", ret);
21350a07fd2Sopenharmony_ci        return ret;
21450a07fd2Sopenharmony_ci    }
21550a07fd2Sopenharmony_ci    std::unique_lock<std::mutex> lck(channelWaitMutex_);
21650a07fd2Sopenharmony_ci    auto status = channelWaitCond_.wait_for(lck, std::chrono::seconds(CHANNEL_WAIT_SECONDS),
21750a07fd2Sopenharmony_ci        [this]() { return isTransReady_.load(); });
21850a07fd2Sopenharmony_ci    if (!status) {
21950a07fd2Sopenharmony_ci        DHLOGE("Wait channel open timeout(%{public}ds).", CHANNEL_WAIT_SECONDS);
22050a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_SA_WAIT_TIMEOUT;
22150a07fd2Sopenharmony_ci    }
22250a07fd2Sopenharmony_ci    isOpened_.store(true);
22350a07fd2Sopenharmony_ci    return DH_SUCCESS;
22450a07fd2Sopenharmony_ci}
22550a07fd2Sopenharmony_ci
22650a07fd2Sopenharmony_ciint32_t DSpeakerDev::Stop()
22750a07fd2Sopenharmony_ci{
22850a07fd2Sopenharmony_ci    DHLOGI("Stop speaker device.");
22950a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(speakerTrans_, DH_SUCCESS);
23050a07fd2Sopenharmony_ci    isOpened_.store(false);
23150a07fd2Sopenharmony_ci    isTransReady_.store(false);
23250a07fd2Sopenharmony_ci    int32_t ret = speakerTrans_->Stop();
23350a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
23450a07fd2Sopenharmony_ci        DHLOGE("Stop speaker trans failed, ret: %{public}d.", ret);
23550a07fd2Sopenharmony_ci        return ret;
23650a07fd2Sopenharmony_ci    }
23750a07fd2Sopenharmony_ci    return DH_SUCCESS;
23850a07fd2Sopenharmony_ci}
23950a07fd2Sopenharmony_ci
24050a07fd2Sopenharmony_ciint32_t DSpeakerDev::Release()
24150a07fd2Sopenharmony_ci{
24250a07fd2Sopenharmony_ci    DHLOGI("Release speaker device.");
24350a07fd2Sopenharmony_ci    if (ashmem_ != nullptr) {
24450a07fd2Sopenharmony_ci        ashmem_->UnmapAshmem();
24550a07fd2Sopenharmony_ci        ashmem_->CloseAshmem();
24650a07fd2Sopenharmony_ci        ashmem_ = nullptr;
24750a07fd2Sopenharmony_ci        DHLOGI("UnInit ashmem success.");
24850a07fd2Sopenharmony_ci    }
24950a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(speakerTrans_, DH_SUCCESS);
25050a07fd2Sopenharmony_ci    int32_t ret = speakerTrans_->Release();
25150a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
25250a07fd2Sopenharmony_ci        DHLOGE("Release speaker trans failed, ret: %{public}d.", ret);
25350a07fd2Sopenharmony_ci    }
25450a07fd2Sopenharmony_ci    DumpFileUtil::CloseDumpFile(&dumpFileCommn_);
25550a07fd2Sopenharmony_ci    DumpFileUtil::CloseDumpFile(&dumpFileFast_);
25650a07fd2Sopenharmony_ci    return DH_SUCCESS;
25750a07fd2Sopenharmony_ci}
25850a07fd2Sopenharmony_ci
25950a07fd2Sopenharmony_ciint32_t DSpeakerDev::Pause()
26050a07fd2Sopenharmony_ci{
26150a07fd2Sopenharmony_ci    DHLOGI("Pause.");
26250a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR);
26350a07fd2Sopenharmony_ci    int32_t ret = speakerTrans_->Pause();
26450a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
26550a07fd2Sopenharmony_ci        DHLOGE("Pause speaker trans failed, ret: %{public}d.", ret);
26650a07fd2Sopenharmony_ci        return ret;
26750a07fd2Sopenharmony_ci    }
26850a07fd2Sopenharmony_ci    DHLOGD("Pause success.");
26950a07fd2Sopenharmony_ci    return DH_SUCCESS;
27050a07fd2Sopenharmony_ci}
27150a07fd2Sopenharmony_ci
27250a07fd2Sopenharmony_ciint32_t DSpeakerDev::Restart()
27350a07fd2Sopenharmony_ci{
27450a07fd2Sopenharmony_ci    DHLOGI("Restart.");
27550a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR);
27650a07fd2Sopenharmony_ci    int32_t ret = speakerTrans_->Restart(param_, param_);
27750a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
27850a07fd2Sopenharmony_ci        DHLOGE("Restart speaker trans failed, ret: %{public}d.", ret);
27950a07fd2Sopenharmony_ci        return ret;
28050a07fd2Sopenharmony_ci    }
28150a07fd2Sopenharmony_ci    DHLOGD("Restart success.");
28250a07fd2Sopenharmony_ci    return DH_SUCCESS;
28350a07fd2Sopenharmony_ci}
28450a07fd2Sopenharmony_ci
28550a07fd2Sopenharmony_cibool DSpeakerDev::IsOpened()
28650a07fd2Sopenharmony_ci{
28750a07fd2Sopenharmony_ci    return isOpened_.load();
28850a07fd2Sopenharmony_ci}
28950a07fd2Sopenharmony_ci
29050a07fd2Sopenharmony_ciint32_t DSpeakerDev::ReadStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data)
29150a07fd2Sopenharmony_ci{
29250a07fd2Sopenharmony_ci    (void)streamId;
29350a07fd2Sopenharmony_ci    (void)data;
29450a07fd2Sopenharmony_ci    DHLOGD("Dspeaker dev not support read stream data.");
29550a07fd2Sopenharmony_ci    return DH_SUCCESS;
29650a07fd2Sopenharmony_ci}
29750a07fd2Sopenharmony_ci
29850a07fd2Sopenharmony_ciint32_t DSpeakerDev::WriteStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data)
29950a07fd2Sopenharmony_ci{
30050a07fd2Sopenharmony_ci    DHLOGD("Write stream data, streamId:%{public}d", streamId);
30150a07fd2Sopenharmony_ci    int64_t startTime = GetNowTimeUs();
30250a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR);
30350a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(data, ERR_DH_AUDIO_NULLPTR);
30450a07fd2Sopenharmony_ci    DumpFileUtil::WriteDumpFile(dumpFileCommn_, static_cast<void *>(data->Data()), data->Size());
30550a07fd2Sopenharmony_ci    int32_t ret = speakerTrans_->FeedAudioData(data);
30650a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
30750a07fd2Sopenharmony_ci        DHLOGE("Write stream data failed, ret: %{public}d.", ret);
30850a07fd2Sopenharmony_ci        return ret;
30950a07fd2Sopenharmony_ci    }
31050a07fd2Sopenharmony_ci    int64_t endTime = GetNowTimeUs();
31150a07fd2Sopenharmony_ci    if (IsOutDurationRange(startTime, endTime, lastwriteStartTime_)) {
31250a07fd2Sopenharmony_ci        DHLOGE("This time write data spend: %{public}" PRId64" us, The interval of write data this time and "
31350a07fd2Sopenharmony_ci            "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastwriteStartTime_);
31450a07fd2Sopenharmony_ci    }
31550a07fd2Sopenharmony_ci    lastwriteStartTime_ = startTime;
31650a07fd2Sopenharmony_ci    return DH_SUCCESS;
31750a07fd2Sopenharmony_ci}
31850a07fd2Sopenharmony_ci
31950a07fd2Sopenharmony_ciint32_t DSpeakerDev::ReadMmapPosition(const int32_t streamId,
32050a07fd2Sopenharmony_ci    uint64_t &frames, CurrentTimeHDF &time)
32150a07fd2Sopenharmony_ci{
32250a07fd2Sopenharmony_ci    DHLOGD("Read mmap position. frames: %{public}" PRIu64", tvsec: %{public}" PRId64", tvNSec:%{public}" PRId64,
32350a07fd2Sopenharmony_ci        readNum_, readTvSec_, readTvNSec_);
32450a07fd2Sopenharmony_ci    frames = readNum_;
32550a07fd2Sopenharmony_ci    time.tvSec = readTvSec_;
32650a07fd2Sopenharmony_ci    time.tvNSec = readTvNSec_;
32750a07fd2Sopenharmony_ci    return DH_SUCCESS;
32850a07fd2Sopenharmony_ci}
32950a07fd2Sopenharmony_ci
33050a07fd2Sopenharmony_ciint32_t DSpeakerDev::RefreshAshmemInfo(const int32_t streamId,
33150a07fd2Sopenharmony_ci    int32_t fd, int32_t ashmemLength, int32_t lengthPerTrans)
33250a07fd2Sopenharmony_ci{
33350a07fd2Sopenharmony_ci    DHLOGD("RefreshAshmemInfo: fd:%{public}d, ashmemLength: %{public}d, lengthPerTrans: %{public}d",
33450a07fd2Sopenharmony_ci        fd, ashmemLength, lengthPerTrans);
33550a07fd2Sopenharmony_ci    if (param_.renderOpts.renderFlags == MMAP_MODE) {
33650a07fd2Sopenharmony_ci        DHLOGI("DSpeaker dev low-latency mode");
33750a07fd2Sopenharmony_ci        if (ashmem_ != nullptr) {
33850a07fd2Sopenharmony_ci            return DH_SUCCESS;
33950a07fd2Sopenharmony_ci        }
34050a07fd2Sopenharmony_ci        if (ashmemLength < ASHMEM_MAX_LEN) {
34150a07fd2Sopenharmony_ci            ashmem_ = sptr<Ashmem>(new Ashmem(fd, ashmemLength));
34250a07fd2Sopenharmony_ci            ashmemLength_ = ashmemLength;
34350a07fd2Sopenharmony_ci            lengthPerTrans_ = lengthPerTrans;
34450a07fd2Sopenharmony_ci            DHLOGI("Create ashmem success. fd:%{public}d, ashmem length: %{public}d, lengthPreTrans: %{public}d",
34550a07fd2Sopenharmony_ci                fd, ashmemLength_, lengthPerTrans_);
34650a07fd2Sopenharmony_ci            bool mapRet = ashmem_->MapReadAndWriteAshmem();
34750a07fd2Sopenharmony_ci            if (!mapRet) {
34850a07fd2Sopenharmony_ci                DHLOGE("Mmap ashmem failed.");
34950a07fd2Sopenharmony_ci                return ERR_DH_AUDIO_NULLPTR;
35050a07fd2Sopenharmony_ci            }
35150a07fd2Sopenharmony_ci        }
35250a07fd2Sopenharmony_ci    }
35350a07fd2Sopenharmony_ci    return DH_SUCCESS;
35450a07fd2Sopenharmony_ci}
35550a07fd2Sopenharmony_ci
35650a07fd2Sopenharmony_ciint32_t DSpeakerDev::MmapStart()
35750a07fd2Sopenharmony_ci{
35850a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(ashmem_, ERR_DH_AUDIO_NULLPTR);
35950a07fd2Sopenharmony_ci    isEnqueueRunning_.store(true);
36050a07fd2Sopenharmony_ci    enqueueDataThread_ = std::thread([this]() { this->EnqueueThread(); });
36150a07fd2Sopenharmony_ci    if (pthread_setname_np(enqueueDataThread_.native_handle(), ENQUEUE_THREAD) != DH_SUCCESS) {
36250a07fd2Sopenharmony_ci        DHLOGE("Enqueue data thread setname failed.");
36350a07fd2Sopenharmony_ci    }
36450a07fd2Sopenharmony_ci    return DH_SUCCESS;
36550a07fd2Sopenharmony_ci}
36650a07fd2Sopenharmony_ci
36750a07fd2Sopenharmony_civoid DSpeakerDev::EnqueueThread()
36850a07fd2Sopenharmony_ci{
36950a07fd2Sopenharmony_ci    readIndex_ = 0;
37050a07fd2Sopenharmony_ci    readNum_ = 0;
37150a07fd2Sopenharmony_ci    frameIndex_ = 0;
37250a07fd2Sopenharmony_ci    int64_t timeIntervalns = static_cast<int64_t>(paramHDF_.period * AUDIO_NS_PER_SECOND / AUDIO_MS_PER_SECOND);
37350a07fd2Sopenharmony_ci    DHLOGI("Enqueue thread start, lengthPerRead length: %{public}d, interval: %{pubic}d.", lengthPerTrans_,
37450a07fd2Sopenharmony_ci        paramHDF_.period);
37550a07fd2Sopenharmony_ci    while (ashmem_ != nullptr && isEnqueueRunning_.load()) {
37650a07fd2Sopenharmony_ci        int64_t timeOffset = UpdateTimeOffset(frameIndex_, timeIntervalns, startTime_);
37750a07fd2Sopenharmony_ci        DHLOGD("Read frameIndex: %{public}" PRId64", timeOffset: %{public}" PRId64, frameIndex_, timeOffset);
37850a07fd2Sopenharmony_ci        auto readData = ashmem_->ReadFromAshmem(lengthPerTrans_, readIndex_);
37950a07fd2Sopenharmony_ci        DHLOGD("Read from ashmem success! read index: %{public}d, readLength: %{public}d.",
38050a07fd2Sopenharmony_ci            readIndex_, lengthPerTrans_);
38150a07fd2Sopenharmony_ci        std::shared_ptr<AudioData> audioData = std::make_shared<AudioData>(lengthPerTrans_);
38250a07fd2Sopenharmony_ci        if (readData != nullptr) {
38350a07fd2Sopenharmony_ci            const uint8_t *readAudioData = reinterpret_cast<const uint8_t *>(readData);
38450a07fd2Sopenharmony_ci            if (memcpy_s(audioData->Data(), audioData->Capacity(), readAudioData, param_.comParam.frameSize) != EOK) {
38550a07fd2Sopenharmony_ci                DHLOGE("Copy audio data failed.");
38650a07fd2Sopenharmony_ci            }
38750a07fd2Sopenharmony_ci        }
38850a07fd2Sopenharmony_ci        CHECK_NULL_VOID(speakerTrans_);
38950a07fd2Sopenharmony_ci        DumpFileUtil::WriteDumpFile(dumpFileFast_, static_cast<void *>(audioData->Data()), audioData->Size());
39050a07fd2Sopenharmony_ci        int32_t ret = speakerTrans_->FeedAudioData(audioData);
39150a07fd2Sopenharmony_ci        if (ret != DH_SUCCESS) {
39250a07fd2Sopenharmony_ci            DHLOGE("Speaker enqueue thread, write stream data failed, ret: %{public}d.", ret);
39350a07fd2Sopenharmony_ci        }
39450a07fd2Sopenharmony_ci        readIndex_ += lengthPerTrans_;
39550a07fd2Sopenharmony_ci        if (readIndex_ >= ashmemLength_) {
39650a07fd2Sopenharmony_ci            readIndex_ = 0;
39750a07fd2Sopenharmony_ci        }
39850a07fd2Sopenharmony_ci        readNum_ += static_cast<uint64_t>(CalculateSampleNum(param_.comParam.sampleRate, paramHDF_.period));
39950a07fd2Sopenharmony_ci        GetCurrentTime(readTvSec_, readTvNSec_);
40050a07fd2Sopenharmony_ci        frameIndex_++;
40150a07fd2Sopenharmony_ci        AbsoluteSleep(startTime_ + frameIndex_ * timeIntervalns - timeOffset);
40250a07fd2Sopenharmony_ci    }
40350a07fd2Sopenharmony_ci}
40450a07fd2Sopenharmony_ci
40550a07fd2Sopenharmony_ciint32_t DSpeakerDev::MmapStop()
40650a07fd2Sopenharmony_ci{
40750a07fd2Sopenharmony_ci    isEnqueueRunning_.store(false);
40850a07fd2Sopenharmony_ci    if (enqueueDataThread_.joinable()) {
40950a07fd2Sopenharmony_ci        enqueueDataThread_.join();
41050a07fd2Sopenharmony_ci    }
41150a07fd2Sopenharmony_ci    DHLOGI("Spk mmap stop end.");
41250a07fd2Sopenharmony_ci    return DH_SUCCESS;
41350a07fd2Sopenharmony_ci}
41450a07fd2Sopenharmony_ci
41550a07fd2Sopenharmony_ciAudioParam DSpeakerDev::GetAudioParam() const
41650a07fd2Sopenharmony_ci{
41750a07fd2Sopenharmony_ci    return param_;
41850a07fd2Sopenharmony_ci}
41950a07fd2Sopenharmony_ci
42050a07fd2Sopenharmony_ciint32_t DSpeakerDev::SendMessage(uint32_t type, std::string content, std::string dstDevId)
42150a07fd2Sopenharmony_ci{
42250a07fd2Sopenharmony_ci    DHLOGD("Send message to remote.");
42350a07fd2Sopenharmony_ci    if (type != static_cast<uint32_t>(OPEN_SPEAKER) && type != static_cast<uint32_t>(CLOSE_SPEAKER) &&
42450a07fd2Sopenharmony_ci        type != static_cast<uint32_t>(CHANGE_PLAY_STATUS) && type != static_cast<uint32_t>(VOLUME_SET) &&
42550a07fd2Sopenharmony_ci        type != static_cast<uint32_t>(VOLUME_MUTE_SET)) {
42650a07fd2Sopenharmony_ci        DHLOGE("Send message to remote. not OPEN_SPK or CLOSE_SPK. type: %{public}u", type);
42750a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_NULLPTR;
42850a07fd2Sopenharmony_ci    }
42950a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR);
43050a07fd2Sopenharmony_ci    speakerTrans_->SendMessage(type, content, dstDevId);
43150a07fd2Sopenharmony_ci    return DH_SUCCESS;
43250a07fd2Sopenharmony_ci}
43350a07fd2Sopenharmony_ci
43450a07fd2Sopenharmony_ciint32_t DSpeakerDev::NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId)
43550a07fd2Sopenharmony_ci{
43650a07fd2Sopenharmony_ci    int32_t ret = DAudioHdiHandler::GetInstance().NotifyEvent(devId_, portId, streamId_, event);
43750a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
43850a07fd2Sopenharmony_ci        DHLOGE("Notify event: %{public}d, result: %{public}s, streamId: %{public}d.",
43950a07fd2Sopenharmony_ci            event.type, event.content.c_str(), streamId_);
44050a07fd2Sopenharmony_ci    }
44150a07fd2Sopenharmony_ci    return DH_SUCCESS;
44250a07fd2Sopenharmony_ci}
44350a07fd2Sopenharmony_ci
44450a07fd2Sopenharmony_ciint32_t DSpeakerDev::OnStateChange(const AudioEventType type)
44550a07fd2Sopenharmony_ci{
44650a07fd2Sopenharmony_ci    DHLOGI("On speaker device state change, type: %{public}d.", type);
44750a07fd2Sopenharmony_ci    AudioEvent event;
44850a07fd2Sopenharmony_ci    switch (type) {
44950a07fd2Sopenharmony_ci        case AudioEventType::DATA_OPENED:
45050a07fd2Sopenharmony_ci            isTransReady_.store(true);
45150a07fd2Sopenharmony_ci            channelWaitCond_.notify_all();
45250a07fd2Sopenharmony_ci            event.type = AudioEventType::SPEAKER_OPENED;
45350a07fd2Sopenharmony_ci            break;
45450a07fd2Sopenharmony_ci        case AudioEventType::DATA_CLOSED:
45550a07fd2Sopenharmony_ci            isOpened_.store(false);
45650a07fd2Sopenharmony_ci            isTransReady_.store(false);
45750a07fd2Sopenharmony_ci            event.type = AudioEventType::SPEAKER_CLOSED;
45850a07fd2Sopenharmony_ci            break;
45950a07fd2Sopenharmony_ci        default:
46050a07fd2Sopenharmony_ci            break;
46150a07fd2Sopenharmony_ci    }
46250a07fd2Sopenharmony_ci    event.content = GetCJsonString(KEY_DH_ID, std::to_string(dhId_).c_str());
46350a07fd2Sopenharmony_ci    std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
46450a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
46550a07fd2Sopenharmony_ci    cbObj->NotifyEvent(event);
46650a07fd2Sopenharmony_ci    return DH_SUCCESS;
46750a07fd2Sopenharmony_ci}
46850a07fd2Sopenharmony_ci
46950a07fd2Sopenharmony_ciint32_t DSpeakerDev::OnDecodeTransDataDone(const std::shared_ptr<AudioData> &audioData)
47050a07fd2Sopenharmony_ci{
47150a07fd2Sopenharmony_ci    (void) audioData;
47250a07fd2Sopenharmony_ci    return DH_SUCCESS;
47350a07fd2Sopenharmony_ci}
47450a07fd2Sopenharmony_ci} // DistributedHardware
47550a07fd2Sopenharmony_ci} // OHOS
476