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