• 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 "dspeaker_dev.h"
17 
18 #include <algorithm>
19 #include <condition_variable>
20 #include <mutex>
21 #include <string>
22 #include <thread>
23 #include <securec.h>
24 
25 #include "daudio_constants.h"
26 #include "daudio_errorcode.h"
27 #include "daudio_hidumper.h"
28 #include "daudio_hisysevent.h"
29 #include "daudio_hitrace.h"
30 #include "daudio_log.h"
31 #include "daudio_radar.h"
32 #include "daudio_source_manager.h"
33 #include "daudio_util.h"
34 
35 #undef DH_LOG_TAG
36 #define DH_LOG_TAG "DSpeakerDev"
37 
38 namespace OHOS {
39 namespace DistributedHardware {
EnableDevice(const int32_t dhId,const std::string & capability)40 int32_t DSpeakerDev::EnableDevice(const int32_t dhId, const std::string &capability)
41 {
42     DHLOGI("Enable IO device, device pin: %{public}d.", dhId);
43     int32_t ret = DAudioHdiHandler::GetInstance().RegisterAudioDevice(devId_, dhId, capability, shared_from_this());
44     if (ret != DH_SUCCESS) {
45         DHLOGE("Register device failed, ret: %{public}d.", ret);
46         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_REGISTER_FAIL, devId_, std::to_string(dhId), ret,
47             "daudio register device failed.");
48         return ret;
49     }
50     dhId_ = dhId;
51     GetCodecCaps(capability);
52     return DH_SUCCESS;
53 }
54 
AddToVec(std::vector<AudioCodecType> & container,const AudioCodecType value)55 void DSpeakerDev::AddToVec(std::vector<AudioCodecType> &container, const AudioCodecType value)
56 {
57     auto it = std::find(container.begin(), container.end(), value);
58     if (it == container.end()) {
59         container.push_back(value);
60     }
61 }
62 
GetCodecCaps(const std::string & capability)63 void DSpeakerDev::GetCodecCaps(const std::string &capability)
64 {
65     auto pos = capability.find(AAC);
66     if (pos != std::string::npos) {
67         AddToVec(codec_, AudioCodecType::AUDIO_CODEC_AAC_EN);
68         DHLOGI("Daudio codec cap: AAC");
69     }
70     pos = capability.find(OPUS);
71     if (pos != std::string::npos) {
72         AddToVec(codec_, AudioCodecType::AUDIO_CODEC_OPUS);
73         DHLOGI("Daudio codec cap: OPUS");
74     }
75 }
76 
DisableDevice(const int32_t dhId)77 int32_t DSpeakerDev::DisableDevice(const int32_t dhId)
78 {
79     DHLOGI("Disable IO device, device pin: %{public}d.", dhId);
80     int32_t ret = DAudioHdiHandler::GetInstance().UnRegisterAudioDevice(devId_, dhId);
81     if (ret != DH_SUCCESS) {
82         DHLOGE("UnRegister failed, ret: %{public}d.", ret);
83         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_UNREGISTER_FAIL, devId_, std::to_string(dhId), ret,
84             "daudio unregister device failed.");
85         return ret;
86     }
87     return DH_SUCCESS;
88 }
89 
IsMimeSupported(const AudioCodecType coder)90 bool DSpeakerDev::IsMimeSupported(const AudioCodecType coder)
91 {
92     auto iter = std::find(codec_.begin(), codec_.end(), coder);
93     if (iter == codec_.end()) {
94         DHLOGI("devices have no cap: %{public}d", static_cast<int>(coder));
95         return false;
96     }
97     return true;
98 }
99 
InitReceiverEngine(IAVEngineProvider * providerPtr)100 int32_t DSpeakerDev::InitReceiverEngine(IAVEngineProvider *providerPtr)
101 {
102     DHLOGI("InitReceiverEngine enter.");
103     return DH_SUCCESS;
104 }
105 
InitSenderEngine(IAVEngineProvider * providerPtr)106 int32_t DSpeakerDev::InitSenderEngine(IAVEngineProvider *providerPtr)
107 {
108     DHLOGI("InitSenderEngine enter");
109     if (speakerTrans_ == nullptr) {
110         speakerTrans_ = std::make_shared<AVTransSenderTransport>(devId_, shared_from_this());
111     }
112     int32_t ret = speakerTrans_->InitEngine(providerPtr);
113     if (ret != DH_SUCCESS) {
114         DHLOGE("Speaker dev initialize av sender adapter failed.");
115         return ret;
116     }
117     return ret;
118 }
119 
InitCtrlTrans()120 int32_t DSpeakerDev::InitCtrlTrans()
121 {
122     DHLOGI("InitCtrlTrans enter");
123     if (speakerCtrlTrans_ == nullptr) {
124         speakerCtrlTrans_ = std::make_shared<DaudioSourceCtrlTrans>(devId_,
125             SESSIONNAME_SPK_SOURCE, SESSIONNAME_SPK_SINK, shared_from_this());
126     }
127     int32_t ret = speakerCtrlTrans_->SetUp(shared_from_this());
128     CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Speaker ctrl SetUp failed.");
129     ret = speakerCtrlTrans_->Start();
130     CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Speaker ctrl Start failed.");
131     return ret;
132 }
133 
OnCtrlTransEvent(const AVTransEvent & event)134 void DSpeakerDev::OnCtrlTransEvent(const AVTransEvent &event)
135 {
136     if (event.type == EventType::EVENT_START_SUCCESS) {
137         OnStateChange(DATA_OPENED);
138     } else if ((event.type == EventType::EVENT_STOP_SUCCESS) ||
139         (event.type == EventType::EVENT_CHANNEL_CLOSED) ||
140         (event.type == EventType::EVENT_START_FAIL)) {
141         OnStateChange(DATA_CLOSED);
142     }
143 }
144 
OnCtrlTransMessage(const std::shared_ptr<AVTransMessage> & message)145 void DSpeakerDev::OnCtrlTransMessage(const std::shared_ptr<AVTransMessage> &message)
146 {
147     CHECK_NULL_VOID(message);
148     DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str());
149     DAudioSourceManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_,
150         message->type_, message->content_);
151 }
152 
OnEngineTransEvent(const AVTransEvent & event)153 void DSpeakerDev::OnEngineTransEvent(const AVTransEvent &event)
154 {
155     if (event.type == EventType::EVENT_START_SUCCESS) {
156         OnStateChange(DATA_OPENED);
157     } else if ((event.type == EventType::EVENT_STOP_SUCCESS) ||
158         (event.type == EventType::EVENT_CHANNEL_CLOSED) ||
159         (event.type == EventType::EVENT_START_FAIL)) {
160         OnStateChange(DATA_CLOSED);
161     }
162 }
163 
OnEngineTransMessage(const std::shared_ptr<AVTransMessage> & message)164 void DSpeakerDev::OnEngineTransMessage(const std::shared_ptr<AVTransMessage> &message)
165 {
166     CHECK_NULL_VOID(message);
167     DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str());
168     DAudioSourceManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_,
169         message->type_, message->content_);
170 }
171 
CreateStream(const int32_t streamId)172 int32_t DSpeakerDev::CreateStream(const int32_t streamId)
173 {
174     DHLOGI("Open stream of speaker device, streamId: %{public}d.", streamId);
175     std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
176     CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
177 
178     cJSON *jParam = cJSON_CreateObject();
179     CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR);
180     cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
181     char *jsonData = cJSON_PrintUnformatted(jParam);
182     if (jsonData == nullptr) {
183         DHLOGE("Failed to create JSON data.");
184         cJSON_Delete(jParam);
185         return ERR_DH_AUDIO_NULLPTR;
186     }
187     std::string jsonDataStr(jsonData);
188     AudioEvent event(AudioEventType::OPEN_SPEAKER, jsonDataStr);
189     cbObj->NotifyEvent(event);
190     DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_OPEN, devId_, std::to_string(dhId_),
191         "daudio spk device open success.");
192     streamId_ = streamId;
193     cJSON_Delete(jParam);
194     cJSON_free(jsonData);
195     DaudioRadar::GetInstance().ReportSpeakerOpen("CreateStream", SpeakerOpen::CREATE_STREAM,
196         BizState::BIZ_STATE_START, DH_SUCCESS);
197     return DH_SUCCESS;
198 }
199 
DestroyStream(const int32_t streamId)200 int32_t DSpeakerDev::DestroyStream(const int32_t streamId)
201 {
202     DHLOGI("Close stream of speaker device streamId: %{public}d.",  streamId);
203     std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
204     CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
205 
206     cJSON *jParam = cJSON_CreateObject();
207     CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR);
208     cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
209     char *jsonData = cJSON_PrintUnformatted(jParam);
210     if (jsonData == nullptr) {
211         DHLOGE("Failed to create JSON data.");
212         cJSON_Delete(jParam);
213         return ERR_DH_AUDIO_NULLPTR;
214     }
215     std::string jsonDataStr(jsonData);
216     AudioEvent event(AudioEventType::CLOSE_SPEAKER, jsonDataStr);
217     cbObj->NotifyEvent(event);
218     DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_CLOSE, devId_, std::to_string(dhId_),
219         "daudio spk device close success.");
220     curPort_ = 0;
221     cJSON_Delete(jParam);
222     cJSON_free(jsonData);
223     DaudioRadar::GetInstance().ReportSpeakerClose("DestroyStream", SpeakerClose::DESTROY_STREAM,
224         BizState::BIZ_STATE_START, DH_SUCCESS);
225     return DH_SUCCESS;
226 }
227 
SetParameters(const int32_t streamId,const AudioParamHDF & param)228 int32_t DSpeakerDev::SetParameters(const int32_t streamId, const AudioParamHDF &param)
229 {
230     DHLOGD("Set speaker parameters {samplerate: %{public}d, channelmask: %{public}d, format: %{public}d, "
231         "streamusage: %{public}d, period: %{public}d, framesize: %{public}d, renderFlags: %{public}d, "
232         "ext{%{public}s}}.", param.sampleRate, param.channelMask, param.bitFormat, param.streamUsage,
233         param.period, param.frameSize, param.renderFlags, param.ext.c_str());
234     curPort_ = dhId_;
235     paramHDF_ = param;
236 
237     param_.comParam.sampleRate = paramHDF_.sampleRate;
238     param_.comParam.channelMask = paramHDF_.channelMask;
239     param_.comParam.bitFormat = paramHDF_.bitFormat;
240     param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC;
241     param_.comParam.frameSize = paramHDF_.frameSize;
242     param_.renderOpts.contentType = CONTENT_TYPE_MUSIC;
243     param_.renderOpts.renderFlags = paramHDF_.renderFlags;
244     param_.renderOpts.streamUsage = paramHDF_.streamUsage;
245     if (paramHDF_.streamUsage == StreamUsage::STREAM_USAGE_VOICE_COMMUNICATION &&
246         IsMimeSupported(AudioCodecType::AUDIO_CODEC_OPUS)) {
247         param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_OPUS;
248     } else if (IsMimeSupported(AudioCodecType::AUDIO_CODEC_AAC_EN)) {
249         param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC_EN;
250     }
251     DHLOGI("codecType: %{public}d", static_cast<int>(param_.comParam.codecType));
252     return DH_SUCCESS;
253 }
254 
NotifyEvent(const int32_t streamId,const AudioEvent & event)255 int32_t DSpeakerDev::NotifyEvent(const int32_t streamId, const AudioEvent &event)
256 {
257     DHLOGD("Notify speaker event.");
258     std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
259     CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
260     AudioEvent audioEvent(event.type, event.content);
261     cbObj->NotifyEvent(audioEvent);
262     return DH_SUCCESS;
263 }
264 
SetUp()265 int32_t DSpeakerDev::SetUp()
266 {
267     DHLOGI("Set up speaker device.");
268     CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR);
269 
270     int32_t ret = speakerTrans_->SetUp(param_, param_, shared_from_this(), CAP_SPK);
271     if (ret != DH_SUCCESS) {
272         DHLOGE("Speaker trans set up failed. ret:%{public}d", ret);
273         return ret;
274     }
275     DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, SPK_DEV_FILENAME, &dumpFileCommn_);
276     DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, SPK_LOWLATENCY_FILENAME, &dumpFileFast_);
277     return DH_SUCCESS;
278 }
279 
Start()280 int32_t DSpeakerDev::Start()
281 {
282     DHLOGI("Start speaker device.");
283     CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR);
284     int32_t ret = speakerTrans_->Start();
285     DaudioRadar::GetInstance().ReportSpeakerOpenProgress("Start", SpeakerOpen::TRANS_START, ret);
286     if (ret != DH_SUCCESS) {
287         DHLOGE("Speaker trans start failed, ret: %{public}d.", ret);
288         return ret;
289     }
290     std::unique_lock<std::mutex> lck(channelWaitMutex_);
291     auto status = channelWaitCond_.wait_for(lck, std::chrono::seconds(CHANNEL_WAIT_SECONDS),
292         [this]() { return isTransReady_.load(); });
293     if (!status) {
294         DHLOGE("Wait channel open timeout(%{public}ds).", CHANNEL_WAIT_SECONDS);
295         return ERR_DH_AUDIO_SA_WAIT_TIMEOUT;
296     }
297     isOpened_.store(true);
298     return DH_SUCCESS;
299 }
300 
Stop()301 int32_t DSpeakerDev::Stop()
302 {
303     DHLOGI("Stop speaker device.");
304     CHECK_NULL_RETURN(speakerTrans_, DH_SUCCESS);
305     isOpened_.store(false);
306     isTransReady_.store(false);
307     int32_t ret = speakerTrans_->Stop();
308     DaudioRadar::GetInstance().ReportSpeakerCloseProgress("Stop", SpeakerClose::STOP_TRANS, ret);
309     if (ret != DH_SUCCESS) {
310         DHLOGE("Stop speaker trans failed, ret: %{public}d.", ret);
311         return ret;
312     }
313     return DH_SUCCESS;
314 }
315 
Release()316 int32_t DSpeakerDev::Release()
317 {
318     DHLOGI("Release speaker device.");
319     if (ashmem_ != nullptr) {
320         ashmem_->UnmapAshmem();
321         ashmem_->CloseAshmem();
322         ashmem_ = nullptr;
323         DHLOGI("UnInit ashmem success.");
324     }
325     if (speakerCtrlTrans_ != nullptr) {
326         int32_t res = speakerCtrlTrans_->Release();
327         CHECK_AND_RETURN_RET_LOG(res != DH_SUCCESS, res, "Speaker ctrl Release failed.");
328     }
329     CHECK_NULL_RETURN(speakerTrans_, DH_SUCCESS);
330     int32_t ret = speakerTrans_->Release();
331     DaudioRadar::GetInstance().ReportSpeakerCloseProgress("Release", SpeakerClose::RELEASE_TRANS, ret);
332     if (ret != DH_SUCCESS) {
333         DHLOGE("Release speaker trans failed, ret: %{public}d.", ret);
334     }
335     DumpFileUtil::CloseDumpFile(&dumpFileCommn_);
336     DumpFileUtil::CloseDumpFile(&dumpFileFast_);
337     return DH_SUCCESS;
338 }
339 
Pause()340 int32_t DSpeakerDev::Pause()
341 {
342     DHLOGI("Pause.");
343     CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR);
344     int32_t ret = speakerTrans_->Pause();
345     if (ret != DH_SUCCESS) {
346         DHLOGE("Pause speaker trans failed, ret: %{public}d.", ret);
347         return ret;
348     }
349     DHLOGD("Pause success.");
350     return DH_SUCCESS;
351 }
352 
Restart()353 int32_t DSpeakerDev::Restart()
354 {
355     DHLOGI("Restart.");
356     CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR);
357     int32_t ret = speakerTrans_->Restart(param_, param_);
358     if (ret != DH_SUCCESS) {
359         DHLOGE("Restart speaker trans failed, ret: %{public}d.", ret);
360         return ret;
361     }
362     DHLOGD("Restart success.");
363     return DH_SUCCESS;
364 }
365 
IsOpened()366 bool DSpeakerDev::IsOpened()
367 {
368     return isOpened_.load();
369 }
370 
ReadStreamData(const int32_t streamId,std::shared_ptr<AudioData> & data)371 int32_t DSpeakerDev::ReadStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data)
372 {
373     (void)streamId;
374     (void)data;
375     DHLOGD("Dspeaker dev not support read stream data.");
376     return DH_SUCCESS;
377 }
378 
WriteStreamData(const int32_t streamId,std::shared_ptr<AudioData> & data)379 int32_t DSpeakerDev::WriteStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data)
380 {
381     DHLOGD("Write stream data, streamId:%{public}d", streamId);
382     int64_t startTime = GetNowTimeUs();
383     CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR);
384     CHECK_NULL_RETURN(data, ERR_DH_AUDIO_NULLPTR);
385     DumpFileUtil::WriteDumpFile(dumpFileCommn_, static_cast<void *>(data->Data()), data->Size());
386     int32_t ret = speakerTrans_->FeedAudioData(data);
387     if (ret != DH_SUCCESS) {
388         DHLOGE("Write stream data failed, ret: %{public}d.", ret);
389         return ret;
390     }
391     int64_t endTime = GetNowTimeUs();
392     if (IsOutDurationRange(startTime, endTime, lastwriteStartTime_)) {
393         DHLOGE("This time write data spend: %{public}" PRId64" us, The interval of write data this time and "
394             "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastwriteStartTime_);
395     }
396     lastwriteStartTime_ = startTime;
397     return DH_SUCCESS;
398 }
399 
ReadMmapPosition(const int32_t streamId,uint64_t & frames,CurrentTimeHDF & time)400 int32_t DSpeakerDev::ReadMmapPosition(const int32_t streamId,
401     uint64_t &frames, CurrentTimeHDF &time)
402 {
403     DHLOGD("Read mmap position. frames: %{public}" PRIu64", tvsec: %{public}" PRId64", tvNSec:%{public}" PRId64,
404         readNum_, readTvSec_, readTvNSec_);
405     frames = readNum_;
406     time.tvSec = readTvSec_;
407     time.tvNSec = readTvNSec_;
408     return DH_SUCCESS;
409 }
410 
RefreshAshmemInfo(const int32_t streamId,int32_t fd,int32_t ashmemLength,int32_t lengthPerTrans)411 int32_t DSpeakerDev::RefreshAshmemInfo(const int32_t streamId,
412     int32_t fd, int32_t ashmemLength, int32_t lengthPerTrans)
413 {
414     DHLOGD("RefreshAshmemInfo: fd:%{public}d, ashmemLength: %{public}d, lengthPerTrans: %{public}d",
415         fd, ashmemLength, lengthPerTrans);
416     if (param_.renderOpts.renderFlags == MMAP_MODE) {
417         DHLOGI("DSpeaker dev low-latency mode");
418         if (ashmem_ != nullptr) {
419             return DH_SUCCESS;
420         }
421         if (ashmemLength < ASHMEM_MAX_LEN) {
422             ashmem_ = sptr<Ashmem>(new Ashmem(fd, ashmemLength));
423             ashmemLength_ = ashmemLength;
424             lengthPerTrans_ = lengthPerTrans;
425             DHLOGI("Create ashmem success. fd:%{public}d, ashmem length: %{public}d, lengthPreTrans: %{public}d",
426                 fd, ashmemLength_, lengthPerTrans_);
427             bool mapRet = ashmem_->MapReadAndWriteAshmem();
428             if (!mapRet) {
429                 DHLOGE("Mmap ashmem failed.");
430                 return ERR_DH_AUDIO_NULLPTR;
431             }
432         }
433     }
434     return DH_SUCCESS;
435 }
436 
MmapStart()437 int32_t DSpeakerDev::MmapStart()
438 {
439     CHECK_NULL_RETURN(ashmem_, ERR_DH_AUDIO_NULLPTR);
440     isEnqueueRunning_.store(true);
441     enqueueDataThread_ = std::thread([this]() { this->EnqueueThread(); });
442     if (pthread_setname_np(enqueueDataThread_.native_handle(), ENQUEUE_THREAD) != DH_SUCCESS) {
443         DHLOGE("Enqueue data thread setname failed.");
444     }
445     return DH_SUCCESS;
446 }
447 
EnqueueThread()448 void DSpeakerDev::EnqueueThread()
449 {
450     readIndex_ = 0;
451     readNum_ = 0;
452     frameIndex_ = 0;
453     int64_t timeIntervalns = static_cast<int64_t>(paramHDF_.period * AUDIO_NS_PER_SECOND / AUDIO_MS_PER_SECOND);
454     DHLOGI("Enqueue thread start, lengthPerRead length: %{public}d, interval: %{pubic}d.", lengthPerTrans_,
455         paramHDF_.period);
456     while (ashmem_ != nullptr && isEnqueueRunning_.load()) {
457         int64_t timeOffset = UpdateTimeOffset(frameIndex_, timeIntervalns, startTime_);
458         DHLOGD("Read frameIndex: %{public}" PRId64", timeOffset: %{public}" PRId64, frameIndex_, timeOffset);
459         auto readData = ashmem_->ReadFromAshmem(lengthPerTrans_, readIndex_);
460         DHLOGD("Read from ashmem success! read index: %{public}d, readLength: %{public}d.",
461             readIndex_, lengthPerTrans_);
462         std::shared_ptr<AudioData> audioData = std::make_shared<AudioData>(lengthPerTrans_);
463         if (readData != nullptr) {
464             const uint8_t *readAudioData = reinterpret_cast<const uint8_t *>(readData);
465             if (memcpy_s(audioData->Data(), audioData->Capacity(), readAudioData, param_.comParam.frameSize) != EOK) {
466                 DHLOGE("Copy audio data failed.");
467             }
468         }
469         CHECK_NULL_VOID(speakerTrans_);
470         DumpFileUtil::WriteDumpFile(dumpFileFast_, static_cast<void *>(audioData->Data()), audioData->Size());
471         int32_t ret = speakerTrans_->FeedAudioData(audioData);
472         if (ret != DH_SUCCESS) {
473             DHLOGE("Speaker enqueue thread, write stream data failed, ret: %{public}d.", ret);
474         }
475         readIndex_ += lengthPerTrans_;
476         if (readIndex_ >= ashmemLength_) {
477             readIndex_ = 0;
478         }
479         readNum_ += static_cast<uint64_t>(CalculateSampleNum(param_.comParam.sampleRate, paramHDF_.period));
480         GetCurrentTime(readTvSec_, readTvNSec_);
481         frameIndex_++;
482         AbsoluteSleep(startTime_ + frameIndex_ * timeIntervalns - timeOffset);
483     }
484 }
485 
MmapStop()486 int32_t DSpeakerDev::MmapStop()
487 {
488     isEnqueueRunning_.store(false);
489     if (enqueueDataThread_.joinable()) {
490         enqueueDataThread_.join();
491     }
492     DHLOGI("Spk mmap stop end.");
493     return DH_SUCCESS;
494 }
495 
GetAudioParam() const496 AudioParam DSpeakerDev::GetAudioParam() const
497 {
498     return param_;
499 }
500 
SendMessage(uint32_t type,std::string content,std::string dstDevId)501 int32_t DSpeakerDev::SendMessage(uint32_t type, std::string content, std::string dstDevId)
502 {
503     DHLOGD("Send message to remote.");
504     if (type != static_cast<uint32_t>(OPEN_SPEAKER) && type != static_cast<uint32_t>(CLOSE_SPEAKER) &&
505         type != static_cast<uint32_t>(CHANGE_PLAY_STATUS) && type != static_cast<uint32_t>(VOLUME_SET) &&
506         type != static_cast<uint32_t>(VOLUME_MUTE_SET)) {
507         DHLOGE("Send message to remote. not OPEN_SPK or CLOSE_SPK. type: %{public}u", type);
508         return ERR_DH_AUDIO_NULLPTR;
509     }
510     CHECK_NULL_RETURN(speakerCtrlTrans_, ERR_DH_AUDIO_NULLPTR);
511     speakerCtrlTrans_->SendAudioEvent(type, content, dstDevId);
512     return DH_SUCCESS;
513 }
514 
NotifyHdfAudioEvent(const AudioEvent & event,const int32_t portId)515 int32_t DSpeakerDev::NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId)
516 {
517     int32_t ret = DAudioHdiHandler::GetInstance().NotifyEvent(devId_, portId, streamId_, event);
518     if (ret != DH_SUCCESS) {
519         DHLOGE("Notify event: %{public}d, result: %{public}s, streamId: %{public}d.",
520             event.type, event.content.c_str(), streamId_);
521     }
522     return DH_SUCCESS;
523 }
524 
OnStateChange(const AudioEventType type)525 int32_t DSpeakerDev::OnStateChange(const AudioEventType type)
526 {
527     DHLOGI("On speaker device state change, type: %{public}d.", type);
528     AudioEvent event;
529     switch (type) {
530         case AudioEventType::DATA_OPENED:
531             isTransReady_.store(true);
532             channelWaitCond_.notify_all();
533             event.type = AudioEventType::SPEAKER_OPENED;
534             break;
535         case AudioEventType::DATA_CLOSED:
536             isOpened_.store(false);
537             isTransReady_.store(false);
538             event.type = AudioEventType::SPEAKER_CLOSED;
539             break;
540         default:
541             break;
542     }
543     event.content = GetCJsonString(KEY_DH_ID, std::to_string(dhId_).c_str());
544     std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
545     CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
546     cbObj->NotifyEvent(event);
547     return DH_SUCCESS;
548 }
549 
OnDecodeTransDataDone(const std::shared_ptr<AudioData> & audioData)550 int32_t DSpeakerDev::OnDecodeTransDataDone(const std::shared_ptr<AudioData> &audioData)
551 {
552     (void) audioData;
553     return DH_SUCCESS;
554 }
555 } // DistributedHardware
556 } // OHOS
557