• 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_client.h"
17 
18 #include "cJSON.h"
19 
20 #include "daudio_constants.h"
21 #include "daudio_hisysevent.h"
22 #include "daudio_sink_hidumper.h"
23 #include "daudio_util.h"
24 #include "daudio_sink_manager.h"
25 
26 #undef DH_LOG_TAG
27 #define DH_LOG_TAG "DSpeakerClient"
28 
29 namespace OHOS {
30 namespace DistributedHardware {
~DSpeakerClient()31 DSpeakerClient::~DSpeakerClient()
32 {
33     DHLOGD("Release speaker client.");
34 }
35 
OnEngineTransEvent(const AVTransEvent & event)36 void DSpeakerClient::OnEngineTransEvent(const AVTransEvent &event)
37 {
38     if (event.type == EventType::EVENT_START_SUCCESS) {
39         OnStateChange(DATA_OPENED);
40     } else if ((event.type == EventType::EVENT_STOP_SUCCESS) ||
41         (event.type == EventType::EVENT_CHANNEL_CLOSED) ||
42         (event.type == EventType::EVENT_START_FAIL)) {
43         OnStateChange(DATA_CLOSED);
44     }
45 }
46 
OnEngineTransMessage(const std::shared_ptr<AVTransMessage> & message)47 void DSpeakerClient::OnEngineTransMessage(const std::shared_ptr<AVTransMessage> &message)
48 {
49     CHECK_NULL_VOID(message);
50     DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str());
51     DAudioSinkManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_,
52         static_cast<int32_t>(message->type_), message->content_);
53 }
54 
OnEngineTransDataAvailable(const std::shared_ptr<AudioData> & audioData)55 void DSpeakerClient::OnEngineTransDataAvailable(const std::shared_ptr<AudioData> &audioData)
56 {
57     DHLOGD("On Engine Data available");
58     OnDecodeTransDataDone(audioData);
59 }
60 
InitReceiverEngine(IAVEngineProvider * providerPtr)61 int32_t DSpeakerClient::InitReceiverEngine(IAVEngineProvider *providerPtr)
62 {
63     DHLOGI("InitReceiverEngine enter.");
64     if (speakerTrans_ == nullptr) {
65         speakerTrans_ = std::make_shared<AVTransReceiverTransport>(devId_, shared_from_this());
66     }
67     int32_t ret = speakerTrans_->InitEngine(providerPtr);
68     if (ret != DH_SUCCESS) {
69         DHLOGE("Spk client initialize av receiver adapter failed.");
70         return ERR_DH_AUDIO_NULLPTR;
71     }
72     return DH_SUCCESS;
73 }
74 
InitCtrlTrans()75 int32_t DSpeakerClient::InitCtrlTrans()
76 {
77     DHLOGI("InitCtrlTrans enter");
78     if (speakerCtrlTrans_ == nullptr) {
79         speakerCtrlTrans_ = std::make_shared<DaudioSinkCtrlTrans>(devId_,
80             SESSIONNAME_SPK_SINK, SESSIONNAME_SPK_SOURCE, shared_from_this());
81     }
82     int32_t ret = speakerCtrlTrans_->SetUp(shared_from_this());
83     CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Speaker ctrl SetUp failed.");
84     return DH_SUCCESS;
85 }
86 
OnCtrlTransEvent(const AVTransEvent & event)87 void DSpeakerClient::OnCtrlTransEvent(const AVTransEvent &event)
88 {
89     if (event.type == EventType::EVENT_START_SUCCESS) {
90         OnStateChange(DATA_OPENED);
91     } else if ((event.type == EventType::EVENT_STOP_SUCCESS) ||
92         (event.type == EventType::EVENT_CHANNEL_CLOSED) ||
93         (event.type == EventType::EVENT_START_FAIL)) {
94         OnStateChange(DATA_CLOSED);
95     }
96 }
97 
OnCtrlTransMessage(const std::shared_ptr<AVTransMessage> & message)98 void DSpeakerClient::OnCtrlTransMessage(const std::shared_ptr<AVTransMessage> &message)
99 {
100     CHECK_NULL_VOID(message);
101     DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str());
102     DAudioSinkManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_,
103         static_cast<int32_t>(message->type_), message->content_);
104 }
105 
CreateAudioRenderer(const AudioParam & param)106 int32_t DSpeakerClient::CreateAudioRenderer(const AudioParam &param)
107 {
108     DHLOGD("Set up spk client: {sampleRate: %{public}d, bitFormat: %{public}d, channelMask: %{public}d,"
109         "frameSize: %{public}d, contentType: %{public}d, renderFlags: %{public}d, streamUsage: %{public}d}.",
110         param.comParam.sampleRate, param.comParam.bitFormat, param.comParam.channelMask, param.comParam.frameSize,
111         param.renderOpts.contentType, param.renderOpts.renderFlags, param.renderOpts.streamUsage);
112     audioParam_ = param;
113     AudioStandard::AudioRendererOptions rendererOptions = {
114         {
115             static_cast<AudioStandard::AudioSamplingRate>(audioParam_.comParam.sampleRate),
116             AudioStandard::AudioEncodingType::ENCODING_PCM,
117             static_cast<AudioStandard::AudioSampleFormat>(audioParam_.comParam.bitFormat),
118             static_cast<AudioStandard::AudioChannel>(audioParam_.comParam.channelMask),
119         },
120         {
121             static_cast<AudioStandard::ContentType>(audioParam_.renderOpts.contentType),
122             static_cast<AudioStandard::StreamUsage>(audioParam_.renderOpts.streamUsage),
123             audioParam_.renderOpts.renderFlags == MMAP_MODE ? AudioStandard::STREAM_FLAG_FAST : 0,
124         }
125     };
126     std::lock_guard<std::mutex> lck(devMtx_);
127     audioRenderer_ = AudioStandard::AudioRenderer::Create(rendererOptions);
128     CHECK_NULL_RETURN(audioRenderer_, ERR_DH_AUDIO_CLIENT_RENDER_CREATE_FAILED);
129 
130     audioRenderer_ ->SetRendererCallback(shared_from_this());
131     if (audioParam_.renderOpts.renderFlags != MMAP_MODE) {
132         return DH_SUCCESS;
133     }
134     int32_t ret = audioRenderer_->SetRendererWriteCallback(shared_from_this());
135     if (ret != DH_SUCCESS) {
136         DHLOGE("Client save write callback failed.");
137         return ERR_DH_AUDIO_CLIENT_RENDER_CREATE_FAILED;
138     }
139     return DH_SUCCESS;
140 }
141 
OnWriteData(size_t length)142 void DSpeakerClient::OnWriteData(size_t length)
143 {
144     AudioStandard::BufferDesc bufDesc;
145     CHECK_NULL_VOID(audioRenderer_);
146     if (audioRenderer_->GetBufferDesc(bufDesc) != DH_SUCCESS || bufDesc.bufLength == 0) {
147         DHLOGE("Get buffer desc failed.");
148         return;
149     }
150     CHECK_NULL_VOID(bufDesc.buffer);
151 
152     std::shared_ptr<AudioData> audioData = nullptr;
153     {
154         std::unique_lock<std::mutex> spkLck(dataQueueMtx_);
155         if (dataQueue_.empty()) {
156             audioData = std::make_shared<AudioData>(bufDesc.bufLength);
157             DHLOGD("Pop spk data, dataQueue is empty. write empty data.");
158         } else {
159             audioData = dataQueue_.front();
160             dataQueue_.pop();
161             uint64_t queueSize = static_cast<uint64_t>(dataQueue_.size());
162             DHLOGD("Pop spk data, dataQueue size: %{public}" PRIu64, queueSize);
163         }
164     }
165     if ((audioData != nullptr) && (audioData->Capacity() != bufDesc.bufLength)) {
166         uint64_t capacity = static_cast<uint64_t>(audioData->Capacity());
167         uint64_t bufLength = static_cast<uint64_t>(bufDesc.bufLength);
168         DHLOGE("Audio data length is not equal to buflength. datalength: %{public}" PRIu64
169             ", bufLength: %{public}" PRIu64, capacity, bufLength);
170     }
171     if (memcpy_s(bufDesc.buffer, bufDesc.bufLength, audioData->Data(), audioData->Capacity()) != EOK) {
172         DHLOGE("Copy audio data failed.");
173     }
174     audioRenderer_->Enqueue(bufDesc);
175 }
176 
SetUp(const AudioParam & param)177 int32_t DSpeakerClient::SetUp(const AudioParam &param)
178 {
179     int32_t ret = CreateAudioRenderer(param);
180     if (ret != DH_SUCCESS) {
181         DHLOGE("Set up failed, Create Audio renderer failed.");
182         return ret;
183     }
184     DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, DUMP_DAUDIO_SPK_AFTER_TRANS_NAME, &dumpFile_);
185     CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR);
186     ret = speakerTrans_->SetUp(audioParam_, audioParam_, shared_from_this(), CAP_SPK);
187     if (ret != DH_SUCCESS) {
188         DHLOGE("Speaker trans setup failed.");
189         return ret;
190     }
191     ret = speakerTrans_->Start();
192     if (ret != DH_SUCCESS) {
193         DHLOGE("Speaker trans start failed.");
194         return ret;
195     }
196     auto pid = getprocpid();
197     ret = AudioStandard::AudioSystemManager::GetInstance()->RegisterVolumeKeyEventCallback(pid, shared_from_this());
198     if (ret != DH_SUCCESS) {
199         DHLOGE("Failed to register volume key event callback.");
200         return ret;
201     }
202     clientStatus_ = AudioStatus::STATUS_READY;
203     return DH_SUCCESS;
204 }
205 
Release()206 int32_t DSpeakerClient::Release()
207 {
208     DHLOGI("Release spk client.");
209     std::lock_guard<std::mutex> lck(devMtx_);
210     if (clientStatus_ != AudioStatus::STATUS_READY && clientStatus_ != AudioStatus::STATUS_STOP) {
211         DHLOGE("Speaker status %{public}d is wrong.", (int32_t)clientStatus_);
212         return ERR_DH_AUDIO_SA_STATUS_ERR;
213     }
214     bool isSucess = true;
215     if (speakerTrans_ != nullptr) {
216         if (speakerTrans_->Stop() != DH_SUCCESS) {
217             DHLOGE("Speaker trans stop failed.");
218             isSucess = false;
219         }
220         if (speakerTrans_->Release() != DH_SUCCESS) {
221             DHLOGE("Speaker trans release failed.");
222             isSucess = false;
223         }
224         speakerTrans_ = nullptr;
225     }
226     if (speakerCtrlTrans_ != nullptr) {
227         if (speakerCtrlTrans_->Release() != DH_SUCCESS) {
228             DHLOGE("Speaker trans release failed.");
229             isSucess = false;
230         }
231         speakerCtrlTrans_ = nullptr;
232     }
233 
234     int32_t ret = AudioStandard::AudioSystemManager::GetInstance()->UnregisterVolumeKeyEventCallback(getprocpid());
235     if (ret != DH_SUCCESS) {
236         DHLOGE("Failed to unregister volume key event callback, error code %{public}d.", ret);
237         isSucess = false;
238     }
239     if (audioRenderer_ != nullptr && !audioRenderer_->Release()) {
240         DHLOGE("Audio renderer release failed.");
241         isSucess = false;
242         audioRenderer_ = nullptr;
243     }
244     clientStatus_ = AudioStatus::STATUS_IDLE;
245     DumpFileUtil::CloseDumpFile(&dumpFile_);
246     return isSucess ? DH_SUCCESS : ERR_DH_AUDIO_CLIENT_RENDER_RELEASE_FAILED;
247 }
248 
StartRender()249 int32_t DSpeakerClient::StartRender()
250 {
251     DHLOGI("Start spk client.");
252     std::lock_guard<std::mutex> lck(devMtx_);
253     CHECK_NULL_RETURN(audioRenderer_, ERR_DH_AUDIO_SA_STATUS_ERR);
254 
255     if (!audioRenderer_->Start()) {
256         DHLOGE("Audio renderer start failed.");
257         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_CLIENT_RENDER_STARTUP_FAILURE,
258             "daudio renderer start failed.");
259         return ERR_DH_AUDIO_CLIENT_RENDER_STARTUP_FAILURE;
260     }
261     if (audioParam_.renderOpts.renderFlags != MMAP_MODE) {
262         isRenderReady_.store(true);
263         renderDataThread_ = std::thread([this]() { this->PlayThreadRunning(); });
264     }
265     clientStatus_ = AudioStatus::STATUS_START;
266     return DH_SUCCESS;
267 }
268 
StopRender()269 int32_t DSpeakerClient::StopRender()
270 {
271     DHLOGI("Stop spk client.");
272     std::lock_guard<std::mutex> lck(devMtx_);
273     if (clientStatus_ != AudioStatus::STATUS_START) {
274         DHLOGE("Renderer is not start or spk status wrong, status: %{public}d.", (int32_t)clientStatus_);
275         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_SA_STATUS_ERR,
276             "daudio renderer is not start or spk status wrong.");
277         return ERR_DH_AUDIO_SA_STATUS_ERR;
278     }
279     if (audioRenderer_ == nullptr) {
280         DHLOGE("Audio renderer is nullptr.");
281         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_NULLPTR,
282             "daudio renderer is nullptr.");
283         return ERR_DH_AUDIO_NULLPTR;
284     }
285 
286     if (audioParam_.renderOpts.renderFlags != MMAP_MODE) {
287         if (isRenderReady_.load()) {
288             isRenderReady_.store(false);
289             if (renderDataThread_.joinable()) {
290                 renderDataThread_.join();
291             }
292         }
293     }
294 
295     if (!audioRenderer_->Stop()) {
296         DHLOGE("Audio renderer stop failed");
297         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_CLIENT_RENDER_STOP_FAILED,
298             "daudio renderer stop failed.");
299         return ERR_DH_AUDIO_CLIENT_RENDER_STOP_FAILED;
300     }
301     clientStatus_ = AudioStatus::STATUS_STOP;
302     return DH_SUCCESS;
303 }
304 
PlayThreadRunning()305 void DSpeakerClient::PlayThreadRunning()
306 {
307     DHLOGD("Start the renderer thread.");
308     if (pthread_setname_np(pthread_self(), RENDERTHREAD) != DH_SUCCESS) {
309         DHLOGE("Render data thread setname failed.");
310     }
311 
312     FillJitterQueue();
313     while (audioRenderer_ != nullptr && isRenderReady_.load()) {
314         int64_t startTime = GetNowTimeUs();
315         std::shared_ptr<AudioData> audioData = nullptr;
316         {
317             std::unique_lock<std::mutex> spkLck(dataQueueMtx_);
318             dataQueueCond_.wait_for(spkLck, std::chrono::milliseconds(REQUEST_DATA_WAIT),
319                 [this]() { return !dataQueue_.empty(); });
320             if (dataQueue_.empty()) {
321                 continue;
322             }
323             audioData = dataQueue_.front();
324             dataQueue_.pop();
325             uint64_t queueSize = static_cast<uint64_t>(dataQueue_.size());
326             DHLOGD("Pop spk data, dataqueue size: %{public}" PRIu64, queueSize);
327         }
328         if (audioData == nullptr) {
329             continue;
330         }
331         DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(audioData->Data()), audioData->Size());
332         int32_t writeOffSet = 0;
333         while (writeOffSet < static_cast<int32_t>(audioData->Capacity())) {
334             int32_t writeLen = audioRenderer_->Write(audioData->Data() + writeOffSet,
335                 static_cast<int32_t>(audioData->Capacity()) - writeOffSet);
336             uint64_t capacity = static_cast<uint64_t>(audioData->Capacity());
337             DHLOGD("Write audio render, write len: %{public}d, raw len: %{public}" PRIu64", offset: %{public}d",
338                 writeLen, capacity, writeOffSet);
339             if (writeLen < 0) {
340                 break;
341             }
342             writeOffSet += writeLen;
343         }
344         int64_t endTime = GetNowTimeUs();
345         if (IsOutDurationRange(startTime, endTime, lastPlayStartTime_)) {
346             DHLOGD("This time play spend: %{public}" PRId64" us, The interval of play this time and "
347                 "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastPlayStartTime_);
348         }
349         lastPlayStartTime_ = startTime;
350     }
351 }
352 
FillJitterQueue()353 void DSpeakerClient::FillJitterQueue()
354 {
355     while (isRenderReady_.load()) {
356         {
357             std::lock_guard<std::mutex> lock(dataQueueMtx_);
358             if (dataQueue_.size() >= DATA_QUEUE_SIZE) {
359                 break;
360             }
361         }
362         usleep(SLEEP_TIME);
363     }
364 }
365 
FlushJitterQueue()366 void DSpeakerClient::FlushJitterQueue()
367 {
368     while (isRenderReady_.load()) {
369         {
370             std::lock_guard<std::mutex> lock(dataQueueMtx_);
371             if (dataQueue_.empty()) {
372                 break;
373             }
374         }
375         usleep(SLEEP_TIME);
376     }
377 }
378 
OnDecodeTransDataDone(const std::shared_ptr<AudioData> & audioData)379 int32_t DSpeakerClient::OnDecodeTransDataDone(const std::shared_ptr<AudioData> &audioData)
380 {
381     DHLOGD("Write stream buffer.");
382     int64_t startTime = GetNowTimeUs();
383     CHECK_NULL_RETURN(audioData, ERR_DH_AUDIO_NULLPTR);
384 
385     std::lock_guard<std::mutex> lock(dataQueueMtx_);
386     while (dataQueue_.size() > DATA_QUEUE_MAX_SIZE) {
387         DHLOGD("Data queue overflow.");
388         dataQueue_.pop();
389     }
390     dataQueue_.push(audioData);
391     dataQueueCond_.notify_all();
392     uint64_t queueSize = static_cast<uint64_t>(dataQueue_.size());
393     DHLOGD("Push new spk data, buf len: %{public}" PRIu64, queueSize);
394     int64_t endTime = GetNowTimeUs();
395     if (IsOutDurationRange(startTime, endTime, lastReceiveStartTime_)) {
396         DHLOGD("This time receivce data spend: %{public}" PRId64" us, Receivce data this time and "
397             "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastReceiveStartTime_);
398     }
399     lastReceiveStartTime_ = startTime;
400     return DH_SUCCESS;
401 }
402 
OnStateChange(const AudioEventType type)403 int32_t DSpeakerClient::OnStateChange(const AudioEventType type)
404 {
405     DHLOGD("On state change. type: %{public}d", type);
406     AudioEvent event;
407     switch (type) {
408         case AudioEventType::DATA_OPENED: {
409             event.type = AudioEventType::SPEAKER_OPENED;
410             event.content = GetVolumeLevel();
411             break;
412         }
413         case AudioEventType::DATA_CLOSED: {
414             event.type = AudioEventType::SPEAKER_CLOSED;
415             event.content = GetCJsonString(KEY_DH_ID, std::to_string(dhId_).c_str());
416             break;
417         }
418         default:
419             DHLOGE("Invalid parameter type: %{public}d.", type);
420             return ERR_DH_AUDIO_NOT_SUPPORT;
421     }
422 
423     std::shared_ptr<IAudioEventCallback> cbObj = eventCallback_.lock();
424     CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
425     cbObj->NotifyEvent(event);
426     return DH_SUCCESS;
427 }
428 
GetVolumeLevel()429 string DSpeakerClient::GetVolumeLevel()
430 {
431     DHLOGD("Get the volume level.");
432     AudioStandard::AudioStreamType streamType = AudioStandard::AudioStreamType::STREAM_DEFAULT;
433     auto volumeType = static_cast<AudioStandard::AudioVolumeType>(1);
434     int32_t volumeLevel = AudioStandard::AudioSystemManager::GetInstance()->GetVolume(volumeType);
435     int32_t maxVolumeLevel = AudioStandard::AudioSystemManager::GetInstance()->GetMaxVolume(volumeType);
436     int32_t minVolumeLevel = AudioStandard::AudioSystemManager::GetInstance()->GetMinVolume(volumeType);
437     bool isUpdateUi = false;
438     cJSON *jParam = cJSON_CreateObject();
439     CHECK_NULL_RETURN(jParam, "");
440 
441     cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
442     cJSON_AddStringToObject(jParam, KEY_CHANGE_TYPE, FIRST_VOLUME_CHANAGE);
443     cJSON_AddStringToObject(jParam, AUDIO_STREAM_TYPE, std::to_string(streamType).c_str());
444     cJSON_AddStringToObject(jParam, VOLUME_LEVEL.c_str(), std::to_string(volumeLevel).c_str());
445     cJSON_AddStringToObject(jParam, IS_UPDATEUI, std::to_string(isUpdateUi).c_str());
446     cJSON_AddStringToObject(jParam, MAX_VOLUME_LEVEL, std::to_string(maxVolumeLevel).c_str());
447     cJSON_AddStringToObject(jParam, MIN_VOLUME_LEVEL, std::to_string(minVolumeLevel).c_str());
448     char *jsonData = cJSON_PrintUnformatted(jParam);
449     if (jsonData == nullptr) {
450         DHLOGE("Failed to create JSON data.");
451         cJSON_Delete(jParam);
452         return "";
453     }
454     std::string str(jsonData);
455     cJSON_Delete(jParam);
456     cJSON_free(jsonData);
457     DHLOGD("Get the volume level result, event: %{public}s.", str.c_str());
458     return str;
459 }
460 
OnVolumeKeyEvent(AudioStandard::VolumeEvent volumeEvent)461 void DSpeakerClient::OnVolumeKeyEvent(AudioStandard::VolumeEvent volumeEvent)
462 {
463     DHLOGD("Volume change event.");
464     std::shared_ptr<IAudioEventCallback> cbObj = eventCallback_.lock();
465     CHECK_NULL_VOID(cbObj);
466 
467     cJSON *jParam = cJSON_CreateObject();
468     CHECK_NULL_VOID(jParam);
469 
470     cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
471     cJSON_AddStringToObject(jParam, KEY_CHANGE_TYPE, VOLUME_CHANAGE);
472     cJSON_AddStringToObject(jParam, AUDIO_STREAM_TYPE, std::to_string(volumeEvent.volumeType).c_str());
473     cJSON_AddStringToObject(jParam, VOLUME_LEVEL.c_str(), std::to_string(volumeEvent.volume).c_str());
474     cJSON_AddStringToObject(jParam, IS_UPDATEUI, std::to_string(volumeEvent.updateUi).c_str());
475     cJSON_AddStringToObject(jParam, VOLUME_GROUP_ID, std::to_string(volumeEvent.volumeGroupId).c_str());
476     char *jsonData = cJSON_PrintUnformatted(jParam);
477     if (jsonData == nullptr) {
478         DHLOGE("Failed to create JSON data.");
479         cJSON_Delete(jParam);
480         return;
481     }
482     std::string str(jsonData);
483     cJSON_Delete(jParam);
484     cJSON_free(jsonData);
485     DHLOGD("Volume change notification result, event: %{public}s.", str.c_str());
486 
487     AudioEvent audioEvent(VOLUME_CHANGE, str);
488     cbObj->NotifyEvent(audioEvent);
489 }
490 
OnInterrupt(const AudioStandard::InterruptEvent & interruptEvent)491 void DSpeakerClient::OnInterrupt(const AudioStandard::InterruptEvent &interruptEvent)
492 {
493     DHLOGD("Audio focus interrupt event.");
494     std::shared_ptr<IAudioEventCallback> cbObj = eventCallback_.lock();
495     CHECK_NULL_VOID(cbObj);
496 
497     cJSON *jParam = cJSON_CreateObject();
498     CHECK_NULL_VOID(jParam);
499 
500     cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
501     cJSON_AddStringToObject(jParam, KEY_CHANGE_TYPE, INTERRUPT_EVENT);
502     cJSON_AddStringToObject(jParam, VOLUME_EVENT_TYPE, std::to_string(interruptEvent.eventType).c_str());
503     cJSON_AddStringToObject(jParam, FORCE_TYPE, std::to_string(interruptEvent.forceType).c_str());
504     cJSON_AddStringToObject(jParam, HINT_TYPE, std::to_string(interruptEvent.hintType).c_str());
505     char *jsonData = cJSON_PrintUnformatted(jParam);
506     if (jsonData == nullptr) {
507         DHLOGE("Failed to create JSON data.");
508         cJSON_Delete(jParam);
509         return;
510     }
511     std::string str(jsonData);
512     cJSON_Delete(jParam);
513     cJSON_free(jsonData);
514     DHLOGD("Audio focus oninterrupt notification result, event: %{public}s.", str.c_str());
515 
516     AudioEvent audioEvent(AUDIO_FOCUS_CHANGE, str);
517     cbObj->NotifyEvent(audioEvent);
518 }
519 
OnStateChange(const AudioStandard::RendererState state,const AudioStandard::StateChangeCmdType cmdType)520 void DSpeakerClient::OnStateChange(const AudioStandard::RendererState state,
521     const AudioStandard::StateChangeCmdType __attribute__((unused)) cmdType)
522 {
523     DHLOGD("On render state change. state: %{public}d", state);
524     std::shared_ptr<IAudioEventCallback> cbObj = eventCallback_.lock();
525     CHECK_NULL_VOID(cbObj);
526 
527     cJSON *jParam = cJSON_CreateObject();
528     CHECK_NULL_VOID(jParam);
529 
530     cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
531     cJSON_AddStringToObject(jParam, KEY_CHANGE_TYPE, RENDER_STATE_CHANGE_EVENT);
532     cJSON_AddStringToObject(jParam, KEY_STATE, std::to_string(state).c_str());
533     char *jsonData = cJSON_PrintUnformatted(jParam);
534     if (jsonData == nullptr) {
535         DHLOGE("Failed to create JSON data.");
536         cJSON_Delete(jParam);
537         return;
538     }
539     std::string str(jsonData);
540     cJSON_Delete(jParam);
541     cJSON_free(jsonData);
542     DHLOGD("Audio render state changes notification result, event: %{public}s.", str.c_str());
543 
544     AudioEvent audioEvent(AUDIO_RENDER_STATE_CHANGE, str);
545     cbObj->NotifyEvent(audioEvent);
546 }
547 
SetAudioParameters(const AudioEvent & event)548 int32_t DSpeakerClient::SetAudioParameters(const AudioEvent &event)
549 {
550     DHLOGD("Set the volume, arg: %{public}s.", event.content.c_str());
551 
552     int32_t audioVolumeType;
553     int32_t ret = GetAudioParamInt(event.content, AUDIO_VOLUME_TYPE, audioVolumeType);
554     if (ret != DH_SUCCESS) {
555         DHLOGE("Get audio volume type failed.");
556         return ret;
557     }
558     auto volumeType = static_cast<AudioStandard::AudioVolumeType>(audioVolumeType);
559     DHLOGD("Audio volume type, volumeType = %{public}d.", volumeType);
560     if (event.type != VOLUME_SET) {
561         DHLOGE("Invalid parameter.");
562         return ERR_DH_AUDIO_CLIENT_PARAM_ERROR;
563     }
564 
565     int32_t audioVolumeLevel;
566     ret = GetAudioParamInt(event.content, VOLUME_LEVEL, audioVolumeLevel);
567     if (ret != DH_SUCCESS) {
568         DHLOGE("Get audio volume level failed.");
569         return ret;
570     }
571     DHLOGD("volume level = %{public}d.", audioVolumeLevel);
572     ret = AudioStandard::AudioSystemManager::GetInstance()->SetVolume(volumeType, audioVolumeLevel);
573     if (ret != DH_SUCCESS) {
574         DHLOGE("Voloume set failed.");
575         return ERR_DH_AUDIO_CLIENT_SET_VOLUME_FAILED;
576     }
577     return DH_SUCCESS;
578 }
579 
SetMute(const AudioEvent & event)580 int32_t DSpeakerClient::SetMute(const AudioEvent &event)
581 {
582     DHLOGD("Set mute, arg: %{public}s.", event.content.c_str());
583     int32_t audioVolumeType;
584     int32_t ret = GetAudioParamInt(event.content, AUDIO_VOLUME_TYPE, audioVolumeType);
585     if (ret != DH_SUCCESS) {
586         DHLOGE("Get audio volume type failed.");
587         return ret;
588     }
589 
590     bool muteStatus = false;
591     ret = GetAudioParamBool(event.content, STREAM_MUTE_STATUS, muteStatus);
592     if (ret != DH_SUCCESS) {
593         DHLOGE("Get mute status failed.");
594         return ret;
595     }
596 
597     auto volumeType = static_cast<AudioStandard::AudioVolumeType>(audioVolumeType);
598     DHLOGD("Audio volume type, volumeType = %{public}d.", volumeType);
599     if (event.type != VOLUME_MUTE_SET) {
600         DHLOGE("Invalid parameter.");
601         return ERR_DH_AUDIO_CLIENT_PARAM_ERROR;
602     }
603     ret = AudioStandard::AudioSystemManager::GetInstance()->SetMute(volumeType, muteStatus);
604     if (ret != DH_SUCCESS) {
605         DHLOGE("Mute set failed.");
606         return ERR_DH_AUDIO_CLIENT_SET_MUTE_FAILED;
607     }
608     return DH_SUCCESS;
609 }
610 
Pause()611 void DSpeakerClient::Pause()
612 {
613     DHLOGI("Pause and flush");
614     FlushJitterQueue();
615     if (audioParam_.renderOpts.renderFlags != MMAP_MODE) {
616         isRenderReady_.store(false);
617         if (renderDataThread_.joinable()) {
618             renderDataThread_.join();
619         }
620     }
621 
622     if (speakerTrans_ == nullptr || speakerTrans_->Pause() != DH_SUCCESS) {
623         DHLOGE("Speaker trans Pause failed.");
624     }
625     if (audioRenderer_ != nullptr) {
626         audioRenderer_->Flush();
627         audioRenderer_->Pause();
628     }
629     clientStatus_ = AudioStatus::STATUS_START;
630     isRenderReady_.store(true);
631 }
632 
ReStart()633 void DSpeakerClient::ReStart()
634 {
635     DHLOGI("ReStart");
636     if (speakerTrans_ == nullptr || speakerTrans_->Restart(audioParam_, audioParam_) != DH_SUCCESS) {
637         DHLOGE("Speaker trans Restart failed.");
638     }
639     if (audioParam_.renderOpts.renderFlags != MMAP_MODE) {
640         isRenderReady_.store(true);
641         renderDataThread_ = std::thread([this]() { this->PlayThreadRunning(); });
642     }
643     if (audioRenderer_ != nullptr) {
644         audioRenderer_->Start();
645     }
646     clientStatus_ = AudioStatus::STATUS_START;
647 }
648 
SendMessage(uint32_t type,std::string content,std::string dstDevId)649 int32_t DSpeakerClient::SendMessage(uint32_t type, std::string content, std::string dstDevId)
650 {
651     DHLOGD("Send message to remote.");
652     if (type != static_cast<uint32_t>(NOTIFY_OPEN_SPEAKER_RESULT) &&
653         type != static_cast<uint32_t>(NOTIFY_OPEN_CTRL_RESULT) &&
654         type != static_cast<uint32_t>(NOTIFY_CLOSE_SPEAKER_RESULT) &&
655         type != static_cast<uint32_t>(VOLUME_CHANGE) &&
656         type != static_cast<uint32_t>(AUDIO_FOCUS_CHANGE) &&
657         type != static_cast<uint32_t>(AUDIO_RENDER_STATE_CHANGE)) {
658         DHLOGE("event type is not NOTIFY_OPEN_SPK or NOTIFY_CLOSE_SPK or OPEN_CTRL. type:%{public}u", type);
659         return ERR_DH_AUDIO_NULLPTR;
660     }
661     CHECK_NULL_RETURN(speakerCtrlTrans_, ERR_DH_AUDIO_NULLPTR);
662     speakerCtrlTrans_->SendAudioEvent(type, content, dstDevId);
663     return DH_SUCCESS;
664 }
665 
PlayStatusChange(const std::string & args)666 void DSpeakerClient::PlayStatusChange(const std::string &args)
667 {
668     DHLOGI("Play status change, args: %{public}s.", args.c_str());
669     std::string changeType = ParseStringFromArgs(args, KEY_CHANGE_TYPE);
670     if (changeType == AUDIO_EVENT_RESTART) {
671         ReStart();
672     } else if (changeType == AUDIO_EVENT_PAUSE) {
673         Pause();
674     } else {
675         DHLOGE("Play status error.");
676     }
677 }
678 
SetAttrs(const std::string & devId,const std::shared_ptr<IAudioEventCallback> & callback)679 void DSpeakerClient::SetAttrs(const std::string &devId, const std::shared_ptr<IAudioEventCallback> &callback)
680 {
681     DHLOGE("Set attrs, not support yet.");
682 }
683 } // DistributedHardware
684 } // OHOS
685