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 "dmic_dev.h"
1750a07fd2Sopenharmony_ci
1850a07fd2Sopenharmony_ci#include <condition_variable>
1950a07fd2Sopenharmony_ci#include <mutex>
2050a07fd2Sopenharmony_ci#include <string>
2150a07fd2Sopenharmony_ci#include <thread>
2250a07fd2Sopenharmony_ci
2350a07fd2Sopenharmony_ci#include "daudio_constants.h"
2450a07fd2Sopenharmony_ci#include "daudio_errorcode.h"
2550a07fd2Sopenharmony_ci#include "daudio_hidumper.h"
2650a07fd2Sopenharmony_ci#include "daudio_hisysevent.h"
2750a07fd2Sopenharmony_ci#include "daudio_hitrace.h"
2850a07fd2Sopenharmony_ci#include "daudio_log.h"
2950a07fd2Sopenharmony_ci#include "daudio_source_manager.h"
3050a07fd2Sopenharmony_ci#include "daudio_util.h"
3150a07fd2Sopenharmony_ci
3250a07fd2Sopenharmony_ci#undef DH_LOG_TAG
3350a07fd2Sopenharmony_ci#define DH_LOG_TAG "DMicDev"
3450a07fd2Sopenharmony_ci
3550a07fd2Sopenharmony_cinamespace OHOS {
3650a07fd2Sopenharmony_cinamespace DistributedHardware {
3750a07fd2Sopenharmony_cistatic constexpr size_t DATA_QUEUE_EXT_SIZE = 20;
3850a07fd2Sopenharmony_civoid DMicDev::OnEngineTransEvent(const AVTransEvent &event)
3950a07fd2Sopenharmony_ci{
4050a07fd2Sopenharmony_ci    if (event.type == EventType::EVENT_START_SUCCESS) {
4150a07fd2Sopenharmony_ci        OnStateChange(DATA_OPENED);
4250a07fd2Sopenharmony_ci    } else if ((event.type == EventType::EVENT_STOP_SUCCESS) ||
4350a07fd2Sopenharmony_ci        (event.type == EventType::EVENT_CHANNEL_CLOSED) ||
4450a07fd2Sopenharmony_ci        (event.type == EventType::EVENT_START_FAIL)) {
4550a07fd2Sopenharmony_ci        OnStateChange(DATA_CLOSED);
4650a07fd2Sopenharmony_ci    }
4750a07fd2Sopenharmony_ci}
4850a07fd2Sopenharmony_ci
4950a07fd2Sopenharmony_civoid DMicDev::OnEngineTransMessage(const std::shared_ptr<AVTransMessage> &message)
5050a07fd2Sopenharmony_ci{
5150a07fd2Sopenharmony_ci    CHECK_NULL_VOID(message);
5250a07fd2Sopenharmony_ci    DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str());
5350a07fd2Sopenharmony_ci    DAudioSourceManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_,
5450a07fd2Sopenharmony_ci        message->type_, message->content_);
5550a07fd2Sopenharmony_ci}
5650a07fd2Sopenharmony_ci
5750a07fd2Sopenharmony_civoid DMicDev::OnEngineTransDataAvailable(const std::shared_ptr<AudioData> &audioData)
5850a07fd2Sopenharmony_ci{
5950a07fd2Sopenharmony_ci    DHLOGD("On Engine Data available");
6050a07fd2Sopenharmony_ci    if (echoCannelOn_) {
6150a07fd2Sopenharmony_ci#ifdef ECHO_CANNEL_ENABLE
6250a07fd2Sopenharmony_ci        if (echoManager_ == nullptr) {
6350a07fd2Sopenharmony_ci            DHLOGE("Echo manager is nullptr.");
6450a07fd2Sopenharmony_ci            return;
6550a07fd2Sopenharmony_ci        }
6650a07fd2Sopenharmony_ci        echoManager_->OnMicDataReceived(audioData);
6750a07fd2Sopenharmony_ci#endif
6850a07fd2Sopenharmony_ci    } else {
6950a07fd2Sopenharmony_ci        OnDecodeTransDataDone(audioData);
7050a07fd2Sopenharmony_ci    }
7150a07fd2Sopenharmony_ci}
7250a07fd2Sopenharmony_ci
7350a07fd2Sopenharmony_ciint32_t DMicDev::InitReceiverEngine(IAVEngineProvider *providerPtr)
7450a07fd2Sopenharmony_ci{
7550a07fd2Sopenharmony_ci    DHLOGI("InitReceiverEngine enter.");
7650a07fd2Sopenharmony_ci    if (micTrans_ == nullptr) {
7750a07fd2Sopenharmony_ci        micTrans_ = std::make_shared<AVTransReceiverTransport>(devId_, shared_from_this());
7850a07fd2Sopenharmony_ci    }
7950a07fd2Sopenharmony_ci    int32_t ret = micTrans_->InitEngine(providerPtr);
8050a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
8150a07fd2Sopenharmony_ci        DHLOGE("Mic dev initialize av receiver adapter failed.");
8250a07fd2Sopenharmony_ci        return ret;
8350a07fd2Sopenharmony_ci    }
8450a07fd2Sopenharmony_ci    ret = micTrans_->CreateCtrl();
8550a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
8650a07fd2Sopenharmony_ci        DHLOGE("Create ctrl channel failed. micdev");
8750a07fd2Sopenharmony_ci        return ret;
8850a07fd2Sopenharmony_ci    }
8950a07fd2Sopenharmony_ci    return DH_SUCCESS;
9050a07fd2Sopenharmony_ci}
9150a07fd2Sopenharmony_ci
9250a07fd2Sopenharmony_ciint32_t DMicDev::InitSenderEngine(IAVEngineProvider *providerPtr)
9350a07fd2Sopenharmony_ci{
9450a07fd2Sopenharmony_ci    DHLOGI("InitReceiverEngine enter.");
9550a07fd2Sopenharmony_ci    return DH_SUCCESS;
9650a07fd2Sopenharmony_ci}
9750a07fd2Sopenharmony_ci
9850a07fd2Sopenharmony_ciint32_t DMicDev::EnableDevice(const int32_t dhId, const std::string &capability)
9950a07fd2Sopenharmony_ci{
10050a07fd2Sopenharmony_ci    DHLOGI("Enable IO device, device pin: %{public}d.", dhId);
10150a07fd2Sopenharmony_ci    int32_t ret = DAudioHdiHandler::GetInstance().RegisterAudioDevice(devId_, dhId, capability, shared_from_this());
10250a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
10350a07fd2Sopenharmony_ci        DHLOGE("Register device failed, ret: %{public}d.", ret);
10450a07fd2Sopenharmony_ci        DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_REGISTER_FAIL, devId_, std::to_string(dhId), ret,
10550a07fd2Sopenharmony_ci            "daudio register device failed.");
10650a07fd2Sopenharmony_ci        return ret;
10750a07fd2Sopenharmony_ci    }
10850a07fd2Sopenharmony_ci    dhId_ = dhId;
10950a07fd2Sopenharmony_ci    return DH_SUCCESS;
11050a07fd2Sopenharmony_ci}
11150a07fd2Sopenharmony_ci
11250a07fd2Sopenharmony_ciint32_t DMicDev::DisableDevice(const int32_t dhId)
11350a07fd2Sopenharmony_ci{
11450a07fd2Sopenharmony_ci    DHLOGI("Disable IO device, device pin: %{public}d.", dhId);
11550a07fd2Sopenharmony_ci    int32_t ret = DAudioHdiHandler::GetInstance().UnRegisterAudioDevice(devId_, dhId);
11650a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
11750a07fd2Sopenharmony_ci        DHLOGE("UnRegister failed, ret: %{public}d.", ret);
11850a07fd2Sopenharmony_ci        DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_UNREGISTER_FAIL, devId_, std::to_string(dhId), ret,
11950a07fd2Sopenharmony_ci            "daudio unregister device failed.");
12050a07fd2Sopenharmony_ci        return ret;
12150a07fd2Sopenharmony_ci    }
12250a07fd2Sopenharmony_ci    return DH_SUCCESS;
12350a07fd2Sopenharmony_ci}
12450a07fd2Sopenharmony_ci
12550a07fd2Sopenharmony_ciint32_t DMicDev::CreateStream(const int32_t streamId)
12650a07fd2Sopenharmony_ci{
12750a07fd2Sopenharmony_ci    DHLOGI("Open stream of mic device streamId: %{public}d.", streamId);
12850a07fd2Sopenharmony_ci    std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
12950a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
13050a07fd2Sopenharmony_ci
13150a07fd2Sopenharmony_ci    cJSON *jParam = cJSON_CreateObject();
13250a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR);
13350a07fd2Sopenharmony_ci    cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
13450a07fd2Sopenharmony_ci    char *jsonData = cJSON_PrintUnformatted(jParam);
13550a07fd2Sopenharmony_ci    if (jsonData == nullptr) {
13650a07fd2Sopenharmony_ci        cJSON_Delete(jParam);
13750a07fd2Sopenharmony_ci        DHLOGE("Failed to create JSON data.");
13850a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_NULLPTR;
13950a07fd2Sopenharmony_ci    }
14050a07fd2Sopenharmony_ci    std::string jsonDataStr(jsonData);
14150a07fd2Sopenharmony_ci    AudioEvent event(AudioEventType::OPEN_MIC, jsonDataStr);
14250a07fd2Sopenharmony_ci    cbObj->NotifyEvent(event);
14350a07fd2Sopenharmony_ci    DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_OPEN, devId_, std::to_string(dhId_),
14450a07fd2Sopenharmony_ci        "daudio mic device open success.");
14550a07fd2Sopenharmony_ci    streamId_ = streamId;
14650a07fd2Sopenharmony_ci    cJSON_Delete(jParam);
14750a07fd2Sopenharmony_ci    cJSON_free(jsonData);
14850a07fd2Sopenharmony_ci    return DH_SUCCESS;
14950a07fd2Sopenharmony_ci}
15050a07fd2Sopenharmony_ci
15150a07fd2Sopenharmony_ciint32_t DMicDev::DestroyStream(const int32_t streamId)
15250a07fd2Sopenharmony_ci{
15350a07fd2Sopenharmony_ci    DHLOGI("Close stream of mic device streamId: %{public}d.", streamId);
15450a07fd2Sopenharmony_ci    std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
15550a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
15650a07fd2Sopenharmony_ci
15750a07fd2Sopenharmony_ci    cJSON *jParam = cJSON_CreateObject();
15850a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR);
15950a07fd2Sopenharmony_ci    cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
16050a07fd2Sopenharmony_ci    char *jsonData = cJSON_PrintUnformatted(jParam);
16150a07fd2Sopenharmony_ci    if (jsonData == nullptr) {
16250a07fd2Sopenharmony_ci        cJSON_Delete(jParam);
16350a07fd2Sopenharmony_ci        DHLOGE("Failed to create JSON data.");
16450a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_NULLPTR;
16550a07fd2Sopenharmony_ci    }
16650a07fd2Sopenharmony_ci    std::string jsonDataStr(jsonData);
16750a07fd2Sopenharmony_ci    AudioEvent event(AudioEventType::CLOSE_MIC, jsonDataStr);
16850a07fd2Sopenharmony_ci    cbObj->NotifyEvent(event);
16950a07fd2Sopenharmony_ci    DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_CLOSE, devId_, std::to_string(dhId_),
17050a07fd2Sopenharmony_ci        "daudio mic device close success.");
17150a07fd2Sopenharmony_ci    cJSON_Delete(jParam);
17250a07fd2Sopenharmony_ci    cJSON_free(jsonData);
17350a07fd2Sopenharmony_ci    curPort_ = 0;
17450a07fd2Sopenharmony_ci    return DH_SUCCESS;
17550a07fd2Sopenharmony_ci}
17650a07fd2Sopenharmony_ci
17750a07fd2Sopenharmony_ciint32_t DMicDev::SetParameters(const int32_t streamId, const AudioParamHDF &param)
17850a07fd2Sopenharmony_ci{
17950a07fd2Sopenharmony_ci    DHLOGD("Set mic parameters {samplerate: %{public}d, channelmask: %{public}d, format: %{public}d, "
18050a07fd2Sopenharmony_ci        "period: %{public}d, framesize: %{public}d, ext{%{public}s}}.", param.sampleRate,
18150a07fd2Sopenharmony_ci        param.channelMask, param.bitFormat, param.period, param.frameSize, param.ext.c_str());
18250a07fd2Sopenharmony_ci    if (param.capturerFlags == MMAP_MODE && param.period != MMAP_NORMAL_PERIOD && param.period != MMAP_VOIP_PERIOD) {
18350a07fd2Sopenharmony_ci        DHLOGE("The period is invalid : %{public}" PRIu32, param.period);
18450a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_SA_PARAM_INVALID;
18550a07fd2Sopenharmony_ci    }
18650a07fd2Sopenharmony_ci    curPort_ = dhId_;
18750a07fd2Sopenharmony_ci    paramHDF_ = param;
18850a07fd2Sopenharmony_ci
18950a07fd2Sopenharmony_ci    param_.comParam.sampleRate = paramHDF_.sampleRate;
19050a07fd2Sopenharmony_ci    param_.comParam.channelMask = paramHDF_.channelMask;
19150a07fd2Sopenharmony_ci    param_.comParam.bitFormat = paramHDF_.bitFormat;
19250a07fd2Sopenharmony_ci    param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC;
19350a07fd2Sopenharmony_ci    param_.comParam.frameSize = paramHDF_.frameSize;
19450a07fd2Sopenharmony_ci    if (paramHDF_.streamUsage == StreamUsage::STREAM_USAGE_VOICE_COMMUNICATION) {
19550a07fd2Sopenharmony_ci        param_.captureOpts.sourceType = SOURCE_TYPE_VOICE_COMMUNICATION;
19650a07fd2Sopenharmony_ci    } else {
19750a07fd2Sopenharmony_ci        param_.captureOpts.sourceType = SOURCE_TYPE_MIC;
19850a07fd2Sopenharmony_ci    }
19950a07fd2Sopenharmony_ci    param_.captureOpts.capturerFlags = paramHDF_.capturerFlags;
20050a07fd2Sopenharmony_ci    if (paramHDF_.capturerFlags == MMAP_MODE) {
20150a07fd2Sopenharmony_ci        lowLatencyHalfSize_ = LOW_LATENCY_JITTER_TIME_MS / paramHDF_.period;
20250a07fd2Sopenharmony_ci        lowLatencyMaxfSize_ = LOW_LATENCY_JITTER_MAX_TIME_MS / paramHDF_.period;
20350a07fd2Sopenharmony_ci    }
20450a07fd2Sopenharmony_ci    return DH_SUCCESS;
20550a07fd2Sopenharmony_ci}
20650a07fd2Sopenharmony_ci
20750a07fd2Sopenharmony_ciint32_t DMicDev::NotifyEvent(const int32_t streamId, const AudioEvent &event)
20850a07fd2Sopenharmony_ci{
20950a07fd2Sopenharmony_ci    DHLOGD("Notify mic event, type: %{public}d.", event.type);
21050a07fd2Sopenharmony_ci    std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
21150a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
21250a07fd2Sopenharmony_ci    switch (event.type) {
21350a07fd2Sopenharmony_ci        case AudioEventType::AUDIO_START:
21450a07fd2Sopenharmony_ci            curStatus_ = AudioStatus::STATUS_START;
21550a07fd2Sopenharmony_ci            isExistedEmpty_.store(false);
21650a07fd2Sopenharmony_ci            break;
21750a07fd2Sopenharmony_ci        case AudioEventType::AUDIO_STOP:
21850a07fd2Sopenharmony_ci            curStatus_ = AudioStatus::STATUS_STOP;
21950a07fd2Sopenharmony_ci            isExistedEmpty_.store(false);
22050a07fd2Sopenharmony_ci            break;
22150a07fd2Sopenharmony_ci        default:
22250a07fd2Sopenharmony_ci            break;
22350a07fd2Sopenharmony_ci    }
22450a07fd2Sopenharmony_ci    AudioEvent audioEvent(event.type, event.content);
22550a07fd2Sopenharmony_ci    cbObj->NotifyEvent(audioEvent);
22650a07fd2Sopenharmony_ci    return DH_SUCCESS;
22750a07fd2Sopenharmony_ci}
22850a07fd2Sopenharmony_ci
22950a07fd2Sopenharmony_ciint32_t DMicDev::SetUp()
23050a07fd2Sopenharmony_ci{
23150a07fd2Sopenharmony_ci    DHLOGI("Set up mic device.");
23250a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR);
23350a07fd2Sopenharmony_ci    int32_t ret = micTrans_->SetUp(param_, param_, shared_from_this(), CAP_MIC);
23450a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
23550a07fd2Sopenharmony_ci        DHLOGE("Mic trans set up failed. ret: %{public}d.", ret);
23650a07fd2Sopenharmony_ci        return ret;
23750a07fd2Sopenharmony_ci    }
23850a07fd2Sopenharmony_ci    echoCannelOn_ = true;
23950a07fd2Sopenharmony_ci#ifdef ECHO_CANNEL_ENABLE
24050a07fd2Sopenharmony_ci    if (echoCannelOn_ && echoManager_ == nullptr) {
24150a07fd2Sopenharmony_ci        echoManager_ = std::make_shared<DAudioEchoCannelManager>();
24250a07fd2Sopenharmony_ci    }
24350a07fd2Sopenharmony_ci    AudioCommonParam info;
24450a07fd2Sopenharmony_ci    info.sampleRate = param_.comParam.sampleRate;
24550a07fd2Sopenharmony_ci    info.channelMask = param_.comParam.channelMask;
24650a07fd2Sopenharmony_ci    info.bitFormat = param_.comParam.bitFormat;
24750a07fd2Sopenharmony_ci    info.frameSize = param_.comParam.frameSize;
24850a07fd2Sopenharmony_ci    if (echoManager_ != nullptr) {
24950a07fd2Sopenharmony_ci        echoManager_->SetUp(info, shared_from_this());
25050a07fd2Sopenharmony_ci    }
25150a07fd2Sopenharmony_ci#endif
25250a07fd2Sopenharmony_ci    DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, DUMP_DAUDIO_MIC_READ_FROM_BUF_NAME, &dumpFileCommn_);
25350a07fd2Sopenharmony_ci    DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, DUMP_DAUDIO_LOWLATENCY_MIC_FROM_BUF_NAME, &dumpFileFast_);
25450a07fd2Sopenharmony_ci    return DH_SUCCESS;
25550a07fd2Sopenharmony_ci}
25650a07fd2Sopenharmony_ci
25750a07fd2Sopenharmony_ciint32_t DMicDev::Start()
25850a07fd2Sopenharmony_ci{
25950a07fd2Sopenharmony_ci    DHLOGI("Start mic device.");
26050a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR);
26150a07fd2Sopenharmony_ci    int32_t ret = micTrans_->Start();
26250a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
26350a07fd2Sopenharmony_ci        DHLOGE("Mic trans start failed, ret: %{public}d.", ret);
26450a07fd2Sopenharmony_ci        return ret;
26550a07fd2Sopenharmony_ci    }
26650a07fd2Sopenharmony_ci    std::unique_lock<std::mutex> lck(channelWaitMutex_);
26750a07fd2Sopenharmony_ci    auto status = channelWaitCond_.wait_for(lck, std::chrono::seconds(CHANNEL_WAIT_SECONDS),
26850a07fd2Sopenharmony_ci        [this]() { return isTransReady_.load(); });
26950a07fd2Sopenharmony_ci    if (!status) {
27050a07fd2Sopenharmony_ci        DHLOGE("Wait channel open timeout(%{public}ds).", CHANNEL_WAIT_SECONDS);
27150a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_SA_WAIT_TIMEOUT;
27250a07fd2Sopenharmony_ci    }
27350a07fd2Sopenharmony_ci    isOpened_.store(true);
27450a07fd2Sopenharmony_ci    return DH_SUCCESS;
27550a07fd2Sopenharmony_ci}
27650a07fd2Sopenharmony_ci
27750a07fd2Sopenharmony_ciint32_t DMicDev::Pause()
27850a07fd2Sopenharmony_ci{
27950a07fd2Sopenharmony_ci    DHLOGI("Not support.");
28050a07fd2Sopenharmony_ci    return DH_SUCCESS;
28150a07fd2Sopenharmony_ci}
28250a07fd2Sopenharmony_ci
28350a07fd2Sopenharmony_ciint32_t DMicDev::Restart()
28450a07fd2Sopenharmony_ci{
28550a07fd2Sopenharmony_ci    DHLOGI("Not surpport.");
28650a07fd2Sopenharmony_ci    return DH_SUCCESS;
28750a07fd2Sopenharmony_ci}
28850a07fd2Sopenharmony_ci
28950a07fd2Sopenharmony_ciint32_t DMicDev::Stop()
29050a07fd2Sopenharmony_ci{
29150a07fd2Sopenharmony_ci    DHLOGI("Stop mic device.");
29250a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(micTrans_, DH_SUCCESS);
29350a07fd2Sopenharmony_ci    isOpened_.store(false);
29450a07fd2Sopenharmony_ci    isTransReady_.store(false);
29550a07fd2Sopenharmony_ci    int32_t ret = micTrans_->Stop();
29650a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
29750a07fd2Sopenharmony_ci        DHLOGE("Stop mic trans failed, ret: %{public}d.", ret);
29850a07fd2Sopenharmony_ci    }
29950a07fd2Sopenharmony_ci#ifdef ECHO_CANNEL_ENABLE
30050a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(echoManager_, DH_SUCCESS);
30150a07fd2Sopenharmony_ci    ret = echoManager_->Stop();
30250a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
30350a07fd2Sopenharmony_ci        DHLOGE("Echo manager stop failed. ret: %{public}d.", ret);
30450a07fd2Sopenharmony_ci        return ret;
30550a07fd2Sopenharmony_ci    }
30650a07fd2Sopenharmony_ci#endif
30750a07fd2Sopenharmony_ci    return DH_SUCCESS;
30850a07fd2Sopenharmony_ci}
30950a07fd2Sopenharmony_ci
31050a07fd2Sopenharmony_ciint32_t DMicDev::Release()
31150a07fd2Sopenharmony_ci{
31250a07fd2Sopenharmony_ci    DHLOGI("Release mic device.");
31350a07fd2Sopenharmony_ci    if (ashmem_ != nullptr) {
31450a07fd2Sopenharmony_ci        ashmem_->UnmapAshmem();
31550a07fd2Sopenharmony_ci        ashmem_->CloseAshmem();
31650a07fd2Sopenharmony_ci        ashmem_ = nullptr;
31750a07fd2Sopenharmony_ci        DHLOGI("UnInit ashmem success.");
31850a07fd2Sopenharmony_ci    }
31950a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(micTrans_, DH_SUCCESS);
32050a07fd2Sopenharmony_ci
32150a07fd2Sopenharmony_ci    int32_t ret = micTrans_->Release();
32250a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
32350a07fd2Sopenharmony_ci        DHLOGE("Release mic trans failed, ret: %{public}d.", ret);
32450a07fd2Sopenharmony_ci        return ret;
32550a07fd2Sopenharmony_ci    }
32650a07fd2Sopenharmony_ci#ifdef ECHO_CANNEL_ENABLE
32750a07fd2Sopenharmony_ci    if (echoManager_ != nullptr) {
32850a07fd2Sopenharmony_ci        echoManager_->Release();
32950a07fd2Sopenharmony_ci        echoManager_ = nullptr;
33050a07fd2Sopenharmony_ci    }
33150a07fd2Sopenharmony_ci#endif
33250a07fd2Sopenharmony_ci    DumpFileUtil::CloseDumpFile(&dumpFileCommn_);
33350a07fd2Sopenharmony_ci    DumpFileUtil::CloseDumpFile(&dumpFileFast_);
33450a07fd2Sopenharmony_ci    return DH_SUCCESS;
33550a07fd2Sopenharmony_ci}
33650a07fd2Sopenharmony_ci
33750a07fd2Sopenharmony_cibool DMicDev::IsOpened()
33850a07fd2Sopenharmony_ci{
33950a07fd2Sopenharmony_ci    return isOpened_.load();
34050a07fd2Sopenharmony_ci}
34150a07fd2Sopenharmony_ci
34250a07fd2Sopenharmony_ciint32_t DMicDev::WriteStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data)
34350a07fd2Sopenharmony_ci{
34450a07fd2Sopenharmony_ci    (void)streamId;
34550a07fd2Sopenharmony_ci    (void)data;
34650a07fd2Sopenharmony_ci    return DH_SUCCESS;
34750a07fd2Sopenharmony_ci}
34850a07fd2Sopenharmony_ci
34950a07fd2Sopenharmony_ciint32_t DMicDev::ReadStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data)
35050a07fd2Sopenharmony_ci{
35150a07fd2Sopenharmony_ci    int64_t startTime = GetNowTimeUs();
35250a07fd2Sopenharmony_ci    if (curStatus_ != AudioStatus::STATUS_START) {
35350a07fd2Sopenharmony_ci        DHLOGE("Distributed audio is not starting status.");
35450a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_FAILED;
35550a07fd2Sopenharmony_ci    }
35650a07fd2Sopenharmony_ci    std::lock_guard<std::mutex> lock(dataQueueMtx_);
35750a07fd2Sopenharmony_ci    uint32_t queSize = dataQueue_.size();
35850a07fd2Sopenharmony_ci    if (insertFrameCnt_ >= queSize || queSize == 0) {
35950a07fd2Sopenharmony_ci        ++insertFrameCnt_;
36050a07fd2Sopenharmony_ci        isExistedEmpty_.store(true);
36150a07fd2Sopenharmony_ci        DHLOGD("Data queue is empty, count :%{public}u.", insertFrameCnt_);
36250a07fd2Sopenharmony_ci        data = std::make_shared<AudioData>(param_.comParam.frameSize);
36350a07fd2Sopenharmony_ci    } else {
36450a07fd2Sopenharmony_ci        while (insertFrameCnt_ > 0) {
36550a07fd2Sopenharmony_ci            DHLOGD("Data discard, count: %{public}u", insertFrameCnt_);
36650a07fd2Sopenharmony_ci            dataQueue_.pop();
36750a07fd2Sopenharmony_ci            --insertFrameCnt_;
36850a07fd2Sopenharmony_ci        }
36950a07fd2Sopenharmony_ci        data = dataQueue_.front();
37050a07fd2Sopenharmony_ci        dataQueue_.pop();
37150a07fd2Sopenharmony_ci    }
37250a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(data, ERR_DH_AUDIO_NULLPTR);
37350a07fd2Sopenharmony_ci    DumpFileUtil::WriteDumpFile(dumpFileCommn_, static_cast<void *>(data->Data()), data->Size());
37450a07fd2Sopenharmony_ci    int64_t endTime = GetNowTimeUs();
37550a07fd2Sopenharmony_ci    if (IsOutDurationRange(startTime, endTime, lastReadStartTime_)) {
37650a07fd2Sopenharmony_ci        DHLOGE("This time read data spend: %{public}" PRId64" us, The interval of read data this time and "
37750a07fd2Sopenharmony_ci            "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastReadStartTime_);
37850a07fd2Sopenharmony_ci    }
37950a07fd2Sopenharmony_ci    lastReadStartTime_ = startTime;
38050a07fd2Sopenharmony_ci    return DH_SUCCESS;
38150a07fd2Sopenharmony_ci}
38250a07fd2Sopenharmony_ci
38350a07fd2Sopenharmony_ciint32_t DMicDev::ReadMmapPosition(const int32_t streamId, uint64_t &frames, CurrentTimeHDF &time)
38450a07fd2Sopenharmony_ci{
38550a07fd2Sopenharmony_ci    DHLOGD("Read mmap position. frames: %{public}" PRIu64", tvsec: %{public}" PRId64", tvNSec:%{public}" PRId64,
38650a07fd2Sopenharmony_ci        writeNum_, writeTvSec_, writeTvNSec_);
38750a07fd2Sopenharmony_ci    frames = writeNum_;
38850a07fd2Sopenharmony_ci    time.tvSec = writeTvSec_;
38950a07fd2Sopenharmony_ci    time.tvNSec = writeTvNSec_;
39050a07fd2Sopenharmony_ci    return DH_SUCCESS;
39150a07fd2Sopenharmony_ci}
39250a07fd2Sopenharmony_ci
39350a07fd2Sopenharmony_ciint32_t DMicDev::RefreshAshmemInfo(const int32_t streamId,
39450a07fd2Sopenharmony_ci    int32_t fd, int32_t ashmemLength, int32_t lengthPerTrans)
39550a07fd2Sopenharmony_ci{
39650a07fd2Sopenharmony_ci    DHLOGD("RefreshAshmemInfo: fd:%{public}d, ashmemLength: %{public}d, lengthPerTrans: %{public}d",
39750a07fd2Sopenharmony_ci        fd, ashmemLength, lengthPerTrans);
39850a07fd2Sopenharmony_ci    if (param_.captureOpts.capturerFlags == MMAP_MODE) {
39950a07fd2Sopenharmony_ci        DHLOGD("DMic dev low-latency mode");
40050a07fd2Sopenharmony_ci        if (ashmem_ != nullptr) {
40150a07fd2Sopenharmony_ci            return DH_SUCCESS;
40250a07fd2Sopenharmony_ci        }
40350a07fd2Sopenharmony_ci        if (ashmemLength < ASHMEM_MAX_LEN) {
40450a07fd2Sopenharmony_ci            ashmem_ = sptr<Ashmem>(new Ashmem(fd, ashmemLength));
40550a07fd2Sopenharmony_ci            ashmemLength_ = ashmemLength;
40650a07fd2Sopenharmony_ci            lengthPerTrans_ = lengthPerTrans;
40750a07fd2Sopenharmony_ci            DHLOGD("Create ashmem success. fd:%{public}d, ashmem length: %{public}d, lengthPreTrans: %{public}d",
40850a07fd2Sopenharmony_ci                fd, ashmemLength_, lengthPerTrans_);
40950a07fd2Sopenharmony_ci            bool mapRet = ashmem_->MapReadAndWriteAshmem();
41050a07fd2Sopenharmony_ci            if (!mapRet) {
41150a07fd2Sopenharmony_ci                DHLOGE("Mmap ashmem failed.");
41250a07fd2Sopenharmony_ci                return ERR_DH_AUDIO_NULLPTR;
41350a07fd2Sopenharmony_ci            }
41450a07fd2Sopenharmony_ci        }
41550a07fd2Sopenharmony_ci    }
41650a07fd2Sopenharmony_ci    return DH_SUCCESS;
41750a07fd2Sopenharmony_ci}
41850a07fd2Sopenharmony_ci
41950a07fd2Sopenharmony_ciint32_t DMicDev::MmapStart()
42050a07fd2Sopenharmony_ci{
42150a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(ashmem_, ERR_DH_AUDIO_NULLPTR);
42250a07fd2Sopenharmony_ci    std::lock_guard<std::mutex> lock(writeAshmemMutex_);
42350a07fd2Sopenharmony_ci    frameIndex_ = 0;
42450a07fd2Sopenharmony_ci    startTime_ = 0;
42550a07fd2Sopenharmony_ci    isEnqueueRunning_.store(true);
42650a07fd2Sopenharmony_ci    enqueueDataThread_ = std::thread([this]() { this->EnqueueThread(); });
42750a07fd2Sopenharmony_ci    if (pthread_setname_np(enqueueDataThread_.native_handle(), ENQUEUE_THREAD) != DH_SUCCESS) {
42850a07fd2Sopenharmony_ci        DHLOGE("Enqueue data thread setname failed.");
42950a07fd2Sopenharmony_ci    }
43050a07fd2Sopenharmony_ci    return DH_SUCCESS;
43150a07fd2Sopenharmony_ci}
43250a07fd2Sopenharmony_ci
43350a07fd2Sopenharmony_civoid DMicDev::EnqueueThread()
43450a07fd2Sopenharmony_ci{
43550a07fd2Sopenharmony_ci    writeIndex_ = 0;
43650a07fd2Sopenharmony_ci    writeNum_ = 0;
43750a07fd2Sopenharmony_ci    int64_t timeIntervalns = static_cast<int64_t>(paramHDF_.period * AUDIO_NS_PER_SECOND / AUDIO_MS_PER_SECOND);
43850a07fd2Sopenharmony_ci    DHLOGD("Enqueue thread start, lengthPerWrite length: %{public}d, interval: %{public}d.", lengthPerTrans_,
43950a07fd2Sopenharmony_ci        paramHDF_.period);
44050a07fd2Sopenharmony_ci    FillJitterQueue();
44150a07fd2Sopenharmony_ci    while (ashmem_ != nullptr && isEnqueueRunning_.load()) {
44250a07fd2Sopenharmony_ci        int64_t timeOffset = UpdateTimeOffset(frameIndex_, timeIntervalns, startTime_);
44350a07fd2Sopenharmony_ci        DHLOGD("Write frameIndex: %{public}" PRId64", timeOffset: %{public}" PRId64, frameIndex_, timeOffset);
44450a07fd2Sopenharmony_ci        std::shared_ptr<AudioData> audioData = nullptr;
44550a07fd2Sopenharmony_ci        {
44650a07fd2Sopenharmony_ci            std::lock_guard<std::mutex> lock(dataQueueMtx_);
44750a07fd2Sopenharmony_ci            if (dataQueue_.empty()) {
44850a07fd2Sopenharmony_ci                DHLOGD("Data queue is Empty.");
44950a07fd2Sopenharmony_ci                audioData = std::make_shared<AudioData>(param_.comParam.frameSize);
45050a07fd2Sopenharmony_ci            } else {
45150a07fd2Sopenharmony_ci                audioData = dataQueue_.front();
45250a07fd2Sopenharmony_ci                dataQueue_.pop();
45350a07fd2Sopenharmony_ci            }
45450a07fd2Sopenharmony_ci            if (audioData == nullptr) {
45550a07fd2Sopenharmony_ci                DHLOGD("The audioData is nullptr.");
45650a07fd2Sopenharmony_ci                continue;
45750a07fd2Sopenharmony_ci            }
45850a07fd2Sopenharmony_ci            DumpFileUtil::WriteDumpFile(dumpFileFast_, static_cast<void *>(audioData->Data()), audioData->Size());
45950a07fd2Sopenharmony_ci            bool writeRet = ashmem_->WriteToAshmem(audioData->Data(), audioData->Size(), writeIndex_);
46050a07fd2Sopenharmony_ci            if (writeRet) {
46150a07fd2Sopenharmony_ci                DHLOGD("Write to ashmem success! write index: %{public}d, writeLength: %{public}d.",
46250a07fd2Sopenharmony_ci                    writeIndex_, lengthPerTrans_);
46350a07fd2Sopenharmony_ci            } else {
46450a07fd2Sopenharmony_ci                DHLOGE("Write data to ashmem failed.");
46550a07fd2Sopenharmony_ci            }
46650a07fd2Sopenharmony_ci        }
46750a07fd2Sopenharmony_ci        writeIndex_ += lengthPerTrans_;
46850a07fd2Sopenharmony_ci        if (writeIndex_ >= ashmemLength_) {
46950a07fd2Sopenharmony_ci            writeIndex_ = 0;
47050a07fd2Sopenharmony_ci        }
47150a07fd2Sopenharmony_ci        writeNum_ += static_cast<uint64_t>(CalculateSampleNum(param_.comParam.sampleRate, paramHDF_.period));
47250a07fd2Sopenharmony_ci        GetCurrentTime(writeTvSec_, writeTvNSec_);
47350a07fd2Sopenharmony_ci        frameIndex_++;
47450a07fd2Sopenharmony_ci        AbsoluteSleep(startTime_ + frameIndex_ * timeIntervalns - timeOffset);
47550a07fd2Sopenharmony_ci    }
47650a07fd2Sopenharmony_ci}
47750a07fd2Sopenharmony_ci
47850a07fd2Sopenharmony_civoid DMicDev::FillJitterQueue()
47950a07fd2Sopenharmony_ci{
48050a07fd2Sopenharmony_ci    while (isEnqueueRunning_.load()) {
48150a07fd2Sopenharmony_ci        {
48250a07fd2Sopenharmony_ci            std::lock_guard<std::mutex> lock(dataQueueMtx_);
48350a07fd2Sopenharmony_ci            if (dataQueue_.size() >= (LOW_LATENCY_JITTER_TIME_MS / paramHDF_.period)) {
48450a07fd2Sopenharmony_ci                break;
48550a07fd2Sopenharmony_ci            }
48650a07fd2Sopenharmony_ci        }
48750a07fd2Sopenharmony_ci        usleep(MMAP_WAIT_FRAME_US);
48850a07fd2Sopenharmony_ci    }
48950a07fd2Sopenharmony_ci    DHLOGD("Mic jitter data queue fill end.");
49050a07fd2Sopenharmony_ci}
49150a07fd2Sopenharmony_ci
49250a07fd2Sopenharmony_ciint32_t DMicDev::MmapStop()
49350a07fd2Sopenharmony_ci{
49450a07fd2Sopenharmony_ci    std::lock_guard<std::mutex> lock(writeAshmemMutex_);
49550a07fd2Sopenharmony_ci    isEnqueueRunning_.store(false);
49650a07fd2Sopenharmony_ci    if (enqueueDataThread_.joinable()) {
49750a07fd2Sopenharmony_ci        enqueueDataThread_.join();
49850a07fd2Sopenharmony_ci    }
49950a07fd2Sopenharmony_ci    DHLOGI("Mic mmap stop end.");
50050a07fd2Sopenharmony_ci    return DH_SUCCESS;
50150a07fd2Sopenharmony_ci}
50250a07fd2Sopenharmony_ci
50350a07fd2Sopenharmony_ciAudioParam DMicDev::GetAudioParam() const
50450a07fd2Sopenharmony_ci{
50550a07fd2Sopenharmony_ci    return param_;
50650a07fd2Sopenharmony_ci}
50750a07fd2Sopenharmony_ci
50850a07fd2Sopenharmony_ciint32_t DMicDev::NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId)
50950a07fd2Sopenharmony_ci{
51050a07fd2Sopenharmony_ci    int32_t ret = DAudioHdiHandler::GetInstance().NotifyEvent(devId_, portId, streamId_, event);
51150a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
51250a07fd2Sopenharmony_ci        DHLOGE("Notify event: %{public}d, result: %{public}s, streamId: %{public}d.",
51350a07fd2Sopenharmony_ci            event.type, event.content.c_str(), streamId_);
51450a07fd2Sopenharmony_ci    }
51550a07fd2Sopenharmony_ci    return DH_SUCCESS;
51650a07fd2Sopenharmony_ci}
51750a07fd2Sopenharmony_ci
51850a07fd2Sopenharmony_ciint32_t DMicDev::OnStateChange(const AudioEventType type)
51950a07fd2Sopenharmony_ci{
52050a07fd2Sopenharmony_ci    DHLOGD("On mic device state change, type: %{public}d", type);
52150a07fd2Sopenharmony_ci    AudioEvent event;
52250a07fd2Sopenharmony_ci    switch (type) {
52350a07fd2Sopenharmony_ci        case AudioEventType::DATA_OPENED:
52450a07fd2Sopenharmony_ci            isTransReady_.store(true);
52550a07fd2Sopenharmony_ci            channelWaitCond_.notify_one();
52650a07fd2Sopenharmony_ci            event.type = AudioEventType::MIC_OPENED;
52750a07fd2Sopenharmony_ci            break;
52850a07fd2Sopenharmony_ci        case AudioEventType::DATA_CLOSED:
52950a07fd2Sopenharmony_ci            isTransReady_.store(false);
53050a07fd2Sopenharmony_ci            event.type = AudioEventType::MIC_CLOSED;
53150a07fd2Sopenharmony_ci            break;
53250a07fd2Sopenharmony_ci        default:
53350a07fd2Sopenharmony_ci            break;
53450a07fd2Sopenharmony_ci    }
53550a07fd2Sopenharmony_ci    event.content = GetCJsonString(KEY_DH_ID, std::to_string(dhId_).c_str());
53650a07fd2Sopenharmony_ci    std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
53750a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
53850a07fd2Sopenharmony_ci    cbObj->NotifyEvent(event);
53950a07fd2Sopenharmony_ci    return DH_SUCCESS;
54050a07fd2Sopenharmony_ci}
54150a07fd2Sopenharmony_ci
54250a07fd2Sopenharmony_ciint32_t DMicDev::SendMessage(uint32_t type, std::string content, std::string dstDevId)
54350a07fd2Sopenharmony_ci{
54450a07fd2Sopenharmony_ci    DHLOGD("Send message to remote.");
54550a07fd2Sopenharmony_ci    if (type != static_cast<uint32_t>(OPEN_MIC) && type != static_cast<uint32_t>(CLOSE_MIC)) {
54650a07fd2Sopenharmony_ci        DHLOGE("Send message to remote. not OPEN_MIC or CLOSE_MIC. type: %{public}u", type);
54750a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_NULLPTR;
54850a07fd2Sopenharmony_ci    }
54950a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR);
55050a07fd2Sopenharmony_ci    micTrans_->SendMessage(type, content, dstDevId);
55150a07fd2Sopenharmony_ci    return DH_SUCCESS;
55250a07fd2Sopenharmony_ci}
55350a07fd2Sopenharmony_ci
55450a07fd2Sopenharmony_ciint32_t DMicDev::OnDecodeTransDataDone(const std::shared_ptr<AudioData> &audioData)
55550a07fd2Sopenharmony_ci{
55650a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(audioData, ERR_DH_AUDIO_NULLPTR);
55750a07fd2Sopenharmony_ci    std::lock_guard<std::mutex> lock(dataQueueMtx_);
55850a07fd2Sopenharmony_ci    dataQueSize_ = curStatus_ != AudioStatus::STATUS_START ?
55950a07fd2Sopenharmony_ci        (param_.captureOpts.capturerFlags == MMAP_MODE ? lowLatencyHalfSize_ : DATA_QUEUE_HALF_SIZE) :
56050a07fd2Sopenharmony_ci        (param_.captureOpts.capturerFlags == MMAP_MODE ? lowLatencyMaxfSize_ : DATA_QUEUE_MAX_SIZE);
56150a07fd2Sopenharmony_ci    if (isExistedEmpty_.load()) {
56250a07fd2Sopenharmony_ci        dataQueSize_ = param_.captureOpts.capturerFlags == MMAP_MODE ? dataQueSize_ : DATA_QUEUE_EXT_SIZE;
56350a07fd2Sopenharmony_ci    }
56450a07fd2Sopenharmony_ci    uint64_t queueSize;
56550a07fd2Sopenharmony_ci    while (dataQueue_.size() > dataQueSize_) {
56650a07fd2Sopenharmony_ci        queueSize = static_cast<uint64_t>(dataQueue_.size());
56750a07fd2Sopenharmony_ci        DHLOGD("Data queue overflow. buf current size: %{public}" PRIu64, queueSize);
56850a07fd2Sopenharmony_ci        dataQueue_.pop();
56950a07fd2Sopenharmony_ci    }
57050a07fd2Sopenharmony_ci    dataQueue_.push(audioData);
57150a07fd2Sopenharmony_ci    queueSize = static_cast<uint64_t>(dataQueue_.size());
57250a07fd2Sopenharmony_ci    DHLOGD("Push new mic data, buf len: %{public}" PRIu64, queueSize);
57350a07fd2Sopenharmony_ci    return DH_SUCCESS;
57450a07fd2Sopenharmony_ci}
57550a07fd2Sopenharmony_ci} // DistributedHardware
57650a07fd2Sopenharmony_ci} // OHOS
577