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