1 /*
2 * Copyright (c) 2024-2025 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 #ifndef LOG_TAG
16 #define LOG_TAG "TonePlayerImpl"
17 #endif
18
19 #include <sys/time.h>
20 #include <utility>
21
22 #include <climits>
23 #include <cmath>
24 #include <cfloat>
25 #include "securec.h"
26 #include "audio_common_log.h"
27 #include "audio_policy_manager.h"
28 #include "tone_player_impl.h"
29 #include "audio_utils.h"
30 #include "audio_errors.h"
31 #include "parameter.h"
32 #ifdef AUDIO_TEL_CORE_SERVICE_ENABLE
33 #include "core_service_client.h"
34 #endif
35 #ifdef AUIDO_TEL_CELLULAR_DATA_ENABLE
36 #include "cellular_data_client.h"
37 #endif
38
39 namespace OHOS {
40 namespace AudioStandard {
41 namespace {
42 constexpr int32_t C20MS = 20;
43 constexpr int32_t C1000MS = 1000;
44 constexpr int32_t CDOUBLE = 2;
45 constexpr int32_t DIGITAMPLITUDE = 800;
46 constexpr int32_t AMPLITUDE = 8000;
47 constexpr int32_t BIT8 = 8;
48 constexpr int32_t SYSPARA_SIZE = 128;
49 const char DEBUG_COUNTRYCODE_NAME[] = "debug.toneplayer.country";
50 const char DEFAULT_STRING[] = "error";
51 const char DUMP_TONEPLAYER_FILENAME[] = "dump_toneplayer_audio.pcm";
52
53 static const std::vector<ToneType> TONE_TYPE_LIST = {
54 TONE_TYPE_DIAL_0,
55 TONE_TYPE_DIAL_1,
56 TONE_TYPE_DIAL_2,
57 TONE_TYPE_DIAL_3,
58 TONE_TYPE_DIAL_4,
59 TONE_TYPE_DIAL_5,
60 TONE_TYPE_DIAL_6,
61 TONE_TYPE_DIAL_7,
62 TONE_TYPE_DIAL_8,
63 TONE_TYPE_DIAL_9,
64 TONE_TYPE_DIAL_S,
65 TONE_TYPE_DIAL_P
66 };
67 }
68
TonePlayerImpl(const std::string cachePath,const AudioRendererInfo & rendereInfo)69 TonePlayerImpl::TonePlayerImpl(const std::string cachePath, const AudioRendererInfo &rendereInfo)
70 {
71 toneState_ = TONE_IDLE;
72 rendererOptions_.streamInfo.encoding = AudioEncodingType::ENCODING_PCM;
73 rendererOptions_.streamInfo.samplingRate = SAMPLE_RATE_48000;
74 rendererOptions_.streamInfo.format = SAMPLE_S16LE;
75 rendererOptions_.streamInfo.channels = MONO;
76
77 // contentType::CONTENT_TYPE_MUSIC;
78 rendererOptions_.rendererInfo.contentType = rendereInfo.contentType;
79
80 // streamUsage::STREAM_USAGE_MEDIA;
81 rendererOptions_.rendererInfo.streamUsage = rendereInfo.streamUsage;
82 rendererOptions_.rendererInfo.rendererFlags = AUDIO_FLAG_FORCED_NORMAL; // use AUDIO_FLAG_FORCED_NORMAL
83 rendererOptions_.rendererInfo.playerType = PLAYER_TYPE_TONE_PLAYER;
84
85 rendererOptions_.strategy = { AudioConcurrencyMode::MIX_WITH_OTHERS };
86 supportedTones_ = AudioPolicyManager::GetInstance().GetSupportedTones(GetCountryCode());
87 toneInfo_ = NULL;
88 initialToneInfo_ = NULL;
89 samplingRate_ = rendererOptions_.streamInfo.samplingRate;
90 }
91
~TonePlayerImpl()92 TonePlayerImpl::~TonePlayerImpl()
93 {
94 AUDIO_INFO_LOG("TonePlayerImpl destructor");
95 if (audioRenderer_ != nullptr) {
96 audioRenderer_->Stop();
97 audioRenderer_->Release();
98 }
99 audioRenderer_ = nullptr;
100 }
101
Create(const AudioRendererInfo & rendererInfo)102 std::shared_ptr<TonePlayer> TonePlayer::Create(const AudioRendererInfo &rendererInfo)
103 {
104 if (!PermissionUtil::VerifySelfPermission()) {
105 AUDIO_ERR_LOG("Create: No system permission");
106 return nullptr;
107 }
108 return std::make_shared<TonePlayerImpl>("", rendererInfo);
109 }
110
Create(const std::string cachePath,const AudioRendererInfo & rendererInfo)111 std::shared_ptr<TonePlayer> TonePlayer::Create(const std::string cachePath, const AudioRendererInfo &rendererInfo)
112 {
113 bool checkPermission = PermissionUtil::VerifySelfPermission();
114 CHECK_AND_RETURN_RET_LOG(checkPermission, nullptr, "Create: No system permission");
115 return std::make_shared<TonePlayerImpl>(cachePath, rendererInfo);
116 }
117
OnInterrupt(const InterruptEvent & interruptEvent)118 void TonePlayerImpl::OnInterrupt(const InterruptEvent &interruptEvent)
119 {
120 AUDIO_INFO_LOG("ToneType %{public}d eventType: %{public}d", toneType_, interruptEvent.eventType);
121 return;
122 }
123
OnStateChange(const RendererState state,const StateChangeCmdType cmdType)124 void TonePlayerImpl::OnStateChange(const RendererState state, const StateChangeCmdType __attribute__((unused)) cmdType)
125 {
126 AUDIO_INFO_LOG("ToneType %{public}d OnStateChange state: %{public}d", toneType_, state);
127 }
128
129 // LCOV_EXCL_START
OnWriteData(size_t length)130 void TonePlayerImpl::OnWriteData(size_t length)
131 {
132 std::lock_guard<std::mutex> lock(optMutex_);
133 if (toneState_ == TONE_RELEASED) {
134 AUDIO_WARNING_LOG("Tone %{public}d is already released", toneType_);
135 return;
136 }
137 BufferDesc bufDesc = {};
138 if (audioRenderer_ != nullptr) {
139 audioRenderer_->GetBufferDesc(bufDesc);
140 } else {
141 AUDIO_ERR_LOG("OnWriteData audioRenderer_ is null");
142 }
143 bufDesc.dataLength = 0;
144 if (bufDesc.bufLength == 0) {
145 AUDIO_WARNING_LOG(" bufDesc bufLength is 0");
146 return;
147 }
148
149 // Clear output buffer: WaveGenerator accumulates into audioBuffer buffer
150 memset_s(bufDesc.buffer, bufDesc.bufLength, 0, bufDesc.bufLength);
151 if (AudioToneSequenceGen(bufDesc) == false) {
152 AUDIO_WARNING_LOG("SequenceGen error");
153 bufDesc.dataLength = bufDesc.bufLength;
154 }
155 if (needFadeOut_) {
156 needFadeOut_ = false;
157 AudioRenderer::FadeOutAudioBuffer(bufDesc, rendererOptions_.streamInfo.format,
158 rendererOptions_.streamInfo.channels);
159 }
160 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(bufDesc.buffer), bufDesc.dataLength);
161 if (audioRenderer_ != nullptr) {
162 audioRenderer_->Enqueue(bufDesc);
163 } else {
164 AUDIO_ERR_LOG("AudioToneDataThreadFunc Enqueue audioRenderer_ is null");
165 }
166 }
167
LoadTone(ToneType toneType)168 bool TonePlayerImpl::LoadTone(ToneType toneType)
169 {
170 std::lock_guard<std::mutex> lock(optMutex_);
171 AUDIO_INFO_LOG("LoadTone type: %{public}d", toneType);
172 bool result = false;
173 bool checkPermission = PermissionUtil::VerifySelfPermission();
174 CHECK_AND_RETURN_RET_LOG(checkPermission, false, "LoadTone: No system permission");
175 if (toneType >= NUM_TONES) {
176 return result;
177 }
178 if (std::find(supportedTones_.begin(), supportedTones_.end(), (int32_t)toneType) == supportedTones_.end()) {
179 return result;
180 }
181 toneType_ = toneType;
182 amplitudeType_ = std::count(TONE_TYPE_LIST.begin(), TONE_TYPE_LIST.end(), toneType_) > 0 ?
183 DIGITAMPLITUDE : AMPLITUDE;
184 initialToneInfo_ = AudioPolicyManager::GetInstance().GetToneConfig(toneType, GetCountryCode());
185 if (initialToneInfo_ != nullptr && initialToneInfo_->segmentCnt == 0) {
186 AUDIO_ERR_LOG("LoadTone failed, calling GetToneConfig returned invalid");
187 return result;
188 }
189 if (!isRendererInited_) {
190 isRendererInited_ = InitAudioRenderer();
191 CHECK_AND_RETURN_RET_LOG(isRendererInited_, false, "InitAudioRenderer failed");
192 }
193 result = InitToneWaveInfo();
194 CHECK_AND_RETURN_RET_LOG(result, false, "InitToneWaveInfo failed");
195 toneState_ = TONE_INIT;
196 DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_CLIENT_PARA, DUMP_TONEPLAYER_FILENAME, &dumpFile_);
197 return result;
198 }
199
StartTone()200 bool TonePlayerImpl::StartTone()
201 {
202 std::lock_guard<std::mutex> lock(optMutex_);
203 AUDIO_INFO_LOG("STARTTONE ToneType %{public}d", toneType_);
204 CHECK_AND_RETURN_RET_LOG(toneState_ == TONE_INIT || toneState_ == TONE_STOPPED, false,
205 "Start audioRenderer_ is null");
206
207 if (!isRendererInited_ || audioRenderer_ == nullptr) {
208 AUDIO_ERR_LOG("Start audioRenderer_ is null");
209 return false;
210 }
211 bool result = audioRenderer_->Start();
212 CHECK_AND_RETURN_RET_LOG(result, result, "Start audioRenderer_ failed");
213 toneState_ = TONE_STARTING;
214 return result;
215 }
216
StopTone()217 bool TonePlayerImpl::StopTone()
218 {
219 std::lock_guard<std::mutex> lock(optMutex_);
220 AUDIO_INFO_LOG("STOPTONE ToneType %{public}d", toneType_);
221
222 if (!isRendererInited_ || audioRenderer_ == nullptr) {
223 AUDIO_ERR_LOG("Stop audioRenderer_ is null");
224 return false;
225 }
226 // in plan: mark state stopping, smooth volume in onwritedata
227 bool result = audioRenderer_->Stop();
228 CHECK_AND_RETURN_RET_LOG(result, result, "Stop audioRenderer_ failed");
229 toneState_ = TONE_STOPPING;
230 return result;
231 }
232
Release()233 bool TonePlayerImpl::Release()
234 {
235 std::unique_lock<std::mutex> lock(optMutex_);
236 toneState_ = TONE_RELEASED;
237 lock.unlock();
238 if (audioRenderer_ != nullptr) {
239 audioRenderer_->Stop();
240 audioRenderer_->Release();
241 audioRenderer_ = nullptr;
242 }
243 DumpFileUtil::CloseDumpFile(&dumpFile_);
244 return true;
245 }
246 // LCOV_EXCL_STOP
247
GetCurrentSegmentUpdated()248 void TonePlayerImpl::GetCurrentSegmentUpdated()
249 {
250 if (toneInfo_->segments[currSegment_].loopCnt) {
251 if (loopCounter_ < toneInfo_->segments[currSegment_].loopCnt) {
252 currSegment_ = toneInfo_->segments[currSegment_].loopIndx;
253 ++loopCounter_;
254 } else {
255 // completed loop. go to next segment
256 loopCounter_ = 0;
257 currSegment_++;
258 }
259 } else {
260 // no looping required , go to next segment
261 currSegment_++;
262 }
263 Trace trace("GetCurrentSegmentUpdated:toneState:" + std::to_string(toneState_) + "currSegment:" +
264 std::to_string(currSegment_));
265 AUDIO_INFO_LOG("GetCurrentSegmentUpdated loopCounter_: %{public}d, currSegment_: %{public}d",
266 loopCounter_, currSegment_);
267 }
268
CheckToneContinuity()269 bool TonePlayerImpl::CheckToneContinuity()
270 {
271 Trace trace("CheckToneContinuity:toneState:" + std::to_string(toneState_) + "currSegment:" +
272 std::to_string(currSegment_));
273 AUDIO_INFO_LOG("CheckToneContinuity Entry loopCounter_: %{public}d, currSegment_: %{public}d",
274 loopCounter_, currSegment_);
275 bool retVal = false;
276 GetCurrentSegmentUpdated();
277
278 // Handle loop if last segment reached
279 if (toneInfo_->segments[currSegment_].duration == 0) {
280 AUDIO_DEBUG_LOG("Last Seg: %{public}d", currSegment_);
281 if (currCount_ < toneInfo_->repeatCnt) {
282 currSegment_ = toneInfo_->repeatSegment;
283 ++currCount_;
284 retVal = true;
285 } else {
286 retVal = false;
287 }
288 } else {
289 retVal = true;
290 }
291 AUDIO_DEBUG_LOG("CheckToneContinuity End loopCounter_: %{public}d, currSegment_: %{public}d currCount_: %{public}d",
292 loopCounter_, currSegment_, currCount_);
293 return retVal;
294 }
295
ContinueToneplay(uint32_t reqSample,int8_t * audioBuffer)296 bool TonePlayerImpl::ContinueToneplay(uint32_t reqSample, int8_t *audioBuffer)
297 {
298 Trace trace("ContinueToneplay:toneState:" + std::to_string(toneState_) + "currSegment:" +
299 std::to_string(currSegment_));
300 if (toneState_ != TONE_RUNNING) {
301 return false;
302 }
303 if (totalSample_ <= nextSegSample_) {
304 if (toneInfo_->segments[currSegment_].duration != 0) {
305 GetSamples(toneInfo_->segments[currSegment_].waveFreq, audioBuffer, reqSample);
306 }
307 if (totalSample_ == nextSegSample_) {
308 needFadeOut_ = true;
309 }
310 return true;
311 }
312
313 if (CheckToneContinuity()) {
314 if (toneInfo_->segments[currSegment_].duration != 0) {
315 sampleCount_ = 0;
316 GetSamples(toneInfo_->segments[currSegment_].waveFreq, audioBuffer, reqSample);
317 }
318 }
319 nextSegSample_ += (toneInfo_->segments[currSegment_].duration * samplingRate_) / C1000MS;
320 AUDIO_INFO_LOG("ContinueToneplay nextSegSample_: %{public}d", nextSegSample_);
321 return true;
322 }
323
GetSamples(uint16_t * freqs,int8_t * buffer,uint32_t reqSamples)324 int32_t TonePlayerImpl::GetSamples(uint16_t *freqs, int8_t *buffer, uint32_t reqSamples)
325 {
326 Trace trace("GetSamples");
327 uint32_t index;
328 uint8_t *data;
329 uint16_t freqVal;
330 float pi = 3.1415926;
331 for (uint32_t i = 0; i <= TONEINFO_MAX_WAVES; i++) {
332 if (freqs[i] == 0) {
333 break;
334 }
335 freqVal = freqs[i];
336 AUDIO_DEBUG_LOG("GetSamples Freq: %{public}d sampleCount_: %{public}d", freqVal, sampleCount_);
337 index = sampleCount_;
338 data = reinterpret_cast<uint8_t*>(buffer);
339 double factor = freqVal * 2 * pi / samplingRate_; // 2 is a parameter in the sine wave formula
340 for (uint32_t idx = 0; idx < reqSamples; idx++) {
341 int16_t sample = amplitudeType_ * sin(factor * index);
342 uint32_t result;
343 if (i == 0) {
344 result = (sample & 0xFF);
345 *data = result & 0xFF;
346 data++;
347 *data = ((sample & 0xFF00) >> BIT8);
348 data++;
349 } else {
350 result = *data + (static_cast<uint16_t>(sample) & 0xFF);
351 *data = result & 0xFF;
352 data++;
353 *data += (result >> BIT8) + ((sample & 0xFF00) >> BIT8);
354 data++;
355 }
356 index++;
357 }
358 }
359 sampleCount_ += reqSamples;
360 return 0;
361 }
362
Str16ToStr8(std::u16string str)363 std::string TonePlayerImpl::Str16ToStr8(std::u16string str)
364 {
365 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert(DEFAULT_STRING);
366 std::string result = convert.to_bytes(str);
367 return result == DEFAULT_STRING ? "" : result;
368 }
369
GetCountryCode()370 std::string TonePlayerImpl::GetCountryCode()
371 {
372 char paramValue[SYSPARA_SIZE] = {0};
373 GetParameter(DEBUG_COUNTRYCODE_NAME, "", paramValue, SYSPARA_SIZE);
374 if (strcmp(paramValue, "")) {
375 AUDIO_DEBUG_LOG("GetParameter %{public}s", paramValue);
376 std::string countryCode(paramValue);
377 for (char &c : countryCode) {
378 c = std::tolower(c);
379 }
380 return countryCode;
381 }
382
383 std::string countryCodeStr8 = "";
384 #if defined(AUDIO_TEL_CORE_SERVICE_ENABLE) && defined(AUIDO_TEL_CELLULAR_DATA_ENABLE)
385 int32_t slotId = Telephony::CellularDataClient::GetInstance().GetDefaultCellularDataSlotId();
386 std::u16string countryCodeForNetwork;
387 DelayedRefSingleton<Telephony::CoreServiceClient>::GetInstance().GetIsoCountryCodeForNetwork(
388 slotId, countryCodeForNetwork);
389 countryCodeStr8 = Str16ToStr8(countryCodeForNetwork);
390 if (countryCodeStr8.empty()) {
391 std::u16string countryCodeForSim;
392 DelayedRefSingleton<Telephony::CoreServiceClient>::GetInstance().GetISOCountryCodeForSim(
393 slotId, countryCodeForSim);
394 countryCodeStr8 = Str16ToStr8(countryCodeForSim);
395 }
396 AUDIO_DEBUG_LOG("GetISOCountryCode %{public}s", paramValue);
397 #endif
398 for (char &c : countryCodeStr8) {
399 c = std::tolower(c);
400 }
401 return countryCodeStr8;
402 }
403
CheckToneStarted(uint32_t reqSample,int8_t * audioBuffer)404 bool TonePlayerImpl::CheckToneStarted(uint32_t reqSample, int8_t *audioBuffer)
405 {
406 Trace trace("CheckToneStarted:toneState:" + std::to_string(toneState_) + "currSegment:" +
407 std::to_string(currSegment_));
408 if (toneState_ != TONE_STARTING) {
409 return false;
410 }
411 toneState_ = TONE_RUNNING;
412 if (toneInfo_->segments[currSegment_].duration != 0) {
413 sampleCount_ = 0;
414 GetSamples(toneInfo_->segments[currSegment_].waveFreq, audioBuffer, reqSample);
415 }
416 return true;
417 }
418
CheckToneStopped()419 bool TonePlayerImpl::CheckToneStopped()
420 {
421 Trace trace("CheckToneStopped:toneState:" + std::to_string(toneState_) + "currSegment:" +
422 std::to_string(currSegment_));
423 if (toneState_ == TONE_STOPPED) {
424 return true;
425 }
426 if (toneInfo_->segments[currSegment_].duration == 0 || totalSample_ > maxSample_ || toneState_ == TONE_STOPPING) {
427 if (toneState_ == TONE_RUNNING) {
428 toneState_ = TONE_STOPPING;
429 AUDIO_DEBUG_LOG("Audicallback move playing to stoping");
430 }
431 return true;
432 }
433 return false;
434 }
435
AudioToneSequenceGen(BufferDesc & bufDesc)436 bool TonePlayerImpl::AudioToneSequenceGen(BufferDesc &bufDesc)
437 {
438 Trace trace("AudioToneSequenceGen");
439 int8_t *audioBuffer = reinterpret_cast<int8_t *>(bufDesc.buffer);
440 uint32_t totalBufAvailable = bufDesc.bufLength / sizeof(int16_t);
441 bool retVal = true;
442 while (totalBufAvailable) {
443 uint32_t reqSamples = totalBufAvailable < processSize_ * CDOUBLE ? totalBufAvailable : processSize_;
444 AUDIO_DEBUG_LOG("AudioToneDataThreadFunc, lReqSmp: %{public}d totalBufAvailable: %{public}d",
445 reqSamples, totalBufAvailable);
446 // Update pcm frame count and end time (current time at the end of this process)
447 totalSample_ += reqSamples;
448 if (CheckToneStopped()) {
449 // in plan: do smooth works
450 AUDIO_PRERELEASE_LOGI("CheckToneStopped true toneType_ %{public}d", toneType_);
451 if (toneState_ == TONE_STOPPING) {
452 toneState_ = TONE_STOPPED;
453 totalBufAvailable = 0;
454 }
455 return false;
456 } else if (CheckToneStarted(reqSamples, audioBuffer)) {
457 bufDesc.dataLength += reqSamples * sizeof(int16_t);
458 } else {
459 if (ContinueToneplay(reqSamples, audioBuffer)) {
460 bufDesc.dataLength += reqSamples * sizeof(int16_t);
461 }
462 }
463 totalBufAvailable -= reqSamples;
464 audioBuffer += reqSamples * sizeof(int16_t);
465 }
466 return retVal;
467 }
468
InitToneWaveInfo()469 bool TonePlayerImpl::InitToneWaveInfo()
470 {
471 AUDIO_INFO_LOG("InitToneWaveInfo ToneType %{public}d", toneType_);
472 if (initialToneInfo_ == NULL) {
473 return false;
474 }
475 toneInfo_ = initialToneInfo_;
476 maxSample_ = TONEINFO_INF;
477
478 // Initialize tone sequencer
479 totalSample_ = 0;
480 currSegment_ = 0;
481 currCount_ = 0;
482 loopCounter_ = 0;
483 if (toneInfo_->segments[0].duration == TONEINFO_INF) {
484 nextSegSample_ = TONEINFO_INF;
485 } else {
486 nextSegSample_ = (toneInfo_->segments[0].duration * samplingRate_) / C1000MS;
487 }
488 AUDIO_INFO_LOG("Prepare wave, nextSegSample_: %{public}d", nextSegSample_);
489 return true;
490 }
491
492 // LCOV_EXCL_START
InitAudioRenderer()493 bool TonePlayerImpl::InitAudioRenderer()
494 {
495 processSize_ = (rendererOptions_.streamInfo.samplingRate * C20MS) / C1000MS;
496 audioRenderer_ = AudioRenderer::CreateRenderer(rendererOptions_);
497 CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, false,
498 "Renderer create failed");
499
500 if (rendererOptions_.rendererInfo.streamUsage == STREAM_USAGE_VOICE_MODEM_COMMUNICATION) {
501 audioRenderer_->EnableVoiceModemCommunicationStartStream(true);
502 }
503
504 size_t targetSize = 0;
505 int32_t ret = audioRenderer_->GetBufferSize(targetSize);
506
507 AUDIO_DEBUG_LOG("Playback renderer created");
508 int32_t setRenderMode = audioRenderer_->SetRenderMode(RENDER_MODE_CALLBACK);
509 CHECK_AND_RETURN_RET_LOG(!setRenderMode, false, "initAudioRenderer: SetRenderMode failed");
510 AUDIO_DEBUG_LOG("SetRenderMode Sucessful");
511
512 if (ret == 0 && targetSize != 0) {
513 size_t bufferDuration = C20MS; // 20 -> 20ms
514 audioRenderer_->SetBufferDuration(bufferDuration);
515 AUDIO_INFO_LOG("Init renderer with buffer %{public}zu, duration %{public}zu", targetSize, bufferDuration);
516 }
517
518 audioRenderer_->SetAudioEffectMode(EFFECT_NONE);
519
520 int32_t setRendererWrite = audioRenderer_->SetRendererWriteCallback(shared_from_this());
521 CHECK_AND_RETURN_RET_LOG(!setRendererWrite, false, "SetRendererWriteCallback failed");
522 AUDIO_DEBUG_LOG("SetRendererWriteCallback Sucessful");
523
524 int32_t setRendererCallback = audioRenderer_->SetRendererCallback(shared_from_this());
525 CHECK_AND_RETURN_RET_LOG(!setRendererCallback, false, "initAudioRenderer: SetRendererCallbackfailed");
526 AUDIO_DEBUG_LOG("SetRendererCallback Sucessful");
527 return true;
528 }
529 // LCOV_EXCL_STOP
530 } // end namespace AudioStandard
531 } // end OHOS
532