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