1 /*
2 * Copyright (c) 2023-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 "RendererInClientInner"
17 #endif
18
19 #include "renderer_in_client.h"
20 #include "renderer_in_client_private.h"
21
22 #include <atomic>
23 #include <cinttypes>
24 #include <condition_variable>
25 #include <sstream>
26 #include <string>
27 #include <mutex>
28 #include <thread>
29
30 #include "iservice_registry.h"
31 #include "system_ability_definition.h"
32 #include "securec.h"
33 #include "hisysevent.h"
34
35 #include "audio_errors.h"
36 #include "audio_policy_manager.h"
37 #include "audio_manager_base.h"
38 #include "audio_renderer_log.h"
39 #include "audio_channel_blend.h"
40 #include "audio_server_death_recipient.h"
41 #include "audio_stream_tracker.h"
42 #include "audio_system_manager.h"
43 #include "futex_tool.h"
44 #include "ipc_stream_listener_impl.h"
45 #include "ipc_stream_listener_stub.h"
46 #include "volume_ramp.h"
47 #include "callback_handler.h"
48 #include "audio_speed.h"
49 #include "audio_spatial_channel_converter.h"
50 #include "audio_policy_manager.h"
51 #include "audio_spatialization_manager.h"
52 #include "policy_handler.h"
53 #include "volume_tools.h"
54
55 #include "media_monitor_manager.h"
56 #include "istandard_audio_service.h"
57
58 using namespace OHOS::HiviewDFX;
59 using namespace OHOS::AppExecFwk;
60
61 namespace OHOS {
62 namespace AudioStandard {
63 namespace {
64 const uint64_t OLD_BUF_DURATION_IN_USEC = 92880; // This value is used for compatibility purposes.
65 const uint64_t MAX_BUF_DURATION_IN_USEC = 2000000; // 2S
66 const int64_t MUTE_PLAY_MIN_DURAION = 3000000000; // 3S
67 const int64_t MUTE_PLAY_MAX_DURAION = 30000000000; // 30S
68 static const size_t MAX_WRITE_SIZE = 20 * 1024 * 1024; // 20M
69 static const int32_t OPERATION_TIMEOUT_IN_MS = 1000; // 1000ms
70 static const int32_t OFFLOAD_OPERATION_TIMEOUT_IN_MS = 8000; // 8000ms for offload
71 static const int32_t WRITE_CACHE_TIMEOUT_IN_MS = 1500; // 1500ms
72 static const int32_t WRITE_BUFFER_TIMEOUT_IN_MS = 20; // ms
73 static const uint32_t WAIT_FOR_NEXT_CB = 10000; // 10ms
74 static constexpr int32_t ONE_MINUTE = 60;
75 static const int32_t MAX_WRITE_INTERVAL_MS = 40;
76 constexpr int32_t RETRY_WAIT_TIME_MS = 500; // 500ms
77 constexpr int32_t MAX_RETRY_COUNT = 8;
78 } // namespace
79
80 static AppExecFwk::BundleInfo gBundleInfo_;
81 std::mutex g_serverProxyMutex;
82 sptr<IStandardAudioService> gServerProxy_ = nullptr;
83
GetAudioServerProxy()84 const sptr<IStandardAudioService> RendererInClientInner::GetAudioServerProxy()
85 {
86 std::lock_guard<std::mutex> lock(g_serverProxyMutex);
87 if (gServerProxy_ == nullptr) {
88 auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
89 if (samgr == nullptr) {
90 AUDIO_ERR_LOG("GetAudioServerProxy: get sa manager failed");
91 return nullptr;
92 }
93 sptr<IRemoteObject> object = samgr->GetSystemAbility(AUDIO_DISTRIBUTED_SERVICE_ID);
94 if (object == nullptr) {
95 AUDIO_ERR_LOG("GetAudioServerProxy: get audio service remote object failed");
96 return nullptr;
97 }
98 gServerProxy_ = iface_cast<IStandardAudioService>(object);
99 if (gServerProxy_ == nullptr) {
100 AUDIO_ERR_LOG("GetAudioServerProxy: get audio service proxy failed");
101 return nullptr;
102 }
103
104 // register death recipent to restore proxy
105 sptr<AudioServerDeathRecipient> asDeathRecipient =
106 new(std::nothrow) AudioServerDeathRecipient(getpid(), getuid());
107 if (asDeathRecipient != nullptr) {
108 asDeathRecipient->SetNotifyCb([] (pid_t pid, pid_t uid) { AudioServerDied(pid, uid); });
109 bool result = object->AddDeathRecipient(asDeathRecipient);
110 if (!result) {
111 AUDIO_ERR_LOG("GetAudioServerProxy: failed to add deathRecipient");
112 }
113 }
114 }
115 sptr<IStandardAudioService> gasp = gServerProxy_;
116 return gasp;
117 }
118
AudioServerDied(pid_t pid,pid_t uid)119 void RendererInClientInner::AudioServerDied(pid_t pid, pid_t uid)
120 {
121 AUDIO_INFO_LOG("audio server died clear proxy, will restore proxy in next call");
122 std::lock_guard<std::mutex> lock(g_serverProxyMutex);
123 gServerProxy_ = nullptr;
124 }
125
RegisterTracker(const std::shared_ptr<AudioClientTracker> & proxyObj)126 void RendererInClientInner::RegisterTracker(const std::shared_ptr<AudioClientTracker> &proxyObj)
127 {
128 if (audioStreamTracker_ && audioStreamTracker_.get() && !streamTrackerRegistered_) {
129 // make sure sessionId_ is valid.
130 AUDIO_INFO_LOG("Calling register tracker, sessionid is %{public}d", sessionId_);
131 AudioRegisterTrackerInfo registerTrackerInfo;
132
133 rendererInfo_.samplingRate = static_cast<AudioSamplingRate>(curStreamParams_.samplingRate);
134 rendererInfo_.format = static_cast<AudioSampleFormat>(curStreamParams_.format);
135 registerTrackerInfo.sessionId = sessionId_;
136 registerTrackerInfo.clientPid = clientPid_;
137 registerTrackerInfo.state = state_;
138 registerTrackerInfo.rendererInfo = rendererInfo_;
139 registerTrackerInfo.capturerInfo = capturerInfo_;
140 registerTrackerInfo.channelCount = curStreamParams_.channels;
141
142 audioStreamTracker_->RegisterTracker(registerTrackerInfo, proxyObj);
143 streamTrackerRegistered_ = true;
144 }
145 }
146
UpdateTracker(const std::string & updateCase)147 void RendererInClientInner::UpdateTracker(const std::string &updateCase)
148 {
149 if (audioStreamTracker_ && audioStreamTracker_.get()) {
150 AUDIO_DEBUG_LOG("Renderer:Calling Update tracker for %{public}s", updateCase.c_str());
151 audioStreamTracker_->UpdateTracker(sessionId_, state_, clientPid_, rendererInfo_, capturerInfo_);
152 }
153 }
154
IsHighResolution() const155 bool RendererInClientInner::IsHighResolution() const noexcept
156 {
157 return eStreamType_ == STREAM_MUSIC && curStreamParams_.samplingRate >= SAMPLE_RATE_48000 &&
158 curStreamParams_.format >= SAMPLE_S24LE;
159 }
160
InitDirectPipeType()161 void RendererInClientInner::InitDirectPipeType()
162 {
163 if (rendererInfo_.rendererFlags == AUDIO_FLAG_VOIP_DIRECT || IsHighResolution()) {
164 AudioPipeType originType = rendererInfo_.pipeType;
165 int32_t type = ipcStream_->GetStreamManagerType();
166 if (type == AUDIO_DIRECT_MANAGER_TYPE) {
167 rendererInfo_.pipeType = (rendererInfo_.rendererFlags == AUDIO_FLAG_VOIP_DIRECT) ?
168 PIPE_TYPE_CALL_OUT : PIPE_TYPE_DIRECT_MUSIC;
169 } else if (originType == PIPE_TYPE_DIRECT_MUSIC) {
170 rendererInfo_.pipeType = PIPE_TYPE_NORMAL_OUT;
171 }
172 }
173 }
174
175 // call this without lock, we should be able to call deinit in any case.
DeinitIpcStream()176 int32_t RendererInClientInner::DeinitIpcStream()
177 {
178 Trace trace("RendererInClientInner::DeinitIpcStream");
179 CHECK_AND_RETURN_RET_LOG(ipcStream_ != nullptr, ERROR,
180 "ipcStream_ is nullptr");
181 ipcStream_->Release(false);
182 return SUCCESS;
183 }
184
ConstructConfig()185 const AudioProcessConfig RendererInClientInner::ConstructConfig()
186 {
187 AudioProcessConfig config = {};
188
189 config.appInfo.appPid = clientPid_;
190 config.appInfo.appUid = clientUid_;
191 config.appInfo.appTokenId = appTokenId_;
192 config.appInfo.appFullTokenId = fullTokenId_;
193
194 config.streamInfo.channels = static_cast<AudioChannel>(curStreamParams_.channels);
195 config.streamInfo.encoding = static_cast<AudioEncodingType>(curStreamParams_.encoding);
196 config.streamInfo.format = static_cast<AudioSampleFormat>(curStreamParams_.format);
197 config.streamInfo.samplingRate = static_cast<AudioSamplingRate>(curStreamParams_.samplingRate);
198 config.streamInfo.channelLayout = static_cast<AudioChannelLayout>(curStreamParams_.channelLayout);
199 config.originalSessionId = curStreamParams_.originalSessionId;
200
201 config.audioMode = AUDIO_MODE_PLAYBACK;
202
203 if (rendererInfo_.rendererFlags != AUDIO_FLAG_NORMAL && rendererInfo_.rendererFlags != AUDIO_FLAG_VOIP_DIRECT &&
204 rendererInfo_.rendererFlags != AUDIO_FLAG_DIRECT) {
205 AUDIO_WARNING_LOG("ConstructConfig find renderer flag invalid:%{public}d", rendererInfo_.rendererFlags);
206 rendererInfo_.rendererFlags = 0;
207 }
208 config.rendererInfo = rendererInfo_;
209
210 config.capturerInfo = {};
211
212 config.streamType = eStreamType_;
213
214 config.deviceType = AudioPolicyManager::GetInstance().GetActiveOutputDevice();
215
216 config.privacyType = privacyType_;
217
218 clientConfig_ = config;
219
220 return config;
221 }
222
InitSharedBuffer()223 int32_t RendererInClientInner::InitSharedBuffer()
224 {
225 CHECK_AND_RETURN_RET_LOG(ipcStream_ != nullptr, ERR_OPERATION_FAILED, "InitSharedBuffer failed, null ipcStream_.");
226 int32_t ret = ipcStream_->ResolveBufferBaseAndGetServerSpanSize(clientBuffer_, spanSizeInFrame_,
227 engineTotalSizeInFrame_);
228
229 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && clientBuffer_ != nullptr, ret, "ResolveBuffer failed:%{public}d", ret);
230
231 uint32_t totalSizeInFrame = 0;
232 uint32_t byteSizePerFrame = 0;
233 ret = clientBuffer_->GetSizeParameter(totalSizeInFrame, byteSizePerFrame);
234
235 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && byteSizePerFrame == sizePerFrameInByte_, ret, "GetSizeParameter failed"
236 ":%{public}d, byteSizePerFrame:%{public}u, sizePerFrameInByte_:%{public}zu", ret, byteSizePerFrame,
237 sizePerFrameInByte_);
238
239 clientSpanSizeInByte_ = spanSizeInFrame_ * byteSizePerFrame;
240
241 AUDIO_INFO_LOG("totalSizeInFrame_[%{public}u] spanSizeInFrame[%{public}u] sizePerFrameInByte_[%{public}zu]"
242 "clientSpanSizeInByte_[%{public}zu]", totalSizeInFrame, spanSizeInFrame_, sizePerFrameInByte_,
243 clientSpanSizeInByte_);
244
245 return SUCCESS;
246 }
247
InitIpcStream()248 int32_t RendererInClientInner::InitIpcStream()
249 {
250 Trace trace("RendererInClientInner::InitIpcStream");
251 AudioProcessConfig config = ConstructConfig();
252 bool resetSilentMode = (gServerProxy_ == nullptr) ? true : false;
253 sptr<IStandardAudioService> gasp = RendererInClientInner::GetAudioServerProxy();
254 CHECK_AND_RETURN_RET_LOG(gasp != nullptr, ERR_OPERATION_FAILED, "Create failed, can not get service.");
255 int32_t errorCode = 0;
256 sptr<IRemoteObject> ipcProxy = nullptr;
257 AudioPlaybackCaptureConfig playbackConfig = {};
258 gasp->CreateAudioProcess(config, errorCode, playbackConfig, ipcProxy);
259 for (int32_t retrycount = 0; (errorCode == ERR_RETRY_IN_CLIENT) && (retrycount < MAX_RETRY_COUNT); retrycount++) {
260 AUDIO_WARNING_LOG("retry in client");
261 std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_WAIT_TIME_MS));
262 gasp->CreateAudioProcess(config, errorCode, playbackConfig, ipcProxy);
263 }
264 CHECK_AND_RETURN_RET_LOG(ipcProxy != nullptr, ERR_OPERATION_FAILED, "failed with null ipcProxy.");
265 ipcStream_ = iface_cast<IIpcStream>(ipcProxy);
266 CHECK_AND_RETURN_RET_LOG(ipcStream_ != nullptr, ERR_OPERATION_FAILED, "failed when iface_cast.");
267
268 // in plan next: old listener_ is destoried here, will server receive dieth notify?
269 listener_ = sptr<IpcStreamListenerImpl>::MakeSptr(shared_from_this());
270 int32_t ret = ipcStream_->RegisterStreamListener(listener_->AsObject());
271 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "RegisterStreamListener failed:%{public}d", ret);
272
273 if (resetSilentMode && gServerProxy_ != nullptr && silentModeAndMixWithOthers_) {
274 ipcStream_->SetSilentModeAndMixWithOthers(silentModeAndMixWithOthers_);
275 }
276 ret = InitSharedBuffer();
277 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "InitSharedBuffer failed:%{public}d", ret);
278
279 ret = ipcStream_->GetAudioSessionID(sessionId_);
280 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "GetAudioSessionID failed:%{public}d", ret);
281 traceTag_ = "[" + std::to_string(sessionId_) + "]RendererInClient"; // [100001]RendererInClient
282 InitCallbackHandler();
283 return SUCCESS;
284 }
285
SetInnerVolume(float volume)286 int32_t RendererInClientInner::SetInnerVolume(float volume)
287 {
288 CHECK_AND_RETURN_RET_LOG(clientBuffer_ != nullptr, ERR_OPERATION_FAILED, "buffer is not inited");
289 clientBuffer_->SetStreamVolume(volume);
290 CHECK_AND_RETURN_RET_LOG(ipcStream_ != nullptr, false, "ipcStream is not inited!");
291 int32_t ret = ipcStream_->SetClientVolume();
292 if (ret != SUCCESS) {
293 AUDIO_ERR_LOG("Set Client Volume failed:%{public}u", ret);
294 return ERROR;
295 }
296 AUDIO_PRERELEASE_LOGI("volume: %{public}f", volume);
297 return SUCCESS;
298 }
299
InitCallbackBuffer(uint64_t bufferDurationInUs)300 void RendererInClientInner::InitCallbackBuffer(uint64_t bufferDurationInUs)
301 {
302 if (bufferDurationInUs > MAX_BUF_DURATION_IN_USEC) {
303 AUDIO_ERR_LOG("InitCallbackBuffer with invalid duration %{public}" PRIu64", use default instead.",
304 bufferDurationInUs);
305 bufferDurationInUs = OLD_BUF_DURATION_IN_USEC;
306 }
307 // Calculate buffer size based on duration.
308
309 size_t metaSize = 0;
310 if (curStreamParams_.encoding == ENCODING_AUDIOVIVID) {
311 CHECK_AND_RETURN_LOG(converter_ != nullptr, "converter is not inited");
312 metaSize = converter_->GetMetaSize();
313 converter_->GetInputBufferSize(cbBufferSize_);
314 } else {
315 cbBufferSize_ = static_cast<size_t>(bufferDurationInUs * curStreamParams_.samplingRate / AUDIO_US_PER_S) *
316 sizePerFrameInByte_;
317 }
318 AUDIO_INFO_LOG("duration %{public}" PRIu64 ", ecodingType: %{public}d, size: %{public}zu, metaSize: %{public}zu",
319 bufferDurationInUs, curStreamParams_.encoding, cbBufferSize_, metaSize);
320 std::lock_guard<std::mutex> lock(cbBufferMutex_);
321 cbBuffer_ = std::make_unique<uint8_t[]>(cbBufferSize_ + metaSize);
322 }
323
324 // Sleep or wait in WaitForRunning to avoid dead looping.
WaitForRunning()325 bool RendererInClientInner::WaitForRunning()
326 {
327 Trace trace("RendererInClientInner::WaitForRunning");
328 // check renderer state_: call client write only in running else wait on statusMutex_
329 std::unique_lock<std::mutex> stateLock(statusMutex_);
330 if (state_ != RUNNING) {
331 bool stopWaiting = cbThreadCv_.wait_for(stateLock, std::chrono::milliseconds(OPERATION_TIMEOUT_IN_MS), [this] {
332 return state_ == RUNNING || cbThreadReleased_;
333 });
334 if (cbThreadReleased_) {
335 AUDIO_INFO_LOG("CBThread end in non-running status, sessionID :%{public}d", sessionId_);
336 return false;
337 }
338 if (!stopWaiting) {
339 AUDIO_DEBUG_LOG("Wait timeout, current state_ is %{public}d", state_.load()); // wait 0.5s
340 return false;
341 }
342 }
343 return true;
344 }
345
ProcessWriteInner(BufferDesc & bufferDesc)346 int32_t RendererInClientInner::ProcessWriteInner(BufferDesc &bufferDesc)
347 {
348 int32_t result = 0; // Ensure result with default value.
349 if (curStreamParams_.encoding == ENCODING_AUDIOVIVID) {
350 if (bufferDesc.dataLength != 0) {
351 result = WriteInner(bufferDesc.buffer, bufferDesc.bufLength, bufferDesc.metaBuffer, bufferDesc.metaLength);
352 } else {
353 AUDIO_WARNING_LOG("INVALID AudioVivid buffer");
354 usleep(WAIT_FOR_NEXT_CB);
355 }
356 }
357 if (curStreamParams_.encoding == ENCODING_PCM) {
358 if (bufferDesc.dataLength != 0) {
359 result = WriteInner(bufferDesc.buffer, bufferDesc.bufLength);
360 sleepCount_ = LOG_COUNT_LIMIT;
361 } else {
362 int32_t readableSizeInFrames = clientBuffer_->GetReadableDataFrames();
363 bool flagTryPrintLog = ((readableSizeInFrames >= 0) && (readableSizeInFrames < spanSizeInFrame_));
364 if (flagTryPrintLog && (sleepCount_++ == LOG_COUNT_LIMIT)) {
365 sleepCount_ = 0;
366 AUDIO_WARNING_LOG("1st or 200 times INVALID buffer");
367 }
368 usleep(WAIT_FOR_NEXT_CB);
369 }
370 }
371 if (result < 0) {
372 AUDIO_WARNING_LOG("Call write fail, result:%{public}d, bufLength:%{public}zu", result, bufferDesc.bufLength);
373 }
374 return result;
375 }
376
CheckBufferNeedWrite()377 bool RendererInClientInner::CheckBufferNeedWrite()
378 {
379 uint32_t totalSizeInFrame = clientBuffer_->GetTotalSizeInFrame();
380 size_t totalSizeInByte = totalSizeInFrame * sizePerFrameInByte_;
381 int32_t writableInFrame = clientBuffer_ -> GetWritableDataFrames();
382 size_t writableSizeInByte = writableInFrame * sizePerFrameInByte_;
383
384 if (writableInFrame <= 0) {
385 return false;
386 }
387
388 if (cbBufferSize_ > totalSizeInByte) {
389 return false;
390 }
391
392 // readable >= engineTotalSizeInFrame_
393 if (static_cast<uint64_t>(writableInFrame) <
394 (static_cast<uint64_t>(totalSizeInFrame) - engineTotalSizeInFrame_)) {
395 return false;
396 }
397
398 if (writableSizeInByte < cbBufferSize_) {
399 return false;
400 }
401
402 return true;
403 }
404
IsRestoreNeeded()405 bool RendererInClientInner::IsRestoreNeeded()
406 {
407 RestoreStatus restoreStatus = clientBuffer_->GetRestoreStatus();
408 if (restoreStatus == NEED_RESTORE) {
409 return true;
410 }
411
412 if (restoreStatus == NEED_RESTORE_TO_NORMAL) {
413 return true;
414 }
415
416 return false;
417 }
418
WaitForBufferNeedWrite()419 void RendererInClientInner::WaitForBufferNeedWrite()
420 {
421 int32_t timeout = offloadEnable_ ? OFFLOAD_OPERATION_TIMEOUT_IN_MS : WRITE_CACHE_TIMEOUT_IN_MS;
422 FutexCode futexRes = clientBuffer_->WaitFor(
423 static_cast<int64_t>(timeout) * AUDIO_US_PER_SECOND,
424 [this] () {
425 if (state_ != RUNNING) {
426 return true;
427 }
428
429 if (IsRestoreNeeded()) {
430 return true;
431 }
432
433 return CheckBufferNeedWrite();
434 });
435 if (futexRes != SUCCESS) {
436 AUDIO_ERR_LOG("futex err: %{public}d", futexRes);
437 }
438 }
439
WriteCallbackFunc()440 bool RendererInClientInner::WriteCallbackFunc()
441 {
442 CHECK_AND_RETURN_RET_LOG(!cbThreadReleased_, false, "Callback thread released");
443 Trace traceLoop("RendererInClientInner::WriteCallbackFunc");
444 if (!WaitForRunning()) {
445 return true;
446 }
447 if (cbBufferQueue_.Size() > 1) { // One callback, one enqueue, queue size should always be 1.
448 AUDIO_WARNING_LOG("The queue is too long, reducing data through loops");
449 }
450 BufferDesc temp;
451 while (cbBufferQueue_.PopNotWait(temp)) {
452 Trace traceQueuePop("RendererInClientInner::QueueWaitPop");
453 if (state_ != RUNNING) {
454 cbBufferQueue_.Push(temp);
455 AUDIO_INFO_LOG("Repush left buffer in queue");
456 break;
457 }
458 traceQueuePop.End();
459 // call write here.
460 int32_t result = ProcessWriteInner(temp);
461 // only run in pause scene, do not repush audiovivid buffer cause metadata error
462 if (result > 0 && static_cast<size_t>(result) < temp.dataLength &&
463 curStreamParams_.encoding == ENCODING_PCM) {
464 BufferDesc tmp = {temp.buffer + static_cast<size_t>(result),
465 temp.bufLength - static_cast<size_t>(result), temp.dataLength - static_cast<size_t>(result)};
466 cbBufferQueue_.Push(tmp);
467 AUDIO_INFO_LOG("Repush %{public}zu bytes in queue", temp.dataLength - static_cast<size_t>(result));
468 break;
469 }
470 }
471
472 WaitForBufferNeedWrite();
473
474 if (state_ != RUNNING) {
475 return true;
476 }
477 // call client write
478 std::shared_ptr<AudioRendererWriteCallback> cb = nullptr;
479 {
480 std::unique_lock<std::mutex> lockCb(writeCbMutex_);
481 cb = writeCb_;
482 }
483 if (cb != nullptr) {
484 Trace traceCb("RendererInClientInner::OnWriteData");
485 cb->OnWriteData(cbBufferSize_);
486 }
487
488 Trace traceQueuePush("RendererInClientInner::QueueWaitPush");
489 std::unique_lock<std::mutex> lockBuffer(cbBufferMutex_);
490 cbBufferQueue_.WaitNotEmptyFor(std::chrono::milliseconds(WRITE_BUFFER_TIMEOUT_IN_MS));
491 return true;
492 }
493
ProcessSpeed(uint8_t * & buffer,size_t & bufferSize,bool & speedCached)494 bool RendererInClientInner::ProcessSpeed(uint8_t *&buffer, size_t &bufferSize, bool &speedCached)
495 {
496 speedCached = false;
497 #ifdef SONIC_ENABLE
498 std::lock_guard lockSpeed(speedMutex_);
499 if (speedEnable_.load()) {
500 Trace trace(traceTag_ + " ProcessSpeed" + std::to_string(speed_));
501 if (audioSpeed_ == nullptr) {
502 AUDIO_ERR_LOG("audioSpeed_ is nullptr, use speed default 1.0");
503 return true;
504 }
505 int32_t outBufferSize = 0;
506 if (audioSpeed_->ChangeSpeedFunc(buffer, bufferSize, speedBuffer_, outBufferSize) == 0) {
507 bufferSize = 0;
508 AUDIO_ERR_LOG("process speed error");
509 return false;
510 }
511 if (outBufferSize == 0) {
512 AUDIO_DEBUG_LOG("speed buffer is not full");
513 return false;
514 }
515 buffer = speedBuffer_.get();
516 bufferSize = static_cast<size_t>(outBufferSize);
517 speedCached = true;
518 }
519 #endif
520 return true;
521 }
522
DfxWriteInterval()523 void RendererInClientInner::DfxWriteInterval()
524 {
525 if (preWriteEndTime_ != 0 &&
526 ((ClockTime::GetCurNano() / AUDIO_US_PER_SECOND) - preWriteEndTime_) > MAX_WRITE_INTERVAL_MS) {
527 AUDIO_WARNING_LOG("[%{public}s] write interval too long cost %{public}" PRId64,
528 logUtilsTag_.c_str(), (ClockTime::GetCurNano() / AUDIO_US_PER_SECOND) - preWriteEndTime_);
529 }
530 }
WriteInner(uint8_t * pcmBuffer,size_t pcmBufferSize,uint8_t * metaBuffer,size_t metaBufferSize)531 int32_t RendererInClientInner::WriteInner(uint8_t *pcmBuffer, size_t pcmBufferSize, uint8_t *metaBuffer,
532 size_t metaBufferSize)
533 {
534 Trace trace("RendererInClient::Write with meta " + std::to_string(pcmBufferSize));
535 CHECK_AND_RETURN_RET_LOG(curStreamParams_.encoding == ENCODING_AUDIOVIVID, ERR_NOT_SUPPORTED,
536 "Write: Write not supported. encoding doesnot match.");
537 BufferDesc bufDesc = {pcmBuffer, pcmBufferSize, pcmBufferSize, metaBuffer, metaBufferSize};
538 CHECK_AND_RETURN_RET_LOG(converter_ != nullptr, ERR_WRITE_FAILED, "Write: converter isn't init.");
539 CHECK_AND_RETURN_RET_LOG(converter_->CheckInputValid(bufDesc), ERR_INVALID_PARAM, "Write: Invalid input.");
540
541 WriteMuteDataSysEvent(pcmBuffer, pcmBufferSize);
542
543 converter_->Process(bufDesc);
544 uint8_t *buffer;
545 uint32_t bufferSize;
546 converter_->GetOutputBufferStream(buffer, bufferSize);
547 return WriteInner(buffer, bufferSize);
548 }
549
FirstFrameProcess()550 void RendererInClientInner::FirstFrameProcess()
551 {
552 if (ipcStream_ == nullptr) {
553 AUDIO_ERR_LOG("Error: ipcStream_ is not initialized!");
554 return;
555 }
556
557 // if first call, call set thread priority. if thread tid change recall set thread priority
558 if (needSetThreadPriority_.exchange(false)) {
559 ipcStream_->RegisterThreadPriority(gettid(),
560 AudioSystemManager::GetInstance()->GetSelfBundleName(clientConfig_.appInfo.appUid), METHOD_WRITE_OR_READ);
561 }
562
563 if (!hasFirstFrameWrited_.exchange(true)) { OnFirstFrameWriting(); }
564 }
565
WriteCacheData(uint8_t * buffer,size_t bufferSize,bool speedCached,size_t oriBufferSize)566 int32_t RendererInClientInner::WriteCacheData(uint8_t *buffer, size_t bufferSize, bool speedCached,
567 size_t oriBufferSize)
568 {
569 CHECK_AND_RETURN_RET_LOG(sizePerFrameInByte_ > 0, ERROR, "sizePerFrameInByte :%{public}zu", sizePerFrameInByte_);
570 size_t remainSize = (bufferSize / sizePerFrameInByte_) * sizePerFrameInByte_;
571
572 RingBufferWrapper inBuffer = {
573 .basicBufferDescs = {{
574 {.buffer = buffer, .bufLength = remainSize},
575 {.buffer = nullptr, .bufLength = 0}
576 }},
577 .dataLength = 0
578 };
579
580 while (remainSize >= sizePerFrameInByte_) {
581 FutexCode futexRes = FUTEX_OPERATION_FAILED;
582 int32_t timeout = offloadEnable_ ? OFFLOAD_OPERATION_TIMEOUT_IN_MS : WRITE_CACHE_TIMEOUT_IN_MS;
583 futexRes = clientBuffer_->WaitFor(static_cast<int64_t>(timeout) * AUDIO_US_PER_SECOND,
584 [this] () {
585 return (state_ != RUNNING) ||
586 (static_cast<uint32_t>(clientBuffer_->GetWritableDataFrames()) > 0);
587 });
588 CHECK_AND_RETURN_RET_LOG(state_ == RUNNING, ERR_ILLEGAL_STATE, "failed with state:%{public}d", state_.load());
589 CHECK_AND_RETURN_RET_LOG(futexRes != FUTEX_TIMEOUT, ERROR,
590 "write data time out, mode is %{public}s", (offloadEnable_ ? "offload" : "normal"));
591
592 uint64_t writePos = clientBuffer_->GetCurWriteFrame();
593 uint64_t readPos = clientBuffer_->GetCurReadFrame();
594 CHECK_AND_RETURN_RET_LOG(writePos >= readPos, ERROR,
595 "writePos: %{public}" PRIu64 " readPos: %{public}" PRIu64 "",
596 writePos, readPos);
597 RingBufferWrapper ringBuffer;
598 int32_t ret = clientBuffer_->GetAllWritableBufferFromPosFrame(writePos, ringBuffer);
599 CHECK_AND_RETURN_RET(ret == SUCCESS && (ringBuffer.dataLength > 0), ERROR);
600 auto copySize = std::min(remainSize, ringBuffer.dataLength);
601 inBuffer.dataLength = copySize;
602 ret = ringBuffer.CopyInputBufferValueToCurBuffer(inBuffer);
603 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "errcode: %{public}d", ret);
604 clientBuffer_->SetCurWriteFrame((writePos + (copySize / sizePerFrameInByte_)), false);
605 inBuffer.SeekFromStart(copySize);
606 remainSize -= copySize;
607 }
608 size_t writtenSize = bufferSize - remainSize;
609
610 preWriteEndTime_ = ClockTime::GetCurNano() / AUDIO_US_PER_SECOND;
611
612 if (!ProcessVolume()) {
613 return ERR_OPERATION_FAILED;
614 }
615 DumpFileUtil::WriteDumpFile(dumpOutFd_, static_cast<void *>(buffer), writtenSize);
616 VolumeTools::DfxOperation({.buffer = buffer, .bufLength = writtenSize, .dataLength = writtenSize},
617 clientConfig_.streamInfo, traceTag_, volumeDataCount_);
618
619 CHECK_AND_RETURN_RET_LOG(ipcStream_ != nullptr, ERR_OPERATION_FAILED, "WriteCacheData failed, null ipcStream_.");
620 ipcStream_->UpdatePosition(); // notiify server update position
621 HandleRendererPositionChanges(writtenSize);
622
623 return speedCached ? oriBufferSize : writtenSize;
624 }
625
WriteInner(uint8_t * buffer,size_t bufferSize)626 int32_t RendererInClientInner::WriteInner(uint8_t *buffer, size_t bufferSize)
627 {
628 // eg: RendererInClient::sessionId:100001 WriteSize:3840
629 DfxWriteInterval();
630 Trace trace(traceTag_+ " WriteSize:" + std::to_string(bufferSize));
631 CHECK_AND_RETURN_RET_LOG(buffer != nullptr && bufferSize < MAX_WRITE_SIZE && bufferSize > 0, ERR_INVALID_PARAM,
632 "invalid size is %{public}zu", bufferSize);
633
634 // Bugfix. Callback threadloop would go into infinite loop, consuming too much data from app
635 // but fail to play them due to audio server's death. Block and exit callback threadloop when server died.
636 if (gServerProxy_ == nullptr) {
637 cbThreadReleased_ = true;
638 uint32_t samplingRate = clientConfig_.streamInfo.samplingRate;
639 uint32_t channels = clientConfig_.streamInfo.channels;
640 uint32_t samplePerFrame = Util::GetSamplePerFrame(clientConfig_.streamInfo.format);
641 // calculate wait time by buffer size, 10e6 is converting seconds to microseconds
642 uint32_t waitTimeUs = bufferSize * 10e6 / (samplingRate * channels * samplePerFrame);
643 AUDIO_ERR_LOG("server is died! wait %{public}d us", waitTimeUs);
644 usleep(waitTimeUs);
645 return ERR_WRITE_BUFFER;
646 }
647
648 CHECK_AND_RETURN_RET_LOG(gServerProxy_ != nullptr, ERROR, "server is died");
649 if (clientBuffer_->GetStreamStatus() == nullptr) {
650 AUDIO_ERR_LOG("The stream status is null!");
651 return ERR_INVALID_PARAM;
652 }
653
654 if (clientBuffer_->GetStreamStatus()->load() == STREAM_STAND_BY) {
655 Trace trace2(traceTag_+ " call start to exit stand-by");
656 CHECK_AND_RETURN_RET_LOG(ipcStream_ != nullptr, ERROR, "ipcStream is not inited!");
657 int32_t ret = ipcStream_->Start();
658 AUDIO_INFO_LOG("%{public}u call start to exit stand-by ret %{public}u", sessionId_, ret);
659 }
660
661 FirstFrameProcess();
662
663 std::lock_guard<std::mutex> lock(writeMutex_);
664
665 size_t oriBufferSize = bufferSize;
666 bool speedCached = false;
667
668 unprocessedFramesBytes_.fetch_add(bufferSize / sizePerFrameInByte_);
669 if (!ProcessSpeed(buffer, bufferSize, speedCached)) {
670 return bufferSize;
671 }
672
673 WriteMuteDataSysEvent(buffer, bufferSize);
674
675 CHECK_AND_RETURN_RET_PRELOG(state_ == RUNNING, ERR_ILLEGAL_STATE,
676 "Write: Illegal state:%{public}u sessionid: %{public}u", state_.load(), sessionId_);
677
678 // hold lock
679 if (isBlendSet_) {
680 audioBlend_.Process(buffer, bufferSize);
681 }
682 totalBytesWrittenAfterFlush_.fetch_add(bufferSize / sizePerFrameInByte_);
683 int32_t result = WriteCacheData(buffer, bufferSize, speedCached, oriBufferSize);
684 MonitorMutePlay(false);
685 return result;
686 }
687
ResetFramePosition()688 void RendererInClientInner::ResetFramePosition()
689 {
690 Trace trace("RendererInClientInner::ResetFramePosition");
691 uint64_t timestampval = 0;
692 uint64_t latency = 0;
693 CHECK_AND_RETURN_LOG(ipcStream_ != nullptr, "ipcStream is not inited!");
694 int32_t ret = ipcStream_->GetAudioPosition(lastFlushReadIndex_, timestampval, latency,
695 Timestamp::Timestampbase::MONOTONIC);
696 CHECK_AND_RETURN_PRELOG(ret == SUCCESS, "Get position failed: %{public}d", ret);
697 ret = ipcStream_->GetSpeedPosition(lastSpeedFlushReadIndex_, timestampval, latency,
698 Timestamp::Timestampbase::MONOTONIC);
699 CHECK_AND_RETURN_PRELOG(ret == SUCCESS, "Get speed position failed: %{public}d", ret);
700 // no need to reset timestamp, only reset frameposition
701 for (int32_t base = 0; base < Timestamp::Timestampbase::BASESIZE; base++) {
702 lastFramePosAndTimePair_[base].first = 0;
703 lastFramePosAndTimePairWithSpeed_[base].first = 0;
704 lastSwitchPosition_[base] = 0;
705 }
706 unprocessedFramesBytes_ = 0;
707 totalBytesWrittenAfterFlush_ = 0;
708 writtenAtSpeedChange_.store(WrittenFramesWithSpeed{0, speed_});
709 }
710
IsMutePlaying()711 bool RendererInClientInner::IsMutePlaying()
712 {
713 // this is updated in DfxOperation
714 if (volumeDataCount_ < 0) {
715 return true;
716 }
717
718 return mutePlaying_;
719 }
720
MonitorMutePlay(bool isPlayEnd)721 void RendererInClientInner::MonitorMutePlay(bool isPlayEnd)
722 {
723 int64_t cur = ClockTime::GetRealNano();
724 // judge if write mute
725 bool isMutePlay = isPlayEnd ? false : IsMutePlaying();
726 // not write mute or play end
727 if (!isMutePlay) {
728 if (mutePlayStartTime_ == 0) {
729 return;
730 }
731 if (cur - mutePlayStartTime_ > MUTE_PLAY_MIN_DURAION) {
732 ReportWriteMuteEvent(cur - mutePlayStartTime_);
733 return;
734 }
735 mutePlayStartTime_ = 0;
736 return;
737 }
738
739 // write mute
740 if (mutePlayStartTime_ == 0) {
741 // record first mute play
742 mutePlayStartTime_ = cur;
743 return;
744 }
745 if (cur - mutePlayStartTime_ > MUTE_PLAY_MAX_DURAION) {
746 ReportWriteMuteEvent(cur - mutePlayStartTime_);
747 }
748 }
749
ReportWriteMuteEvent(int64_t mutePlayDuration)750 void RendererInClientInner::ReportWriteMuteEvent(int64_t mutePlayDuration)
751 {
752 mutePlayDuration /= AUDIO_US_PER_SECOND; // ns -> ms
753 bool isMute = GetMute();
754 bool isClientMute = muteCmd_ == CMD_FROM_CLIENT;
755 uint8_t muteState = (isClientMute ? 0x0 : 0x4) | (isMute ? 0x1 : 0x0);
756
757 AUDIO_WARNING_LOG("[%{public}d]MutePlaying for %{public}" PRId64" ms, muteState:%{public}d", sessionId_,
758 mutePlayDuration, muteState);
759 std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
760 Media::MediaMonitor::AUDIO, Media::MediaMonitor::APP_WRITE_MUTE, Media::MediaMonitor::EventType::FAULT_EVENT);
761 bean->Add("UID", appUid_); // for APP_BUNDLE_NAME
762 bean->Add("STREAM_TYPE", clientConfig_.rendererInfo.streamUsage);
763 bean->Add("SESSION_ID", static_cast<int32_t>(sessionId_));
764 bean->Add("STREAM_VOLUME", clientVolume_);
765 bean->Add("MUTE_STATE", static_cast<int32_t>(muteState));
766 bean->Add("APP_BACKGROUND_STATE", 0);
767 bean->Add("MUTE_PLAY_START_TIME", static_cast<uint64_t>(mutePlayStartTime_ / AUDIO_US_PER_SECOND));
768 bean->Add("MUTE_PLAY_DURATION", static_cast<int32_t>(mutePlayDuration));
769 Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
770 mutePlayStartTime_ = 0; // reset it to 0 for next record
771 }
772
WriteMuteDataSysEvent(uint8_t * buffer,size_t bufferSize)773 void RendererInClientInner::WriteMuteDataSysEvent(uint8_t *buffer, size_t bufferSize)
774 {
775 if (silentModeAndMixWithOthers_) {
776 return;
777 }
778 if (IsInvalidBuffer(buffer, bufferSize)) {
779 if (startMuteTime_ == 0) {
780 startMuteTime_ = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
781 }
782 std::time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
783 if ((currentTime - startMuteTime_ >= ONE_MINUTE) && !isUpEvent_) {
784 AUDIO_WARNING_LOG("write silent data for some time");
785 isUpEvent_ = true;
786 std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
787 Media::MediaMonitor::AUDIO, Media::MediaMonitor::BACKGROUND_SILENT_PLAYBACK,
788 Media::MediaMonitor::FREQUENCY_AGGREGATION_EVENT);
789 bean->Add("CLIENT_UID", appUid_);
790 Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
791 }
792 } else if (buffer[0] != 0 && startMuteTime_ != 0) {
793 startMuteTime_ = 0;
794 }
795 }
796
IsInvalidBuffer(uint8_t * buffer,size_t bufferSize)797 bool RendererInClientInner::IsInvalidBuffer(uint8_t *buffer, size_t bufferSize)
798 {
799 bool isInvalid = false;
800 uint8_t ui8Data = 0;
801 int16_t i16Data = 0;
802 switch (clientConfig_.streamInfo.format) {
803 case SAMPLE_U8:
804 CHECK_AND_RETURN_RET_LOG(bufferSize > 0, false, "buffer size is too small");
805 ui8Data = *buffer;
806 isInvalid = ui8Data == 0;
807 break;
808 case SAMPLE_S16LE:
809 CHECK_AND_RETURN_RET_LOG(bufferSize > 1, false, "buffer size is too small");
810 i16Data = *(reinterpret_cast<const int16_t*>(buffer));
811 isInvalid = i16Data == 0;
812 break;
813 default:
814 break;
815 }
816 return isInvalid;
817 }
818
ProcessVolume()819 bool RendererInClientInner::ProcessVolume()
820 {
821 // volume process in client
822 if (volumeRamp_.IsActive()) {
823 // do not call SetVolume here.
824 clientVolume_ = volumeRamp_.GetRampVolume();
825 AUDIO_INFO_LOG("clientVolume_:%{public}f", clientVolume_);
826 Trace traceVolume("RendererInClientInner::WriteCacheData:Ramp:clientVolume_:" + std::to_string(clientVolume_));
827 SetInnerVolume(clientVolume_);
828 }
829 return true;
830 }
831
RegisterSpatializationStateEventListener()832 int32_t RendererInClientInner::RegisterSpatializationStateEventListener()
833 {
834 if (firstSpatializationRegistered_) {
835 firstSpatializationRegistered_ = false;
836 } else {
837 UnregisterSpatializationStateEventListener(spatializationRegisteredSessionID_);
838 }
839
840 if (!spatializationStateChangeCallback_) {
841 spatializationStateChangeCallback_ = std::make_shared<SpatializationStateChangeCallbackImpl>();
842 CHECK_AND_RETURN_RET_LOG(spatializationStateChangeCallback_, ERROR, "Memory Allocation Failed !!");
843 }
844 spatializationStateChangeCallback_->SetRendererInClientPtr(shared_from_this());
845
846 int32_t ret = AudioPolicyManager::GetInstance().RegisterSpatializationStateEventListener(
847 sessionId_, rendererInfo_.streamUsage, spatializationStateChangeCallback_);
848 CHECK_AND_RETURN_RET_LOG(ret == 0, ERROR, "RegisterSpatializationStateEventListener failed");
849 spatializationRegisteredSessionID_ = sessionId_;
850
851 return SUCCESS;
852 }
853
UnregisterSpatializationStateEventListener(uint32_t sessionID)854 int32_t RendererInClientInner::UnregisterSpatializationStateEventListener(uint32_t sessionID)
855 {
856 int32_t ret = AudioPolicyManager::GetInstance().UnregisterSpatializationStateEventListener(sessionID);
857 CHECK_AND_RETURN_RET_LOG(ret == 0, ERROR, "UnregisterSpatializationStateEventListener failed");
858 return SUCCESS;
859 }
860
DrainAudioStreamInner(bool stopFlag)861 bool RendererInClientInner::DrainAudioStreamInner(bool stopFlag)
862 {
863 Trace trace("RendererInClientInner::DrainAudioStreamInner " + std::to_string(sessionId_));
864 if (state_ != RUNNING) {
865 AUDIO_ERR_LOG("Drain failed. Illegal state:%{public}u", state_.load());
866 return false;
867 }
868
869 CHECK_AND_RETURN_RET_LOG(ipcStream_ != nullptr, false, "ipcStream is not inited!");
870 AUDIO_INFO_LOG("stopFlag:%{public}d", stopFlag);
871 int32_t ret = ipcStream_->Drain(stopFlag);
872 if (ret != SUCCESS) {
873 AUDIO_ERR_LOG("Drain call server failed:%{public}u", ret);
874 return false;
875 }
876 std::unique_lock<std::mutex> waitLock(callServerMutex_);
877 bool stopWaiting = callServerCV_.wait_for(waitLock, std::chrono::milliseconds(OPERATION_TIMEOUT_IN_MS), [this] {
878 return notifiedOperation_ == DRAIN_STREAM; // will be false when got notified.
879 });
880
881 // clear cbBufferQueue
882 if (renderMode_ == RENDER_MODE_CALLBACK && stopFlag) {
883 cbBufferQueue_.Clear();
884 if (memset_s(cbBuffer_.get(), cbBufferSize_, 0, cbBufferSize_) != EOK) {
885 AUDIO_ERR_LOG("memset_s buffer failed");
886 };
887 }
888
889 if (notifiedOperation_ != DRAIN_STREAM || notifiedResult_ != SUCCESS) {
890 AUDIO_ERR_LOG("Drain failed: %{public}s Operation:%{public}d result:%{public}" PRId64".",
891 (!stopWaiting ? "timeout" : "no timeout"), notifiedOperation_, notifiedResult_);
892 notifiedOperation_ = MAX_OPERATION_CODE;
893 return false;
894 }
895 notifiedOperation_ = MAX_OPERATION_CODE;
896 waitLock.unlock();
897 AUDIO_INFO_LOG("Drain stream SUCCESS, sessionId: %{public}d", sessionId_);
898 return true;
899 }
900
RegisterThreadPriorityOnStart(StateChangeCmdType cmdType)901 void RendererInClientInner::RegisterThreadPriorityOnStart(StateChangeCmdType cmdType)
902 {
903 pid_t tid;
904 switch (rendererInfo_.playerType) {
905 case PLAYER_TYPE_ARKTS_AUDIO_RENDERER:
906 // main thread
907 tid = getpid();
908 break;
909 case PLAYER_TYPE_OH_AUDIO_RENDERER:
910 tid = gettid();
911 break;
912 default:
913 return;
914 }
915
916 if (cmdType == CMD_FROM_CLIENT) {
917 std::lock_guard lock(lastCallStartByUserTidMutex_);
918 lastCallStartByUserTid_ = tid;
919 } else if (cmdType == CMD_FROM_SYSTEM) {
920 std::lock_guard lock(lastCallStartByUserTidMutex_);
921 CHECK_AND_RETURN_LOG(lastCallStartByUserTid_.has_value(), "has not value");
922 tid = lastCallStartByUserTid_.value();
923 } else {
924 AUDIO_ERR_LOG("illegal param");
925 return;
926 }
927
928 ipcStream_->RegisterThreadPriority(tid,
929 AudioSystemManager::GetInstance()->GetSelfBundleName(clientConfig_.appInfo.appUid), METHOD_START);
930 }
931
ResetCallbackLoopTid()932 void RendererInClientInner::ResetCallbackLoopTid()
933 {
934 AUDIO_INFO_LOG("to -1");
935 callbackLoopTid_ = -1;
936 }
937
SpatializationStateChangeCallbackImpl()938 SpatializationStateChangeCallbackImpl::SpatializationStateChangeCallbackImpl()
939 {
940 AUDIO_INFO_LOG("Instance create");
941 }
942
~SpatializationStateChangeCallbackImpl()943 SpatializationStateChangeCallbackImpl::~SpatializationStateChangeCallbackImpl()
944 {
945 AUDIO_INFO_LOG("Instance destory");
946 }
947
SetRendererInClientPtr(std::shared_ptr<RendererInClientInner> rendererInClientPtr)948 void SpatializationStateChangeCallbackImpl::SetRendererInClientPtr(
949 std::shared_ptr<RendererInClientInner> rendererInClientPtr)
950 {
951 rendererInClientPtr_ = rendererInClientPtr;
952 }
953
OnSpatializationStateChange(const AudioSpatializationState & spatializationState)954 void SpatializationStateChangeCallbackImpl::OnSpatializationStateChange(
955 const AudioSpatializationState &spatializationState)
956 {
957 std::shared_ptr<RendererInClientInner> rendererInClient = rendererInClientPtr_.lock();
958 if (rendererInClient != nullptr) {
959 rendererInClient->OnSpatializationStateChange(spatializationState);
960 }
961 }
962
FlushSpeedBuffer()963 void RendererInClientInner::FlushSpeedBuffer()
964 {
965 std::lock_guard lock(speedMutex_);
966
967 if (audioSpeed_ != nullptr) {
968 audioSpeed_->Flush();
969 }
970 }
971
SetSpeedInner(float speed)972 int32_t RendererInClientInner::SetSpeedInner(float speed)
973 {
974 // set the speed to 1.0 and the speed has never been turned on, no actual sonic stream is created.
975 if (isEqual(speed, SPEED_NORMAL) && !speedEnable_) {
976 speed_ = speed;
977 return SUCCESS;
978 }
979
980 if (audioSpeed_ == nullptr) {
981 audioSpeed_ = std::make_unique<AudioSpeed>(curStreamParams_.samplingRate, curStreamParams_.format,
982 curStreamParams_.channels);
983 GetBufferSize(bufferSize_);
984 speedBuffer_ = std::make_unique<uint8_t[]>(MAX_SPEED_BUFFER_SIZE);
985 }
986 audioSpeed_->SetSpeed(speed);
987 writtenAtSpeedChange_.store(WrittenFramesWithSpeed{totalBytesWrittenAfterFlush_.load(), speed_});
988 speed_ = speed;
989 speedEnable_ = true;
990 AUDIO_DEBUG_LOG("SetSpeed %{public}f, OffloadEnable %{public}d", speed_, offloadEnable_);
991 return SUCCESS;
992 }
993 } // namespace AudioStandard
994 } // namespace OHOS
995