• 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 "PaRendererStreamImpl"
17 #endif
18 
19 #ifdef FEATURE_POWER_MANAGER
20 #include "power_mgr_client.h"
21 #endif
22 
23 #include "pa_renderer_stream_impl.h"
24 
25 #include <chrono>
26 
27 #include "safe_map.h"
28 #include "pa_adapter_tools.h"
29 #include "audio_effect_chain_manager.h"
30 #include "audio_errors.h"
31 #include "audio_service_log.h"
32 #include "common/hdi_adapter_info.h"
33 #include "manager/hdi_adapter_manager.h"
34 #include "sink/i_audio_render_sink.h"
35 #include "policy_handler.h"
36 #include "audio_volume.h"
37 #include "audio_limiter_manager.h"
38 
39 namespace OHOS {
40 namespace AudioStandard {
41 static SafeMap<void *, std::weak_ptr<PaRendererStreamImpl>> rendererStreamInstanceMap_;
42 static const int32_t PA_STREAM_IMPL_TIMEOUT = 5; // 5s
43 const uint32_t DOUBLE_VALUE = 2;
44 const uint32_t MAX_LENGTH_OFFLOAD = 500;
45 const int32_t OFFLOAD_HDI_CACHE1 = 200; // ms, should equal with val in hdi_sink.c
46 const int32_t OFFLOAD_HDI_CACHE2 = 7000; // ms, should equal with val in hdi_sink.c
47 const int32_t OFFLOAD_HDI_CACHE3 = 500; // ms, should equal with val in hdi_sink.c for movie
48 const uint32_t OFFLOAD_BUFFER = 50;
49 const uint64_t AUDIO_CYCLE_TIME_US = 20000;
50 const uint64_t BUF_LENGTH_IN_MS = 20;
51 const uint64_t CAST_BUF_LENGTH_IN_MS = 10;
52 
CheckReturnIfStreamInvalid(pa_stream * paStream,const int32_t retVal)53 static int32_t CheckReturnIfStreamInvalid(pa_stream *paStream, const int32_t retVal)
54 {
55     do {
56         if (!(paStream && PA_STREAM_IS_GOOD(pa_stream_get_state(paStream)))) {
57             return retVal;
58         }
59     } while (false);
60     return SUCCESS;
61 }
62 
PaRendererStreamImpl(pa_stream * paStream,AudioProcessConfig processConfig,pa_threaded_mainloop * mainloop)63 PaRendererStreamImpl::PaRendererStreamImpl(pa_stream *paStream, AudioProcessConfig processConfig,
64     pa_threaded_mainloop *mainloop)
65 {
66     mainloop_ = mainloop;
67     paStream_ = paStream;
68     processConfig_ = processConfig;
69     effectMode_ = processConfig.rendererInfo.effectMode;
70 }
71 
~PaRendererStreamImpl()72 PaRendererStreamImpl::~PaRendererStreamImpl()
73 {
74     AUDIO_DEBUG_LOG("~PaRendererStreamImpl");
75 
76     PaLockGuard lock(mainloop_);
77     rendererStreamInstanceMap_.Erase(this);
78     if (paStream_) {
79         if (!releasedFlag_) {
80             pa_stream_set_state_callback(paStream_, nullptr, nullptr);
81             pa_stream_set_write_callback(paStream_, nullptr, nullptr);
82             pa_stream_set_latency_update_callback(paStream_, nullptr, nullptr);
83             pa_stream_set_underflow_callback(paStream_, nullptr, nullptr);
84             pa_stream_set_moved_callback(paStream_, nullptr, nullptr);
85             pa_stream_set_started_callback(paStream_, nullptr, nullptr);
86             pa_stream_disconnect(paStream_);
87         }
88         pa_stream_unref(paStream_);
89         paStream_ = nullptr;
90     }
91 }
92 
InitParams()93 int32_t PaRendererStreamImpl::InitParams()
94 {
95     PaLockGuard lock(mainloop_);
96     rendererStreamInstanceMap_.Insert(this, weak_from_this());
97     if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) { return ERR_ILLEGAL_STATE; }
98 
99     sinkInputIndex_ = pa_stream_get_index(paStream_);
100     pa_stream_set_moved_callback(paStream_, PAStreamMovedCb,
101         reinterpret_cast<void *>(this)); // used to notify sink/source moved
102     pa_stream_set_write_callback(paStream_, PAStreamWriteCb, reinterpret_cast<void *>(this));
103     pa_stream_set_underflow_callback(paStream_, PAStreamUnderFlowCb, reinterpret_cast<void *>(this));
104     pa_stream_set_started_callback(paStream_, PAStreamSetStartedCb, reinterpret_cast<void *>(this));
105     pa_stream_set_underflow_ohos_callback(paStream_, PAStreamUnderFlowCountAddCb, reinterpret_cast<void *>(this));
106 
107     // Get byte size per frame
108     const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_);
109     CHECK_AND_RETURN_RET_LOG(sampleSpec != nullptr, ERR_OPERATION_FAILED, "pa_sample_spec sampleSpec is nullptr");
110     AUDIO_INFO_LOG("sampleSpec: channels: %{public}u, formats: %{public}d, rate: %{public}d", sampleSpec->channels,
111         sampleSpec->format, sampleSpec->rate);
112 
113     if (sampleSpec->channels != processConfig_.streamInfo.channels) {
114         AUDIO_WARNING_LOG("Unequal channels, in server: %{public}d, in client: %{public}d", sampleSpec->channels,
115             processConfig_.streamInfo.channels);
116     }
117     if (static_cast<uint8_t>(sampleSpec->format) != processConfig_.streamInfo.format) { // In plan
118         AUDIO_WARNING_LOG("Unequal format, in server: %{public}d, in client: %{public}d", sampleSpec->format,
119             processConfig_.streamInfo.format);
120     }
121     byteSizePerFrame_ = pa_frame_size(sampleSpec);
122 
123     // Get min buffer size in frame
124     const pa_buffer_attr *bufferAttr = pa_stream_get_buffer_attr(paStream_);
125     if (bufferAttr == nullptr) {
126         int32_t count = ++bufferNullCount_;
127         AUDIO_ERR_LOG("pa_stream_get_buffer_attr returned nullptr count is %{public}d", count);
128         if (count >= 5) { // bufferAttr is nullptr 5 times, reboot audioserver
129             sleep(3); // sleep 3 seconds to dump stacktrace
130             AudioXCollie audioXCollie("AudioServer::Kill", 1, nullptr, nullptr, AUDIO_XCOLLIE_FLAG_RECOVERY);
131             sleep(2); // sleep 2 seconds to dump stacktrace
132         }
133         return ERR_OPERATION_FAILED;
134     }
135     bufferNullCount_ = 0;
136     minBufferSize_ = (size_t)bufferAttr->minreq;
137     if (byteSizePerFrame_ == 0) {
138         AUDIO_ERR_LOG("byteSizePerFrame_ should not be zero.");
139         return ERR_INVALID_PARAM;
140     }
141     spanSizeInFrame_ = minBufferSize_ / byteSizePerFrame_;
142 
143     lock.Unlock();
144 
145     AudioVolume::GetInstance()->SetFadeoutState(sinkInputIndex_, NO_FADE);
146     // In plan: Get data from xml
147     effectSceneName_ = processConfig_.rendererInfo.sceneType;
148 
149     clientVolume_ = 1.0f;
150     ResetOffload();
151 
152     return SUCCESS;
153 }
154 
Start()155 int32_t PaRendererStreamImpl::Start()
156 {
157     AUDIO_INFO_LOG("[%{public}u] Enter", streamIndex_);
158     PaLockGuard lock(mainloop_);
159     if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
160         return ERR_ILLEGAL_STATE;
161     }
162     pa_operation *operation = nullptr;
163 
164     pa_stream_state_t state = pa_stream_get_state(paStream_);
165     if (state != PA_STREAM_READY) {
166         return ERR_OPERATION_FAILED;
167     }
168 
169     streamCmdStatus_ = 0;
170     uint32_t oldFadeFlag = AudioVolume::GetInstance()->GetFadeoutState(sinkInputIndex_);
171     AudioVolume::GetInstance()->SetFadeoutState(sinkInputIndex_, NO_FADE);
172     if (oldFadeFlag != NO_FADE) {
173         AUDIO_INFO_LOG("SinkInput[%{public}u] fadeflag:%{public}u set to NO_FADE", sinkInputIndex_, oldFadeFlag);
174     }
175     operation = pa_stream_cork(paStream_, 0, PAStreamStartSuccessCb, reinterpret_cast<void *>(this));
176     CHECK_AND_RETURN_RET_LOG(operation != nullptr, ERR_OPERATION_FAILED, "pa_stream_cork operation is null");
177     pa_operation_unref(operation);
178 
179     std::shared_ptr<AudioEffectVolume> audioEffectVolume = AudioEffectVolume::GetInstance();
180     if (audioEffectVolume != nullptr) {
181         std::string sessionIDTemp = std::to_string(streamIndex_);
182         audioEffectVolume->SetStreamVolume(sessionIDTemp, clientVolume_);
183     }
184 
185     return SUCCESS;
186 }
187 
Pause(bool isStandby)188 int32_t PaRendererStreamImpl::Pause(bool isStandby)
189 {
190     AUDIO_INFO_LOG("[%{public}u] Enter", streamIndex_);
191     CHECK_AND_RETURN_RET_LOG(isReleased_ == false, ERR_ILLEGAL_STATE,
192         "paStream[%{public}u] has been released", streamIndex_);
193     PaLockGuard palock(mainloop_, true);
194     if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
195         return ERR_ILLEGAL_STATE;
196     }
197     pa_operation *operation = nullptr;
198     pa_stream_state_t state = pa_stream_get_state(paStream_);
199     if (state != PA_STREAM_READY) {
200         AUDIO_ERR_LOG("Stream Stop failed!");
201         return ERR_OPERATION_FAILED;
202     }
203 
204     AudioVolume::GetInstance()->SetFadeoutState(sinkInputIndex_, DO_FADE);
205     if (!offloadEnable_) {
206         palock.Unlock();
207         {
208             std::unique_lock<std::mutex> lock(fadingMutex_);
209             const int32_t WAIT_TIME_MS = 40;
210             fadingCondition_.wait_for(lock, std::chrono::milliseconds(WAIT_TIME_MS));
211         }
212         palock.Relock();
213     }
214 
215     CHECK_AND_RETURN_RET_LOG(isReleased_ == false, ERR_ILLEGAL_STATE,
216         "paStream[%{public}u] has been released", streamIndex_);
217     CHECK_AND_RETURN_RET_LOG(paStream_ != nullptr, ERR_ILLEGAL_STATE, "paStream[%{public}u] is null", streamIndex_);
218     isStandbyPause_ = isStandby;
219     operation = pa_stream_cork(paStream_, 1, PAStreamPauseSuccessCb, reinterpret_cast<void *>(this));
220     pa_operation_unref(operation);
221     CHECK_AND_RETURN_RET_LOG(operation != nullptr, ERR_OPERATION_FAILED, "pa_stream_cork operation is null");
222     palock.Unlock();
223 
224     if (effectMode_ == EFFECT_DEFAULT) {
225         AudioEffectChainManager *audioEffectChainManager = AudioEffectChainManager::GetInstance();
226         if (audioEffectChainManager == nullptr) {
227             AUDIO_INFO_LOG("audioEffectChainManager is null");
228         } else {
229             AUDIO_INFO_LOG("Pause make init effect buffer");
230             std::string sessionIDTemp = std::to_string(streamIndex_);
231             audioEffectChainManager->InitEffectBuffer(sessionIDTemp);
232         }
233     }
234 
235     std::shared_ptr<AudioEffectVolume> audioEffectVolume = AudioEffectVolume::GetInstance();
236     if (audioEffectVolume != nullptr) {
237         std::string sessionIDTemp = std::to_string(streamIndex_);
238         audioEffectVolume->StreamVolumeDelete(sessionIDTemp);
239     }
240     return SUCCESS;
241 }
242 
Flush()243 int32_t PaRendererStreamImpl::Flush()
244 {
245     AUDIO_INFO_LOG("[%{public}u] Enter", streamIndex_);
246     PaLockGuard lock(mainloop_);
247     if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
248         return ERR_ILLEGAL_STATE;
249     }
250 
251     pa_operation *operation = nullptr;
252     pa_stream_state_t state = pa_stream_get_state(paStream_);
253     if (state != PA_STREAM_READY) {
254         AUDIO_ERR_LOG("Stream Flush failed!");
255         return ERR_OPERATION_FAILED;
256     }
257 
258     streamFlushStatus_ = 0;
259     operation = pa_stream_flush(paStream_, PAStreamFlushSuccessCb, reinterpret_cast<void *>(this));
260     if (operation == nullptr) {
261         AUDIO_ERR_LOG("Stream Flush Operation failed!");
262         return ERR_OPERATION_FAILED;
263     }
264     Trace trace("PaRendererStreamImpl::InitAudioEffectChainDynamic");
265 
266     if (effectMode_ == EFFECT_DEFAULT) {
267         AudioEffectChainManager *audioEffectChainManager = AudioEffectChainManager::GetInstance();
268         if (audioEffectChainManager == nullptr) {
269             AUDIO_INFO_LOG("audioEffectChainManager is null");
270         } else {
271             AUDIO_INFO_LOG("Flush make init effect buffer");
272             std::string sessionIDTemp = std::to_string(streamIndex_);
273             audioEffectChainManager->InitEffectBuffer(sessionIDTemp);
274         }
275     }
276 
277     pa_operation_unref(operation);
278     return SUCCESS;
279 }
280 
Drain(bool stopFlag)281 int32_t PaRendererStreamImpl::Drain(bool stopFlag)
282 {
283     AUDIO_INFO_LOG("[%{public}u] Enter", streamIndex_);
284     PaLockGuard lock(mainloop_);
285     if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
286         return ERR_ILLEGAL_STATE;
287     }
288     isDrain_ = true;
289 
290     pa_operation *operation = nullptr;
291     pa_stream_state_t state = pa_stream_get_state(paStream_);
292     if (state != PA_STREAM_READY) {
293         AUDIO_ERR_LOG("Stream drain failed, state is not ready");
294         return ERR_OPERATION_FAILED;
295     }
296     streamDrainStatus_ = 0;
297     if (stopFlag && !offloadEnable_) {
298         AudioVolume::GetInstance()->SetStopFadeoutState(sinkInputIndex_, DO_FADE);
299         isDoFadeOut = true;
300     }
301     operation = pa_stream_drain(paStream_, PAStreamDrainSuccessCb, reinterpret_cast<void *>(this));
302     pa_operation_unref(operation);
303     return SUCCESS;
304 }
305 
Stop()306 int32_t PaRendererStreamImpl::Stop()
307 {
308     AUDIO_INFO_LOG("[%{public}u] Enter", streamIndex_);
309     CHECK_AND_RETURN_RET_LOG(isReleased_ == false, ERR_ILLEGAL_STATE,
310         "paStream[%{public}u] has been released", streamIndex_);
311     state_ = STOPPING;
312     PaLockGuard palock(mainloop_);
313 
314     if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
315         return ERR_ILLEGAL_STATE;
316     }
317 
318     if (!isDoFadeOut && !offloadEnable_) {
319         AudioVolume::GetInstance()->SetFadeoutState(sinkInputIndex_, DO_FADE);
320         palock.Unlock();
321         {
322             std::unique_lock<std::mutex> lock(fadingMutex_);
323             const int32_t WAIT_TIME_MS = 20;
324             fadingCondition_.wait_for(lock, std::chrono::milliseconds(WAIT_TIME_MS));
325         }
326         palock.Relock();
327     }
328     isDoFadeOut = false;
329     CHECK_AND_RETURN_RET_LOG(isReleased_ == false, ERR_ILLEGAL_STATE,
330         "paStream[%{public}u] has been released", streamIndex_);
331     CHECK_AND_RETURN_RET_LOG(paStream_ != nullptr, ERR_ILLEGAL_STATE, "paStream[%{public}u] is null", streamIndex_);
332 
333     pa_operation *operation = pa_stream_cork(paStream_, 1, PaRendererStreamImpl::PAStreamAsyncStopSuccessCb,
334         reinterpret_cast<void *>(this));
335     CHECK_AND_RETURN_RET_LOG(operation != nullptr, ERR_OPERATION_FAILED, "pa_stream_cork operation is null");
336     pa_operation_unref(operation);
337 
338     if (effectMode_ == EFFECT_DEFAULT) {
339         AudioEffectChainManager *audioEffectChainManager = AudioEffectChainManager::GetInstance();
340         if (audioEffectChainManager == nullptr) {
341             AUDIO_INFO_LOG("audioEffectChainManager is null");
342         } else {
343             AUDIO_INFO_LOG("Stop make init effect buffer");
344             std::string sessionIDTemp = std::to_string(streamIndex_);
345             audioEffectChainManager->InitEffectBuffer(sessionIDTemp);
346         }
347     }
348 
349     std::shared_ptr<AudioEffectVolume> audioEffectVolume = AudioEffectVolume::GetInstance();
350     if (audioEffectVolume != nullptr) {
351         std::string sessionIDTemp = std::to_string(streamIndex_);
352         audioEffectVolume->StreamVolumeDelete(sessionIDTemp);
353     }
354 
355     return SUCCESS;
356 }
357 
Release()358 int32_t PaRendererStreamImpl::Release()
359 {
360     AUDIO_INFO_LOG("[%{public}u] Enter", streamIndex_);
361     isReleased_ = true;
362     if (state_ == RUNNING) {
363         PaLockGuard lock(mainloop_);
364         if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
365             return ERR_ILLEGAL_STATE;
366         }
367         pa_operation *operation = pa_stream_cork(paStream_, 1, nullptr, nullptr);
368         CHECK_AND_RETURN_RET_LOG(operation != nullptr, ERR_OPERATION_FAILED, "pa_stream_cork operation is null");
369         pa_operation_unref(operation);
370     }
371 
372     std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
373     if (statusCallback != nullptr) {
374         statusCallback->OnStatusUpdate(OPERATION_RELEASED);
375     }
376     state_ = RELEASED;
377 
378     if (effectMode_ == EFFECT_DEFAULT) {
379         AudioEffectChainManager *audioEffectChainManager = AudioEffectChainManager::GetInstance();
380         if (audioEffectChainManager == nullptr) {
381             AUDIO_INFO_LOG("audioEffectChainManager is null");
382         } else {
383             AUDIO_INFO_LOG("Release make init effect buffer");
384             std::string sessionIDTemp = std::to_string(streamIndex_);
385             audioEffectChainManager->InitEffectBuffer(sessionIDTemp);
386         }
387     }
388 
389     std::shared_ptr<AudioEffectVolume> audioEffectVolume = AudioEffectVolume::GetInstance();
390     if (audioEffectVolume != nullptr) {
391         std::string sessionIDTemp = std::to_string(streamIndex_);
392         audioEffectVolume->StreamVolumeDelete(sessionIDTemp);
393     }
394 
395     AudioVolume::GetInstance()->RemoveFadeoutState(sinkInputIndex_);
396     AudioVolume::GetInstance()->RemoveStopFadeoutState(sinkInputIndex_);
397     isDoFadeOut = false;
398 
399     PaLockGuard lock(mainloop_);
400     if (paStream_) {
401         pa_stream_set_state_callback(paStream_, nullptr, nullptr);
402         pa_stream_set_write_callback(paStream_, nullptr, nullptr);
403         pa_stream_set_latency_update_callback(paStream_, nullptr, nullptr);
404         pa_stream_set_underflow_callback(paStream_, nullptr, nullptr);
405         pa_stream_set_moved_callback(paStream_, nullptr, nullptr);
406         pa_stream_set_started_callback(paStream_, nullptr, nullptr);
407 
408         pa_stream_disconnect(paStream_);
409         releasedFlag_ = true;
410     }
411 
412     return SUCCESS;
413 }
414 
GetStreamFramesWritten(uint64_t & framesWritten)415 int32_t PaRendererStreamImpl::GetStreamFramesWritten(uint64_t &framesWritten)
416 {
417     CHECK_AND_RETURN_RET_LOG(byteSizePerFrame_ != 0, ERR_ILLEGAL_STATE, "Error frame size");
418     framesWritten = totalBytesWritten_ / byteSizePerFrame_;
419     return SUCCESS;
420 }
421 
GetCurrentTimeStamp(uint64_t & timestamp)422 int32_t PaRendererStreamImpl::GetCurrentTimeStamp(uint64_t &timestamp)
423 {
424     PaLockGuard lock(mainloop_);
425     if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
426         return ERR_ILLEGAL_STATE;
427     }
428     if (state_ == RELEASED) {
429         AUDIO_WARNING_LOG("stream is released, remain current timestamp unchanged");
430         return SUCCESS;
431     }
432     AudioXCollie audioXCollie("PaRendererStreamImpl::GetCurrentTimeStamp", PA_STREAM_IMPL_TIMEOUT,
433         [](void *) {
434             AUDIO_ERR_LOG("pulseAudio timeout");
435         }, nullptr, AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
436 
437     UpdatePaTimingInfo();
438 
439     const pa_timing_info *info = pa_stream_get_timing_info(paStream_);
440     if (info == nullptr) {
441         AUDIO_ERR_LOG("pa_stream_get_timing_info failed");
442         return ERR_OPERATION_FAILED;
443     }
444 
445     const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_);
446     timestamp = pa_bytes_to_usec(info->write_index, sampleSpec);
447     return SUCCESS;
448 }
449 
GetCurrentPosition(uint64_t & framePosition,uint64_t & timestamp,uint64_t & latency,int32_t base)450 int32_t PaRendererStreamImpl::GetCurrentPosition(uint64_t &framePosition, uint64_t &timestamp, uint64_t &latency,
451     int32_t base)
452 {
453     Trace trace("PaRendererStreamImpl::GetCurrentPosition");
454     PaLockGuard lock(mainloop_);
455     if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
456         return ERR_ILLEGAL_STATE;
457     }
458     if (state_ == RELEASED) {
459         AUDIO_WARNING_LOG("stream is released, remain current position unchanged");
460         return SUCCESS;
461     }
462     AudioXCollie audioXCollie("PaRendererStreamImpl::GetCurrentPosition", PA_STREAM_IMPL_TIMEOUT,
463         [](void *) { AUDIO_ERR_LOG("pulseAudio timeout"); }, nullptr,
464         AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
465 
466     pa_usec_t curTimeGetLatency = pa_rtclock_now();
467     if (curTimeGetLatency - preTimeGetPaLatency_ > AUDIO_CYCLE_TIME_US || firstGetPaLatency_) { // 20000 cycle time
468         UpdatePaTimingInfo();
469         firstGetPaLatency_ = false;
470         preTimeGetPaLatency_ = curTimeGetLatency;
471     }
472 
473     const pa_timing_info *info = pa_stream_get_timing_info(paStream_);
474     CHECK_AND_RETURN_RET_LOG(info != nullptr, ERR_OPERATION_FAILED, "pa_stream_get_timing_info failed");
475     const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_);
476     uint64_t readIndex = pa_bytes_to_usec(info->read_index, sampleSpec);
477     framePosition = readIndex * sampleSpec->rate / AUDIO_US_PER_S;
478     latency = info->sink_usec * sampleSpec->rate / AUDIO_US_PER_S;
479     lock.Unlock();
480 
481     // Processing data for algorithmic time delays
482     uint32_t algorithmLatency = GetEffectChainLatency();
483     if (!offloadEnable_) {
484         latency += algorithmLatency * sampleSpec->rate / AUDIO_MS_PER_S;
485     }
486     // Processing data for a2dpoffload time delays
487     uint32_t a2dpOffloadLatency = GetA2dpOffloadLatency();
488     latency += a2dpOffloadLatency * sampleSpec->rate / AUDIO_MS_PER_S;
489     // Processing data for nearlink time delays
490     uint32_t nearlinkLatency = GetNearlinkLatency();
491     latency += nearlinkLatency * sampleSpec->rate / AUDIO_MS_PER_S;
492 
493     int64_t stamp = 0;
494     stamp = base == Timestamp::BOOTTIME ? ClockTime::GetBootNano() : ClockTime::GetCurNano();
495     timestamp = stamp >= 0 ? stamp : 0;
496 
497     AUDIO_DEBUG_LOG("Latency info: framePosition: %{public}" PRIu64 ",readIndex %{public}" PRIu64
498         ", base %{public}d, timestamp %{public}" PRIu64
499         ", effect latency: %{public}u ms, a2dp offload latency: %{public}u ms, nearlink latency: %{public}u ms",
500         framePosition, readIndex, base, timestamp, algorithmLatency, a2dpOffloadLatency, nearlinkLatency);
501     return SUCCESS;
502 }
503 
PAStreamUpdateTimingInfoSuccessCb(pa_stream * stream,int32_t success,void * userdata)504 void PaRendererStreamImpl::PAStreamUpdateTimingInfoSuccessCb(pa_stream *stream, int32_t success, void *userdata)
505 {
506     PaRendererStreamImpl *rendererStreamImpl = (PaRendererStreamImpl *)userdata;
507     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)rendererStreamImpl->mainloop_;
508     pa_threaded_mainloop_signal(mainLoop, 0);
509 }
510 
GetLatency(uint64_t & latency)511 int32_t PaRendererStreamImpl::GetLatency(uint64_t &latency)
512 {
513     Trace trace("PaRendererStreamImpl::GetLatency");
514     AudioXCollie audioXCollie("PaRendererStreamImpl::GetLatency", PA_STREAM_IMPL_TIMEOUT,
515         [](void *) {
516             AUDIO_ERR_LOG("pulseAudio timeout");
517         }, nullptr, AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
518     pa_usec_t curTimeGetLatency = pa_rtclock_now();
519     if (curTimeGetLatency - preTimeGetLatency_ < AUDIO_CYCLE_TIME_US && !firstGetLatency_) { // 20000 cycle time
520         latency = preLatency_;
521         return SUCCESS;
522     }
523     PaLockGuard lock(mainloop_);
524     if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
525         return ERR_ILLEGAL_STATE;
526     }
527     if (state_ == RELEASED) {
528         AUDIO_WARNING_LOG("stream is released, latency is 0");
529         latency = 0;
530         return SUCCESS;
531     }
532     pa_usec_t paLatency {0};
533 
534     UpdatePaTimingInfo();
535     const pa_timing_info *info = pa_stream_get_timing_info(paStream_);
536     CHECK_AND_RETURN_RET_LOG(info != nullptr, ERR_OPERATION_FAILED, "pa_stream_get_timing_info failed");
537     const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_);
538     uint64_t readIndex = pa_bytes_to_usec(info->read_index < 0 ? 0 : info->read_index, sampleSpec);
539     uint64_t writeIndex = pa_bytes_to_usec(info->write_index < 0 ? 0 : info->write_index, sampleSpec);
540     pa_usec_t usec = readIndex >= info->sink_usec ? readIndex - info->sink_usec : 0;
541     paLatency = writeIndex >= usec ? writeIndex - usec : 0;
542     lock.Unlock();
543 
544     latency = paLatency;
545     uint32_t algorithmLatency = GetEffectChainLatency();
546     latency += offloadEnable_ ? 0 : algorithmLatency * AUDIO_US_PER_MS;
547     uint32_t a2dpOffloadLatency = GetA2dpOffloadLatency();
548     latency += a2dpOffloadLatency * AUDIO_US_PER_MS;
549     uint32_t nearlinkLatency = GetNearlinkLatency();
550     latency += nearlinkLatency * AUDIO_US_PER_MS;
551     uint32_t limiterLatency = GetLimiterLatency();
552     latency += limiterLatency * AUDIO_US_PER_MS;
553 
554     AUDIO_DEBUG_LOG("total latency: %{public}" PRIu64 ", pa latency: %{public}" PRIu64 ", algo latency: %{public}u ms"
555         ", a2dp offload latency: %{public}u ms, nearlink latency: %{public}u ms, lmt latency: %{public}u ms"
556         ", write: %{public}" PRIu64 ", read: %{public}" PRIu64 ", sink:%{public}" PRIu64 "", latency, paLatency,
557         algorithmLatency, a2dpOffloadLatency, nearlinkLatency, limiterLatency, writeIndex, readIndex, info->sink_usec);
558 
559     preLatency_ = latency;
560     preTimeGetLatency_ = curTimeGetLatency;
561     firstGetLatency_ = false;
562     return SUCCESS;
563 }
564 
GetEffectChainLatency()565 uint32_t PaRendererStreamImpl::GetEffectChainLatency()
566 {
567     AudioEffectChainManager *audioEffectChainManager = AudioEffectChainManager::GetInstance();
568     uint32_t algorithmLatency = 0;
569     if (audioEffectChainManager != nullptr) {
570         algorithmLatency = audioEffectChainManager->GetLatency(std::to_string(streamIndex_));
571     }
572     return algorithmLatency;
573 }
574 
GetA2dpOffloadLatency()575 uint32_t PaRendererStreamImpl::GetA2dpOffloadLatency()
576 {
577     Trace trace("PaRendererStreamImpl::GetA2dpOffloadLatency");
578     uint32_t a2dpOffloadLatency = 0;
579     uint64_t a2dpOffloadSendDataSize = 0;
580     uint32_t a2dpOffloadTimestamp = 0;
581     auto& handle = PolicyHandler::GetInstance();
582     int32_t ret = handle.OffloadGetRenderPosition(a2dpOffloadLatency, a2dpOffloadSendDataSize, a2dpOffloadTimestamp);
583     if (ret != SUCCESS) {
584         AUDIO_ERR_LOG("OffloadGetRenderPosition failed");
585     }
586     return a2dpOffloadLatency;
587 }
588 
GetNearlinkLatency()589 uint32_t PaRendererStreamImpl::GetNearlinkLatency()
590 {
591     Trace trace("PaRendererStreamImpl::GetNearlinkLatency");
592     uint32_t nearlinkLatency = 0;
593     auto &handler = PolicyHandler::GetInstance();
594     int32_t ret = handler.NearlinkGetRenderPosition(nearlinkLatency);
595     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, 0, "NearlinkGetRenderPosition failed");
596 
597     return nearlinkLatency;
598 }
599 
GetLimiterLatency()600 uint32_t PaRendererStreamImpl::GetLimiterLatency()
601 {
602     AudioLmtManager *audioLmtManager = AudioLmtManager::GetInstance();
603     uint32_t limiterLatency = 0;
604     if (audioLmtManager != nullptr) {
605         int32_t sinkIndex = static_cast<int32_t>(pa_stream_get_device_index(paStream_));
606         limiterLatency = audioLmtManager->GetLatency(sinkIndex);
607     }
608     return limiterLatency;
609 }
610 
SetRate(int32_t rate)611 int32_t PaRendererStreamImpl::SetRate(int32_t rate)
612 {
613     AUDIO_INFO_LOG("SetRate in");
614     PaLockGuard lock(mainloop_);
615     if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
616         return ERR_ILLEGAL_STATE;
617     }
618     uint32_t currentRate = processConfig_.streamInfo.samplingRate;
619     switch (rate) {
620         case RENDER_RATE_NORMAL:
621             break;
622         case RENDER_RATE_DOUBLE:
623             currentRate *= DOUBLE_VALUE;
624             break;
625         case RENDER_RATE_HALF:
626             currentRate /= DOUBLE_VALUE;
627             break;
628         default:
629             return ERR_INVALID_PARAM;
630     }
631     renderRate_ = rate;
632 
633     pa_operation *operation = pa_stream_update_sample_rate(paStream_, currentRate, nullptr, nullptr);
634     if (operation != nullptr) {
635         pa_operation_unref(operation);
636     } else {
637         AUDIO_ERR_LOG("SetRate: operation is nullptr!");
638     }
639     return SUCCESS;
640 }
641 
SetAudioEffectMode(int32_t effectMode)642 int32_t PaRendererStreamImpl::SetAudioEffectMode(int32_t effectMode)
643 {
644     AUDIO_INFO_LOG("SetAudioEffectMode: %{public}d", effectMode);
645     PaLockGuard lock(mainloop_);
646     if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
647         return ERR_ILLEGAL_STATE;
648     }
649 
650     effectMode_ = effectMode;
651     const std::string effectModeName = GetEffectModeName(effectMode_);
652 
653     pa_proplist *propList = pa_proplist_new();
654     if (propList == nullptr) {
655         AUDIO_ERR_LOG("pa_proplist_new failed");
656         return ERR_OPERATION_FAILED;
657     }
658 
659     pa_proplist_sets(propList, "scene.mode", effectModeName.c_str());
660     pa_operation *updatePropOperation = pa_stream_proplist_update(paStream_, PA_UPDATE_REPLACE, propList,
661         nullptr, nullptr);
662     pa_proplist_free(propList);
663     CHECK_AND_RETURN_RET_LOG(updatePropOperation != nullptr, ERR_OPERATION_FAILED, "updatePropOperation is nullptr!");
664     pa_operation_unref(updatePropOperation);
665 
666     return SUCCESS;
667 }
668 
GetEffectModeName(int32_t effectMode)669 const std::string PaRendererStreamImpl::GetEffectModeName(int32_t effectMode)
670 {
671     std::string name;
672     switch (effectMode) {
673         case 0: // AudioEffectMode::EFFECT_NONE
674             name = "EFFECT_NONE";
675             break;
676         default:
677             name = "EFFECT_DEFAULT";
678     }
679 
680     const std::string modeName = name;
681     return modeName;
682 }
683 
GetAudioEffectMode(int32_t & effectMode)684 int32_t PaRendererStreamImpl::GetAudioEffectMode(int32_t &effectMode)
685 {
686     effectMode = effectMode_;
687     return SUCCESS;
688 }
689 
SetPrivacyType(int32_t privacyType)690 int32_t PaRendererStreamImpl::SetPrivacyType(int32_t privacyType)
691 {
692     AUDIO_DEBUG_LOG("SetInnerCapturerState: %{public}d", privacyType);
693     privacyType_ = privacyType;
694     return SUCCESS;
695 }
696 
GetPrivacyType(int32_t & privacyType)697 int32_t PaRendererStreamImpl::GetPrivacyType(int32_t &privacyType)
698 {
699     privacyType_ = privacyType;
700     return SUCCESS;
701 }
702 
SetSpeed(float speed)703 int32_t PaRendererStreamImpl::SetSpeed(float speed)
704 {
705     AUDIO_WARNING_LOG("not support");
706     return ERR_NOT_SUPPORTED;
707 }
708 
RegisterStatusCallback(const std::weak_ptr<IStatusCallback> & callback)709 void PaRendererStreamImpl::RegisterStatusCallback(const std::weak_ptr<IStatusCallback> &callback)
710 {
711     AUDIO_DEBUG_LOG("RegisterStatusCallback in");
712     statusCallback_ = callback;
713 }
714 
RegisterWriteCallback(const std::weak_ptr<IWriteCallback> & callback)715 void PaRendererStreamImpl::RegisterWriteCallback(const std::weak_ptr<IWriteCallback> &callback)
716 {
717     AUDIO_DEBUG_LOG("RegisterWriteCallback in");
718     writeCallback_ = callback;
719 }
720 
DequeueBuffer(size_t length)721 BufferDesc PaRendererStreamImpl::DequeueBuffer(size_t length)
722 {
723     BufferDesc bufferDesc;
724     bufferDesc.bufLength = length;
725     // DequeueBuffer is called in PAStreamWriteCb which is running in mainloop, so don't need lock mainloop.
726     pa_stream_begin_write(paStream_, reinterpret_cast<void **>(&bufferDesc.buffer), &bufferDesc.bufLength);
727     return bufferDesc;
728 }
729 
EnqueueBuffer(const BufferDesc & bufferDesc)730 int32_t PaRendererStreamImpl::EnqueueBuffer(const BufferDesc &bufferDesc)
731 {
732     Trace trace("PaRendererStreamImpl::EnqueueBuffer " + std::to_string(bufferDesc.bufLength) + " totalBytesWritten" +
733         std::to_string(totalBytesWritten_));
734     int32_t error = 0;
735     if (offloadEnable_) {
736         error = OffloadUpdatePolicyInWrite();
737         CHECK_AND_RETURN_RET_LOG(error == SUCCESS, error, "OffloadUpdatePolicyInWrite failed");
738     }
739 
740     // EnqueueBuffer is called in mainloop in most cases and don't need lock.
741     PaLockGuard palock(mainloop_, true);
742 
743     if (paStream_ == nullptr) {
744         AUDIO_ERR_LOG("paStream is nullptr!");
745         return ERR_ILLEGAL_STATE;
746     }
747 
748     error = pa_stream_write(paStream_, static_cast<void*>(bufferDesc.buffer), bufferDesc.bufLength, nullptr,
749         0LL, PA_SEEK_RELATIVE);
750     if (error < 0) {
751         AUDIO_ERR_LOG("Write stream failed");
752         pa_stream_cancel_write(paStream_);
753     }
754     totalBytesWritten_ += bufferDesc.bufLength;
755     return SUCCESS;
756 }
757 
PAStreamWriteCb(pa_stream * stream,size_t length,void * userdata)758 void PaRendererStreamImpl::PAStreamWriteCb(pa_stream *stream, size_t length, void *userdata)
759 {
760     CHECK_AND_RETURN_LOG(userdata, "PAStreamWriteCb: userdata is null");
761 
762     std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
763     if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
764         AUDIO_ERR_LOG("streamImpl is nullptr!");
765         return;
766     }
767     auto streamImpl = paRendererStreamWeakPtr.lock();
768     CHECK_AND_RETURN_LOG(streamImpl, "PAStreamWriteCb: userdata is null");
769 
770     Trace trace("PaRendererStreamImpl::PAStreamWriteCb sink-input:" + std::to_string(streamImpl->sinkInputIndex_) +
771         " length:" + std::to_string(length));
772     std::shared_ptr<IWriteCallback> writeCallback = streamImpl->writeCallback_.lock();
773     if (writeCallback != nullptr) {
774         writeCallback->OnWriteData(length);
775     } else {
776         AUDIO_ERR_LOG("Write callback is nullptr!");
777     }
778 }
779 
PAStreamMovedCb(pa_stream * stream,void * userdata)780 void PaRendererStreamImpl::PAStreamMovedCb(pa_stream *stream, void *userdata)
781 {
782     CHECK_AND_RETURN_LOG(userdata, "PAStreamMovedCb: userdata is null");
783 
784     // get stream informations.
785     uint32_t deviceIndex = pa_stream_get_device_index(stream); // pa_context_get_sink_info_by_index
786     uint32_t streamIndex = pa_stream_get_index(stream); // get pa_stream index
787     const char *deviceName = pa_stream_get_device_name(stream);
788 
789     std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
790     if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
791         AUDIO_ERR_LOG("streamImpl is nullptr!");
792         return;
793     }
794     auto streamImpl = paRendererStreamWeakPtr.lock();
795     CHECK_AND_RETURN_LOG(streamImpl, "PAStreamMovedCb: userdata is null");
796 
797     if (deviceName != nullptr && !strcmp(deviceName, REMOTE_CAST_INNER_CAPTURER_SINK_NAME)) {
798         streamImpl->remoteCastMovedFlag_ = true;
799         streamImpl->UpdateBufferSize(CAST_BUF_LENGTH_IN_MS);
800     } else if (streamImpl->remoteCastMovedFlag_) {
801         streamImpl->remoteCastMovedFlag_ = false;
802         streamImpl->UpdateBufferSize(BUF_LENGTH_IN_MS);
803     }
804 
805     // Return 1 if the sink or source this stream is connected to has been suspended.
806     // This will return 0 if not, and a negative value on error.
807     int res = pa_stream_is_suspended(stream);
808     AUDIO_WARNING_LOG("PAstream:[%{public}d] moved to index:[%{public}d] suspended:[%{public}d]",
809         streamIndex, deviceIndex, res);
810 }
811 
PAStreamUnderFlowCb(pa_stream * stream,void * userdata)812 void PaRendererStreamImpl::PAStreamUnderFlowCb(pa_stream *stream, void *userdata)
813 {
814     Trace trace("PaRendererStreamImpl::PAStreamUnderFlowCb");
815     CHECK_AND_RETURN_LOG(userdata, "userdata is null");
816 
817     std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
818     if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
819         AUDIO_ERR_LOG("streamImpl is nullptr!");
820         return;
821     }
822     auto streamImpl = paRendererStreamWeakPtr.lock();
823     CHECK_AND_RETURN_LOG(streamImpl, "PAStreamWriteCb: userdata is null");
824 
825     streamImpl->underFlowCount_++;
826     std::shared_ptr<IStatusCallback> statusCallback = streamImpl->statusCallback_.lock();
827     if (statusCallback != nullptr) {
828         statusCallback->OnStatusUpdate(OPERATION_UNDERRUN);
829     }
830     AUDIO_WARNING_LOG("PaRendererStreamImpl underrun: %{public}d!", streamImpl->underFlowCount_);
831 }
832 
PAStreamUnderFlowCountAddCb(pa_stream * stream,void * userdata)833 void PaRendererStreamImpl::PAStreamUnderFlowCountAddCb(pa_stream *stream, void *userdata)
834 {
835     Trace trace("PaRendererStreamImpl::PAStreamUnderFlowCountAddCb");
836     CHECK_AND_RETURN_LOG(userdata, "userdata is null");
837 
838     std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
839     if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
840         AUDIO_ERR_LOG("streamImpl is nullptr");
841         return;
842     }
843     auto streamImpl = paRendererStreamWeakPtr.lock();
844     CHECK_AND_RETURN_LOG(streamImpl, "PAStreamWriteCb: userdata is null");
845 
846     std::shared_ptr<IStatusCallback> statusCallback = streamImpl->statusCallback_.lock();
847     if (statusCallback != nullptr) {
848         statusCallback->OnStatusUpdate(OPERATION_UNDERFLOW);
849     }
850 }
851 
PAStreamSetStartedCb(pa_stream * stream,void * userdata)852 void PaRendererStreamImpl::PAStreamSetStartedCb(pa_stream *stream, void *userdata)
853 {
854     CHECK_AND_RETURN_LOG(userdata, "PAStreamSetStartedCb: userdata is null");
855     AUDIO_PRERELEASE_LOGI("PAStreamSetStartedCb");
856     Trace trace("PaRendererStreamImpl::PAStreamSetStartedCb");
857 }
858 
PAStreamStartSuccessCb(pa_stream * stream,int32_t success,void * userdata)859 void PaRendererStreamImpl::PAStreamStartSuccessCb(pa_stream *stream, int32_t success, void *userdata)
860 {
861     AUDIO_INFO_LOG("PAStreamStartSuccessCb in");
862     CHECK_AND_RETURN_LOG(userdata, "PAStreamStartSuccessCb: userdata is null");
863 
864     std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
865     if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
866         AUDIO_ERR_LOG("streamImpl is nullptr");
867         return;
868     }
869     auto streamImpl = paRendererStreamWeakPtr.lock();
870     CHECK_AND_RETURN_LOG(streamImpl, "PAStreamWriteCb: userdata is null");
871 
872     streamImpl->state_ = RUNNING;
873     streamImpl->offloadTsLast_ = 0;
874     std::shared_ptr<IStatusCallback> statusCallback = streamImpl->statusCallback_.lock();
875     if (statusCallback != nullptr) {
876         statusCallback->OnStatusUpdate(OPERATION_STARTED);
877     }
878     streamImpl->streamCmdStatus_ = success;
879 }
880 
PAStreamPauseSuccessCb(pa_stream * stream,int32_t success,void * userdata)881 void PaRendererStreamImpl::PAStreamPauseSuccessCb(pa_stream *stream, int32_t success, void *userdata)
882 {
883     CHECK_AND_RETURN_LOG(userdata, "PAStreamPauseSuccessCb: userdata is null");
884 
885     std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
886     if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
887         AUDIO_ERR_LOG("streamImpl is nullptr");
888         return;
889     }
890     auto streamImpl = paRendererStreamWeakPtr.lock();
891     CHECK_AND_RETURN_LOG(streamImpl, "PAStreamWriteCb: userdata is null");
892 
893     streamImpl->state_ = PAUSED;
894     if (streamImpl->offloadEnable_ && !streamImpl->isStandbyPause_) {
895         streamImpl->offloadTsLast_ = 0;
896         streamImpl->ResetOffload();
897     }
898     std::shared_ptr<IStatusCallback> statusCallback = streamImpl->statusCallback_.lock();
899     if (statusCallback != nullptr) {
900         statusCallback->OnStatusUpdate(OPERATION_PAUSED);
901     }
902     streamImpl->streamCmdStatus_ = success;
903 }
904 
PAStreamFlushSuccessCb(pa_stream * stream,int32_t success,void * userdata)905 void PaRendererStreamImpl::PAStreamFlushSuccessCb(pa_stream *stream, int32_t success, void *userdata)
906 {
907     CHECK_AND_RETURN_LOG(userdata, "PAStreamFlushSuccessCb: userdata is null");
908     std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
909     if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
910         AUDIO_ERR_LOG("streamImpl is nullptr");
911         return;
912     }
913     auto streamImpl = paRendererStreamWeakPtr.lock();
914     CHECK_AND_RETURN_LOG(streamImpl, "Userdata is null");
915 
916     std::shared_ptr<IStatusCallback> statusCallback = streamImpl->statusCallback_.lock();
917     if (statusCallback != nullptr) {
918         statusCallback->OnStatusUpdate(OPERATION_FLUSHED);
919     }
920     streamImpl->streamFlushStatus_ = success;
921 }
922 
PAStreamDrainSuccessCb(pa_stream * stream,int32_t success,void * userdata)923 void PaRendererStreamImpl::PAStreamDrainSuccessCb(pa_stream *stream, int32_t success, void *userdata)
924 {
925     CHECK_AND_RETURN_LOG(userdata, "PAStreamDrainSuccessCb: userdata is null");
926 
927     std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
928     if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
929         AUDIO_ERR_LOG("streamImpl is nullptr");
930         return;
931     }
932     auto streamImpl = paRendererStreamWeakPtr.lock();
933     CHECK_AND_RETURN_LOG(streamImpl, "PAStreamWriteCb: userdata is null");
934 
935     std::shared_ptr<IStatusCallback> statusCallback = streamImpl->statusCallback_.lock();
936     if (statusCallback != nullptr) {
937         statusCallback->OnStatusUpdate(OPERATION_DRAINED);
938     }
939     streamImpl->streamDrainStatus_ = success;
940     streamImpl->isDrain_ = false;
941 }
942 
PAStreamDrainInStopCb(pa_stream * stream,int32_t success,void * userdata)943 void PaRendererStreamImpl::PAStreamDrainInStopCb(pa_stream *stream, int32_t success, void *userdata)
944 {
945     CHECK_AND_RETURN_LOG(userdata, "PAStreamDrainInStopCb: userdata is null");
946 
947     PaRendererStreamImpl *streamImpl = static_cast<PaRendererStreamImpl *>(userdata);
948     pa_operation *operation = pa_stream_cork(streamImpl->paStream_, 1,
949         PaRendererStreamImpl::PAStreamAsyncStopSuccessCb, userdata);
950 
951     CHECK_AND_RETURN_LOG(operation != nullptr, "pa_stream_cork operation is null");
952 
953     pa_operation_unref(operation);
954     streamImpl->streamDrainStatus_ = success;
955 }
956 
PAStreamAsyncStopSuccessCb(pa_stream * stream,int32_t success,void * userdata)957 void PaRendererStreamImpl::PAStreamAsyncStopSuccessCb(pa_stream *stream, int32_t success, void *userdata)
958 {
959     AUDIO_DEBUG_LOG("PAStreamAsyncStopSuccessCb in");
960     CHECK_AND_RETURN_LOG(userdata, "PAStreamAsyncStopSuccessCb: userdata is null");
961     std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
962     if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
963         AUDIO_ERR_LOG("streamImpl is nullptr");
964         return;
965     }
966     auto streamImpl = paRendererStreamWeakPtr.lock();
967     CHECK_AND_RETURN_LOG(streamImpl, "PAStreamWriteCb: userdata is null");
968 
969     streamImpl->state_ = STOPPED;
970     std::shared_ptr<IStatusCallback> statusCallback = streamImpl->statusCallback_.lock();
971 
972     if (statusCallback != nullptr) {
973         statusCallback->OnStatusUpdate(OPERATION_STOPPED);
974     }
975 }
976 
GetMinimumBufferSize(size_t & minBufferSize) const977 int32_t PaRendererStreamImpl::GetMinimumBufferSize(size_t &minBufferSize) const
978 {
979     minBufferSize = minBufferSize_;
980     return SUCCESS;
981 }
982 
GetByteSizePerFrame(size_t & byteSizePerFrame) const983 void PaRendererStreamImpl::GetByteSizePerFrame(size_t &byteSizePerFrame) const
984 {
985     byteSizePerFrame = byteSizePerFrame_;
986 }
987 
GetSpanSizePerFrame(size_t & spanSizeInFrame) const988 void PaRendererStreamImpl::GetSpanSizePerFrame(size_t &spanSizeInFrame) const
989 {
990     spanSizeInFrame = spanSizeInFrame_;
991 }
992 
SetStreamIndex(uint32_t index)993 void PaRendererStreamImpl::SetStreamIndex(uint32_t index)
994 {
995     AUDIO_INFO_LOG("Using index/sessionId %{public}d", index);
996     streamIndex_ = index;
997 }
998 
GetStreamIndex()999 uint32_t PaRendererStreamImpl::GetStreamIndex()
1000 {
1001     return streamIndex_;
1002 }
1003 
1004 // offload
GetWritableSize()1005 size_t PaRendererStreamImpl::GetWritableSize()
1006 {
1007     PaLockGuard lock(mainloop_, true);
1008     if (paStream_ == nullptr) {
1009         return 0;
1010     }
1011     return pa_stream_writable_size(paStream_);
1012 }
1013 
OffloadSetVolume(float volume)1014 int32_t PaRendererStreamImpl::OffloadSetVolume(float volume)
1015 {
1016     if (!offloadEnable_) {
1017         return ERR_OPERATION_FAILED;
1018     }
1019     uint32_t id = HdiAdapterManager::GetInstance().GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_OFFLOAD);
1020     std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(id);
1021     CHECK_AND_RETURN_RET_LOG(sink != nullptr, ERROR, "Renderer is null.");
1022     return sink->SetVolume(volume, volume);
1023 }
1024 
SetOffloadDataCallbackState(int32_t state)1025 int32_t PaRendererStreamImpl::SetOffloadDataCallbackState(int32_t state)
1026 {
1027     AUDIO_INFO_LOG("SetOffloadDataCallbackState state: %{public}d", state);
1028     if (!offloadEnable_) {
1029         return ERR_OPERATION_FAILED;
1030     }
1031     uint32_t id = HdiAdapterManager::GetInstance().GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_OFFLOAD);
1032     std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(id);
1033     CHECK_AND_RETURN_RET_LOG(sink != nullptr, ERROR, "Renderer is null.");
1034     return sink->SetOffloadRenderCallbackType(static_cast<RenderCallbackType>(state));
1035 }
1036 
UpdateSpatializationState(bool spatializationEnabled,bool headTrackingEnabled)1037 int32_t PaRendererStreamImpl::UpdateSpatializationState(bool spatializationEnabled, bool headTrackingEnabled)
1038 {
1039     PaLockGuard lock(mainloop_);
1040     if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
1041         return ERR_ILLEGAL_STATE;
1042     }
1043 
1044     pa_proplist *propList = pa_proplist_new();
1045     if (propList == nullptr) {
1046         AUDIO_ERR_LOG("pa_proplist_new failed");
1047         return ERR_OPERATION_FAILED;
1048     }
1049 
1050     pa_proplist_sets(propList, "spatialization.enabled", std::to_string(spatializationEnabled).c_str());
1051     pa_proplist_sets(propList, "headtracking.enabled", std::to_string(headTrackingEnabled).c_str());
1052     pa_operation *updatePropOperation = pa_stream_proplist_update(paStream_, PA_UPDATE_REPLACE, propList,
1053         nullptr, nullptr);
1054     pa_proplist_free(propList);
1055     CHECK_AND_RETURN_RET_LOG(updatePropOperation != nullptr, ERR_OPERATION_FAILED, "updatePropOperation is nullptr");
1056     pa_operation_unref(updatePropOperation);
1057 
1058     return SUCCESS;
1059 }
1060 
OffloadGetPresentationPosition(uint64_t & frames,int64_t & timeSec,int64_t & timeNanoSec)1061 int32_t PaRendererStreamImpl::OffloadGetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec)
1062 {
1063     uint32_t id = HdiAdapterManager::GetInstance().GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_OFFLOAD);
1064     std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(id);
1065     CHECK_AND_RETURN_RET_LOG(sink != nullptr, ERROR, "Renderer is null.");
1066     return sink->GetPresentationPosition(frames, timeSec, timeNanoSec);
1067 }
1068 
OffloadSetBufferSize(uint32_t sizeMs)1069 int32_t PaRendererStreamImpl::OffloadSetBufferSize(uint32_t sizeMs)
1070 {
1071     uint32_t id = HdiAdapterManager::GetInstance().GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_OFFLOAD);
1072     std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(id);
1073     CHECK_AND_RETURN_RET_LOG(sink != nullptr, ERROR, "Renderer is null.");
1074     return sink->SetBufferSize(sizeMs);
1075 }
1076 
GetOffloadApproximatelyCacheTime(uint64_t & timestamp,uint64_t & paWriteIndex,uint64_t & cacheTimeDsp,uint64_t & cacheTimePa)1077 int32_t PaRendererStreamImpl::GetOffloadApproximatelyCacheTime(uint64_t &timestamp, uint64_t &paWriteIndex,
1078     uint64_t &cacheTimeDsp, uint64_t &cacheTimePa)
1079 {
1080     if (!offloadEnable_) {
1081         return ERR_OPERATION_FAILED;
1082     }
1083     PaLockGuard lock(mainloop_);
1084     if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
1085         return ERR_ILLEGAL_STATE;
1086     }
1087 
1088     pa_operation *operation = pa_stream_update_timing_info(paStream_, NULL, NULL);
1089     if (operation != nullptr) {
1090         pa_operation_unref(operation);
1091     } else {
1092         AUDIO_ERR_LOG("pa_stream_update_timing_info failed");
1093     }
1094 
1095     const pa_timing_info *info = pa_stream_get_timing_info(paStream_);
1096     if (info == nullptr) {
1097         AUDIO_WARNING_LOG("pa_stream_get_timing_info failed");
1098         return SUCCESS;
1099     }
1100 
1101     const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_);
1102     uint64_t readIndex = pa_bytes_to_usec(info->read_index, sampleSpec);
1103     uint64_t writeIndex = pa_bytes_to_usec(info->write_index, sampleSpec);
1104     timestamp = info->timestamp.tv_sec * AUDIO_US_PER_SECOND + info->timestamp.tv_usec;
1105     lock.Unlock();
1106 
1107     uint64_t cacheTimeInPulse = writeIndex > readIndex ? writeIndex - readIndex : 0;
1108     cacheTimePa = cacheTimeInPulse;
1109     paWriteIndex = writeIndex;
1110 
1111     bool first = offloadTsLast_ == 0;
1112     offloadTsLast_ = readIndex;
1113 
1114     uint64_t frames = 0;
1115     int64_t timeSec = 0;
1116     int64_t timeNanoSec = 0;
1117     OffloadGetPresentationPosition(frames, timeSec, timeNanoSec);
1118     int64_t timeDelta = static_cast<int64_t>(timestamp) -
1119                         static_cast<int64_t>(timeSec * AUDIO_US_PER_SECOND + timeNanoSec / AUDIO_NS_PER_US);
1120     int64_t framesInt = static_cast<int64_t>(frames) + timeDelta;
1121     framesInt = framesInt > 0 ? framesInt : 0;
1122     int64_t readIndexInt = static_cast<int64_t>(readIndex);
1123     if (framesInt + offloadTsOffset_ < readIndexInt - static_cast<int64_t>(
1124         (OFFLOAD_HDI_CACHE2 + MAX_LENGTH_OFFLOAD + OFFLOAD_BUFFER) * AUDIO_US_PER_MS) ||
1125         framesInt + offloadTsOffset_ > readIndexInt || first) {
1126         offloadTsOffset_ = readIndexInt - framesInt;
1127     }
1128     cacheTimeDsp = static_cast<uint64_t>(readIndexInt - (framesInt + offloadTsOffset_));
1129     return SUCCESS;
1130 }
1131 
OffloadUpdatePolicyInWrite()1132 int32_t PaRendererStreamImpl::OffloadUpdatePolicyInWrite()
1133 {
1134     int error = 0;
1135     if ((lastOffloadUpdateFinishTime_ != 0) &&
1136         (std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) > lastOffloadUpdateFinishTime_)) {
1137         AUDIO_INFO_LOG("PaWriteStream switching curTime %{public}" PRIu64 ", switchTime %{public}" PRIu64,
1138             std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()), lastOffloadUpdateFinishTime_);
1139         error = OffloadUpdatePolicy(offloadNextStateTargetPolicy_, true);
1140     }
1141     return error;
1142 }
1143 
SyncOffloadMode()1144 void PaRendererStreamImpl::SyncOffloadMode()
1145 {
1146     std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
1147     if (statusCallback != nullptr) {
1148         if (offloadEnable_) {
1149             statusCallback->OnStatusUpdate(OPERATION_SET_OFFLOAD_ENABLE);
1150         } else {
1151             statusCallback->OnStatusUpdate(OPERATION_UNSET_OFFLOAD_ENABLE);
1152         }
1153     }
1154 }
1155 
ResetOffload()1156 void PaRendererStreamImpl::ResetOffload()
1157 {
1158     offloadEnable_ = false;
1159     SyncOffloadMode();
1160     offloadTsOffset_ = 0;
1161     offloadTsLast_ = 0;
1162     OffloadUpdatePolicy(OFFLOAD_DEFAULT, true);
1163 }
1164 
OffloadUpdatePolicy(AudioOffloadType statePolicy,bool force)1165 int32_t PaRendererStreamImpl::OffloadUpdatePolicy(AudioOffloadType statePolicy, bool force)
1166 {
1167     // if possible turn on the buffer immediately(long buffer -> short buffer), turn it at once.
1168     if (statePolicy < offloadStatePolicy_ || offloadStatePolicy_ == OFFLOAD_DEFAULT || force) {
1169         AUDIO_DEBUG_LOG("Update statePolicy immediately: %{public}d -> %{public}d, force(%d)",
1170             offloadStatePolicy_, statePolicy, force);
1171         lastOffloadUpdateFinishTime_ = 0;
1172         PaLockGuard lock(mainloop_, true);
1173         if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
1174             AUDIO_ERR_LOG("Set offload mode: invalid stream state, quit SetStreamOffloadMode due err");
1175             return ERR_ILLEGAL_STATE;
1176         }
1177         pa_proplist *propList = pa_proplist_new();
1178         CHECK_AND_RETURN_RET_LOG(propList != nullptr, ERR_OPERATION_FAILED, "pa_proplist_new failed");
1179         if (offloadEnable_) {
1180             pa_proplist_sets(propList, "stream.offload.enable", "1");
1181         } else {
1182             pa_proplist_sets(propList, "stream.offload.enable", "0");
1183         }
1184         AudioVolume::GetInstance()->SetOffloadType(sinkInputIndex_, statePolicy);
1185 
1186         pa_operation *updatePropOperation =
1187             pa_stream_proplist_update(paStream_, PA_UPDATE_REPLACE, propList, nullptr, nullptr);
1188         if (updatePropOperation == nullptr) {
1189             AUDIO_ERR_LOG("pa_stream_proplist_update failed!");
1190             pa_proplist_free(propList);
1191             return ERR_OPERATION_FAILED;
1192         }
1193         pa_proplist_free(propList);
1194         pa_operation_unref(updatePropOperation);
1195 
1196         if ((statePolicy != OFFLOAD_DEFAULT && offloadStatePolicy_ != OFFLOAD_DEFAULT) ||
1197             offloadStatePolicy_ == OFFLOAD_INACTIVE_BACKGROUND) {
1198             const uint32_t bufLenMs = processConfig_.streamType == STREAM_MOVIE ? OFFLOAD_HDI_CACHE3 :
1199                 (statePolicy > 1 ? OFFLOAD_HDI_CACHE2 : OFFLOAD_HDI_CACHE1);
1200             OffloadSetBufferSize(bufLenMs);
1201         }
1202 
1203         offloadStatePolicy_ = statePolicy;
1204         offloadNextStateTargetPolicy_ = statePolicy; // Fix here if sometimes can't cut into state 3
1205     } else {
1206         // Otherwise, hdi_sink.c's times detects the stateTarget change and switches later
1207         // this time is checked the PaWriteStream to check if the switch has been made
1208         AUDIO_DEBUG_LOG("Update statePolicy in 3 seconds: %{public}d -> %{public}d", offloadStatePolicy_, statePolicy);
1209         lastOffloadUpdateFinishTime_ = std::chrono::system_clock::to_time_t(
1210             std::chrono::system_clock::now() + std::chrono::seconds(3)); // add 3s latency to change offload state
1211         offloadNextStateTargetPolicy_ = statePolicy;
1212     }
1213 
1214     return SUCCESS;
1215 }
1216 
SetOffloadMode(int32_t state,bool isAppBack)1217 int32_t PaRendererStreamImpl::SetOffloadMode(int32_t state, bool isAppBack)
1218 {
1219 #ifdef FEATURE_POWER_MANAGER
1220     static const std::set<PowerMgr::PowerState> screenOffTable = {
1221         PowerMgr::PowerState::INACTIVE, PowerMgr::PowerState::STAND_BY,
1222         PowerMgr::PowerState::DOZE, PowerMgr::PowerState::SLEEP,
1223         PowerMgr::PowerState::HIBERNATE,
1224     };
1225     AudioOffloadType statePolicy = OFFLOAD_DEFAULT;
1226     auto powerState = static_cast<PowerMgr::PowerState>(state);
1227     if (screenOffTable.count(powerState)) {
1228         statePolicy = OFFLOAD_INACTIVE_BACKGROUND;
1229     } else {
1230         statePolicy = OFFLOAD_ACTIVE_FOREGROUND;
1231     }
1232 
1233     if (statePolicy == OFFLOAD_DEFAULT) {
1234         AUDIO_ERR_LOG("impossible INPUT branch error");
1235         return ERR_OPERATION_FAILED;
1236     }
1237 
1238     AUDIO_INFO_LOG("calling set stream offloadMode PowerState: %{public}d, isAppBack: %{public}d", state, isAppBack);
1239 
1240     if (offloadNextStateTargetPolicy_ == statePolicy) {
1241         return SUCCESS;
1242     }
1243 
1244     offloadEnable_ = true;
1245     SyncOffloadMode();
1246     if (OffloadUpdatePolicy(statePolicy, false) != SUCCESS) {
1247         return ERR_OPERATION_FAILED;
1248     }
1249 #else
1250     AUDIO_INFO_LOG("SetStreamOffloadMode not available, FEATURE_POWER_MANAGER no define");
1251 #endif
1252     return SUCCESS;
1253 }
1254 
UnsetOffloadMode()1255 int32_t PaRendererStreamImpl::UnsetOffloadMode()
1256 {
1257     offloadEnable_ = false;
1258     SyncOffloadMode();
1259     return OffloadUpdatePolicy(OFFLOAD_DEFAULT, true);
1260 }
1261 
UpdateMaxLength(uint32_t maxLength)1262 int32_t PaRendererStreamImpl::UpdateMaxLength(uint32_t maxLength)
1263 {
1264     uint32_t tlength = 4; // 4 is tlength of dup playback
1265     uint32_t prebuf = 2; // 2 is prebuf of dup playback
1266     uint32_t maxlength = maxLength;
1267     AUDIO_INFO_LOG("dup playback stream tlength: %{public}u, maxlength: %{public}u prebuf: %{public}u", tlength,
1268         maxlength, prebuf);
1269 
1270     PaLockGuard lock(mainloop_);
1271     const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_);
1272     pa_buffer_attr bufferAttr;
1273     bufferAttr.fragsize = static_cast<uint32_t>(-1);
1274     bufferAttr.prebuf = pa_usec_to_bytes(20 * PA_USEC_PER_MSEC * prebuf, sampleSpec); // 20 buf len in ms
1275     bufferAttr.maxlength = pa_usec_to_bytes(20 * PA_USEC_PER_MSEC * maxlength, sampleSpec); // 20 buf len in ms
1276     bufferAttr.tlength = pa_usec_to_bytes(20 * PA_USEC_PER_MSEC * tlength, sampleSpec); // 20 buf len in ms
1277     bufferAttr.minreq = pa_usec_to_bytes(20 * PA_USEC_PER_MSEC, sampleSpec); // 20 buf len in ms
1278 
1279     pa_operation *operation = pa_stream_set_buffer_attr(paStream_, &bufferAttr, nullptr, nullptr);
1280     if (operation != nullptr) {
1281         pa_operation_unref(operation);
1282     }
1283     return SUCCESS;
1284 }
1285 
UpdateBufferSize(uint32_t bufferLength)1286 int32_t PaRendererStreamImpl::UpdateBufferSize(uint32_t bufferLength)
1287 {
1288     uint32_t tlength = 4; // 4 is tlength of dup playback
1289     uint32_t prebuf = 1; // 1 is prebuf of dup playback
1290     uint32_t maxlength = 4; // 4 is maxlength of dup playback
1291 
1292     const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_);
1293     pa_buffer_attr bufferAttr;
1294     bufferAttr.fragsize = static_cast<uint32_t>(-1);
1295     bufferAttr.prebuf = pa_usec_to_bytes(20 * PA_USEC_PER_MSEC * prebuf, sampleSpec); // 20 buf len in ms
1296     bufferAttr.maxlength = pa_usec_to_bytes(20 * PA_USEC_PER_MSEC * maxlength, sampleSpec); // 20 buf len in ms
1297     bufferAttr.tlength = pa_usec_to_bytes(bufferLength * PA_USEC_PER_MSEC * tlength, sampleSpec); // 20 buf len in ms
1298     bufferAttr.minreq = pa_usec_to_bytes(bufferLength * PA_USEC_PER_MSEC, sampleSpec); // 20 buf len in ms
1299 
1300     pa_operation *operation = pa_stream_set_buffer_attr(paStream_, &bufferAttr, nullptr, nullptr);
1301     if (operation != nullptr) {
1302         pa_operation_unref(operation);
1303     }
1304     return SUCCESS;
1305 }
1306 
GetAudioProcessConfig() const1307 AudioProcessConfig PaRendererStreamImpl::GetAudioProcessConfig() const noexcept
1308 {
1309     return processConfig_;
1310 }
1311 
Peek(std::vector<char> * audioBuffer,int32_t & index)1312 int32_t PaRendererStreamImpl::Peek(std::vector<char> *audioBuffer, int32_t &index)
1313 {
1314     return SUCCESS;
1315 }
1316 
ReturnIndex(int32_t index)1317 int32_t PaRendererStreamImpl::ReturnIndex(int32_t index)
1318 {
1319     return SUCCESS;
1320 }
1321 
BlockStream()1322 void PaRendererStreamImpl::BlockStream() noexcept
1323 {
1324     return;
1325 }
1326 // offload end
1327 
SetClientVolume(float clientVolume)1328 int32_t PaRendererStreamImpl::SetClientVolume(float clientVolume)
1329 {
1330     if (clientVolume < MIN_FLOAT_VOLUME || clientVolume > MAX_FLOAT_VOLUME) {
1331         AUDIO_ERR_LOG("SetClientVolume with invalid clientVolume %{public}f", clientVolume);
1332         return ERR_INVALID_PARAM;
1333     }
1334 
1335     AudioEffectChainManager *audioEffectChainManager = AudioEffectChainManager::GetInstance();
1336     audioEffectChainManager->StreamVolumeUpdate(std::to_string(streamIndex_), clientVolume);
1337     AUDIO_PRERELEASE_LOGI("set client volume success");
1338 
1339     return SUCCESS;
1340 }
1341 
SetLoudnessGain(float loudnessGain)1342 int32_t PaRendererStreamImpl::SetLoudnessGain(float loudnessGain)
1343 {
1344     AUDIO_INFO_LOG("PA set loudnessGain: %{public}f", loudnessGain);
1345     return SUCCESS;
1346 }
1347 
UpdatePaTimingInfo()1348 void PaRendererStreamImpl::UpdatePaTimingInfo()
1349 {
1350     pa_operation *operation = pa_stream_update_timing_info(paStream_, PAStreamUpdateTimingInfoSuccessCb, (void *)this);
1351     if (operation != nullptr) {
1352         auto start_time = std::chrono::steady_clock::now();
1353         while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
1354             auto update_time = std::chrono::steady_clock::now() - start_time;
1355             CHECK_AND_BREAK_LOG(update_time <= std::chrono::seconds(PA_STREAM_IMPL_TIMEOUT << 1),
1356                 "pa_stream_update_timing_info timeout");
1357             pa_threaded_mainloop_wait(mainloop_);
1358         }
1359         pa_operation_unref(operation);
1360     } else {
1361         AUDIO_ERR_LOG("pa_stream_update_timing_info failed");
1362     }
1363 }
1364 } // namespace AudioStandard
1365 } // namespace OHOS
1366