• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 
16 #include "audio_service_client.h"
17 
18 #include <fstream>
19 
20 #include "iservice_registry.h"
21 #include "media_log.h"
22 #include "securec.h"
23 #include "system_ability_definition.h"
24 #include "unistd.h"
25 
26 using namespace std;
27 
28 namespace OHOS {
29 namespace AudioStandard {
30 AudioRendererCallbacks::~AudioRendererCallbacks() = default;
31 AudioCapturerCallbacks::~AudioCapturerCallbacks() = default;
32 
33 #ifdef PRODUCT_M40
34 const uint64_t LATENCY_IN_MSEC = 45UL;
35 #else
36 const uint64_t LATENCY_IN_MSEC = 50UL;
37 #endif
38 const uint32_t READ_TIMEOUT_IN_SEC = 5;
39 const uint32_t DOUBLE_VALUE = 2;
40 const uint32_t MAX_LENGTH_FACTOR = 5;
41 const uint32_t T_LENGTH_FACTOR = 4;
42 const uint64_t MIN_BUF_DURATION_IN_USEC = 92880;
43 
44 const string PATH_SEPARATOR = "/";
45 const string COOKIE_FILE_NAME = "cookie";
46 
47 #define CHECK_AND_RETURN_IFINVALID(expr) \
48 do {                                     \
49     if (!(expr)) {                       \
50         return AUDIO_CLIENT_ERR;         \
51     }                                    \
52 } while (false)
53 
54 #define CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, error) \
55 do {                                                                    \
56     if (!context || !paStream || !mainLoop                              \
57         || !PA_CONTEXT_IS_GOOD(pa_context_get_state(context))           \
58         || !PA_STREAM_IS_GOOD(pa_stream_get_state(paStream))) {         \
59         return error;                                                   \
60     }                                                                   \
61 } while (false)
62 
63 #define CHECK_PA_STATUS_FOR_WRITE(mainLoop, context, paStream, pError, retVal) \
64 do {                                                                           \
65     if (!context || !paStream || !mainLoop                                     \
66         || !PA_CONTEXT_IS_GOOD(pa_context_get_state(context))                  \
67         || !PA_STREAM_IS_GOOD(pa_stream_get_state(paStream))) {                \
68             pError = pa_context_errno(context);                                \
69         return retVal;                                                         \
70     }                                                                          \
71 } while (false)
72 
ConvertFromPAAudioParams(pa_sample_spec paSampleSpec)73 AudioStreamParams AudioServiceClient::ConvertFromPAAudioParams(pa_sample_spec paSampleSpec)
74 {
75     AudioStreamParams audioParams;
76 
77     audioParams.channels = paSampleSpec.channels;
78     audioParams.samplingRate = paSampleSpec.rate;
79     audioParams.encoding = ENCODING_PCM;
80 
81     switch (paSampleSpec.format) {
82         case PA_SAMPLE_U8:
83             audioParams.format = SAMPLE_U8;
84             break;
85         case PA_SAMPLE_S16LE:
86             audioParams.format = SAMPLE_S16LE;
87             break;
88         case PA_SAMPLE_S24LE:
89             audioParams.format = SAMPLE_S24LE;
90             break;
91         case PA_SAMPLE_S32LE:
92             audioParams.format = SAMPLE_S32LE;
93             break;
94         default:
95             audioParams.format = INVALID_WIDTH;
96             break;
97     }
98 
99     return audioParams;
100 }
101 
ConvertToPAAudioParams(AudioStreamParams audioParams)102 pa_sample_spec AudioServiceClient::ConvertToPAAudioParams(AudioStreamParams audioParams)
103 {
104     pa_sample_spec paSampleSpec;
105 
106     paSampleSpec.channels = audioParams.channels;
107     paSampleSpec.rate     = audioParams.samplingRate;
108 
109     switch ((AudioSampleFormat)audioParams.format) {
110         case SAMPLE_U8:
111             paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_U8;
112             break;
113         case SAMPLE_S16LE:
114             paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_S16LE;
115             break;
116         case SAMPLE_S24LE:
117             paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_S24LE;
118             break;
119         case SAMPLE_S32LE:
120             paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_S32LE;
121             break;
122         default:
123             paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_INVALID;
124             break;
125     }
126 
127     return paSampleSpec;
128 }
129 
AlignToAudioFrameSize(size_t l,const pa_sample_spec & ss)130 static size_t AlignToAudioFrameSize(size_t l, const pa_sample_spec &ss)
131 {
132     size_t fs = pa_frame_size(&ss);
133     if (fs == 0) {
134         MEDIA_ERR_LOG(" Error: pa_frame_size returned  0");
135         return 0;
136     }
137 
138     return (l / fs) * fs;
139 }
140 
PAStreamStartSuccessCb(pa_stream * stream,int32_t success,void * userdata)141 void AudioServiceClient::PAStreamStartSuccessCb(pa_stream *stream, int32_t success, void *userdata)
142 {
143     if (!userdata) {
144         MEDIA_ERR_LOG("AudioServiceClient::PAStreamStartSuccessCb: userdata is null");
145         return;
146     }
147 
148     AudioServiceClient *asClient = static_cast<AudioServiceClient *>(userdata);
149     pa_threaded_mainloop *mainLoop = static_cast<pa_threaded_mainloop *>(asClient->mainLoop);
150 
151     asClient->state_ = RUNNING;
152     std::shared_ptr<AudioStreamCallback> streamCb = asClient->streamCallback_.lock();
153     if (streamCb != nullptr) {
154         streamCb->OnStateChange(asClient->state_);
155     }
156     asClient->streamCmdStatus = success;
157     pa_threaded_mainloop_signal(mainLoop, 0);
158 }
159 
PAStreamStopSuccessCb(pa_stream * stream,int32_t success,void * userdata)160 void AudioServiceClient::PAStreamStopSuccessCb(pa_stream *stream, int32_t success, void *userdata)
161 {
162     if (!userdata) {
163         MEDIA_ERR_LOG("AudioServiceClient::PAStreamStopSuccessCb: userdata is null");
164         return;
165     }
166 
167     AudioServiceClient *asClient = static_cast<AudioServiceClient *>(userdata);
168     pa_threaded_mainloop *mainLoop = static_cast<pa_threaded_mainloop *>(asClient->mainLoop);
169 
170     asClient->state_ = STOPPED;
171     std::shared_ptr<AudioStreamCallback> streamCb = asClient->streamCallback_.lock();
172     if (streamCb != nullptr) {
173         streamCb->OnStateChange(asClient->state_);
174     }
175     asClient->streamCmdStatus = success;
176     pa_threaded_mainloop_signal(mainLoop, 0);
177 }
178 
PAStreamPauseSuccessCb(pa_stream * stream,int32_t success,void * userdata)179 void AudioServiceClient::PAStreamPauseSuccessCb(pa_stream *stream, int32_t success, void *userdata)
180 {
181     if (!userdata) {
182         MEDIA_ERR_LOG("AudioServiceClient::PAStreamPauseSuccessCb: userdata is null");
183         return;
184     }
185 
186     AudioServiceClient *asClient = static_cast<AudioServiceClient *>(userdata);
187     pa_threaded_mainloop *mainLoop = static_cast<pa_threaded_mainloop *>(asClient->mainLoop);
188 
189     asClient->state_ = PAUSED;
190     std::shared_ptr<AudioStreamCallback> streamCb = asClient->streamCallback_.lock();
191     if (streamCb != nullptr) {
192         streamCb->OnStateChange(asClient->state_);
193     }
194     asClient->streamCmdStatus = success;
195     pa_threaded_mainloop_signal(mainLoop, 0);
196 }
197 
PAStreamDrainSuccessCb(pa_stream * stream,int32_t success,void * userdata)198 void AudioServiceClient::PAStreamDrainSuccessCb(pa_stream *stream, int32_t success, void *userdata)
199 {
200     if (!userdata) {
201         MEDIA_ERR_LOG("AudioServiceClient::PAStreamDrainSuccessCb: userdata is null");
202         return;
203     }
204 
205     AudioServiceClient *asClient = (AudioServiceClient *)userdata;
206     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)asClient->mainLoop;
207 
208     asClient->streamDrainStatus = success;
209     pa_threaded_mainloop_signal(mainLoop, 0);
210 }
211 
PAStreamFlushSuccessCb(pa_stream * stream,int32_t success,void * userdata)212 void AudioServiceClient::PAStreamFlushSuccessCb(pa_stream *stream, int32_t success, void *userdata)
213 {
214     if (!userdata) {
215         MEDIA_ERR_LOG("AudioServiceClient::PAStreamFlushSuccessCb: userdata is null");
216         return;
217     }
218     AudioServiceClient *asClient = (AudioServiceClient *)userdata;
219     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)asClient->mainLoop;
220 
221     asClient->streamFlushStatus = success;
222     pa_threaded_mainloop_signal(mainLoop, 0);
223 }
224 
PAStreamReadCb(pa_stream * stream,size_t length,void * userdata)225 void AudioServiceClient::PAStreamReadCb(pa_stream *stream, size_t length, void *userdata)
226 {
227     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)userdata;
228     pa_threaded_mainloop_signal(mainLoop, 0);
229 }
230 
PAStreamSetBufAttrSuccessCb(pa_stream * stream,int32_t success,void * userdata)231 void AudioServiceClient::PAStreamSetBufAttrSuccessCb(pa_stream *stream, int32_t success, void *userdata)
232 {
233     if (!userdata) {
234         MEDIA_ERR_LOG("AudioServiceClient::PAStreamSetBufAttrSuccessCb: userdata is null");
235         return;
236     }
237     AudioServiceClient *asClient = (AudioServiceClient *)userdata;
238     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)asClient->mainLoop;
239 
240     MEDIA_DEBUG_LOG("AAudioServiceClient::PAStreamSetBufAttrSuccessCb is called");
241     if (!success) {
242         MEDIA_ERR_LOG("AAudioServiceClient::PAStreamSetBufAttrSuccessCb SetBufAttr failed");
243     } else {
244         MEDIA_ERR_LOG("AAudioServiceClient::PAStreamSetBufAttrSuccessCb SetBufAttr success");
245     }
246     pa_threaded_mainloop_signal(mainLoop, 0);
247 }
248 
SetAudioRenderMode(AudioRenderMode renderMode)249 int32_t AudioServiceClient::SetAudioRenderMode(AudioRenderMode renderMode)
250 {
251     MEDIA_DEBUG_LOG("AudioServiceClient::SetAudioRenderMode begin");
252     renderMode_ = renderMode;
253 
254     if (renderMode_ != RENDER_MODE_CALLBACK) {
255         return AUDIO_CLIENT_SUCCESS;
256     }
257 
258     CHECK_AND_RETURN_IFINVALID(mainLoop && context && paStream);
259     pa_threaded_mainloop_lock(mainLoop);
260     pa_buffer_attr bufferAttr;
261     bufferAttr.fragsize = static_cast<uint32_t>(-1);
262     bufferAttr.prebuf = AlignToAudioFrameSize(pa_usec_to_bytes(MIN_BUF_DURATION_IN_USEC, &sampleSpec), sampleSpec);
263     bufferAttr.maxlength = static_cast<uint32_t>(-1);
264     bufferAttr.tlength = static_cast<uint32_t>(-1);
265     bufferAttr.minreq = bufferAttr.prebuf;
266     pa_operation *operation = pa_stream_set_buffer_attr(paStream, &bufferAttr,
267         PAStreamSetBufAttrSuccessCb, (void *)this);
268         while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
269         pa_threaded_mainloop_wait(mainLoop);
270     }
271     pa_operation_unref(operation);
272     pa_threaded_mainloop_unlock(mainLoop);
273 
274     MEDIA_DEBUG_LOG("AudioServiceClient::SetAudioRenderMode end");
275 
276     return AUDIO_CLIENT_SUCCESS;
277 }
278 
GetAudioRenderMode()279 AudioRenderMode AudioServiceClient::GetAudioRenderMode()
280 {
281     return renderMode_;
282 }
283 
SaveWriteCallback(const std::weak_ptr<AudioRendererWriteCallback> & callback)284 int32_t AudioServiceClient::SaveWriteCallback(const std::weak_ptr<AudioRendererWriteCallback> &callback)
285 {
286     if (callback.lock() == nullptr) {
287         MEDIA_ERR_LOG("AudioServiceClient::SaveWriteCallback callback == nullptr");
288         return AUDIO_CLIENT_INIT_ERR;
289     }
290     writeCallback_ = callback;
291 
292     return AUDIO_CLIENT_SUCCESS;
293 }
294 
PAStreamWriteCb(pa_stream * stream,size_t length,void * userdata)295 void AudioServiceClient::PAStreamWriteCb(pa_stream *stream, size_t length, void *userdata)
296 {
297     MEDIA_INFO_LOG("AudioServiceClient::Inside PA write callback");
298     if (!userdata) {
299         MEDIA_ERR_LOG("AudioServiceClient::PAStreamWriteCb: userdata is null");
300         return;
301     }
302 
303     auto asClient = static_cast<AudioServiceClient *>(userdata);
304     auto mainLoop = static_cast<pa_threaded_mainloop *>(asClient->mainLoop);
305     pa_threaded_mainloop_signal(mainLoop, 0);
306 
307     if (asClient->renderMode_ != RENDER_MODE_CALLBACK) {
308         return;
309     }
310 
311     std::shared_ptr<AudioRendererWriteCallback> cb = asClient->writeCallback_.lock();
312     if (cb != nullptr) {
313         size_t requestSize;
314         asClient->GetMinimumBufferSize(requestSize);
315         MEDIA_INFO_LOG("AudioServiceClient::PAStreamWriteCb: cb != nullptr firing OnWriteData");
316         MEDIA_INFO_LOG("AudioServiceClient::OnWriteData requestSize : %{public}zu", requestSize);
317         cb->OnWriteData(requestSize);
318     } else {
319         MEDIA_ERR_LOG("AudioServiceClient::PAStreamWriteCb: cb == nullptr not firing OnWriteData");
320     }
321 }
322 
PAStreamUnderFlowCb(pa_stream * stream,void * userdata)323 void AudioServiceClient::PAStreamUnderFlowCb(pa_stream *stream, void *userdata)
324 {
325     if (!userdata) {
326         MEDIA_ERR_LOG("AudioServiceClient::PAStreamUnderFlowCb: userdata is null");
327         return;
328     }
329 
330     AudioServiceClient *asClient = (AudioServiceClient *)userdata;
331     asClient->underFlowCount++;
332 }
333 
PAStreamLatencyUpdateCb(pa_stream * stream,void * userdata)334 void AudioServiceClient::PAStreamLatencyUpdateCb(pa_stream *stream, void *userdata)
335 {
336     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)userdata;
337     pa_threaded_mainloop_signal(mainLoop, 0);
338 }
339 
PAStreamStateCb(pa_stream * stream,void * userdata)340 void AudioServiceClient::PAStreamStateCb(pa_stream *stream, void *userdata)
341 {
342     if (!userdata) {
343         MEDIA_ERR_LOG("AudioServiceClient::PAStreamStateCb: userdata is null");
344         return;
345     }
346 
347     AudioServiceClient *asClient = (AudioServiceClient *)userdata;
348     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)asClient->mainLoop;
349 
350     if (asClient->mAudioRendererCallbacks)
351         asClient->mAudioRendererCallbacks->OnStreamStateChangeCb();
352 
353     MEDIA_INFO_LOG("Current Stream State: %d", pa_stream_get_state(stream));
354 
355     switch (pa_stream_get_state(stream)) {
356         case PA_STREAM_READY:
357         case PA_STREAM_FAILED:
358         case PA_STREAM_TERMINATED:
359             pa_threaded_mainloop_signal(mainLoop, 0);
360             break;
361 
362         case PA_STREAM_UNCONNECTED:
363         case PA_STREAM_CREATING:
364         default:
365             break;
366     }
367 }
368 
PAContextStateCb(pa_context * context,void * userdata)369 void AudioServiceClient::PAContextStateCb(pa_context *context, void *userdata)
370 {
371     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)userdata;
372 
373     MEDIA_INFO_LOG("Current Context State: %d", pa_context_get_state(context));
374 
375     switch (pa_context_get_state(context)) {
376         case PA_CONTEXT_READY:
377         case PA_CONTEXT_TERMINATED:
378         case PA_CONTEXT_FAILED:
379             pa_threaded_mainloop_signal(mainLoop, 0);
380             break;
381 
382         case PA_CONTEXT_UNCONNECTED:
383         case PA_CONTEXT_CONNECTING:
384         case PA_CONTEXT_AUTHORIZING:
385         case PA_CONTEXT_SETTING_NAME:
386         default:
387             break;
388     }
389 }
390 
AudioServiceClient()391 AudioServiceClient::AudioServiceClient()
392 {
393     isMainLoopStarted = false;
394     isContextConnected = false;
395     isStreamConnected = false;
396 
397     sinkDevices.clear();
398     sourceDevices.clear();
399     sinkInputs.clear();
400     sourceOutputs.clear();
401     clientInfo.clear();
402 
403     mVolumeFactor = 1.0f;
404     mStreamType = STREAM_MUSIC;
405     mAudioSystemMgr = nullptr;
406 
407     streamIndex = 0;
408     volumeChannels = STEREO;
409     streamInfoUpdated = false;
410 
411     renderRate = RENDER_RATE_NORMAL;
412     renderMode_ = RENDER_MODE_NORMAL;
413 
414     eAudioClientType = AUDIO_SERVICE_CLIENT_PLAYBACK;
415 
416     mFrameSize = 0;
417     mFrameMarkPosition = 0;
418     mMarkReached = false;
419     mFramePeriodNumber = 0;
420 
421     mTotalBytesWritten = 0;
422     mFramePeriodWritten = 0;
423     mTotalBytesRead = 0;
424     mFramePeriodRead = 0;
425     mRenderPositionCb = nullptr;
426     mRenderPeriodPositionCb = nullptr;
427 
428     mAudioRendererCallbacks = nullptr;
429     mAudioCapturerCallbacks = nullptr;
430     internalReadBuffer = nullptr;
431     mainLoop = nullptr;
432     paStream = nullptr;
433     context  = nullptr;
434     api = nullptr;
435 
436     internalRdBufIndex = 0;
437     internalRdBufLen = 0;
438     streamCmdStatus = 0;
439     streamDrainStatus = 0;
440     streamFlushStatus = 0;
441     underFlowCount = 0;
442 
443     acache.readIndex = 0;
444     acache.writeIndex = 0;
445     acache.isFull = false;
446     acache.totalCacheSize = 0;
447     acache.buffer = nullptr;
448 
449     setBufferSize = 0;
450     PAStreamCorkSuccessCb = PAStreamStopSuccessCb;
451 }
452 
ResetPAAudioClient()453 void AudioServiceClient::ResetPAAudioClient()
454 {
455     lock_guard<mutex> lock(ctrlMutex);
456     if (mainLoop && (isMainLoopStarted == true))
457         pa_threaded_mainloop_stop(mainLoop);
458 
459     if (paStream) {
460         pa_stream_set_state_callback(paStream, nullptr, nullptr);
461         pa_stream_set_write_callback(paStream, nullptr, nullptr);
462         pa_stream_set_read_callback(paStream, nullptr, nullptr);
463         pa_stream_set_latency_update_callback(paStream, nullptr, nullptr);
464         pa_stream_set_underflow_callback(paStream, nullptr, nullptr);
465 
466         if (isStreamConnected == true)
467             pa_stream_disconnect(paStream);
468         pa_stream_unref(paStream);
469     }
470 
471     if (context) {
472         pa_context_set_state_callback(context, nullptr, nullptr);
473         if (isContextConnected == true)
474             pa_context_disconnect(context);
475         pa_context_unref(context);
476     }
477 
478     if (mainLoop)
479         pa_threaded_mainloop_free(mainLoop);
480 
481     for (auto &thread : mPositionCBThreads) {
482         if (thread && thread->joinable()) {
483             thread->join();
484         }
485     }
486 
487     for (auto &thread : mPeriodPositionCBThreads) {
488         if (thread && thread->joinable()) {
489             thread->join();
490         }
491     }
492 
493     if (appCookiePath.compare("")) {
494         remove(appCookiePath.c_str());
495         appCookiePath = "";
496     }
497 
498     isMainLoopStarted  = false;
499     isContextConnected = false;
500     isStreamConnected  = false;
501 
502     sinkDevices.clear();
503     sourceDevices.clear();
504     sinkInputs.clear();
505     sourceOutputs.clear();
506     clientInfo.clear();
507 
508     mAudioRendererCallbacks = nullptr;
509     mAudioCapturerCallbacks = nullptr;
510     internalReadBuffer      = nullptr;
511 
512     mainLoop = nullptr;
513     paStream = nullptr;
514     context  = nullptr;
515     api      = nullptr;
516 
517     internalRdBufIndex = 0;
518     internalRdBufLen   = 0;
519     underFlowCount     = 0;
520 
521     acache.buffer = nullptr;
522     acache.readIndex = 0;
523     acache.writeIndex = 0;
524     acache.isFull = false;
525     acache.totalCacheSize = 0;
526 
527     setBufferSize = 0;
528     PAStreamCorkSuccessCb = nullptr;
529 }
530 
~AudioServiceClient()531 AudioServiceClient::~AudioServiceClient()
532 {
533     ResetPAAudioClient();
534 }
535 
SetEnv()536 void AudioServiceClient::SetEnv()
537 {
538     MEDIA_INFO_LOG("SetEnv called");
539     int ret = 0;
540     const char *env_home_pa = getenv("HOME");
541     if (!env_home_pa) {
542         ret = setenv("HOME", PA_HOME_DIR, 1);
543         MEDIA_INFO_LOG("set env HOME: %{public}d", ret);
544     }
545 
546     const char *env_runtime_pa = getenv("PULSE_RUNTIME_PATH");
547     if (!env_runtime_pa) {
548         ret = setenv("PULSE_RUNTIME_PATH", PA_RUNTIME_DIR, 1);
549         MEDIA_INFO_LOG("set env PULSE_RUNTIME_DIR: %{public}d", ret);
550     }
551 
552     const char *env_state_pa = getenv("PULSE_STATE_PATH");
553     if (!env_state_pa) {
554         ret = setenv("PULSE_STATE_PATH", PA_STATE_DIR, 1);
555         MEDIA_INFO_LOG("set env PULSE_STATE_PATH: %{public}d", ret);
556     }
557 }
558 
SetApplicationCachePath(const std::string cachePath)559 void AudioServiceClient::SetApplicationCachePath(const std::string cachePath)
560 {
561     MEDIA_DEBUG_LOG("SetApplicationCachePath in");
562     cachePath_ = cachePath;
563 }
564 
Initialize(ASClientType eClientType)565 int32_t AudioServiceClient::Initialize(ASClientType eClientType)
566 {
567     int error = PA_ERR_INTERNAL;
568     eAudioClientType = eClientType;
569 
570     mMarkReached = false;
571     mTotalBytesWritten = 0;
572     mFramePeriodWritten = 0;
573     mTotalBytesRead = 0;
574     mFramePeriodRead = 0;
575 
576     SetEnv();
577     mAudioSystemMgr = AudioSystemManager::GetInstance();
578 
579     mainLoop = pa_threaded_mainloop_new();
580     if (mainLoop == nullptr)
581         return AUDIO_CLIENT_INIT_ERR;
582 
583     api = pa_threaded_mainloop_get_api(mainLoop);
584     if (api == nullptr) {
585         ResetPAAudioClient();
586         return AUDIO_CLIENT_INIT_ERR;
587     }
588 
589     context = pa_context_new(api, "AudioServiceClient");
590     if (context == nullptr) {
591         ResetPAAudioClient();
592         return AUDIO_CLIENT_INIT_ERR;
593     }
594 
595     pa_context_set_state_callback(context, PAContextStateCb, mainLoop);
596 
597     if (!cachePath_.empty()) {
598         MEDIA_DEBUG_LOG("abilityContext not null");
599         int32_t size = 0;
600         const char *cookieData = mAudioSystemMgr->RetrieveCookie(size);
601         if (size <= 0) {
602             MEDIA_ERR_LOG("Error retrieving cookie");
603             return AUDIO_CLIENT_INIT_ERR;
604         }
605 
606         appCookiePath = cachePath_ + PATH_SEPARATOR + COOKIE_FILE_NAME;
607 
608         ofstream cookieCache(appCookiePath.c_str(), std::ofstream::binary);
609         cookieCache.write(cookieData, size);
610         cookieCache.flush();
611         cookieCache.close();
612 
613         pa_context_load_cookie_from_file(context, appCookiePath.c_str());
614     }
615 
616     if (pa_context_connect(context, nullptr, PA_CONTEXT_NOFAIL, nullptr) < 0) {
617         error = pa_context_errno(context);
618         MEDIA_ERR_LOG("context connect error: %{public}s", pa_strerror(error));
619         ResetPAAudioClient();
620         return AUDIO_CLIENT_INIT_ERR;
621     }
622 
623     isContextConnected = true;
624     pa_threaded_mainloop_lock(mainLoop);
625 
626     if (pa_threaded_mainloop_start(mainLoop) < 0) {
627         pa_threaded_mainloop_unlock(mainLoop);
628         ResetPAAudioClient();
629         return AUDIO_CLIENT_INIT_ERR;
630     }
631 
632     isMainLoopStarted = true;
633     while (true) {
634         pa_context_state_t state = pa_context_get_state(context);
635         if (state == PA_CONTEXT_READY)
636             break;
637 
638         if (!PA_CONTEXT_IS_GOOD(state)) {
639             error = pa_context_errno(context);
640             MEDIA_ERR_LOG("context bad state error: %{public}s", pa_strerror(error));
641             pa_threaded_mainloop_unlock(mainLoop);
642             ResetPAAudioClient();
643             return AUDIO_CLIENT_INIT_ERR;
644         }
645 
646         pa_threaded_mainloop_wait(mainLoop);
647     }
648 
649     if (appCookiePath.compare("")) {
650         remove(appCookiePath.c_str());
651         appCookiePath = "";
652     }
653 
654     pa_threaded_mainloop_unlock(mainLoop);
655     return AUDIO_CLIENT_SUCCESS;
656 }
657 
GetStreamName(AudioStreamType audioType)658 const std::string AudioServiceClient::GetStreamName(AudioStreamType audioType)
659 {
660     std::string name;
661     switch (audioType) {
662         case STREAM_VOICE_ASSISTANT:
663             name = "voice_assistant";
664             break;
665         case STREAM_VOICE_CALL:
666             name = "voice_call";
667             break;
668         case STREAM_SYSTEM:
669             name = "system";
670             break;
671         case STREAM_RING:
672             name = "ring";
673             break;
674         case STREAM_MUSIC:
675             name = "music";
676             break;
677         case STREAM_ALARM:
678             name = "alarm";
679             break;
680         case STREAM_NOTIFICATION:
681             name = "notification";
682             break;
683         case STREAM_BLUETOOTH_SCO:
684             name = "bluetooth_sco";
685             break;
686         case STREAM_DTMF:
687             name = "dtmf";
688             break;
689         case STREAM_TTS:
690             name = "tts";
691             break;
692         case STREAM_ACCESSIBILITY:
693             name = "accessibility";
694             break;
695         default:
696             name = "unknown";
697     }
698 
699     const std::string streamName = name;
700     return streamName;
701 }
702 
ConnectStreamToPA()703 int32_t AudioServiceClient::ConnectStreamToPA()
704 {
705     int error, result;
706 
707     CHECK_AND_RETURN_IFINVALID(mainLoop && context && paStream);
708     pa_threaded_mainloop_lock(mainLoop);
709 
710     pa_buffer_attr bufferAttr;
711     bufferAttr.fragsize = static_cast<uint32_t>(-1);
712 
713     bufferAttr.prebuf = pa_usec_to_bytes(LATENCY_IN_MSEC * PA_USEC_PER_MSEC, &sampleSpec);
714     bufferAttr.maxlength = pa_usec_to_bytes(LATENCY_IN_MSEC * PA_USEC_PER_MSEC * MAX_LENGTH_FACTOR, &sampleSpec);
715     bufferAttr.tlength = pa_usec_to_bytes(LATENCY_IN_MSEC * PA_USEC_PER_MSEC * T_LENGTH_FACTOR, &sampleSpec);
716     bufferAttr.minreq = pa_usec_to_bytes(LATENCY_IN_MSEC * PA_USEC_PER_MSEC, &sampleSpec);
717 
718     if (eAudioClientType == AUDIO_SERVICE_CLIENT_PLAYBACK)
719         result = pa_stream_connect_playback(paStream, nullptr, &bufferAttr,
720                                             (pa_stream_flags_t)(PA_STREAM_ADJUST_LATENCY
721                                             | PA_STREAM_INTERPOLATE_TIMING
722                                             | PA_STREAM_START_CORKED
723                                             | PA_STREAM_AUTO_TIMING_UPDATE
724                                             | PA_STREAM_VARIABLE_RATE), nullptr, nullptr);
725     else
726         result = pa_stream_connect_record(paStream, nullptr, nullptr,
727                                           (pa_stream_flags_t)(PA_STREAM_INTERPOLATE_TIMING
728                                           | PA_STREAM_ADJUST_LATENCY
729                                           | PA_STREAM_START_CORKED
730                                           | PA_STREAM_AUTO_TIMING_UPDATE));
731 
732     if (result < 0) {
733         error = pa_context_errno(context);
734         MEDIA_ERR_LOG("connection to stream error: %{public}d", error);
735         pa_threaded_mainloop_unlock(mainLoop);
736         ResetPAAudioClient();
737         return AUDIO_CLIENT_CREATE_STREAM_ERR;
738     }
739 
740     while (true) {
741         pa_stream_state_t state = pa_stream_get_state(paStream);
742         if (state == PA_STREAM_READY)
743             break;
744 
745         if (!PA_STREAM_IS_GOOD(state)) {
746             error = pa_context_errno(context);
747             pa_threaded_mainloop_unlock(mainLoop);
748             MEDIA_ERR_LOG("connection to stream error: %{public}d", error);
749             ResetPAAudioClient();
750             return AUDIO_CLIENT_CREATE_STREAM_ERR;
751         }
752 
753         pa_threaded_mainloop_wait(mainLoop);
754     }
755 
756     isStreamConnected = true;
757     pa_threaded_mainloop_unlock(mainLoop);
758     return AUDIO_CLIENT_SUCCESS;
759 }
760 
InitializeAudioCache()761 int32_t AudioServiceClient::InitializeAudioCache()
762 {
763     MEDIA_INFO_LOG("Initializing internal audio cache");
764     CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
765 
766     const pa_buffer_attr *bufferAttr = pa_stream_get_buffer_attr(paStream);
767     if (bufferAttr == nullptr) {
768         MEDIA_ERR_LOG("pa stream get buffer attribute returned null");
769         return AUDIO_CLIENT_INIT_ERR;
770     }
771 
772     acache.buffer = make_unique<uint8_t[]>(bufferAttr->minreq);
773     if (acache.buffer == nullptr) {
774         MEDIA_ERR_LOG("Allocate memory for buffer failed");
775         return AUDIO_CLIENT_INIT_ERR;
776     }
777 
778     acache.readIndex = 0;
779     acache.writeIndex = 0;
780     acache.totalCacheSize = bufferAttr->minreq;
781     acache.isFull = false;
782     return AUDIO_CLIENT_SUCCESS;
783 }
784 
CreateStream(AudioStreamParams audioParams,AudioStreamType audioType)785 int32_t AudioServiceClient::CreateStream(AudioStreamParams audioParams, AudioStreamType audioType)
786 {
787     int error;
788 
789     CHECK_AND_RETURN_IFINVALID(mainLoop && context);
790 
791     if (eAudioClientType == AUDIO_SERVICE_CLIENT_CONTROLLER) {
792         return AUDIO_CLIENT_INVALID_PARAMS_ERR;
793     }
794 
795     pa_threaded_mainloop_lock(mainLoop);
796     mStreamType = audioType;
797     const std::string streamName = GetStreamName(audioType);
798 
799     auto timenow = chrono::system_clock::to_time_t(chrono::system_clock::now());
800     const std::string streamStartTime = ctime(&timenow);
801 
802     sampleSpec = ConvertToPAAudioParams(audioParams);
803     mFrameSize = pa_frame_size(&sampleSpec);
804 
805     pa_proplist *propList = pa_proplist_new();
806     if (propList == nullptr) {
807         MEDIA_ERR_LOG("pa_proplist_new failed");
808         ResetPAAudioClient();
809         return AUDIO_CLIENT_CREATE_STREAM_ERR;
810     }
811 
812     pa_proplist_sets(propList, "stream.type", streamName.c_str());
813     pa_proplist_sets(propList, "stream.volumeFactor", std::to_string(mVolumeFactor).c_str());
814     pa_proplist_sets(propList, "stream.sessionID", std::to_string(pa_context_get_index(context)).c_str());
815     pa_proplist_sets(propList, "stream.startTime", streamStartTime.c_str());
816 
817     if (!(paStream = pa_stream_new_with_proplist(context, streamName.c_str(), &sampleSpec, nullptr, propList))) {
818         error = pa_context_errno(context);
819         pa_proplist_free(propList);
820         pa_threaded_mainloop_unlock(mainLoop);
821         ResetPAAudioClient();
822         return AUDIO_CLIENT_CREATE_STREAM_ERR;
823     }
824 
825     pa_proplist_free(propList);
826     pa_stream_set_state_callback(paStream, PAStreamStateCb, (void *)this);
827     pa_stream_set_write_callback(paStream, PAStreamWriteCb, (void *)this);
828     pa_stream_set_read_callback(paStream, PAStreamReadCb, mainLoop);
829     pa_stream_set_latency_update_callback(paStream, PAStreamLatencyUpdateCb, mainLoop);
830     pa_stream_set_underflow_callback(paStream, PAStreamUnderFlowCb, (void *)this);
831 
832     pa_threaded_mainloop_unlock(mainLoop);
833 
834     error = ConnectStreamToPA();
835     if (error < 0) {
836         MEDIA_ERR_LOG("Create Stream Failed");
837         ResetPAAudioClient();
838         return AUDIO_CLIENT_CREATE_STREAM_ERR;
839     }
840 
841     if (eAudioClientType == AUDIO_SERVICE_CLIENT_PLAYBACK) {
842         error = InitializeAudioCache();
843         if (error < 0) {
844             MEDIA_ERR_LOG("Initialize audio cache failed");
845             ResetPAAudioClient();
846             return AUDIO_CLIENT_CREATE_STREAM_ERR;
847         }
848 
849         if (SetStreamRenderRate(renderRate) != AUDIO_CLIENT_SUCCESS) {
850             MEDIA_ERR_LOG("Set render rate failed");
851         }
852     }
853 
854     state_ = PREPARED;
855     std::shared_ptr<AudioStreamCallback> streamCb = streamCallback_.lock();
856     if (streamCb != nullptr) {
857         streamCb->OnStateChange(state_);
858     }
859 
860     MEDIA_INFO_LOG("Created Stream");
861     return AUDIO_CLIENT_SUCCESS;
862 }
863 
GetSessionID(uint32_t & sessionID) const864 int32_t AudioServiceClient::GetSessionID(uint32_t &sessionID) const
865 {
866     MEDIA_DEBUG_LOG("AudioServiceClient: GetSessionID");
867     uint32_t client_index = pa_context_get_index(context);
868     if (client_index == PA_INVALID_INDEX) {
869         return AUDIO_CLIENT_ERR;
870     }
871 
872     sessionID = client_index;
873 
874     return AUDIO_CLIENT_SUCCESS;
875 }
876 
StartStream()877 int32_t AudioServiceClient::StartStream()
878 {
879     int error;
880 
881     CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
882     pa_operation *operation = nullptr;
883 
884     pa_threaded_mainloop_lock(mainLoop);
885 
886     pa_stream_state_t state = pa_stream_get_state(paStream);
887     if (state != PA_STREAM_READY) {
888         error = pa_context_errno(context);
889         pa_threaded_mainloop_unlock(mainLoop);
890         MEDIA_ERR_LOG("Stream Start Failed, error: %{public}d", error);
891         ResetPAAudioClient();
892         return AUDIO_CLIENT_START_STREAM_ERR;
893     }
894 
895     streamCmdStatus = 0;
896     operation = pa_stream_cork(paStream, 0, PAStreamStartSuccessCb, (void *)this);
897 
898     while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
899         pa_threaded_mainloop_wait(mainLoop);
900     }
901     pa_operation_unref(operation);
902     pa_threaded_mainloop_unlock(mainLoop);
903 
904     if (!streamCmdStatus) {
905         MEDIA_ERR_LOG("Stream Start Failed");
906         ResetPAAudioClient();
907         return AUDIO_CLIENT_START_STREAM_ERR;
908     } else {
909         MEDIA_INFO_LOG("Stream Started Successfully");
910         return AUDIO_CLIENT_SUCCESS;
911     }
912 }
913 
PauseStream()914 int32_t AudioServiceClient::PauseStream()
915 {
916     lock_guard<mutex> lock(ctrlMutex);
917     PAStreamCorkSuccessCb = PAStreamPauseSuccessCb;
918     int32_t ret = CorkStream();
919     if (ret) {
920         return ret;
921     }
922 
923     if (!streamCmdStatus) {
924         MEDIA_ERR_LOG("Stream Pasue Failed");
925         return AUDIO_CLIENT_ERR;
926     } else {
927         MEDIA_INFO_LOG("Stream Pasued Successfully");
928         return AUDIO_CLIENT_SUCCESS;
929     }
930 }
931 
StopStream()932 int32_t AudioServiceClient::StopStream()
933 {
934     lock_guard<mutex> lock(ctrlMutex);
935     PAStreamCorkSuccessCb = PAStreamStopSuccessCb;
936     int32_t ret = CorkStream();
937     if (ret) {
938         return ret;
939     }
940 
941     if (!streamCmdStatus) {
942         MEDIA_ERR_LOG("Stream Stop Failed");
943         return AUDIO_CLIENT_ERR;
944     } else {
945         MEDIA_INFO_LOG("Stream Stopped Successfully");
946         if (internalRdBufLen) {
947             (void)pa_stream_drop(paStream);
948             internalReadBuffer = nullptr;
949             internalRdBufLen = 0;
950             internalRdBufIndex = 0;
951         }
952         return AUDIO_CLIENT_SUCCESS;
953     }
954 }
955 
CorkStream()956 int32_t AudioServiceClient::CorkStream()
957 {
958     CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
959     pa_operation *operation = nullptr;
960 
961     pa_threaded_mainloop_lock(mainLoop);
962     pa_stream_state_t state = pa_stream_get_state(paStream);
963     if (state != PA_STREAM_READY) {
964         int32_t error = pa_context_errno(context);
965         pa_threaded_mainloop_unlock(mainLoop);
966         MEDIA_ERR_LOG("Stream Stop Failed : %{public}d", error);
967         return AUDIO_CLIENT_ERR;
968     }
969 
970     streamCmdStatus = 0;
971     operation = pa_stream_cork(paStream, 1, PAStreamCorkSuccessCb, (void *)this);
972 
973     while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
974         pa_threaded_mainloop_wait(mainLoop);
975     }
976     pa_operation_unref(operation);
977     pa_threaded_mainloop_unlock(mainLoop);
978 
979     return AUDIO_CLIENT_SUCCESS;
980 }
981 
FlushStream()982 int32_t AudioServiceClient::FlushStream()
983 {
984     int error;
985     CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
986     pa_operation *operation = nullptr;
987 
988     lock_guard<mutex> lock(dataMutex);
989     pa_threaded_mainloop_lock(mainLoop);
990 
991     pa_stream_state_t state = pa_stream_get_state(paStream);
992     if (state != PA_STREAM_READY) {
993         error = pa_context_errno(context);
994         pa_threaded_mainloop_unlock(mainLoop);
995         MEDIA_ERR_LOG("Stream Flush Failed, error: %{public}d", error);
996         return AUDIO_CLIENT_ERR;
997     }
998 
999     streamFlushStatus = 0;
1000     operation = pa_stream_flush(paStream, PAStreamFlushSuccessCb, (void *)this);
1001     if (operation == nullptr) {
1002         MEDIA_ERR_LOG("Stream Flush Operation Failed");
1003         pa_threaded_mainloop_unlock(mainLoop);
1004         return AUDIO_CLIENT_ERR;
1005     }
1006 
1007     while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
1008         pa_threaded_mainloop_wait(mainLoop);
1009     }
1010     pa_operation_unref(operation);
1011     pa_threaded_mainloop_unlock(mainLoop);
1012 
1013     if (!streamFlushStatus) {
1014         MEDIA_ERR_LOG("Stream Flush Failed");
1015         return AUDIO_CLIENT_ERR;
1016     } else {
1017         MEDIA_INFO_LOG("Stream Flushed Successfully");
1018         acache.readIndex = 0;
1019         acache.writeIndex = 0;
1020         acache.isFull = false;
1021         return AUDIO_CLIENT_SUCCESS;
1022     }
1023 }
1024 
DrainStream()1025 int32_t AudioServiceClient::DrainStream()
1026 {
1027     uint32_t error;
1028 
1029     if (eAudioClientType != AUDIO_SERVICE_CLIENT_PLAYBACK) {
1030         MEDIA_ERR_LOG("Drain is not supported");
1031         return AUDIO_CLIENT_ERR;
1032     }
1033 
1034     lock_guard<mutex> lock(dataMutex);
1035 
1036     error = DrainAudioCache();
1037     if (error != AUDIO_CLIENT_SUCCESS) {
1038         MEDIA_ERR_LOG("Audio cache drain failed");
1039         return AUDIO_CLIENT_ERR;
1040     }
1041 
1042     CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
1043     pa_operation *operation = nullptr;
1044 
1045     pa_threaded_mainloop_lock(mainLoop);
1046 
1047     pa_stream_state_t state = pa_stream_get_state(paStream);
1048     if (state != PA_STREAM_READY) {
1049         error = pa_context_errno(context);
1050         pa_threaded_mainloop_unlock(mainLoop);
1051         MEDIA_ERR_LOG("Stream Drain Failed");
1052         return AUDIO_CLIENT_ERR;
1053     }
1054 
1055     streamDrainStatus = 0;
1056     operation = pa_stream_drain(paStream, PAStreamDrainSuccessCb, (void *)this);
1057 
1058     while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
1059         pa_threaded_mainloop_wait(mainLoop);
1060     }
1061     pa_operation_unref(operation);
1062     pa_threaded_mainloop_unlock(mainLoop);
1063 
1064     if (!streamDrainStatus) {
1065         MEDIA_ERR_LOG("Stream Drain Failed");
1066         return AUDIO_CLIENT_ERR;
1067     } else {
1068         MEDIA_INFO_LOG("Stream Drained Successfully");
1069         return AUDIO_CLIENT_SUCCESS;
1070     }
1071 }
1072 
SetStreamVolume(uint32_t sessionID,uint32_t volume)1073 int32_t AudioServiceClient::SetStreamVolume(uint32_t sessionID, uint32_t volume)
1074 {
1075     return AUDIO_CLIENT_SUCCESS;
1076 }
1077 
PaWriteStream(const uint8_t * buffer,size_t & length)1078 int32_t AudioServiceClient::PaWriteStream(const uint8_t *buffer, size_t &length)
1079 {
1080     int error = 0;
1081 
1082     while (length > 0) {
1083         size_t writableSize;
1084 
1085         while (!(writableSize = pa_stream_writable_size(paStream))) {
1086             pa_threaded_mainloop_wait(mainLoop);
1087         }
1088 
1089         MEDIA_INFO_LOG("Write stream: writable size = %{public}zu, length = %{public}zu",
1090                        writableSize, length);
1091         if (writableSize > length) {
1092             writableSize = length;
1093         }
1094 
1095         writableSize = AlignToAudioFrameSize(writableSize, sampleSpec);
1096         if (writableSize == 0) {
1097             MEDIA_ERR_LOG("Align to frame size failed");
1098             error = AUDIO_CLIENT_WRITE_STREAM_ERR;
1099             break;
1100         }
1101 
1102         error = pa_stream_write(paStream, (void *)buffer, writableSize, nullptr, 0LL,
1103                                 PA_SEEK_RELATIVE);
1104         if (error < 0) {
1105             MEDIA_ERR_LOG("Write stream failed");
1106             error = AUDIO_CLIENT_WRITE_STREAM_ERR;
1107             break;
1108         }
1109 
1110         MEDIA_INFO_LOG("Writable size: %{public}zu, bytes to write: %{public}zu, return val: %{public}d",
1111                        writableSize, length, error);
1112         buffer = buffer + writableSize;
1113         length -= writableSize;
1114 
1115         HandleRenderPositionCallbacks(writableSize);
1116     }
1117 
1118     return error;
1119 }
1120 
HandleRenderPositionCallbacks(size_t bytesWritten)1121 void AudioServiceClient::HandleRenderPositionCallbacks(size_t bytesWritten)
1122 {
1123     mTotalBytesWritten += bytesWritten;
1124     if (mFrameSize == 0) {
1125         MEDIA_ERR_LOG("HandleRenderPositionCallbacks: capturePeriodPositionCb not set");
1126         return;
1127     }
1128 
1129     uint64_t writtenFrameNumber = mTotalBytesWritten / mFrameSize;
1130     MEDIA_DEBUG_LOG("frame size: %{public}d", mFrameSize);
1131 
1132     {
1133         std::lock_guard<std::mutex> lock(rendererMarkReachedMutex_);
1134         if (!mMarkReached && mRenderPositionCb) {
1135             MEDIA_DEBUG_LOG("frame mark position: %{public}" PRIu64 ", Total frames written: %{public}" PRIu64,
1136                 static_cast<uint64_t>(mFrameMarkPosition), static_cast<uint64_t>(writtenFrameNumber));
1137             if (writtenFrameNumber >= mFrameMarkPosition) {
1138                 MEDIA_DEBUG_LOG("audio service client OnMarkReached");
1139                 mPositionCBThreads.emplace_back(std::make_unique<std::thread>(&RendererPositionCallback::OnMarkReached,
1140                                                 mRenderPositionCb, mFrameMarkPosition));
1141                 mMarkReached = true;
1142             }
1143         }
1144     }
1145 
1146     {
1147         std::lock_guard<std::mutex> lock(rendererPeriodReachedMutex_);
1148         if (mRenderPeriodPositionCb) {
1149             mFramePeriodWritten += (bytesWritten / mFrameSize);
1150             MEDIA_DEBUG_LOG("frame period number: %{public}" PRIu64 ", Total frames written: %{public}" PRIu64,
1151                 static_cast<uint64_t>(mFramePeriodNumber), static_cast<uint64_t>(writtenFrameNumber));
1152             if (mFramePeriodWritten >= mFramePeriodNumber) {
1153                 mFramePeriodWritten %= mFramePeriodNumber;
1154                 MEDIA_DEBUG_LOG("OnPeriodReached, remaining frames: %{public}" PRIu64,
1155                     static_cast<uint64_t>(mFramePeriodWritten));
1156                 mPeriodPositionCBThreads.emplace_back(std::make_unique<std::thread>(
1157                     &RendererPeriodPositionCallback::OnPeriodReached, mRenderPeriodPositionCb, mFramePeriodNumber));
1158             }
1159         }
1160     }
1161 }
1162 
DrainAudioCache()1163 int32_t AudioServiceClient::DrainAudioCache()
1164 {
1165     CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
1166     pa_threaded_mainloop_lock(mainLoop);
1167 
1168     int32_t error = 0;
1169     if (acache.buffer == nullptr) {
1170         MEDIA_ERR_LOG("Drain cache failed");
1171         return AUDIO_CLIENT_ERR;
1172     }
1173 
1174     size_t length = acache.writeIndex - acache.readIndex;
1175     const uint8_t *buffer = acache.buffer.get();
1176 
1177     error = PaWriteStream(buffer, length);
1178 
1179     acache.readIndex = 0;
1180     acache.writeIndex = 0;
1181 
1182     pa_threaded_mainloop_unlock(mainLoop);
1183     return error;
1184 }
1185 
WriteToAudioCache(const StreamBuffer & stream)1186 size_t AudioServiceClient::WriteToAudioCache(const StreamBuffer &stream)
1187 {
1188     if (stream.buffer == nullptr) {
1189         return 0;
1190     }
1191 
1192     const uint8_t *inputBuffer = stream.buffer;
1193     uint8_t *cacheBuffer = acache.buffer.get() + acache.writeIndex;
1194 
1195     size_t inputLen = stream.bufferLen;
1196 
1197     while (inputLen > 0) {
1198         size_t writableSize = acache.totalCacheSize - acache.writeIndex;
1199 
1200         if (writableSize > inputLen) {
1201             writableSize = inputLen;
1202         }
1203 
1204         if (writableSize == 0) {
1205             break;
1206         }
1207 
1208         if (memcpy_s(cacheBuffer, acache.totalCacheSize, inputBuffer, writableSize)) {
1209             break;
1210         }
1211 
1212         inputBuffer = inputBuffer + writableSize;
1213         cacheBuffer = cacheBuffer + writableSize;
1214         inputLen -= writableSize;
1215         acache.writeIndex += writableSize;
1216     }
1217 
1218     if ((acache.writeIndex - acache.readIndex) == acache.totalCacheSize) {
1219         acache.isFull = true;
1220     }
1221 
1222     return (stream.bufferLen - inputLen);
1223 }
1224 
WriteStreamInCb(const StreamBuffer & stream,int32_t & pError)1225 size_t AudioServiceClient::WriteStreamInCb(const StreamBuffer &stream, int32_t &pError)
1226 {
1227     lock_guard<mutex> lock(dataMutex);
1228     int error = 0;
1229 
1230     CHECK_PA_STATUS_FOR_WRITE(mainLoop, context, paStream, pError, 0);
1231     pa_threaded_mainloop_lock(mainLoop);
1232 
1233     const uint8_t *buffer = stream.buffer;
1234     size_t length = stream.bufferLen;
1235     error = PaWriteStream(buffer, length);
1236     pa_threaded_mainloop_unlock(mainLoop);
1237     pError = error;
1238     return (stream.bufferLen - length);
1239 }
1240 
WriteStream(const StreamBuffer & stream,int32_t & pError)1241 size_t AudioServiceClient::WriteStream(const StreamBuffer &stream, int32_t &pError)
1242 {
1243     lock_guard<mutex> lock(dataMutex);
1244     int error = 0;
1245     size_t cachedLen = WriteToAudioCache(stream);
1246 
1247     if (!acache.isFull) {
1248         pError = error;
1249         return cachedLen;
1250     }
1251 
1252     CHECK_PA_STATUS_FOR_WRITE(mainLoop, context, paStream, pError, 0);
1253     pa_threaded_mainloop_lock(mainLoop);
1254 
1255     if (acache.buffer == nullptr) {
1256         MEDIA_ERR_LOG("Buffer is null");
1257         pError = AUDIO_CLIENT_WRITE_STREAM_ERR;
1258         return cachedLen;
1259     }
1260 
1261     const uint8_t *buffer = acache.buffer.get();
1262     size_t length = acache.totalCacheSize;
1263 
1264     error = PaWriteStream(buffer, length);
1265     acache.readIndex += acache.totalCacheSize;
1266     acache.isFull = false;
1267 
1268     if (!error && (length >= 0) && !acache.isFull) {
1269         uint8_t *cacheBuffer = acache.buffer.get();
1270         uint32_t offset = acache.readIndex;
1271         uint32_t size = (acache.writeIndex - acache.readIndex);
1272         if (size > 0) {
1273             if (memcpy_s(cacheBuffer, acache.totalCacheSize, cacheBuffer + offset, size)) {
1274                 MEDIA_ERR_LOG("Update cache failed");
1275                 pError = AUDIO_CLIENT_WRITE_STREAM_ERR;
1276                 return cachedLen;
1277             }
1278             MEDIA_INFO_LOG("rearranging the audio cache");
1279         }
1280         acache.readIndex = 0;
1281         acache.writeIndex = 0;
1282 
1283         if (cachedLen < stream.bufferLen) {
1284             StreamBuffer str;
1285             str.buffer = stream.buffer + cachedLen;
1286             str.bufferLen = stream.bufferLen - cachedLen;
1287             MEDIA_INFO_LOG("writing pending data to audio cache: %{public}d", str.bufferLen);
1288             cachedLen += WriteToAudioCache(str);
1289         }
1290     }
1291 
1292     pa_threaded_mainloop_unlock(mainLoop);
1293     pError = error;
1294     return cachedLen;
1295 }
1296 
UpdateReadBuffer(uint8_t * buffer,size_t & length,size_t & readSize)1297 int32_t AudioServiceClient::UpdateReadBuffer(uint8_t *buffer, size_t &length, size_t &readSize)
1298 {
1299     size_t l = (internalRdBufLen < length) ? internalRdBufLen : length;
1300     if (memcpy_s(buffer, length, (const uint8_t*)internalReadBuffer + internalRdBufIndex, l)) {
1301         MEDIA_ERR_LOG("Update read buffer failed");
1302         return AUDIO_CLIENT_READ_STREAM_ERR;
1303     }
1304 
1305     length -= l;
1306     internalRdBufIndex += l;
1307     internalRdBufLen -= l;
1308     readSize += l;
1309 
1310     if (!internalRdBufLen) {
1311         int retVal = pa_stream_drop(paStream);
1312         internalReadBuffer = nullptr;
1313         internalRdBufLen = 0;
1314         internalRdBufIndex = 0;
1315         if (retVal < 0) {
1316             MEDIA_ERR_LOG("pa_stream_drop failed, retVal: %{public}d", retVal);
1317             return AUDIO_CLIENT_READ_STREAM_ERR;
1318         }
1319     }
1320 
1321     return 0;
1322 }
1323 
OnTimeOut()1324 void AudioServiceClient::OnTimeOut()
1325 {
1326     MEDIA_ERR_LOG("Inside read timeout callback");
1327     pa_threaded_mainloop_lock(mainLoop);
1328     pa_threaded_mainloop_signal(mainLoop, 0);
1329     pa_threaded_mainloop_unlock(mainLoop);
1330 }
1331 
HandleCapturePositionCallbacks(size_t bytesRead)1332 void AudioServiceClient::HandleCapturePositionCallbacks(size_t bytesRead)
1333 {
1334     mTotalBytesRead += bytesRead;
1335     if (mFrameSize == 0) {
1336         MEDIA_ERR_LOG("HandleCapturePositionCallbacks: capturePeriodPositionCb not set");
1337         return;
1338     }
1339 
1340     uint64_t readFrameNumber = mTotalBytesRead / mFrameSize;
1341     MEDIA_DEBUG_LOG("frame size: %{public}d", mFrameSize);
1342     {
1343         std::lock_guard<std::mutex> lock(capturerMarkReachedMutex_);
1344         if (!mMarkReached && mCapturePositionCb) {
1345             MEDIA_DEBUG_LOG("frame mark position: %{public}" PRIu64 ", Total frames read: %{public}" PRIu64,
1346                 static_cast<uint64_t>(mFrameMarkPosition), static_cast<uint64_t>(readFrameNumber));
1347             if (readFrameNumber >= mFrameMarkPosition) {
1348                 MEDIA_DEBUG_LOG("audio service client capturer OnMarkReached");
1349                 mPositionCBThreads.emplace_back(std::make_unique<std::thread>(&CapturerPositionCallback::OnMarkReached,
1350                                                 mCapturePositionCb, mFrameMarkPosition));
1351                 mMarkReached = true;
1352             }
1353         }
1354     }
1355 
1356     {
1357         std::lock_guard<std::mutex> lock(capturerPeriodReachedMutex_);
1358         if (mCapturePeriodPositionCb) {
1359             mFramePeriodRead += (bytesRead / mFrameSize);
1360             MEDIA_DEBUG_LOG("frame period number: %{public}" PRIu64 ", Total frames read: %{public}" PRIu64,
1361                 static_cast<uint64_t>(mFramePeriodNumber), static_cast<uint64_t>(readFrameNumber));
1362             if (mFramePeriodRead >= mFramePeriodNumber) {
1363                 mFramePeriodRead %= mFramePeriodNumber;
1364                 MEDIA_DEBUG_LOG("audio service client OnPeriodReached, remaining frames: %{public}" PRIu64,
1365                     static_cast<uint64_t>(mFramePeriodRead));
1366                 mPeriodPositionCBThreads.emplace_back(std::make_unique<std::thread>(
1367                     &CapturerPeriodPositionCallback::OnPeriodReached, mCapturePeriodPositionCb, mFramePeriodNumber));
1368             }
1369         }
1370     }
1371 }
1372 
ReadStream(StreamBuffer & stream,bool isBlocking)1373 int32_t AudioServiceClient::ReadStream(StreamBuffer &stream, bool isBlocking)
1374 {
1375     uint8_t *buffer = stream.buffer;
1376     size_t length = stream.bufferLen;
1377     size_t readSize = 0;
1378 
1379     CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
1380 
1381     lock_guard<mutex> lock(dataMutex);
1382     pa_threaded_mainloop_lock(mainLoop);
1383     while (length > 0) {
1384         while (!internalReadBuffer) {
1385             int retVal = pa_stream_peek(paStream, &internalReadBuffer, &internalRdBufLen);
1386             if (retVal < 0) {
1387                 MEDIA_ERR_LOG("pa_stream_peek failed, retVal: %{public}d", retVal);
1388                 pa_threaded_mainloop_unlock(mainLoop);
1389                 return AUDIO_CLIENT_READ_STREAM_ERR;
1390             }
1391 
1392             if (internalRdBufLen <= 0) {
1393                 if (isBlocking) {
1394                     StartTimer(READ_TIMEOUT_IN_SEC);
1395                     pa_threaded_mainloop_wait(mainLoop);
1396                     StopTimer();
1397                     if (IsTimeOut()) {
1398                         MEDIA_ERR_LOG("Read timeout");
1399                         pa_threaded_mainloop_unlock(mainLoop);
1400                         return AUDIO_CLIENT_READ_STREAM_ERR;
1401                     }
1402                 } else {
1403                     pa_threaded_mainloop_unlock(mainLoop);
1404                     HandleCapturePositionCallbacks(readSize);
1405                     return readSize;
1406                 }
1407             } else if (!internalReadBuffer) {
1408                 retVal = pa_stream_drop(paStream);
1409                 if (retVal < 0) {
1410                     MEDIA_ERR_LOG("pa_stream_drop failed, retVal: %{public}d", retVal);
1411                     pa_threaded_mainloop_unlock(mainLoop);
1412                     return AUDIO_CLIENT_READ_STREAM_ERR;
1413                 }
1414             } else {
1415                 internalRdBufIndex = 0;
1416                 MEDIA_INFO_LOG("buffer size from PA: %{public}zu", internalRdBufLen);
1417             }
1418         }
1419 
1420         if (UpdateReadBuffer(buffer, length, readSize) != 0) {
1421             pa_threaded_mainloop_unlock(mainLoop);
1422             return AUDIO_CLIENT_READ_STREAM_ERR;
1423         }
1424         buffer = stream.buffer + readSize;
1425     }
1426     pa_threaded_mainloop_unlock(mainLoop);
1427     HandleCapturePositionCallbacks(readSize);
1428 
1429     return readSize;
1430 }
1431 
ReleaseStream()1432 int32_t AudioServiceClient::ReleaseStream()
1433 {
1434     ResetPAAudioClient();
1435     state_ = RELEASED;
1436 
1437     std::shared_ptr<AudioStreamCallback> streamCb = streamCallback_.lock();
1438     if (streamCb != nullptr) {
1439         streamCb->OnStateChange(state_);
1440     }
1441 
1442     return AUDIO_CLIENT_SUCCESS;
1443 }
1444 
SetBufferSizeInMsec(int32_t bufferSizeInMsec)1445 int32_t AudioServiceClient::SetBufferSizeInMsec(int32_t bufferSizeInMsec)
1446 {
1447     size_t bufferSize =  pa_usec_to_bytes(bufferSizeInMsec * PA_USEC_PER_MSEC, &sampleSpec);
1448     setBufferSize = bufferSize;
1449     return AUDIO_CLIENT_SUCCESS;
1450 }
1451 
GetMinimumBufferSize(size_t & minBufferSize) const1452 int32_t AudioServiceClient::GetMinimumBufferSize(size_t &minBufferSize) const
1453 {
1454     CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
1455 
1456     const pa_buffer_attr *bufferAttr = pa_stream_get_buffer_attr(paStream);
1457 
1458     if (bufferAttr == nullptr) {
1459         MEDIA_ERR_LOG("pa_stream_get_buffer_attr returned nullptr");
1460         return AUDIO_CLIENT_ERR;
1461     }
1462 
1463     if (eAudioClientType == AUDIO_SERVICE_CLIENT_PLAYBACK) {
1464         if (renderMode_ == RENDER_MODE_CALLBACK) {
1465             minBufferSize = (size_t)bufferAttr->minreq;
1466         } else {
1467             if (setBufferSize) {
1468                 minBufferSize = setBufferSize;
1469             } else {
1470                 minBufferSize = (size_t)bufferAttr->minreq;
1471             }
1472         }
1473     }
1474 
1475     if (eAudioClientType == AUDIO_SERVICE_CLIENT_RECORD) {
1476         minBufferSize = (size_t)bufferAttr->fragsize;
1477     }
1478 
1479     return AUDIO_CLIENT_SUCCESS;
1480 }
1481 
GetMinimumFrameCount(uint32_t & frameCount) const1482 int32_t AudioServiceClient::GetMinimumFrameCount(uint32_t &frameCount) const
1483 {
1484     CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
1485     size_t minBufferSize = 0;
1486 
1487     const pa_buffer_attr *bufferAttr = pa_stream_get_buffer_attr(paStream);
1488 
1489     if (bufferAttr == nullptr) {
1490         MEDIA_ERR_LOG("pa_stream_get_buffer_attr returned nullptr");
1491         return AUDIO_CLIENT_ERR;
1492     }
1493 
1494     if (eAudioClientType == AUDIO_SERVICE_CLIENT_PLAYBACK) {
1495         if (renderMode_ == RENDER_MODE_CALLBACK) {
1496             minBufferSize = (size_t)bufferAttr->minreq;
1497         } else {
1498             if (setBufferSize) {
1499                 minBufferSize = setBufferSize;
1500             } else {
1501                 minBufferSize = (size_t)bufferAttr->minreq;
1502             }
1503         }
1504     }
1505 
1506     if (eAudioClientType == AUDIO_SERVICE_CLIENT_RECORD) {
1507         minBufferSize = (size_t)bufferAttr->fragsize;
1508     }
1509 
1510     uint32_t bytesPerSample = pa_frame_size(&sampleSpec);
1511     if (bytesPerSample == 0) {
1512         MEDIA_ERR_LOG("GetMinimumFrameCount Failed");
1513         return AUDIO_CLIENT_ERR;
1514     }
1515 
1516     frameCount = minBufferSize / bytesPerSample;
1517     MEDIA_INFO_LOG("frame count: %d", frameCount);
1518     return AUDIO_CLIENT_SUCCESS;
1519 }
1520 
GetSamplingRate() const1521 uint32_t AudioServiceClient::GetSamplingRate() const
1522 {
1523     return DEFAULT_SAMPLING_RATE;
1524 }
1525 
GetChannelCount() const1526 uint8_t AudioServiceClient::GetChannelCount() const
1527 {
1528     return DEFAULT_CHANNEL_COUNT;
1529 }
1530 
GetSampleSize() const1531 uint8_t AudioServiceClient::GetSampleSize() const
1532 {
1533     return DEFAULT_SAMPLE_SIZE;
1534 }
1535 
GetAudioStreamParams(AudioStreamParams & audioParams) const1536 int32_t AudioServiceClient::GetAudioStreamParams(AudioStreamParams& audioParams) const
1537 {
1538     CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
1539     const pa_sample_spec *paSampleSpec = pa_stream_get_sample_spec(paStream);
1540 
1541     if (!paSampleSpec) {
1542         MEDIA_ERR_LOG("GetAudioStreamParams Failed");
1543         return AUDIO_CLIENT_ERR;
1544     }
1545 
1546     audioParams = ConvertFromPAAudioParams(*paSampleSpec);
1547     return AUDIO_CLIENT_SUCCESS;
1548 }
1549 
GetStreamVolume(uint32_t sessionID)1550 uint32_t AudioServiceClient::GetStreamVolume(uint32_t sessionID)
1551 {
1552     return DEFAULT_STREAM_VOLUME;
1553 }
1554 
GetCurrentTimeStamp(uint64_t & timeStamp) const1555 int32_t AudioServiceClient::GetCurrentTimeStamp(uint64_t &timeStamp) const
1556 {
1557     CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
1558     int32_t retVal = AUDIO_CLIENT_SUCCESS;
1559 
1560     pa_threaded_mainloop_lock(mainLoop);
1561     const pa_timing_info *info = pa_stream_get_timing_info(paStream);
1562     if (info == nullptr) {
1563         retVal = AUDIO_CLIENT_ERR;
1564     } else {
1565         if (eAudioClientType == AUDIO_SERVICE_CLIENT_PLAYBACK) {
1566             timeStamp = pa_bytes_to_usec(info->write_index, &sampleSpec);
1567         } else if (eAudioClientType == AUDIO_SERVICE_CLIENT_RECORD) {
1568             if (pa_stream_get_time(paStream, &timeStamp)) {
1569                 MEDIA_ERR_LOG("AudioServiceClient::GetCurrentTimeStamp failed for AUDIO_SERVICE_CLIENT_RECORD");
1570             }
1571         }
1572     }
1573     pa_threaded_mainloop_unlock(mainLoop);
1574 
1575     return retVal;
1576 }
1577 
GetAudioLatency(uint64_t & latency) const1578 int32_t AudioServiceClient::GetAudioLatency(uint64_t &latency) const
1579 {
1580     CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR);
1581     pa_usec_t paLatency;
1582     pa_usec_t cacheLatency;
1583     int32_t retVal = AUDIO_CLIENT_SUCCESS;
1584     int negative;
1585     bool getPALatency = false;
1586 
1587     // Get PA latency
1588     pa_threaded_mainloop_lock(mainLoop);
1589     while (!getPALatency) {
1590         if (pa_stream_get_latency(paStream, &paLatency, &negative) >= 0) {
1591             if (negative) {
1592                 latency = 0;
1593                 retVal = AUDIO_CLIENT_ERR;
1594                 return retVal;
1595             }
1596             getPALatency = true;
1597             break;
1598         }
1599         MEDIA_INFO_LOG("waiting for audio latency information");
1600         pa_threaded_mainloop_wait(mainLoop);
1601     }
1602     pa_threaded_mainloop_unlock(mainLoop);
1603 
1604     if (eAudioClientType == AUDIO_SERVICE_CLIENT_PLAYBACK) {
1605         // Get audio write cache latency
1606         cacheLatency = pa_bytes_to_usec((acache.totalCacheSize - acache.writeIndex), &sampleSpec);
1607 
1608         // Total latency will be sum of audio write cache latency + PA latency
1609         latency = paLatency + cacheLatency;
1610         MEDIA_INFO_LOG("total latency: %{public}" PRIu64 ", pa latency: %{public}"
1611             PRIu64 ", cache latency: %{public}" PRIu64, latency, paLatency, cacheLatency);
1612     } else if (eAudioClientType == AUDIO_SERVICE_CLIENT_RECORD) {
1613         // Get audio read cache latency
1614         cacheLatency = pa_bytes_to_usec(internalRdBufLen, &sampleSpec);
1615 
1616         // Total latency will be sum of audio read cache latency + PA latency
1617         latency = paLatency + cacheLatency;
1618         MEDIA_INFO_LOG("total latency: %{public}" PRIu64 ", pa latency: %{public}" PRIu64, latency, paLatency);
1619     }
1620 
1621     return retVal;
1622 }
1623 
RegisterAudioRendererCallbacks(const AudioRendererCallbacks & cb)1624 void AudioServiceClient::RegisterAudioRendererCallbacks(const AudioRendererCallbacks &cb)
1625 {
1626     MEDIA_INFO_LOG("Registering audio render callbacks");
1627     mAudioRendererCallbacks = (AudioRendererCallbacks *)&cb;
1628 }
1629 
RegisterAudioCapturerCallbacks(const AudioCapturerCallbacks & cb)1630 void AudioServiceClient::RegisterAudioCapturerCallbacks(const AudioCapturerCallbacks &cb)
1631 {
1632     MEDIA_INFO_LOG("Registering audio record callbacks");
1633     mAudioCapturerCallbacks = (AudioCapturerCallbacks *)&cb;
1634 }
1635 
SetRendererPositionCallback(int64_t markPosition,const std::shared_ptr<RendererPositionCallback> & callback)1636 void AudioServiceClient::SetRendererPositionCallback(int64_t markPosition,
1637     const std::shared_ptr<RendererPositionCallback> &callback)
1638 {
1639     MEDIA_INFO_LOG("Registering render frame position callback");
1640     MEDIA_INFO_LOG("mark position: %{public}" PRIu64, markPosition);
1641     mFrameMarkPosition = markPosition;
1642     mRenderPositionCb = callback;
1643     mMarkReached = false;
1644 }
1645 
UnsetRendererPositionCallback()1646 void AudioServiceClient::UnsetRendererPositionCallback()
1647 {
1648     MEDIA_INFO_LOG("Unregistering render frame position callback");
1649     std::lock_guard<std::mutex> lock(rendererMarkReachedMutex_);
1650     mRenderPositionCb = nullptr;
1651     mMarkReached = false;
1652     mFrameMarkPosition = 0;
1653 }
1654 
SetRendererPeriodPositionCallback(int64_t periodPosition,const std::shared_ptr<RendererPeriodPositionCallback> & callback)1655 void AudioServiceClient::SetRendererPeriodPositionCallback(int64_t periodPosition,
1656     const std::shared_ptr<RendererPeriodPositionCallback> &callback)
1657 {
1658     MEDIA_INFO_LOG("Registering render period position callback");
1659     mFramePeriodNumber = periodPosition;
1660     if ((mFrameSize != 0) && (mFramePeriodNumber != 0)) {
1661         mFramePeriodWritten = (mTotalBytesWritten / mFrameSize) % mFramePeriodNumber;
1662     } else {
1663         MEDIA_ERR_LOG("AudioServiceClient::SetRendererPeriodPositionCallback failed");
1664         return;
1665     }
1666     mRenderPeriodPositionCb = callback;
1667 }
1668 
UnsetRendererPeriodPositionCallback()1669 void AudioServiceClient::UnsetRendererPeriodPositionCallback()
1670 {
1671     MEDIA_INFO_LOG("Unregistering render period position callback");
1672     std::lock_guard<std::mutex> lock(rendererPeriodReachedMutex_);
1673     mRenderPeriodPositionCb = nullptr;
1674     mFramePeriodWritten = 0;
1675     mFramePeriodNumber = 0;
1676 }
1677 
SetCapturerPositionCallback(int64_t markPosition,const std::shared_ptr<CapturerPositionCallback> & callback)1678 void AudioServiceClient::SetCapturerPositionCallback(int64_t markPosition,
1679     const std::shared_ptr<CapturerPositionCallback> &callback)
1680 {
1681     MEDIA_INFO_LOG("Registering capture frame position callback");
1682     MEDIA_INFO_LOG("mark position: %{public}" PRIu64, markPosition);
1683     mFrameMarkPosition = markPosition;
1684     mCapturePositionCb = callback;
1685     mMarkReached = false;
1686 }
1687 
UnsetCapturerPositionCallback()1688 void AudioServiceClient::UnsetCapturerPositionCallback()
1689 {
1690     MEDIA_INFO_LOG("Unregistering capture frame position callback");
1691     std::lock_guard<std::mutex> lock(capturerMarkReachedMutex_);
1692     mCapturePositionCb = nullptr;
1693     mMarkReached = false;
1694     mFrameMarkPosition = 0;
1695 }
1696 
SetCapturerPeriodPositionCallback(int64_t periodPosition,const std::shared_ptr<CapturerPeriodPositionCallback> & callback)1697 void AudioServiceClient::SetCapturerPeriodPositionCallback(int64_t periodPosition,
1698     const std::shared_ptr<CapturerPeriodPositionCallback> &callback)
1699 {
1700     MEDIA_INFO_LOG("Registering period position callback");
1701     mFramePeriodNumber = periodPosition;
1702     if ((mFrameSize != 0) && (mFramePeriodNumber) != 0) {
1703         mFramePeriodRead = (mTotalBytesRead / mFrameSize) % mFramePeriodNumber;
1704     } else {
1705         MEDIA_INFO_LOG("AudioServiceClient::SetCapturerPeriodPositionCallback failed");
1706         return;
1707     }
1708     mCapturePeriodPositionCb = callback;
1709 }
1710 
UnsetCapturerPeriodPositionCallback()1711 void AudioServiceClient::UnsetCapturerPeriodPositionCallback()
1712 {
1713     MEDIA_INFO_LOG("Unregistering period position callback");
1714     std::lock_guard<std::mutex> lock(capturerPeriodReachedMutex_);
1715     mCapturePeriodPositionCb = nullptr;
1716     mFramePeriodRead = 0;
1717     mFramePeriodNumber = 0;
1718 }
1719 
SetStreamType(AudioStreamType audioStreamType)1720 int32_t AudioServiceClient::SetStreamType(AudioStreamType audioStreamType)
1721 {
1722     MEDIA_INFO_LOG("SetStreamType: %{public}d", audioStreamType);
1723 
1724     if (context == nullptr) {
1725         MEDIA_ERR_LOG("context is null");
1726         return AUDIO_CLIENT_ERR;
1727     }
1728 
1729     pa_threaded_mainloop_lock(mainLoop);
1730 
1731     mStreamType = audioStreamType;
1732     const std::string streamName = GetStreamName(audioStreamType);
1733 
1734     pa_proplist *propList = pa_proplist_new();
1735     if (propList == nullptr) {
1736         MEDIA_ERR_LOG("pa_proplist_new failed");
1737         pa_threaded_mainloop_unlock(mainLoop);
1738         return AUDIO_CLIENT_ERR;
1739     }
1740 
1741     pa_proplist_sets(propList, "stream.type", streamName.c_str());
1742     pa_proplist_sets(propList, "media.name", streamName.c_str());
1743     pa_operation *updatePropOperation = pa_stream_proplist_update(paStream, PA_UPDATE_REPLACE, propList,
1744         nullptr, nullptr);
1745     pa_proplist_free(propList);
1746     pa_operation_unref(updatePropOperation);
1747 
1748     pa_threaded_mainloop_unlock(mainLoop);
1749 
1750     return AUDIO_CLIENT_SUCCESS;
1751 }
1752 
SetStreamVolume(float volume)1753 int32_t AudioServiceClient::SetStreamVolume(float volume)
1754 {
1755     lock_guard<mutex> lock(ctrlMutex);
1756     MEDIA_INFO_LOG("SetVolume volume: %{public}f", volume);
1757 
1758     if (context == nullptr) {
1759         MEDIA_ERR_LOG("context is null");
1760         return AUDIO_CLIENT_ERR;
1761     }
1762 
1763     /* Validate and return INVALID_PARAMS error */
1764     if ((volume < MIN_STREAM_VOLUME_LEVEL) || (volume > MAX_STREAM_VOLUME_LEVEL)) {
1765         MEDIA_ERR_LOG("Invalid Volume Input!");
1766         return AUDIO_CLIENT_INVALID_PARAMS_ERR;
1767     }
1768 
1769     pa_threaded_mainloop_lock(mainLoop);
1770 
1771     mVolumeFactor = volume;
1772     pa_proplist *propList = pa_proplist_new();
1773     if (propList == nullptr) {
1774         MEDIA_ERR_LOG("pa_proplist_new failed");
1775         pa_threaded_mainloop_unlock(mainLoop);
1776         return AUDIO_CLIENT_ERR;
1777     }
1778 
1779     pa_proplist_sets(propList, "stream.volumeFactor", std::to_string(mVolumeFactor).c_str());
1780     pa_operation *updatePropOperation = pa_stream_proplist_update(paStream, PA_UPDATE_REPLACE, propList,
1781         nullptr, nullptr);
1782     pa_proplist_free(propList);
1783     pa_operation_unref(updatePropOperation);
1784 
1785     if (mAudioSystemMgr == nullptr) {
1786         MEDIA_ERR_LOG("System manager instance is null");
1787         pa_threaded_mainloop_unlock(mainLoop);
1788         return AUDIO_CLIENT_ERR;
1789     }
1790 
1791     if (!streamInfoUpdated) {
1792         uint32_t idx = pa_stream_get_index(paStream);
1793         pa_operation *operation = pa_context_get_sink_input_info(context, idx, AudioServiceClient::GetSinkInputInfoCb,
1794             reinterpret_cast<void *>(this));
1795         if (operation == nullptr) {
1796             MEDIA_ERR_LOG("pa_context_get_sink_input_info_list returned null");
1797             pa_threaded_mainloop_unlock(mainLoop);
1798             return AUDIO_CLIENT_ERR;
1799         }
1800 
1801         pa_threaded_mainloop_accept(mainLoop);
1802 
1803         pa_operation_unref(operation);
1804     } else {
1805         SetPaVolume(*this);
1806     }
1807 
1808     pa_threaded_mainloop_unlock(mainLoop);
1809 
1810     return AUDIO_CLIENT_SUCCESS;
1811 }
1812 
GetStreamVolume()1813 float AudioServiceClient::GetStreamVolume()
1814 {
1815     return mVolumeFactor;
1816 }
1817 
GetSinkInputInfoCb(pa_context * context,const pa_sink_input_info * info,int eol,void * userdata)1818 void AudioServiceClient::GetSinkInputInfoCb(pa_context *context, const pa_sink_input_info *info, int eol,
1819     void *userdata)
1820 {
1821     MEDIA_INFO_LOG("GetSinkInputInfoVolumeCb in");
1822     AudioServiceClient *thiz = reinterpret_cast<AudioServiceClient *>(userdata);
1823 
1824     if (eol < 0) {
1825         MEDIA_ERR_LOG("Failed to get sink input information: %{public}s", pa_strerror(pa_context_errno(context)));
1826         return;
1827     }
1828 
1829     if (eol) {
1830         pa_threaded_mainloop_signal(thiz->mainLoop, 1);
1831         return;
1832     }
1833 
1834     if (info->proplist == nullptr) {
1835         MEDIA_ERR_LOG("Invalid prop list for sink input (%{public}d).", info->index);
1836         return;
1837     }
1838 
1839     thiz->cvolume = info->volume;
1840     thiz->streamIndex = info->index;
1841     thiz->volumeChannels = info->channel_map.channels;
1842     thiz->streamInfoUpdated = true;
1843 
1844     SetPaVolume(*thiz);
1845 
1846     return;
1847 }
1848 
SetPaVolume(const AudioServiceClient & client)1849 void AudioServiceClient::SetPaVolume(const AudioServiceClient &client)
1850 {
1851     pa_cvolume cv = client.cvolume;
1852     int32_t systemVolumeInt
1853         = client.mAudioSystemMgr->GetVolume(static_cast<AudioSystemManager::AudioVolumeType>(client.mStreamType));
1854     float systemVolume = AudioSystemManager::MapVolumeToHDI(systemVolumeInt);
1855     float vol = systemVolume * client.mVolumeFactor;
1856 
1857     AudioRingerMode ringerMode = client.mAudioSystemMgr->GetRingerMode();
1858     if ((client.mStreamType == STREAM_RING) && (ringerMode != RINGER_MODE_NORMAL)) {
1859         vol = MIN_STREAM_VOLUME_LEVEL;
1860     }
1861 
1862     uint32_t volume = pa_sw_volume_from_linear(vol);
1863     pa_cvolume_set(&cv, client.volumeChannels, volume);
1864     pa_operation_unref(pa_context_set_sink_input_volume(client.context, client.streamIndex, &cv, nullptr, nullptr));
1865 
1866     MEDIA_INFO_LOG("Applied volume : %{public}f, pa volume: %{public}d", vol, volume);
1867 }
1868 
SetStreamRenderRate(AudioRendererRate audioRendererRate)1869 int32_t AudioServiceClient::SetStreamRenderRate(AudioRendererRate audioRendererRate)
1870 {
1871     MEDIA_INFO_LOG("SetStreamRenderRate in");
1872     renderRate = audioRendererRate;
1873     if (!paStream) {
1874         return AUDIO_CLIENT_SUCCESS;
1875     }
1876 
1877     uint32_t rate = sampleSpec.rate;
1878     switch (audioRendererRate) {
1879         case RENDER_RATE_NORMAL:
1880             break;
1881         case RENDER_RATE_DOUBLE:
1882             rate *= DOUBLE_VALUE;
1883             break;
1884         case RENDER_RATE_HALF:
1885             rate /= DOUBLE_VALUE;
1886             break;
1887         default:
1888             return AUDIO_CLIENT_INVALID_PARAMS_ERR;
1889     }
1890 
1891     pa_threaded_mainloop_lock(mainLoop);
1892     pa_operation *operation = pa_stream_update_sample_rate(paStream, rate, nullptr, nullptr);
1893     pa_operation_unref(operation);
1894     pa_threaded_mainloop_unlock(mainLoop);
1895 
1896     return AUDIO_CLIENT_SUCCESS;
1897 }
1898 
GetStreamRenderRate()1899 AudioRendererRate AudioServiceClient::GetStreamRenderRate()
1900 {
1901     return renderRate;
1902 }
1903 
SaveStreamCallback(const std::weak_ptr<AudioStreamCallback> & callback)1904 void AudioServiceClient::SaveStreamCallback(const std::weak_ptr<AudioStreamCallback> &callback)
1905 {
1906     streamCallback_ = callback;
1907 
1908     if (state_ != PREPARED) {
1909         return;
1910     }
1911 
1912     std::shared_ptr<AudioStreamCallback> streamCb = streamCallback_.lock();
1913     if (streamCb != nullptr) {
1914         streamCb->OnStateChange(state_);
1915     }
1916 }
1917 } // namespace AudioStandard
1918 } // namespace OHOS
1919