• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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