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 ¶m)
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