• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_radar.h"
30 #include "daudio_source_manager.h"
31 #include "daudio_util.h"
32 
33 #undef DH_LOG_TAG
34 #define DH_LOG_TAG "DMicDev"
35 
36 namespace OHOS {
37 namespace DistributedHardware {
38 static constexpr size_t DATA_QUEUE_EXT_SIZE = 20;
OnEngineTransEvent(const AVTransEvent & event)39 void DMicDev::OnEngineTransEvent(const AVTransEvent &event)
40 {
41     if (event.type == EventType::EVENT_START_SUCCESS) {
42         OnStateChange(DATA_OPENED);
43     } else if ((event.type == EventType::EVENT_STOP_SUCCESS) ||
44         (event.type == EventType::EVENT_CHANNEL_CLOSED) ||
45         (event.type == EventType::EVENT_START_FAIL)) {
46         OnStateChange(DATA_CLOSED);
47     }
48 }
49 
OnEngineTransMessage(const std::shared_ptr<AVTransMessage> & message)50 void DMicDev::OnEngineTransMessage(const std::shared_ptr<AVTransMessage> &message)
51 {
52     CHECK_NULL_VOID(message);
53     DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str());
54     DAudioSourceManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_,
55         message->type_, message->content_);
56 }
57 
OnEngineTransDataAvailable(const std::shared_ptr<AudioData> & audioData)58 void DMicDev::OnEngineTransDataAvailable(const std::shared_ptr<AudioData> &audioData)
59 {
60     std::lock_guard<std::mutex> lock(ringbufferMutex_);
61     CHECK_NULL_VOID(ringBuffer_);
62     if (ringBuffer_->RingBufferInsert(audioData->Data(), static_cast<int32_t>(audioData->Capacity())) != DH_SUCCESS) {
63         DHLOGE("Insert ringbuffer failed.");
64         return;
65     }
66     DHLOGD("ringbuffer insert one");
67 }
68 
ReadFromRingbuffer()69 void DMicDev::ReadFromRingbuffer()
70 {
71     std::shared_ptr<AudioData> sendData = std::make_shared<AudioData>(frameSize_);
72     bool canRead = false;
73     while (isRingbufferOn_.load()) {
74         CHECK_NULL_VOID(ringBuffer_);
75         canRead = false;
76         {
77             std::lock_guard<std::mutex> lock(ringbufferMutex_);
78             if (ringBuffer_->CanBufferReadLen(frameSize_)) {
79                 canRead = true;
80             }
81         }
82         if (!canRead) {
83             DHLOGD("Can not read from ringbuffer.");
84             std::this_thread::sleep_for(std::chrono::milliseconds(RINGBUFFER_WAIT_SECONDS));
85             continue;
86         }
87         {
88             std::lock_guard<std::mutex> lock(ringbufferMutex_);
89             if (ringBuffer_->RingBufferGetData(sendData->Data(), sendData->Capacity()) != DH_SUCCESS) {
90                 DHLOGE("Read ringbuffer failed.");
91                 continue;
92             }
93         }
94         SendToProcess(sendData);
95     }
96 }
97 
SendToProcess(const std::shared_ptr<AudioData> & audioData)98 void DMicDev::SendToProcess(const std::shared_ptr<AudioData> &audioData)
99 {
100     DHLOGD("On Engine Data available");
101     if (echoCannelOn_) {
102 #ifdef ECHO_CANNEL_ENABLE
103         if (echoManager_ == nullptr) {
104             DHLOGE("Echo manager is nullptr.");
105             return;
106         }
107         echoManager_->OnMicDataReceived(audioData);
108 #endif
109     } else {
110         OnDecodeTransDataDone(audioData);
111     }
112 }
113 
InitReceiverEngine(IAVEngineProvider * providerPtr)114 int32_t DMicDev::InitReceiverEngine(IAVEngineProvider *providerPtr)
115 {
116     DHLOGI("InitReceiverEngine enter.");
117     if (micTrans_ == nullptr) {
118         micTrans_ = std::make_shared<AVTransReceiverTransport>(devId_, shared_from_this());
119     }
120     int32_t ret = micTrans_->InitEngine(providerPtr);
121     if (ret != DH_SUCCESS) {
122         DHLOGE("Mic dev initialize av receiver adapter failed.");
123         return ret;
124     }
125     return DH_SUCCESS;
126 }
127 
InitSenderEngine(IAVEngineProvider * providerPtr)128 int32_t DMicDev::InitSenderEngine(IAVEngineProvider *providerPtr)
129 {
130     DHLOGI("InitReceiverEngine enter.");
131     return DH_SUCCESS;
132 }
133 
InitCtrlTrans()134 int32_t DMicDev::InitCtrlTrans()
135 {
136     DHLOGI("InitCtrlTrans enter");
137     if (micCtrlTrans_ == nullptr) {
138         micCtrlTrans_ = std::make_shared<DaudioSourceCtrlTrans>(devId_,
139             SESSIONNAME_MIC_SOURCE, SESSIONNAME_MIC_SINK, shared_from_this());
140     }
141     int32_t ret = micCtrlTrans_->SetUp(shared_from_this());
142     CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Mic ctrl SetUp failed.");
143     ret = micCtrlTrans_->Start();
144     CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Mic ctrl Start failed.");
145     return ret;
146 }
147 
OnCtrlTransEvent(const AVTransEvent & event)148 void DMicDev::OnCtrlTransEvent(const AVTransEvent &event)
149 {
150     if (event.type == EventType::EVENT_START_SUCCESS) {
151         OnStateChange(DATA_OPENED);
152     } else if ((event.type == EventType::EVENT_STOP_SUCCESS) ||
153         (event.type == EventType::EVENT_CHANNEL_CLOSED) ||
154         (event.type == EventType::EVENT_START_FAIL)) {
155         OnStateChange(DATA_CLOSED);
156     }
157 }
158 
OnCtrlTransMessage(const std::shared_ptr<AVTransMessage> & message)159 void DMicDev::OnCtrlTransMessage(const std::shared_ptr<AVTransMessage> &message)
160 {
161     CHECK_NULL_VOID(message);
162     DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str());
163     DAudioSourceManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_,
164         message->type_, message->content_);
165 }
166 
EnableDevice(const int32_t dhId,const std::string & capability)167 int32_t DMicDev::EnableDevice(const int32_t dhId, const std::string &capability)
168 {
169     DHLOGI("Enable IO device, device pin: %{public}d.", dhId);
170     int32_t ret = DAudioHdiHandler::GetInstance().RegisterAudioDevice(devId_, dhId, capability, shared_from_this());
171     if (ret != DH_SUCCESS) {
172         DHLOGE("Register device failed, ret: %{public}d.", ret);
173         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_REGISTER_FAIL, devId_, std::to_string(dhId), ret,
174             "daudio register device failed.");
175         return ret;
176     }
177     dhId_ = dhId;
178     auto pos = capability.find(SUB_PROTOCOLVER);
179     if (pos != std::string::npos) {
180         DHLOGD("ProtocolVer : 2.0");
181     } else {
182         isNeedCodec_.store(false);
183         DHLOGD("ProtocolVer : 1.0");
184     }
185     return DH_SUCCESS;
186 }
187 
DisableDevice(const int32_t dhId)188 int32_t DMicDev::DisableDevice(const int32_t dhId)
189 {
190     DHLOGI("Disable IO device, device pin: %{public}d.", dhId);
191     int32_t ret = DAudioHdiHandler::GetInstance().UnRegisterAudioDevice(devId_, dhId);
192     if (ret != DH_SUCCESS) {
193         DHLOGE("UnRegister failed, ret: %{public}d.", ret);
194         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_UNREGISTER_FAIL, devId_, std::to_string(dhId), ret,
195             "daudio unregister device failed.");
196         return ret;
197     }
198     return DH_SUCCESS;
199 }
200 
CreateStream(const int32_t streamId)201 int32_t DMicDev::CreateStream(const int32_t streamId)
202 {
203     DHLOGI("Open stream of mic device streamId: %{public}d.", streamId);
204     std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
205     CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
206 
207     cJSON *jParam = cJSON_CreateObject();
208     CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR);
209     cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
210     char *jsonData = cJSON_PrintUnformatted(jParam);
211     if (jsonData == nullptr) {
212         cJSON_Delete(jParam);
213         DHLOGE("Failed to create JSON data.");
214         return ERR_DH_AUDIO_NULLPTR;
215     }
216     std::string jsonDataStr(jsonData);
217     AudioEvent event(AudioEventType::OPEN_MIC, jsonDataStr);
218     cbObj->NotifyEvent(event);
219     DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_OPEN, devId_, std::to_string(dhId_),
220         "daudio mic device open success.");
221     streamId_ = streamId;
222     cJSON_Delete(jParam);
223     cJSON_free(jsonData);
224     DaudioRadar::GetInstance().ReportMicOpen("Start", MicOpen::CREATE_STREAM,
225         BizState::BIZ_STATE_START, DH_SUCCESS);
226     return DH_SUCCESS;
227 }
228 
DestroyStream(const int32_t streamId)229 int32_t DMicDev::DestroyStream(const int32_t streamId)
230 {
231     DHLOGI("Close stream of mic device streamId: %{public}d.", streamId);
232     std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
233     CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
234 
235     cJSON *jParam = cJSON_CreateObject();
236     CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR);
237     cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
238     char *jsonData = cJSON_PrintUnformatted(jParam);
239     if (jsonData == nullptr) {
240         cJSON_Delete(jParam);
241         DHLOGE("Failed to create JSON data.");
242         return ERR_DH_AUDIO_NULLPTR;
243     }
244     std::string jsonDataStr(jsonData);
245     AudioEvent event(AudioEventType::CLOSE_MIC, jsonDataStr);
246     cbObj->NotifyEvent(event);
247     DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_CLOSE, devId_, std::to_string(dhId_),
248         "daudio mic device close success.");
249     cJSON_Delete(jParam);
250     cJSON_free(jsonData);
251     curPort_ = 0;
252     DaudioRadar::GetInstance().ReportMicClose("DestroyStream", MicClose::DESTROY_STREAM,
253         BizState::BIZ_STATE_START, DH_SUCCESS);
254     return DH_SUCCESS;
255 }
256 
SetParameters(const int32_t streamId,const AudioParamHDF & param)257 int32_t DMicDev::SetParameters(const int32_t streamId, const AudioParamHDF &param)
258 {
259     DHLOGD("Set mic parameters {samplerate: %{public}d, channelmask: %{public}d, format: %{public}d, "
260         "period: %{public}d, framesize: %{public}d, ext{%{public}s}}.", param.sampleRate,
261         param.channelMask, param.bitFormat, param.period, param.frameSize, param.ext.c_str());
262     if (param.capturerFlags == MMAP_MODE && param.period != MMAP_NORMAL_PERIOD && param.period != MMAP_VOIP_PERIOD) {
263         DHLOGE("The period is invalid : %{public}" PRIu32, param.period);
264         return ERR_DH_AUDIO_SA_PARAM_INVALID;
265     }
266     curPort_ = dhId_;
267     paramHDF_ = param;
268 
269     param_.comParam.sampleRate = paramHDF_.sampleRate;
270     param_.comParam.channelMask = paramHDF_.channelMask;
271     param_.comParam.bitFormat = paramHDF_.bitFormat;
272     param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC;
273     if (isNeedCodec_.load()) {
274         param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC_EN;
275     }
276     DHLOGD("isNeedCodec_ : %{public}d.", isNeedCodec_.load());
277     param_.comParam.frameSize = paramHDF_.frameSize;
278     if (paramHDF_.streamUsage == StreamUsage::STREAM_USAGE_VOICE_COMMUNICATION) {
279         param_.captureOpts.sourceType = SOURCE_TYPE_VOICE_COMMUNICATION;
280     } else {
281         param_.captureOpts.sourceType = SOURCE_TYPE_MIC;
282     }
283     param_.captureOpts.capturerFlags = paramHDF_.capturerFlags;
284     if (paramHDF_.capturerFlags == MMAP_MODE) {
285         lowLatencyHalfSize_ = LOW_LATENCY_JITTER_TIME_MS / paramHDF_.period;
286         lowLatencyMaxfSize_ = LOW_LATENCY_JITTER_MAX_TIME_MS / paramHDF_.period;
287     }
288     return DH_SUCCESS;
289 }
290 
NotifyEvent(const int32_t streamId,const AudioEvent & event)291 int32_t DMicDev::NotifyEvent(const int32_t streamId, const AudioEvent &event)
292 {
293     DHLOGD("Notify mic event, type: %{public}d.", event.type);
294     std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
295     CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
296     switch (event.type) {
297         case AudioEventType::AUDIO_START:
298             curStatus_ = AudioStatus::STATUS_START;
299             isExistedEmpty_.store(false);
300             break;
301         case AudioEventType::AUDIO_STOP:
302             curStatus_ = AudioStatus::STATUS_STOP;
303             isExistedEmpty_.store(false);
304             break;
305         default:
306             break;
307     }
308     AudioEvent audioEvent(event.type, event.content);
309     cbObj->NotifyEvent(audioEvent);
310     return DH_SUCCESS;
311 }
312 
SetUp()313 int32_t DMicDev::SetUp()
314 {
315     DHLOGI("Set up mic device.");
316     CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR);
317     int32_t ret = micTrans_->SetUp(param_, param_, shared_from_this(), CAP_MIC);
318     if (ret != DH_SUCCESS) {
319         DHLOGE("Mic trans set up failed. ret: %{public}d.", ret);
320         return ret;
321     }
322     frameSize_ = static_cast<int32_t>(param_.comParam.frameSize);
323     {
324         std::lock_guard<std::mutex> lock(ringbufferMutex_);
325         ringBuffer_ = std::make_unique<DaudioRingBuffer>();
326         ringBuffer_->RingBufferInit(frameData_);
327         CHECK_NULL_RETURN(frameData_, ERR_DH_AUDIO_NULLPTR);
328     }
329     isRingbufferOn_.store(true);
330     ringbufferThread_ = std::thread([ptr = shared_from_this()]() {
331         if (!ptr) {
332             return;
333         }
334         ptr->ReadFromRingbuffer();
335     });
336     echoCannelOn_ = true;
337 #ifdef ECHO_CANNEL_ENABLE
338     if (echoCannelOn_ && echoManager_ == nullptr) {
339         echoManager_ = std::make_shared<DAudioEchoCannelManager>();
340     }
341     AudioCommonParam info;
342     info.sampleRate = param_.comParam.sampleRate;
343     info.channelMask = param_.comParam.channelMask;
344     info.bitFormat = param_.comParam.bitFormat;
345     info.frameSize = param_.comParam.frameSize;
346     if (echoManager_ != nullptr) {
347         echoManager_->SetUp(info, shared_from_this());
348     }
349 #endif
350     DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, DUMP_DAUDIO_MIC_READ_FROM_BUF_NAME, &dumpFileCommn_);
351     DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, DUMP_DAUDIO_LOWLATENCY_MIC_FROM_BUF_NAME, &dumpFileFast_);
352     return DH_SUCCESS;
353 }
354 
Start()355 int32_t DMicDev::Start()
356 {
357     DHLOGI("Start mic device.");
358     CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR);
359     int32_t ret = micTrans_->Start();
360     DaudioRadar::GetInstance().ReportMicOpenProgress("Start", MicOpen::TRANS_START, ret);
361     if (ret != DH_SUCCESS) {
362         DHLOGE("Mic trans start failed, ret: %{public}d.", ret);
363         return ret;
364     }
365     std::unique_lock<std::mutex> lck(channelWaitMutex_);
366     auto status = channelWaitCond_.wait_for(lck, std::chrono::seconds(CHANNEL_WAIT_SECONDS),
367         [this]() { return isTransReady_.load(); });
368     if (!status) {
369         DHLOGE("Wait channel open timeout(%{public}ds).", CHANNEL_WAIT_SECONDS);
370         return ERR_DH_AUDIO_SA_WAIT_TIMEOUT;
371     }
372     isOpened_.store(true);
373     return DH_SUCCESS;
374 }
375 
Pause()376 int32_t DMicDev::Pause()
377 {
378     DHLOGI("Not support.");
379     return DH_SUCCESS;
380 }
381 
Restart()382 int32_t DMicDev::Restart()
383 {
384     DHLOGI("Not surpport.");
385     return DH_SUCCESS;
386 }
387 
Stop()388 int32_t DMicDev::Stop()
389 {
390     DHLOGI("Stop mic device.");
391     CHECK_NULL_RETURN(micTrans_, DH_SUCCESS);
392     isOpened_.store(false);
393     isTransReady_.store(false);
394     int32_t ret = micTrans_->Stop();
395     if (ret != DH_SUCCESS) {
396         DHLOGE("Stop mic trans failed, ret: %{public}d.", ret);
397     }
398 #ifdef ECHO_CANNEL_ENABLE
399     CHECK_NULL_RETURN(echoManager_, DH_SUCCESS);
400     ret = echoManager_->Stop();
401     DaudioRadar::GetInstance().ReportMicCloseProgress("Stop", MicClose::STOP_TRANS, ret);
402     if (ret != DH_SUCCESS) {
403         DHLOGE("Echo manager stop failed. ret: %{public}d.", ret);
404         return ret;
405     }
406 #endif
407     return DH_SUCCESS;
408 }
409 
Release()410 int32_t DMicDev::Release()
411 {
412     DHLOGI("Release mic device.");
413     if (ashmem_ != nullptr) {
414         ashmem_->UnmapAshmem();
415         ashmem_->CloseAshmem();
416         ashmem_ = nullptr;
417         DHLOGI("UnInit ashmem success.");
418     }
419     if (micCtrlTrans_ != nullptr) {
420         int32_t res = micCtrlTrans_->Release();
421         CHECK_AND_RETURN_RET_LOG(res != DH_SUCCESS, res, "Mic ctrl Release failed.");
422     }
423     CHECK_NULL_RETURN(micTrans_, DH_SUCCESS);
424 
425     int32_t ret = micTrans_->Release();
426     DaudioRadar::GetInstance().ReportMicCloseProgress("Release", MicClose::RELEASE_TRANS, ret);
427     if (ret != DH_SUCCESS) {
428         DHLOGE("Release mic trans failed, ret: %{public}d.", ret);
429         return ret;
430     }
431     isRingbufferOn_.store(false);
432     if (ringbufferThread_.joinable()) {
433         ringbufferThread_.join();
434     }
435     {
436         std::lock_guard<std::mutex> lock(ringbufferMutex_);
437         ringBuffer_ = nullptr;
438         if (frameData_ != nullptr) {
439             delete[] frameData_;
440             frameData_ = nullptr;
441         }
442     }
443 #ifdef ECHO_CANNEL_ENABLE
444     if (echoManager_ != nullptr) {
445         echoManager_->Release();
446         echoManager_ = nullptr;
447     }
448 #endif
449     DumpFileUtil::CloseDumpFile(&dumpFileCommn_);
450     DumpFileUtil::CloseDumpFile(&dumpFileFast_);
451     return DH_SUCCESS;
452 }
453 
IsOpened()454 bool DMicDev::IsOpened()
455 {
456     return isOpened_.load();
457 }
458 
WriteStreamData(const int32_t streamId,std::shared_ptr<AudioData> & data)459 int32_t DMicDev::WriteStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data)
460 {
461     (void)streamId;
462     (void)data;
463     return DH_SUCCESS;
464 }
465 
ReadStreamData(const int32_t streamId,std::shared_ptr<AudioData> & data)466 int32_t DMicDev::ReadStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data)
467 {
468     int64_t startTime = GetNowTimeUs();
469     if (curStatus_ != AudioStatus::STATUS_START) {
470         DHLOGE("Distributed audio is not starting status.");
471         return ERR_DH_AUDIO_FAILED;
472     }
473     std::lock_guard<std::mutex> lock(dataQueueMtx_);
474     uint32_t queSize = dataQueue_.size();
475     if (queSize == 0) {
476         isExistedEmpty_.store(true);
477         DHLOGD("Data queue is empty");
478         data = std::make_shared<AudioData>(param_.comParam.frameSize);
479     } else {
480         data = dataQueue_.front();
481         dataQueue_.pop();
482     }
483     CHECK_NULL_RETURN(data, ERR_DH_AUDIO_NULLPTR);
484     DumpFileUtil::WriteDumpFile(dumpFileCommn_, static_cast<void *>(data->Data()), data->Size());
485     int64_t endTime = GetNowTimeUs();
486     if (IsOutDurationRange(startTime, endTime, lastReadStartTime_)) {
487         DHLOGE("This time read data spend: %{public}" PRId64" us, The interval of read data this time and "
488             "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastReadStartTime_);
489     }
490     lastReadStartTime_ = startTime;
491     return DH_SUCCESS;
492 }
493 
ReadMmapPosition(const int32_t streamId,uint64_t & frames,CurrentTimeHDF & time)494 int32_t DMicDev::ReadMmapPosition(const int32_t streamId, uint64_t &frames, CurrentTimeHDF &time)
495 {
496     DHLOGD("Read mmap position. frames: %{public}" PRIu64", tvsec: %{public}" PRId64", tvNSec:%{public}" PRId64,
497         writeNum_, writeTvSec_, writeTvNSec_);
498     frames = writeNum_;
499     time.tvSec = writeTvSec_;
500     time.tvNSec = writeTvNSec_;
501     return DH_SUCCESS;
502 }
503 
RefreshAshmemInfo(const int32_t streamId,int32_t fd,int32_t ashmemLength,int32_t lengthPerTrans)504 int32_t DMicDev::RefreshAshmemInfo(const int32_t streamId,
505     int32_t fd, int32_t ashmemLength, int32_t lengthPerTrans)
506 {
507     DHLOGD("RefreshAshmemInfo: fd:%{public}d, ashmemLength: %{public}d, lengthPerTrans: %{public}d",
508         fd, ashmemLength, lengthPerTrans);
509     if (param_.captureOpts.capturerFlags == MMAP_MODE) {
510         DHLOGD("DMic dev low-latency mode");
511         if (ashmem_ != nullptr) {
512             return DH_SUCCESS;
513         }
514         if (ashmemLength < ASHMEM_MAX_LEN) {
515             ashmem_ = sptr<Ashmem>(new Ashmem(fd, ashmemLength));
516             ashmemLength_ = ashmemLength;
517             lengthPerTrans_ = lengthPerTrans;
518             DHLOGD("Create ashmem success. fd:%{public}d, ashmem length: %{public}d, lengthPreTrans: %{public}d",
519                 fd, ashmemLength_, lengthPerTrans_);
520             bool mapRet = ashmem_->MapReadAndWriteAshmem();
521             if (!mapRet) {
522                 DHLOGE("Mmap ashmem failed.");
523                 return ERR_DH_AUDIO_NULLPTR;
524             }
525         }
526     }
527     return DH_SUCCESS;
528 }
529 
MmapStart()530 int32_t DMicDev::MmapStart()
531 {
532     CHECK_NULL_RETURN(ashmem_, ERR_DH_AUDIO_NULLPTR);
533     std::lock_guard<std::mutex> lock(writeAshmemMutex_);
534     frameIndex_ = 0;
535     startTime_ = 0;
536     isEnqueueRunning_.store(true);
537     enqueueDataThread_ = std::thread([ptr = shared_from_this()]() {
538         if (!ptr) {
539             return;
540         }
541         ptr->EnqueueThread();
542     });
543     if (pthread_setname_np(enqueueDataThread_.native_handle(), ENQUEUE_THREAD) != DH_SUCCESS) {
544         DHLOGE("Enqueue data thread setname failed.");
545     }
546     return DH_SUCCESS;
547 }
548 
EnqueueThread()549 void DMicDev::EnqueueThread()
550 {
551     writeIndex_ = 0;
552     writeNum_ = 0;
553     int64_t timeIntervalns = static_cast<int64_t>(paramHDF_.period * AUDIO_NS_PER_SECOND / AUDIO_MS_PER_SECOND);
554     DHLOGD("Enqueue thread start, lengthPerWrite length: %{public}d, interval: %{public}d.", lengthPerTrans_,
555         paramHDF_.period);
556     FillJitterQueue();
557     while (ashmem_ != nullptr && isEnqueueRunning_.load()) {
558         int64_t timeOffset = UpdateTimeOffset(frameIndex_, timeIntervalns, startTime_);
559         DHLOGD("Write frameIndex: %{public}" PRId64", timeOffset: %{public}" PRId64, frameIndex_, timeOffset);
560         std::shared_ptr<AudioData> audioData = nullptr;
561         {
562             std::lock_guard<std::mutex> lock(dataQueueMtx_);
563             if (dataQueue_.empty()) {
564                 DHLOGD("Data queue is Empty.");
565                 audioData = std::make_shared<AudioData>(param_.comParam.frameSize);
566             } else {
567                 audioData = dataQueue_.front();
568                 dataQueue_.pop();
569             }
570             if (audioData == nullptr) {
571                 DHLOGD("The audioData is nullptr.");
572                 continue;
573             }
574             DumpFileUtil::WriteDumpFile(dumpFileFast_, static_cast<void *>(audioData->Data()), audioData->Size());
575             bool writeRet = ashmem_->WriteToAshmem(audioData->Data(), audioData->Size(), writeIndex_);
576             if (writeRet) {
577                 DHLOGD("Write to ashmem success! write index: %{public}d, writeLength: %{public}d.",
578                     writeIndex_, lengthPerTrans_);
579             } else {
580                 DHLOGE("Write data to ashmem failed.");
581             }
582         }
583         writeIndex_ += lengthPerTrans_;
584         if (writeIndex_ >= ashmemLength_) {
585             writeIndex_ = 0;
586         }
587         writeNum_ += static_cast<uint64_t>(CalculateSampleNum(param_.comParam.sampleRate, paramHDF_.period));
588         GetCurrentTime(writeTvSec_, writeTvNSec_);
589         frameIndex_++;
590         AbsoluteSleep(startTime_ + frameIndex_ * timeIntervalns - timeOffset);
591     }
592 }
593 
FillJitterQueue()594 void DMicDev::FillJitterQueue()
595 {
596     while (isEnqueueRunning_.load()) {
597         {
598             std::lock_guard<std::mutex> lock(dataQueueMtx_);
599             if (dataQueue_.size() >= (LOW_LATENCY_JITTER_TIME_MS / paramHDF_.period)) {
600                 break;
601             }
602         }
603         usleep(MMAP_WAIT_FRAME_US);
604     }
605     DHLOGD("Mic jitter data queue fill end.");
606 }
607 
MmapStop()608 int32_t DMicDev::MmapStop()
609 {
610     std::lock_guard<std::mutex> lock(writeAshmemMutex_);
611     isEnqueueRunning_.store(false);
612     if (enqueueDataThread_.joinable()) {
613         enqueueDataThread_.join();
614     }
615     DHLOGI("Mic mmap stop end.");
616     return DH_SUCCESS;
617 }
618 
GetAudioParam() const619 AudioParam DMicDev::GetAudioParam() const
620 {
621     return param_;
622 }
623 
NotifyHdfAudioEvent(const AudioEvent & event,const int32_t portId)624 int32_t DMicDev::NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId)
625 {
626     int32_t ret = DAudioHdiHandler::GetInstance().NotifyEvent(devId_, portId, streamId_, event);
627     if (ret != DH_SUCCESS) {
628         DHLOGE("Notify event: %{public}d, result: %{public}s, streamId: %{public}d.",
629             event.type, event.content.c_str(), streamId_);
630     }
631     return DH_SUCCESS;
632 }
633 
OnStateChange(const AudioEventType type)634 int32_t DMicDev::OnStateChange(const AudioEventType type)
635 {
636     DHLOGD("On mic device state change, type: %{public}d", type);
637     AudioEvent event;
638     switch (type) {
639         case AudioEventType::DATA_OPENED:
640             isTransReady_.store(true);
641             channelWaitCond_.notify_one();
642             event.type = AudioEventType::MIC_OPENED;
643             break;
644         case AudioEventType::DATA_CLOSED:
645             isTransReady_.store(false);
646             event.type = AudioEventType::MIC_CLOSED;
647             break;
648         default:
649             break;
650     }
651     event.content = GetCJsonString(KEY_DH_ID, std::to_string(dhId_).c_str());
652     std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
653     CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
654     cbObj->NotifyEvent(event);
655     return DH_SUCCESS;
656 }
657 
SendMessage(uint32_t type,std::string content,std::string dstDevId)658 int32_t DMicDev::SendMessage(uint32_t type, std::string content, std::string dstDevId)
659 {
660     DHLOGD("Send message to remote.");
661     if (type != static_cast<uint32_t>(OPEN_MIC) && type != static_cast<uint32_t>(CLOSE_MIC)) {
662         DHLOGE("Send message to remote. not OPEN_MIC or CLOSE_MIC. type: %{public}u", type);
663         return ERR_DH_AUDIO_NULLPTR;
664     }
665     CHECK_NULL_RETURN(micCtrlTrans_, ERR_DH_AUDIO_NULLPTR);
666     micCtrlTrans_->SendAudioEvent(type, content, dstDevId);
667     return DH_SUCCESS;
668 }
669 
OnDecodeTransDataDone(const std::shared_ptr<AudioData> & audioData)670 int32_t DMicDev::OnDecodeTransDataDone(const std::shared_ptr<AudioData> &audioData)
671 {
672     CHECK_NULL_RETURN(audioData, ERR_DH_AUDIO_NULLPTR);
673     std::lock_guard<std::mutex> lock(dataQueueMtx_);
674     dataQueSize_ = curStatus_ != AudioStatus::STATUS_START ?
675         (param_.captureOpts.capturerFlags == MMAP_MODE ? lowLatencyHalfSize_ : DATA_QUEUE_HALF_SIZE) :
676         (param_.captureOpts.capturerFlags == MMAP_MODE ? lowLatencyMaxfSize_ : DATA_QUEUE_MAX_SIZE);
677     if (isExistedEmpty_.load()) {
678         dataQueSize_ = param_.captureOpts.capturerFlags == MMAP_MODE ? dataQueSize_ : DATA_QUEUE_EXT_SIZE;
679     }
680     uint64_t queueSize;
681     while (dataQueue_.size() > dataQueSize_) {
682         queueSize = static_cast<uint64_t>(dataQueue_.size());
683         DHLOGD("Data queue overflow. buf current size: %{public}" PRIu64, queueSize);
684         dataQueue_.pop();
685     }
686     dataQueue_.push(audioData);
687     queueSize = static_cast<uint64_t>(dataQueue_.size());
688     DHLOGD("Push new mic data, buf len: %{public}" PRIu64, queueSize);
689     return DH_SUCCESS;
690 }
691 } // DistributedHardware
692 } // OHOS
693