1 /*
2  * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "dmic_dev.h"
17 
18 #include <condition_variable>
19 #include <mutex>
20 #include <string>
21 #include <thread>
22 
23 #include "daudio_constants.h"
24 #include "daudio_errorcode.h"
25 #include "daudio_hidumper.h"
26 #include "daudio_hisysevent.h"
27 #include "daudio_hitrace.h"
28 #include "daudio_log.h"
29 #include "daudio_source_manager.h"
30 #include "daudio_util.h"
31 
32 #undef DH_LOG_TAG
33 #define DH_LOG_TAG "DMicDev"
34 
35 namespace OHOS {
36 namespace DistributedHardware {
37 static constexpr size_t DATA_QUEUE_EXT_SIZE = 20;
OnEngineTransEvent(const AVTransEvent & event)38 void DMicDev::OnEngineTransEvent(const AVTransEvent &event)
39 {
40     if (event.type == EventType::EVENT_START_SUCCESS) {
41         OnStateChange(DATA_OPENED);
42     } else if ((event.type == EventType::EVENT_STOP_SUCCESS) ||
43         (event.type == EventType::EVENT_CHANNEL_CLOSED) ||
44         (event.type == EventType::EVENT_START_FAIL)) {
45         OnStateChange(DATA_CLOSED);
46     }
47 }
48 
OnEngineTransMessage(const std::shared_ptr<AVTransMessage> & message)49 void DMicDev::OnEngineTransMessage(const std::shared_ptr<AVTransMessage> &message)
50 {
51     CHECK_NULL_VOID(message);
52     DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str());
53     DAudioSourceManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_,
54         message->type_, message->content_);
55 }
56 
OnEngineTransDataAvailable(const std::shared_ptr<AudioData> & audioData)57 void DMicDev::OnEngineTransDataAvailable(const std::shared_ptr<AudioData> &audioData)
58 {
59     DHLOGD("On Engine Data available");
60     if (echoCannelOn_) {
61 #ifdef ECHO_CANNEL_ENABLE
62         if (echoManager_ == nullptr) {
63             DHLOGE("Echo manager is nullptr.");
64             return;
65         }
66         echoManager_->OnMicDataReceived(audioData);
67 #endif
68     } else {
69         OnDecodeTransDataDone(audioData);
70     }
71 }
72 
InitReceiverEngine(IAVEngineProvider * providerPtr)73 int32_t DMicDev::InitReceiverEngine(IAVEngineProvider *providerPtr)
74 {
75     DHLOGI("InitReceiverEngine enter.");
76     if (micTrans_ == nullptr) {
77         micTrans_ = std::make_shared<AVTransReceiverTransport>(devId_, shared_from_this());
78     }
79     int32_t ret = micTrans_->InitEngine(providerPtr);
80     if (ret != DH_SUCCESS) {
81         DHLOGE("Mic dev initialize av receiver adapter failed.");
82         return ret;
83     }
84     ret = micTrans_->CreateCtrl();
85     if (ret != DH_SUCCESS) {
86         DHLOGE("Create ctrl channel failed. micdev");
87         return ret;
88     }
89     return DH_SUCCESS;
90 }
91 
InitSenderEngine(IAVEngineProvider * providerPtr)92 int32_t DMicDev::InitSenderEngine(IAVEngineProvider *providerPtr)
93 {
94     DHLOGI("InitReceiverEngine enter.");
95     return DH_SUCCESS;
96 }
97 
EnableDevice(const int32_t dhId,const std::string & capability)98 int32_t DMicDev::EnableDevice(const int32_t dhId, const std::string &capability)
99 {
100     DHLOGI("Enable IO device, device pin: %{public}d.", dhId);
101     int32_t ret = DAudioHdiHandler::GetInstance().RegisterAudioDevice(devId_, dhId, capability, shared_from_this());
102     if (ret != DH_SUCCESS) {
103         DHLOGE("Register device failed, ret: %{public}d.", ret);
104         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_REGISTER_FAIL, devId_, std::to_string(dhId), ret,
105             "daudio register device failed.");
106         return ret;
107     }
108     dhId_ = dhId;
109     return DH_SUCCESS;
110 }
111 
DisableDevice(const int32_t dhId)112 int32_t DMicDev::DisableDevice(const int32_t dhId)
113 {
114     DHLOGI("Disable IO device, device pin: %{public}d.", dhId);
115     int32_t ret = DAudioHdiHandler::GetInstance().UnRegisterAudioDevice(devId_, dhId);
116     if (ret != DH_SUCCESS) {
117         DHLOGE("UnRegister failed, ret: %{public}d.", ret);
118         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_UNREGISTER_FAIL, devId_, std::to_string(dhId), ret,
119             "daudio unregister device failed.");
120         return ret;
121     }
122     return DH_SUCCESS;
123 }
124 
CreateStream(const int32_t streamId)125 int32_t DMicDev::CreateStream(const int32_t streamId)
126 {
127     DHLOGI("Open stream of mic device streamId: %{public}d.", streamId);
128     std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
129     CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
130 
131     cJSON *jParam = cJSON_CreateObject();
132     CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR);
133     cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
134     char *jsonData = cJSON_PrintUnformatted(jParam);
135     if (jsonData == nullptr) {
136         cJSON_Delete(jParam);
137         DHLOGE("Failed to create JSON data.");
138         return ERR_DH_AUDIO_NULLPTR;
139     }
140     std::string jsonDataStr(jsonData);
141     AudioEvent event(AudioEventType::OPEN_MIC, jsonDataStr);
142     cbObj->NotifyEvent(event);
143     DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_OPEN, devId_, std::to_string(dhId_),
144         "daudio mic device open success.");
145     streamId_ = streamId;
146     cJSON_Delete(jParam);
147     cJSON_free(jsonData);
148     return DH_SUCCESS;
149 }
150 
DestroyStream(const int32_t streamId)151 int32_t DMicDev::DestroyStream(const int32_t streamId)
152 {
153     DHLOGI("Close stream of mic device streamId: %{public}d.", streamId);
154     std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
155     CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
156 
157     cJSON *jParam = cJSON_CreateObject();
158     CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR);
159     cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
160     char *jsonData = cJSON_PrintUnformatted(jParam);
161     if (jsonData == nullptr) {
162         cJSON_Delete(jParam);
163         DHLOGE("Failed to create JSON data.");
164         return ERR_DH_AUDIO_NULLPTR;
165     }
166     std::string jsonDataStr(jsonData);
167     AudioEvent event(AudioEventType::CLOSE_MIC, jsonDataStr);
168     cbObj->NotifyEvent(event);
169     DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_CLOSE, devId_, std::to_string(dhId_),
170         "daudio mic device close success.");
171     cJSON_Delete(jParam);
172     cJSON_free(jsonData);
173     curPort_ = 0;
174     return DH_SUCCESS;
175 }
176 
SetParameters(const int32_t streamId,const AudioParamHDF & param)177 int32_t DMicDev::SetParameters(const int32_t streamId, const AudioParamHDF &param)
178 {
179     DHLOGD("Set mic parameters {samplerate: %{public}d, channelmask: %{public}d, format: %{public}d, "
180         "period: %{public}d, framesize: %{public}d, ext{%{public}s}}.", param.sampleRate,
181         param.channelMask, param.bitFormat, param.period, param.frameSize, param.ext.c_str());
182     if (param.capturerFlags == MMAP_MODE && param.period != MMAP_NORMAL_PERIOD && param.period != MMAP_VOIP_PERIOD) {
183         DHLOGE("The period is invalid : %{public}" PRIu32, param.period);
184         return ERR_DH_AUDIO_SA_PARAM_INVALID;
185     }
186     curPort_ = dhId_;
187     paramHDF_ = param;
188 
189     param_.comParam.sampleRate = paramHDF_.sampleRate;
190     param_.comParam.channelMask = paramHDF_.channelMask;
191     param_.comParam.bitFormat = paramHDF_.bitFormat;
192     param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC;
193     param_.comParam.frameSize = paramHDF_.frameSize;
194     if (paramHDF_.streamUsage == StreamUsage::STREAM_USAGE_VOICE_COMMUNICATION) {
195         param_.captureOpts.sourceType = SOURCE_TYPE_VOICE_COMMUNICATION;
196     } else {
197         param_.captureOpts.sourceType = SOURCE_TYPE_MIC;
198     }
199     param_.captureOpts.capturerFlags = paramHDF_.capturerFlags;
200     if (paramHDF_.capturerFlags == MMAP_MODE) {
201         lowLatencyHalfSize_ = LOW_LATENCY_JITTER_TIME_MS / paramHDF_.period;
202         lowLatencyMaxfSize_ = LOW_LATENCY_JITTER_MAX_TIME_MS / paramHDF_.period;
203     }
204     return DH_SUCCESS;
205 }
206 
NotifyEvent(const int32_t streamId,const AudioEvent & event)207 int32_t DMicDev::NotifyEvent(const int32_t streamId, const AudioEvent &event)
208 {
209     DHLOGD("Notify mic event, type: %{public}d.", event.type);
210     std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
211     CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
212     switch (event.type) {
213         case AudioEventType::AUDIO_START:
214             curStatus_ = AudioStatus::STATUS_START;
215             isExistedEmpty_.store(false);
216             break;
217         case AudioEventType::AUDIO_STOP:
218             curStatus_ = AudioStatus::STATUS_STOP;
219             isExistedEmpty_.store(false);
220             break;
221         default:
222             break;
223     }
224     AudioEvent audioEvent(event.type, event.content);
225     cbObj->NotifyEvent(audioEvent);
226     return DH_SUCCESS;
227 }
228 
SetUp()229 int32_t DMicDev::SetUp()
230 {
231     DHLOGI("Set up mic device.");
232     CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR);
233     int32_t ret = micTrans_->SetUp(param_, param_, shared_from_this(), CAP_MIC);
234     if (ret != DH_SUCCESS) {
235         DHLOGE("Mic trans set up failed. ret: %{public}d.", ret);
236         return ret;
237     }
238     echoCannelOn_ = true;
239 #ifdef ECHO_CANNEL_ENABLE
240     if (echoCannelOn_ && echoManager_ == nullptr) {
241         echoManager_ = std::make_shared<DAudioEchoCannelManager>();
242     }
243     AudioCommonParam info;
244     info.sampleRate = param_.comParam.sampleRate;
245     info.channelMask = param_.comParam.channelMask;
246     info.bitFormat = param_.comParam.bitFormat;
247     info.frameSize = param_.comParam.frameSize;
248     if (echoManager_ != nullptr) {
249         echoManager_->SetUp(info, shared_from_this());
250     }
251 #endif
252     DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, DUMP_DAUDIO_MIC_READ_FROM_BUF_NAME, &dumpFileCommn_);
253     DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, DUMP_DAUDIO_LOWLATENCY_MIC_FROM_BUF_NAME, &dumpFileFast_);
254     return DH_SUCCESS;
255 }
256 
Start()257 int32_t DMicDev::Start()
258 {
259     DHLOGI("Start mic device.");
260     CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR);
261     int32_t ret = micTrans_->Start();
262     if (ret != DH_SUCCESS) {
263         DHLOGE("Mic trans start failed, ret: %{public}d.", ret);
264         return ret;
265     }
266     std::unique_lock<std::mutex> lck(channelWaitMutex_);
267     auto status = channelWaitCond_.wait_for(lck, std::chrono::seconds(CHANNEL_WAIT_SECONDS),
268         [this]() { return isTransReady_.load(); });
269     if (!status) {
270         DHLOGE("Wait channel open timeout(%{public}ds).", CHANNEL_WAIT_SECONDS);
271         return ERR_DH_AUDIO_SA_WAIT_TIMEOUT;
272     }
273     isOpened_.store(true);
274     return DH_SUCCESS;
275 }
276 
Pause()277 int32_t DMicDev::Pause()
278 {
279     DHLOGI("Not support.");
280     return DH_SUCCESS;
281 }
282 
Restart()283 int32_t DMicDev::Restart()
284 {
285     DHLOGI("Not surpport.");
286     return DH_SUCCESS;
287 }
288 
Stop()289 int32_t DMicDev::Stop()
290 {
291     DHLOGI("Stop mic device.");
292     CHECK_NULL_RETURN(micTrans_, DH_SUCCESS);
293     isOpened_.store(false);
294     isTransReady_.store(false);
295     int32_t ret = micTrans_->Stop();
296     if (ret != DH_SUCCESS) {
297         DHLOGE("Stop mic trans failed, ret: %{public}d.", ret);
298     }
299 #ifdef ECHO_CANNEL_ENABLE
300     CHECK_NULL_RETURN(echoManager_, DH_SUCCESS);
301     ret = echoManager_->Stop();
302     if (ret != DH_SUCCESS) {
303         DHLOGE("Echo manager stop failed. ret: %{public}d.", ret);
304         return ret;
305     }
306 #endif
307     return DH_SUCCESS;
308 }
309 
Release()310 int32_t DMicDev::Release()
311 {
312     DHLOGI("Release mic device.");
313     if (ashmem_ != nullptr) {
314         ashmem_->UnmapAshmem();
315         ashmem_->CloseAshmem();
316         ashmem_ = nullptr;
317         DHLOGI("UnInit ashmem success.");
318     }
319     CHECK_NULL_RETURN(micTrans_, DH_SUCCESS);
320 
321     int32_t ret = micTrans_->Release();
322     if (ret != DH_SUCCESS) {
323         DHLOGE("Release mic trans failed, ret: %{public}d.", ret);
324         return ret;
325     }
326 #ifdef ECHO_CANNEL_ENABLE
327     if (echoManager_ != nullptr) {
328         echoManager_->Release();
329         echoManager_ = nullptr;
330     }
331 #endif
332     DumpFileUtil::CloseDumpFile(&dumpFileCommn_);
333     DumpFileUtil::CloseDumpFile(&dumpFileFast_);
334     return DH_SUCCESS;
335 }
336 
IsOpened()337 bool DMicDev::IsOpened()
338 {
339     return isOpened_.load();
340 }
341 
WriteStreamData(const int32_t streamId,std::shared_ptr<AudioData> & data)342 int32_t DMicDev::WriteStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data)
343 {
344     (void)streamId;
345     (void)data;
346     return DH_SUCCESS;
347 }
348 
ReadStreamData(const int32_t streamId,std::shared_ptr<AudioData> & data)349 int32_t DMicDev::ReadStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data)
350 {
351     int64_t startTime = GetNowTimeUs();
352     if (curStatus_ != AudioStatus::STATUS_START) {
353         DHLOGE("Distributed audio is not starting status.");
354         return ERR_DH_AUDIO_FAILED;
355     }
356     std::lock_guard<std::mutex> lock(dataQueueMtx_);
357     uint32_t queSize = dataQueue_.size();
358     if (insertFrameCnt_ >= queSize || queSize == 0) {
359         ++insertFrameCnt_;
360         isExistedEmpty_.store(true);
361         DHLOGD("Data queue is empty, count :%{public}u.", insertFrameCnt_);
362         data = std::make_shared<AudioData>(param_.comParam.frameSize);
363     } else {
364         while (insertFrameCnt_ > 0) {
365             DHLOGD("Data discard, count: %{public}u", insertFrameCnt_);
366             dataQueue_.pop();
367             --insertFrameCnt_;
368         }
369         data = dataQueue_.front();
370         dataQueue_.pop();
371     }
372     CHECK_NULL_RETURN(data, ERR_DH_AUDIO_NULLPTR);
373     DumpFileUtil::WriteDumpFile(dumpFileCommn_, static_cast<void *>(data->Data()), data->Size());
374     int64_t endTime = GetNowTimeUs();
375     if (IsOutDurationRange(startTime, endTime, lastReadStartTime_)) {
376         DHLOGE("This time read data spend: %{public}" PRId64" us, The interval of read data this time and "
377             "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastReadStartTime_);
378     }
379     lastReadStartTime_ = startTime;
380     return DH_SUCCESS;
381 }
382 
ReadMmapPosition(const int32_t streamId,uint64_t & frames,CurrentTimeHDF & time)383 int32_t DMicDev::ReadMmapPosition(const int32_t streamId, uint64_t &frames, CurrentTimeHDF &time)
384 {
385     DHLOGD("Read mmap position. frames: %{public}" PRIu64", tvsec: %{public}" PRId64", tvNSec:%{public}" PRId64,
386         writeNum_, writeTvSec_, writeTvNSec_);
387     frames = writeNum_;
388     time.tvSec = writeTvSec_;
389     time.tvNSec = writeTvNSec_;
390     return DH_SUCCESS;
391 }
392 
RefreshAshmemInfo(const int32_t streamId,int32_t fd,int32_t ashmemLength,int32_t lengthPerTrans)393 int32_t DMicDev::RefreshAshmemInfo(const int32_t streamId,
394     int32_t fd, int32_t ashmemLength, int32_t lengthPerTrans)
395 {
396     DHLOGD("RefreshAshmemInfo: fd:%{public}d, ashmemLength: %{public}d, lengthPerTrans: %{public}d",
397         fd, ashmemLength, lengthPerTrans);
398     if (param_.captureOpts.capturerFlags == MMAP_MODE) {
399         DHLOGD("DMic dev low-latency mode");
400         if (ashmem_ != nullptr) {
401             return DH_SUCCESS;
402         }
403         if (ashmemLength < ASHMEM_MAX_LEN) {
404             ashmem_ = sptr<Ashmem>(new Ashmem(fd, ashmemLength));
405             ashmemLength_ = ashmemLength;
406             lengthPerTrans_ = lengthPerTrans;
407             DHLOGD("Create ashmem success. fd:%{public}d, ashmem length: %{public}d, lengthPreTrans: %{public}d",
408                 fd, ashmemLength_, lengthPerTrans_);
409             bool mapRet = ashmem_->MapReadAndWriteAshmem();
410             if (!mapRet) {
411                 DHLOGE("Mmap ashmem failed.");
412                 return ERR_DH_AUDIO_NULLPTR;
413             }
414         }
415     }
416     return DH_SUCCESS;
417 }
418 
MmapStart()419 int32_t DMicDev::MmapStart()
420 {
421     CHECK_NULL_RETURN(ashmem_, ERR_DH_AUDIO_NULLPTR);
422     std::lock_guard<std::mutex> lock(writeAshmemMutex_);
423     frameIndex_ = 0;
424     startTime_ = 0;
425     isEnqueueRunning_.store(true);
426     enqueueDataThread_ = std::thread([this]() { this->EnqueueThread(); });
427     if (pthread_setname_np(enqueueDataThread_.native_handle(), ENQUEUE_THREAD) != DH_SUCCESS) {
428         DHLOGE("Enqueue data thread setname failed.");
429     }
430     return DH_SUCCESS;
431 }
432 
EnqueueThread()433 void DMicDev::EnqueueThread()
434 {
435     writeIndex_ = 0;
436     writeNum_ = 0;
437     int64_t timeIntervalns = static_cast<int64_t>(paramHDF_.period * AUDIO_NS_PER_SECOND / AUDIO_MS_PER_SECOND);
438     DHLOGD("Enqueue thread start, lengthPerWrite length: %{public}d, interval: %{public}d.", lengthPerTrans_,
439         paramHDF_.period);
440     FillJitterQueue();
441     while (ashmem_ != nullptr && isEnqueueRunning_.load()) {
442         int64_t timeOffset = UpdateTimeOffset(frameIndex_, timeIntervalns, startTime_);
443         DHLOGD("Write frameIndex: %{public}" PRId64", timeOffset: %{public}" PRId64, frameIndex_, timeOffset);
444         std::shared_ptr<AudioData> audioData = nullptr;
445         {
446             std::lock_guard<std::mutex> lock(dataQueueMtx_);
447             if (dataQueue_.empty()) {
448                 DHLOGD("Data queue is Empty.");
449                 audioData = std::make_shared<AudioData>(param_.comParam.frameSize);
450             } else {
451                 audioData = dataQueue_.front();
452                 dataQueue_.pop();
453             }
454             if (audioData == nullptr) {
455                 DHLOGD("The audioData is nullptr.");
456                 continue;
457             }
458             DumpFileUtil::WriteDumpFile(dumpFileFast_, static_cast<void *>(audioData->Data()), audioData->Size());
459             bool writeRet = ashmem_->WriteToAshmem(audioData->Data(), audioData->Size(), writeIndex_);
460             if (writeRet) {
461                 DHLOGD("Write to ashmem success! write index: %{public}d, writeLength: %{public}d.",
462                     writeIndex_, lengthPerTrans_);
463             } else {
464                 DHLOGE("Write data to ashmem failed.");
465             }
466         }
467         writeIndex_ += lengthPerTrans_;
468         if (writeIndex_ >= ashmemLength_) {
469             writeIndex_ = 0;
470         }
471         writeNum_ += static_cast<uint64_t>(CalculateSampleNum(param_.comParam.sampleRate, paramHDF_.period));
472         GetCurrentTime(writeTvSec_, writeTvNSec_);
473         frameIndex_++;
474         AbsoluteSleep(startTime_ + frameIndex_ * timeIntervalns - timeOffset);
475     }
476 }
477 
FillJitterQueue()478 void DMicDev::FillJitterQueue()
479 {
480     while (isEnqueueRunning_.load()) {
481         {
482             std::lock_guard<std::mutex> lock(dataQueueMtx_);
483             if (dataQueue_.size() >= (LOW_LATENCY_JITTER_TIME_MS / paramHDF_.period)) {
484                 break;
485             }
486         }
487         usleep(MMAP_WAIT_FRAME_US);
488     }
489     DHLOGD("Mic jitter data queue fill end.");
490 }
491 
MmapStop()492 int32_t DMicDev::MmapStop()
493 {
494     std::lock_guard<std::mutex> lock(writeAshmemMutex_);
495     isEnqueueRunning_.store(false);
496     if (enqueueDataThread_.joinable()) {
497         enqueueDataThread_.join();
498     }
499     DHLOGI("Mic mmap stop end.");
500     return DH_SUCCESS;
501 }
502 
GetAudioParam() const503 AudioParam DMicDev::GetAudioParam() const
504 {
505     return param_;
506 }
507 
NotifyHdfAudioEvent(const AudioEvent & event,const int32_t portId)508 int32_t DMicDev::NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId)
509 {
510     int32_t ret = DAudioHdiHandler::GetInstance().NotifyEvent(devId_, portId, streamId_, event);
511     if (ret != DH_SUCCESS) {
512         DHLOGE("Notify event: %{public}d, result: %{public}s, streamId: %{public}d.",
513             event.type, event.content.c_str(), streamId_);
514     }
515     return DH_SUCCESS;
516 }
517 
OnStateChange(const AudioEventType type)518 int32_t DMicDev::OnStateChange(const AudioEventType type)
519 {
520     DHLOGD("On mic device state change, type: %{public}d", type);
521     AudioEvent event;
522     switch (type) {
523         case AudioEventType::DATA_OPENED:
524             isTransReady_.store(true);
525             channelWaitCond_.notify_one();
526             event.type = AudioEventType::MIC_OPENED;
527             break;
528         case AudioEventType::DATA_CLOSED:
529             isTransReady_.store(false);
530             event.type = AudioEventType::MIC_CLOSED;
531             break;
532         default:
533             break;
534     }
535     event.content = GetCJsonString(KEY_DH_ID, std::to_string(dhId_).c_str());
536     std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
537     CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
538     cbObj->NotifyEvent(event);
539     return DH_SUCCESS;
540 }
541 
SendMessage(uint32_t type,std::string content,std::string dstDevId)542 int32_t DMicDev::SendMessage(uint32_t type, std::string content, std::string dstDevId)
543 {
544     DHLOGD("Send message to remote.");
545     if (type != static_cast<uint32_t>(OPEN_MIC) && type != static_cast<uint32_t>(CLOSE_MIC)) {
546         DHLOGE("Send message to remote. not OPEN_MIC or CLOSE_MIC. type: %{public}u", type);
547         return ERR_DH_AUDIO_NULLPTR;
548     }
549     CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR);
550     micTrans_->SendMessage(type, content, dstDevId);
551     return DH_SUCCESS;
552 }
553 
OnDecodeTransDataDone(const std::shared_ptr<AudioData> & audioData)554 int32_t DMicDev::OnDecodeTransDataDone(const std::shared_ptr<AudioData> &audioData)
555 {
556     CHECK_NULL_RETURN(audioData, ERR_DH_AUDIO_NULLPTR);
557     std::lock_guard<std::mutex> lock(dataQueueMtx_);
558     dataQueSize_ = curStatus_ != AudioStatus::STATUS_START ?
559         (param_.captureOpts.capturerFlags == MMAP_MODE ? lowLatencyHalfSize_ : DATA_QUEUE_HALF_SIZE) :
560         (param_.captureOpts.capturerFlags == MMAP_MODE ? lowLatencyMaxfSize_ : DATA_QUEUE_MAX_SIZE);
561     if (isExistedEmpty_.load()) {
562         dataQueSize_ = param_.captureOpts.capturerFlags == MMAP_MODE ? dataQueSize_ : DATA_QUEUE_EXT_SIZE;
563     }
564     uint64_t queueSize;
565     while (dataQueue_.size() > dataQueSize_) {
566         queueSize = static_cast<uint64_t>(dataQueue_.size());
567         DHLOGD("Data queue overflow. buf current size: %{public}" PRIu64, queueSize);
568         dataQueue_.pop();
569     }
570     dataQueue_.push(audioData);
571     queueSize = static_cast<uint64_t>(dataQueue_.size());
572     DHLOGD("Push new mic data, buf len: %{public}" PRIu64, queueSize);
573     return DH_SUCCESS;
574 }
575 } // DistributedHardware
576 } // OHOS
577