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 #ifndef ST_PULSEAUDIO_AUDIO_SERVICE_ADAPTER_IMPL_H
17 #define ST_PULSEAUDIO_AUDIO_SERVICE_ADAPTER_IMPL_H
18
19 #include "pulse_audio_service_adapter_impl.h"
20
21 #include <sstream>
22 #include <unistd.h>
23
24 #include "audio_errors.h"
25 #include "audio_log.h"
26 #include "hisysevent.h"
27
28 using namespace std;
29
30 namespace OHOS {
31 namespace AudioStandard {
32 static unique_ptr<AudioServiceAdapterCallback> g_audioServiceAdapterCallback;
33 std::unordered_map<uint32_t, uint32_t> PulseAudioServiceAdapterImpl::sinkIndexSessionIDMap;
34
35 AudioServiceAdapter::~AudioServiceAdapter() = default;
36 PulseAudioServiceAdapterImpl::~PulseAudioServiceAdapterImpl() = default;
37
CreateAudioAdapter(unique_ptr<AudioServiceAdapterCallback> cb)38 unique_ptr<AudioServiceAdapter> AudioServiceAdapter::CreateAudioAdapter(unique_ptr<AudioServiceAdapterCallback> cb)
39 {
40 if (!cb) {
41 AUDIO_ERR_LOG("AudioServiceAdapter::CreateAudioAdapter cb is nullptr!");
42 return nullptr;
43 }
44 return make_unique<PulseAudioServiceAdapterImpl>(cb);
45 }
46
PulseAudioServiceAdapterImpl(unique_ptr<AudioServiceAdapterCallback> & cb)47 PulseAudioServiceAdapterImpl::PulseAudioServiceAdapterImpl(unique_ptr<AudioServiceAdapterCallback> &cb)
48 {
49 g_audioServiceAdapterCallback = move(cb);
50 }
51
Connect()52 bool PulseAudioServiceAdapterImpl::Connect()
53 {
54 mMainLoop = pa_threaded_mainloop_new();
55 if (!mMainLoop) {
56 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] MainLoop creation failed");
57 return false;
58 }
59
60 if (pa_threaded_mainloop_start(mMainLoop) < 0) {
61 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Failed to start mainloop");
62 pa_threaded_mainloop_free(mMainLoop);
63 return false;
64 }
65
66 pa_threaded_mainloop_lock(mMainLoop);
67
68 while (true) {
69 pa_context_state_t state;
70
71 if (mContext != nullptr) {
72 state = pa_context_get_state(mContext);
73 if (state == PA_CONTEXT_READY) {
74 break;
75 }
76 // if pulseaudio is ready, retry connect to pulseaudio. before retry wait for sometime. reduce sleep later
77 usleep(PA_CONNECT_RETRY_SLEEP_IN_MICRO_SECONDS);
78 }
79
80 bool result = ConnectToPulseAudio();
81 if (!result || !PA_CONTEXT_IS_GOOD(pa_context_get_state(mContext))) {
82 continue;
83 }
84
85 AUDIO_DEBUG_LOG("[PulseAudioServiceAdapterImpl] pa context not ready... wait");
86
87 // Wait for the context to be ready
88 pa_threaded_mainloop_wait(mMainLoop);
89 }
90
91 pa_threaded_mainloop_unlock(mMainLoop);
92
93 return true;
94 }
95
ConnectToPulseAudio()96 bool PulseAudioServiceAdapterImpl::ConnectToPulseAudio()
97 {
98 if (mContext != nullptr) {
99 AUDIO_INFO_LOG("[PulseAudioServiceAdapterImpl] context is not null, disconnect first!");
100 pa_context_disconnect(mContext);
101 pa_context_set_state_callback(mContext, nullptr, nullptr);
102 pa_context_set_subscribe_callback(mContext, nullptr, nullptr);
103 pa_context_unref(mContext);
104 }
105
106 pa_proplist *proplist = pa_proplist_new();
107 pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "PulseAudio Service");
108 pa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, "com.ohos.pulseaudio.service");
109 mContext = pa_context_new_with_proplist(pa_threaded_mainloop_get_api(mMainLoop), nullptr, proplist);
110 pa_proplist_free(proplist);
111
112 if (mContext == nullptr) {
113 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] creating pa context failed");
114 return false;
115 }
116
117 pa_context_set_state_callback(mContext, PulseAudioServiceAdapterImpl::PaContextStateCb, this);
118 if (pa_context_connect(mContext, nullptr, PA_CONTEXT_NOFAIL, nullptr) < 0) {
119 if (pa_context_errno(mContext) == PA_ERR_INVALID) {
120 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] pa context connect failed: %{public}s",
121 pa_strerror(pa_context_errno(mContext)));
122 goto Fail;
123 }
124 }
125
126 return true;
127
128 Fail:
129 /* Make sure we don't get any further callbacks */
130 pa_context_set_state_callback(mContext, nullptr, nullptr);
131 pa_context_set_subscribe_callback(mContext, nullptr, nullptr);
132 pa_context_unref(mContext);
133 return false;
134 }
135
OpenAudioPort(string audioPortName,string moduleArgs)136 uint32_t PulseAudioServiceAdapterImpl::OpenAudioPort(string audioPortName, string moduleArgs)
137 {
138 unique_ptr<UserData> userData = make_unique<UserData>();
139 userData->thiz = this;
140
141 pa_threaded_mainloop_lock(mMainLoop);
142 if (mContext == nullptr) {
143 AUDIO_ERR_LOG("[OpenAudioPort] mContext is nullptr");
144 pa_threaded_mainloop_unlock(mMainLoop);
145 return ERROR;
146 }
147
148 pa_operation *operation = pa_context_load_module(mContext, audioPortName.c_str(), moduleArgs.c_str(),
149 PaModuleLoadCb, reinterpret_cast<void*>(userData.get()));
150 if (operation == nullptr) {
151 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] pa_context_load_module returned nullptr");
152 pa_threaded_mainloop_unlock(mMainLoop);
153 return PA_INVALID_INDEX;
154 }
155
156 while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
157 pa_threaded_mainloop_wait(mMainLoop);
158 }
159
160 pa_operation_unref(operation);
161 pa_threaded_mainloop_unlock(mMainLoop);
162
163 if (userData->idx == PA_INVALID_INDEX) {
164 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] OpenAudioPort returned invalid index");
165 return PA_INVALID_INDEX;
166 }
167
168 return userData->idx;
169 }
170
CloseAudioPort(int32_t audioHandleIndex)171 int32_t PulseAudioServiceAdapterImpl::CloseAudioPort(int32_t audioHandleIndex)
172 {
173 pa_threaded_mainloop_lock(mMainLoop);
174 if (mContext == nullptr) {
175 AUDIO_ERR_LOG("[CloseAudioPort] mContext is nullptr");
176 pa_threaded_mainloop_unlock(mMainLoop);
177 return ERROR;
178 }
179
180 pa_operation *operation = pa_context_unload_module(mContext, audioHandleIndex, nullptr, nullptr);
181 if (operation == nullptr) {
182 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] pa_context_unload_module returned nullptr!");
183 pa_threaded_mainloop_unlock(mMainLoop);
184 return ERROR;
185 }
186
187 pa_operation_unref(operation);
188 pa_threaded_mainloop_unlock(mMainLoop);
189 return SUCCESS;
190 }
191
SuspendAudioDevice(string & audioPortName,bool isSuspend)192 int32_t PulseAudioServiceAdapterImpl::SuspendAudioDevice(string &audioPortName, bool isSuspend)
193 {
194 AUDIO_INFO_LOG("SuspendAudioDevice: [%{public}s] : [%{public}d]", audioPortName.c_str(), isSuspend);
195 pa_threaded_mainloop_lock(mMainLoop);
196 if (mContext == nullptr) {
197 AUDIO_ERR_LOG("[SuspendAudioDevice] mContext is nullptr");
198 pa_threaded_mainloop_unlock(mMainLoop);
199 return ERROR;
200 }
201
202 auto suspendFlag = isSuspend ? 1 : 0;
203 pa_operation *operation = pa_context_suspend_sink_by_name(mContext, audioPortName.c_str(), suspendFlag,
204 nullptr, nullptr);
205 if (operation == nullptr) {
206 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] pa_context_suspend_sink_by_name failed!");
207 pa_threaded_mainloop_unlock(mMainLoop);
208 return ERR_OPERATION_FAILED;
209 }
210
211 pa_operation_unref(operation);
212 pa_threaded_mainloop_unlock(mMainLoop);
213
214 return SUCCESS;
215 }
216
SetDefaultSink(string name)217 int32_t PulseAudioServiceAdapterImpl::SetDefaultSink(string name)
218 {
219 pa_threaded_mainloop_lock(mMainLoop);
220 if (mContext == nullptr) {
221 AUDIO_ERR_LOG("[SetDefaultSink] mContext is nullptr");
222 pa_threaded_mainloop_unlock(mMainLoop);
223 return ERROR;
224 }
225
226 pa_operation *operation = pa_context_set_default_sink(mContext, name.c_str(), nullptr, nullptr);
227 if (operation == nullptr) {
228 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] pa_context_set_default_sink failed!");
229 pa_threaded_mainloop_unlock(mMainLoop);
230 return ERR_OPERATION_FAILED;
231 }
232 isSetDefaultSink_ = true;
233 pa_operation_unref(operation);
234 pa_threaded_mainloop_unlock(mMainLoop);
235
236 return SUCCESS;
237 }
238
SetDefaultSource(string name)239 int32_t PulseAudioServiceAdapterImpl::SetDefaultSource(string name)
240 {
241 pa_threaded_mainloop_lock(mMainLoop);
242 if (mContext == nullptr) {
243 AUDIO_ERR_LOG("[SetDefaultSource] mContext is nullptr");
244 pa_threaded_mainloop_unlock(mMainLoop);
245 return ERROR;
246 }
247
248 pa_operation *operation = pa_context_set_default_source(mContext, name.c_str(), nullptr, nullptr);
249 if (operation == nullptr) {
250 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] pa_context_set_default_source failed!");
251 pa_threaded_mainloop_unlock(mMainLoop);
252 return ERR_OPERATION_FAILED;
253 }
254 pa_operation_unref(operation);
255 pa_threaded_mainloop_unlock(mMainLoop);
256
257 return SUCCESS;
258 }
259
PaGetSinksCb(pa_context * c,const pa_sink_info * i,int eol,void * userdata)260 void PulseAudioServiceAdapterImpl::PaGetSinksCb(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
261 {
262 UserData *userData = reinterpret_cast<UserData *>(userdata);
263 PulseAudioServiceAdapterImpl *thiz = userData->thiz;
264 if (eol < 0) {
265 AUDIO_ERR_LOG("[PaGetSinksCb] Failed to get sink information: %{public}s",
266 pa_strerror(pa_context_errno(c)));
267 return;
268 }
269
270 if (eol) {
271 pa_threaded_mainloop_signal(thiz->mMainLoop, 0);
272 return;
273 }
274
275 if (i->proplist == nullptr) {
276 AUDIO_ERR_LOG("[PaGetSinksCb] Invalid Proplist for sink (%{public}d).", i->index);
277 return;
278 }
279
280 const char *adapterCStr = pa_proplist_gets(i->proplist, PA_PROP_DEVICE_STRING);
281 AUDIO_INFO_LOG("[PaGetSinksCb] sink[%{public}d] device[%{public}s] name[%{public}s]", i->index, adapterCStr,
282 i->name);
283 std::string sinkDeviceName(adapterCStr);
284 std::string sinkName(i->name);
285 SinkInfo sinkInfo = {};
286 sinkInfo.sinkId = i->index;
287 sinkInfo.sinkName = sinkName;
288 sinkInfo.adapterName = sinkDeviceName;
289 userData->sinkInfos.push_back(sinkInfo);
290 }
291
GetAllSinks()292 std::vector<SinkInfo> PulseAudioServiceAdapterImpl::GetAllSinks()
293 {
294 AUDIO_INFO_LOG("GetAllSinks enter.");
295 lock_guard<mutex> lock(mMutex);
296 unique_ptr<UserData> userData = make_unique<UserData>();
297 userData->thiz = this;
298 userData->sinkInfos = {};
299
300 if (mContext == nullptr) {
301 AUDIO_ERR_LOG("GetAllSinks mContext is nullptr");
302 return userData->sinkInfos;
303 }
304
305 pa_threaded_mainloop_lock(mMainLoop);
306
307 pa_operation *operation = pa_context_get_sink_info_list(mContext,
308 PulseAudioServiceAdapterImpl::PaGetSinksCb, reinterpret_cast<void*>(userData.get()));
309 if (operation == nullptr) {
310 AUDIO_ERR_LOG("GetAllSinks pa_context_get_sink_info_list returned nullptr");
311 pa_threaded_mainloop_unlock(mMainLoop);
312 return userData->sinkInfos;
313 }
314
315 while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
316 pa_threaded_mainloop_wait(mMainLoop);
317 }
318
319 pa_operation_unref(operation);
320 pa_threaded_mainloop_unlock(mMainLoop);
321
322 AUDIO_INFO_LOG("GetAllSinks end, get [%{public}zu] sinks.", userData->sinkInfos.size());
323 return userData->sinkInfos;
324 }
325
GetTargetSinks(std::string adapterName)326 std::vector<uint32_t> PulseAudioServiceAdapterImpl::GetTargetSinks(std::string adapterName)
327 {
328 std::vector<SinkInfo> sinkInfos = GetAllSinks();
329 std::vector<uint32_t> targetSinkIds = {};
330 for (size_t i = 0; i < sinkInfos.size(); i++) {
331 if (sinkInfos[i].adapterName == adapterName) {
332 targetSinkIds.push_back(sinkInfos[i].sinkId);
333 }
334 }
335 return targetSinkIds;
336 }
337
SetLocalDefaultSink(std::string name)338 int32_t PulseAudioServiceAdapterImpl::SetLocalDefaultSink(std::string name)
339 {
340 std::vector<SinkInput> allSinkInputs = GetAllSinkInputs();
341
342 std::string remoteDevice = "remote";
343 std::vector<uint32_t> remoteSinks = GetTargetSinks(remoteDevice);
344
345 // filter sink-inputs which are not connected with remote sinks.
346 for (auto sinkInput : allSinkInputs) {
347 uint32_t sink = sinkInput.deviceSinkId;
348 if (std::find(remoteSinks.begin(), remoteSinks.end(), sink) != remoteSinks.end()) {
349 AUDIO_INFO_LOG("[SetLocalDefaultSink] sink-input[%{public}d] connects with remote device[%{public}d]",
350 sinkInput.paStreamId, sinkInput.deviceSinkId);
351 continue;
352 } else {
353 uint32_t invalidSinkId = PA_INVALID_INDEX;
354 MoveSinkInputByIndexOrName(sinkInput.paStreamId, invalidSinkId, name);
355 }
356 }
357
358 return SUCCESS;
359 }
360
MoveSinkInputByIndexOrName(uint32_t sinkInputId,uint32_t sinkIndex,std::string sinkName)361 int32_t PulseAudioServiceAdapterImpl::MoveSinkInputByIndexOrName(uint32_t sinkInputId, uint32_t sinkIndex,
362 std::string sinkName)
363 {
364 lock_guard<mutex> lock(mMutex);
365
366 unique_ptr<UserData> userData = make_unique<UserData>();
367 userData->thiz = this;
368
369 if (mContext == nullptr) {
370 AUDIO_ERR_LOG("[MoveSinkInputByIndexOrName] SetVolume mContext is nullptr");
371 return ERROR;
372 }
373 pa_threaded_mainloop_lock(mMainLoop);
374 pa_operation *operation = nullptr;
375 if (sinkName.empty()) {
376 operation = pa_context_move_sink_input_by_index(mContext, sinkInputId, sinkIndex,
377 PulseAudioServiceAdapterImpl::PaMoveSinkInputCb, reinterpret_cast<void *>(userData.get()));
378 } else {
379 operation = pa_context_move_sink_input_by_name(mContext, sinkInputId, sinkName.c_str(),
380 PulseAudioServiceAdapterImpl::PaMoveSinkInputCb, reinterpret_cast<void *>(userData.get()));
381 }
382
383 if (operation == nullptr) {
384 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] pa_context_get_sink_input_info_list nullptr");
385 pa_threaded_mainloop_unlock(mMainLoop);
386 return ERROR;
387 }
388 while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
389 pa_threaded_mainloop_wait(mMainLoop);
390 }
391 pa_operation_unref(operation);
392 pa_threaded_mainloop_unlock(mMainLoop);
393
394 int result = userData->moveResult;
395 AUDIO_DEBUG_LOG("move result:[%{public}d]", result);
396
397 return SUCCESS;
398 }
399
MoveSourceOutputByIndexOrName(uint32_t sourceOutputId,uint32_t sourceIndex,std::string sourceName)400 int32_t PulseAudioServiceAdapterImpl::MoveSourceOutputByIndexOrName(uint32_t sourceOutputId, uint32_t sourceIndex,
401 std::string sourceName)
402 {
403 lock_guard<mutex> lock(mMutex);
404
405 unique_ptr<UserData> userData = make_unique<UserData>();
406 userData->thiz = this;
407
408 if (mContext == nullptr) {
409 AUDIO_ERR_LOG("[MoveSourceOutputByIndexOrName] SetVolume mContext is nullptr");
410 return ERROR;
411 }
412 pa_threaded_mainloop_lock(mMainLoop);
413 pa_operation *operation = nullptr;
414 if (sourceName.empty()) {
415 operation = pa_context_move_source_output_by_index(mContext, sourceOutputId, sourceIndex,
416 PulseAudioServiceAdapterImpl::PaMoveSourceOutputCb, reinterpret_cast<void *>(userData.get()));
417 } else {
418 operation = pa_context_move_source_output_by_name(mContext, sourceOutputId, sourceName.c_str(),
419 PulseAudioServiceAdapterImpl::PaMoveSourceOutputCb, reinterpret_cast<void *>(userData.get()));
420 }
421
422 if (operation == nullptr) {
423 AUDIO_ERR_LOG("[MoveSourceOutputByIndexOrName] pa_context_get_sink_input_info_list nullptr");
424 pa_threaded_mainloop_unlock(mMainLoop);
425 return ERROR;
426 }
427 while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
428 pa_threaded_mainloop_wait(mMainLoop);
429 }
430 pa_operation_unref(operation);
431 pa_threaded_mainloop_unlock(mMainLoop);
432
433 int result = userData->moveResult;
434 AUDIO_DEBUG_LOG("move result:[%{public}d]", result);
435
436 return SUCCESS;
437 }
438
SetVolume(AudioStreamType streamType,float volume)439 int32_t PulseAudioServiceAdapterImpl::SetVolume(AudioStreamType streamType, float volume)
440 {
441 lock_guard<mutex> lock(mMutex);
442
443 unique_ptr<UserData> userData = make_unique<UserData>();
444 if (userData == nullptr) {
445 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] SetVolume UserData memory alloc failed");
446 return ERROR;
447 }
448
449 userData->thiz = this;
450 userData->volume = volume;
451 userData->streamType = streamType;
452
453 if (mContext == nullptr) {
454 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] SetVolume mContext is nullptr");
455 return ERROR;
456 }
457 pa_threaded_mainloop_lock(mMainLoop);
458 pa_operation *operation = pa_context_get_sink_input_info_list(mContext,
459 PulseAudioServiceAdapterImpl::PaGetSinkInputInfoVolumeCb, reinterpret_cast<void*>(userData.get()));
460 if (operation == nullptr) {
461 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] pa_context_get_sink_input_info_list nullptr");
462 pa_threaded_mainloop_unlock(mMainLoop);
463 return ERROR;
464 }
465 userData.release();
466
467 pa_threaded_mainloop_accept(mMainLoop);
468
469 pa_operation_unref(operation);
470 pa_threaded_mainloop_unlock(mMainLoop);
471
472 return SUCCESS;
473 }
474
SetSourceOutputMute(int32_t uid,bool setMute)475 int32_t PulseAudioServiceAdapterImpl::SetSourceOutputMute(int32_t uid, bool setMute)
476 {
477 if (mContext == nullptr) {
478 AUDIO_ERR_LOG("[SetSourceOutputMute] mContext is nullptr");
479 return ERROR;
480 }
481 vector<SourceOutput> sourOutputs = GetAllSourceOutputs();
482 lock_guard<mutex> lock(mMutex);
483 int32_t streamSet = 0;
484 for (uint32_t i = 0; i < sourOutputs.size(); i ++) {
485 if (sourOutputs[i].uid == uid) {
486 pa_operation_unref(pa_context_set_source_output_mute(mContext, sourOutputs[i].paStreamId, (setMute ? 1 : 0),
487 nullptr, nullptr));
488 AUDIO_INFO_LOG("[SetSourceOutputMute] set source output Mute : %{public}s for stream :uid %{public}d",
489 (setMute ? "true" : "false"), sourOutputs[i].uid);
490 streamSet++;
491 }
492 }
493 AUDIO_INFO_LOG("[SetSourceOutputMute] set %{public}d %{public}s", streamSet, (setMute ? "mute" : "unmuted"));
494 return streamSet;
495 }
496
497
SetMute(AudioStreamType streamType,bool mute)498 int32_t PulseAudioServiceAdapterImpl::SetMute(AudioStreamType streamType, bool mute)
499 {
500 lock_guard<mutex> lock(mMutex);
501
502 unique_ptr<UserData> userData = make_unique<UserData>();
503 userData->thiz = this;
504 userData->mute = mute;
505 userData->streamType = streamType;
506
507 if (mContext == nullptr) {
508 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] SetMute mContext is nullptr");
509 return ERROR;
510 }
511 pa_threaded_mainloop_lock(mMainLoop);
512
513 pa_operation *operation = pa_context_get_sink_input_info_list(mContext,
514 PulseAudioServiceAdapterImpl::PaGetSinkInputInfoMuteCb, reinterpret_cast<void*>(userData.get()));
515 if (operation == nullptr) {
516 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] pa_context_get_sink_input_info_list returned nullptr");
517 pa_threaded_mainloop_unlock(mMainLoop);
518 return ERROR;
519 }
520
521 while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
522 pa_threaded_mainloop_wait(mMainLoop);
523 }
524
525 pa_operation_unref(operation);
526 pa_threaded_mainloop_unlock(mMainLoop);
527
528 return SUCCESS;
529 }
530
IsMute(AudioStreamType streamType)531 bool PulseAudioServiceAdapterImpl::IsMute(AudioStreamType streamType)
532 {
533 lock_guard<mutex> lock(mMutex);
534 if (!isSetDefaultSink_) {
535 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] IsMute not SetDefaultSink first");
536 return false;
537 }
538 unique_ptr<UserData> userData = make_unique<UserData>();
539 userData->thiz = this;
540 userData->streamType = streamType;
541 userData->mute = false;
542
543 if (mContext == nullptr) {
544 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] IsMute mContext is nullptr");
545 return false;
546 }
547
548 pa_threaded_mainloop_lock(mMainLoop);
549
550 pa_operation *operation = pa_context_get_sink_input_info_list(mContext,
551 PulseAudioServiceAdapterImpl::PaGetSinkInputInfoMuteStatusCb, reinterpret_cast<void*>(userData.get()));
552 if (operation == nullptr) {
553 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] pa_context_get_sink_input_info_list returned nullptr");
554 pa_threaded_mainloop_unlock(mMainLoop);
555 return false;
556 }
557
558 while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
559 pa_threaded_mainloop_wait(mMainLoop);
560 }
561
562 pa_operation_unref(operation);
563 pa_threaded_mainloop_unlock(mMainLoop);
564
565 return (userData->mute) ? true : false;
566 }
567
IsStreamActive(AudioStreamType streamType)568 bool PulseAudioServiceAdapterImpl::IsStreamActive(AudioStreamType streamType)
569 {
570 lock_guard<mutex> lock(mMutex);
571 if (!isSetDefaultSink_) {
572 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] IsStreamActive not SetDefaultSink first");
573 return false;
574 }
575 unique_ptr<UserData> userData = make_unique<UserData>();
576 userData->thiz = this;
577 userData->streamType = streamType;
578 userData->isCorked = true;
579
580 if (mContext == nullptr) {
581 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] IsStreamActive mContext is nullptr");
582 return false;
583 }
584
585 pa_threaded_mainloop_lock(mMainLoop);
586
587 pa_operation *operation = pa_context_get_sink_input_info_list(mContext,
588 PulseAudioServiceAdapterImpl::PaGetSinkInputInfoCorkStatusCb, reinterpret_cast<void*>(userData.get()));
589 if (operation == nullptr) {
590 AUDIO_ERR_LOG("[IsStreamActive] pa_context_get_sink_input_info_list returned nullptr");
591 pa_threaded_mainloop_unlock(mMainLoop);
592 return false;
593 }
594
595 while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
596 pa_threaded_mainloop_wait(mMainLoop);
597 }
598
599 pa_operation_unref(operation);
600 pa_threaded_mainloop_unlock(mMainLoop);
601
602 AUDIO_INFO_LOG("[IsStreamActive] cork for stream %s : %d",
603 GetNameByStreamType(streamType).c_str(), userData->isCorked);
604
605 return (userData->isCorked) ? false : true;
606 }
607
GetAllSinkInputs()608 vector<SinkInput> PulseAudioServiceAdapterImpl::GetAllSinkInputs()
609 {
610 AUDIO_INFO_LOG("GetAllSinkInputs enter");
611 unique_ptr<UserData> userData = make_unique<UserData>();
612 userData->thiz = this;
613 userData->sinkInfos = GetAllSinks();
614
615 lock_guard<mutex> lock(mMutex);
616 if (mContext == nullptr) {
617 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] GetAllSinkInputs mContext is nullptr");
618 return userData->sinkInputList;
619 }
620
621 pa_threaded_mainloop_lock(mMainLoop);
622
623 pa_operation *operation = pa_context_get_sink_input_info_list(mContext,
624 PulseAudioServiceAdapterImpl::PaGetAllSinkInputsCb, reinterpret_cast<void*>(userData.get()));
625 if (operation == nullptr) {
626 AUDIO_ERR_LOG("[GetAllSinkInputs] pa_context_get_sink_input_info_list returned nullptr");
627 pa_threaded_mainloop_unlock(mMainLoop);
628 return userData->sinkInputList;
629 }
630
631 while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
632 pa_threaded_mainloop_wait(mMainLoop);
633 }
634
635 pa_operation_unref(operation);
636 pa_threaded_mainloop_unlock(mMainLoop);
637
638 AUDIO_INFO_LOG("GetAllSinkInputs get:[%{public}zu]", userData->sinkInputList.size());
639 return userData->sinkInputList;
640 }
641
GetAllSourceOutputs()642 vector<SourceOutput> PulseAudioServiceAdapterImpl::GetAllSourceOutputs()
643 {
644 lock_guard<mutex> lock(mMutex);
645
646 unique_ptr<UserData> userData = make_unique<UserData>();
647 userData->thiz = this;
648
649 if (mContext == nullptr) {
650 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] GetAllSourceOutputs mContext is nullptr");
651 return userData->sourceOutputList;
652 }
653
654 pa_threaded_mainloop_lock(mMainLoop);
655
656 pa_operation *operation = pa_context_get_source_output_info_list(mContext,
657 PulseAudioServiceAdapterImpl::PaGetAllSourceOutputsCb, reinterpret_cast<void*>(userData.get()));
658 if (operation == nullptr) {
659 AUDIO_ERR_LOG("[GetAllSourceOutputs] pa_context_get_source_output_info_list returned nullptr");
660 pa_threaded_mainloop_unlock(mMainLoop);
661 return userData->sourceOutputList;
662 }
663
664 while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
665 pa_threaded_mainloop_wait(mMainLoop);
666 }
667
668 pa_operation_unref(operation);
669 pa_threaded_mainloop_unlock(mMainLoop);
670
671 return userData->sourceOutputList;
672 }
673
Disconnect()674 void PulseAudioServiceAdapterImpl::Disconnect()
675 {
676 if (mContext != nullptr) {
677 AUDIO_INFO_LOG("[PulseAudioServiceAdapterImpl] disconnect context!");
678 pa_context_disconnect(mContext);
679 /* Make sure we don't get any further callbacks */
680 pa_context_set_state_callback(mContext, nullptr, nullptr);
681 pa_context_set_subscribe_callback(mContext, nullptr, nullptr);
682 pa_context_unref(mContext);
683 }
684
685 if (mMainLoop != nullptr) {
686 pa_threaded_mainloop_stop(mMainLoop);
687 pa_threaded_mainloop_free(mMainLoop);
688 }
689 }
690
GetNameByStreamType(AudioStreamType streamType)691 string PulseAudioServiceAdapterImpl::GetNameByStreamType(AudioStreamType streamType)
692 {
693 switch (streamType) {
694 case STREAM_MUSIC:
695 return "music";
696 case STREAM_RING:
697 return "ring";
698 case STREAM_SYSTEM:
699 return "system";
700 case STREAM_NOTIFICATION:
701 return "notification";
702 case STREAM_ALARM:
703 return "alarm";
704 case STREAM_DTMF:
705 return "dtmf";
706 case STREAM_VOICE_CALL:
707 return "voice_call";
708 case STREAM_VOICE_ASSISTANT:
709 return "voice_assistant";
710 default:
711 return "";
712 }
713 }
714
GetIdByStreamType(string streamType)715 AudioStreamType PulseAudioServiceAdapterImpl::GetIdByStreamType(string streamType)
716 {
717 AudioStreamType stream;
718
719 if (!streamType.compare(string("music"))) {
720 stream = STREAM_MUSIC;
721 } else if (!streamType.compare(string("ring"))) {
722 stream = STREAM_RING;
723 } else if (!streamType.compare(string("system"))) {
724 stream = STREAM_SYSTEM;
725 } else if (!streamType.compare(string("notification"))) {
726 stream = STREAM_NOTIFICATION;
727 } else if (!streamType.compare(string("alarm"))) {
728 stream = STREAM_ALARM;
729 } else if (!streamType.compare(string("voice_call"))) {
730 stream = STREAM_VOICE_CALL;
731 } else if (!streamType.compare(string("voice_assistant"))) {
732 stream = STREAM_VOICE_ASSISTANT;
733 } else {
734 stream = STREAM_MUSIC;
735 }
736
737 return stream;
738 }
739
PaGetSinkInputInfoMuteStatusCb(pa_context * c,const pa_sink_input_info * i,int eol,void * userdata)740 void PulseAudioServiceAdapterImpl::PaGetSinkInputInfoMuteStatusCb(pa_context *c, const pa_sink_input_info *i, int eol,
741 void *userdata)
742 {
743 UserData *userData = reinterpret_cast<UserData*>(userdata);
744 PulseAudioServiceAdapterImpl *thiz = userData->thiz;
745
746 if (eol < 0) {
747 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Failed to get sink input information: %{public}s",
748 pa_strerror(pa_context_errno(c)));
749 return;
750 }
751
752 if (eol) {
753 pa_threaded_mainloop_signal(thiz->mMainLoop, 0);
754 return;
755 }
756
757 if (i->proplist == nullptr) {
758 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Invalid Proplist for sink input (%{public}d).", i->index);
759 return;
760 }
761
762 const char *streamtype = pa_proplist_gets(i->proplist, "stream.type");
763 if (streamtype == nullptr) {
764 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Invalid StreamType.");
765 return;
766 }
767
768 string streamType(streamtype);
769 if (!streamType.compare(thiz->GetNameByStreamType(userData->streamType))) {
770 userData->mute = i->mute;
771 AUDIO_INFO_LOG("[PulseAudioServiceAdapterImpl] Mute : %{public}d for stream : %{public}s",
772 userData->mute, i->name);
773 }
774
775 return;
776 }
777
PaGetSinkInputInfoMuteCb(pa_context * c,const pa_sink_input_info * i,int eol,void * userdata)778 void PulseAudioServiceAdapterImpl::PaGetSinkInputInfoMuteCb(pa_context *c, const pa_sink_input_info *i,
779 int eol, void *userdata)
780 {
781 UserData *userData = reinterpret_cast<UserData*>(userdata);
782 PulseAudioServiceAdapterImpl *thiz = userData->thiz;
783
784 if (eol < 0) {
785 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Failed to get sink input information: %{public}s",
786 pa_strerror(pa_context_errno(c)));
787 return;
788 }
789
790 if (eol) {
791 pa_threaded_mainloop_signal(thiz->mMainLoop, 0);
792 return;
793 }
794
795 if (i->proplist == nullptr) {
796 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Invalid Proplist for sink input (%{public}d).", i->index);
797 return;
798 }
799
800 const char *streamtype = pa_proplist_gets(i->proplist, "stream.type");
801 if (streamtype == nullptr) {
802 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Invalid StreamType.");
803 return;
804 }
805
806 string streamType(streamtype);
807 if (!streamType.compare(thiz->GetNameByStreamType(userData->streamType))) {
808 pa_operation_unref(pa_context_set_sink_input_mute(c, i->index, (userData->mute) ? 1 : 0, nullptr, nullptr));
809 AUDIO_INFO_LOG("[PulseAudioServiceAdapterImpl] Applied Mute : %{public}d for stream : %{public}s",
810 userData->mute, i->name);
811 }
812
813 return;
814 }
815
PaMoveSinkInputCb(pa_context * c,int success,void * userdata)816 void PulseAudioServiceAdapterImpl::PaMoveSinkInputCb(pa_context *c, int success, void *userdata)
817 {
818 UserData *userData = reinterpret_cast<UserData *>(userdata);
819
820 AUDIO_INFO_LOG("[PaMoveSinkInputCb] result[%{public}d]", success);
821 userData->moveResult = success;
822
823 pa_threaded_mainloop_signal(userData->thiz->mMainLoop, 0);
824
825 return;
826 }
827
PaMoveSourceOutputCb(pa_context * c,int success,void * userdata)828 void PulseAudioServiceAdapterImpl::PaMoveSourceOutputCb(pa_context *c, int success, void *userdata)
829 {
830 UserData *userData = reinterpret_cast<UserData *>(userdata);
831
832 AUDIO_INFO_LOG("[PaMoveSourceOutputCb] result[%{public}d]", success);
833 userData->moveResult = success;
834
835 pa_threaded_mainloop_signal(userData->thiz->mMainLoop, 0);
836
837 return;
838 }
839
PaContextStateCb(pa_context * c,void * userdata)840 void PulseAudioServiceAdapterImpl::PaContextStateCb(pa_context *c, void *userdata)
841 {
842 PulseAudioServiceAdapterImpl *thiz = reinterpret_cast<PulseAudioServiceAdapterImpl*>(userdata);
843
844 switch (pa_context_get_state(c)) {
845 case PA_CONTEXT_UNCONNECTED:
846 case PA_CONTEXT_CONNECTING:
847 case PA_CONTEXT_AUTHORIZING:
848 case PA_CONTEXT_SETTING_NAME:
849 break;
850
851 case PA_CONTEXT_READY: {
852 pa_context_set_subscribe_callback(c, PulseAudioServiceAdapterImpl::PaSubscribeCb, thiz);
853
854 pa_operation *operation = pa_context_subscribe(c, (pa_subscription_mask_t)
855 (PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE |
856 PA_SUBSCRIPTION_MASK_SINK_INPUT | PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT |
857 PA_SUBSCRIPTION_MASK_CARD), nullptr, nullptr);
858 if (operation == nullptr) {
859 pa_threaded_mainloop_signal(thiz->mMainLoop, 0);
860 return;
861 }
862 pa_operation_unref(operation);
863 pa_threaded_mainloop_signal(thiz->mMainLoop, 0);
864 break;
865 }
866
867 case PA_CONTEXT_FAILED:
868 pa_threaded_mainloop_signal(thiz->mMainLoop, 0);
869 return;
870
871 case PA_CONTEXT_TERMINATED:
872 default:
873 return;
874 }
875 }
876
PaModuleLoadCb(pa_context * c,uint32_t idx,void * userdata)877 void PulseAudioServiceAdapterImpl::PaModuleLoadCb(pa_context *c, uint32_t idx, void *userdata)
878 {
879 UserData *userData = reinterpret_cast<UserData*>(userdata);
880 if (idx == PA_INVALID_INDEX) {
881 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Failure: %{public}s", pa_strerror(pa_context_errno(c)));
882 userData->idx = PA_INVALID_INDEX;
883 } else {
884 userData->idx = idx;
885 }
886 pa_threaded_mainloop_signal(userData->thiz->mMainLoop, 0);
887
888 return;
889 }
890
PaGetSinkInputInfoVolumeCb(pa_context * c,const pa_sink_input_info * i,int eol,void * userdata)891 void PulseAudioServiceAdapterImpl::PaGetSinkInputInfoVolumeCb(pa_context *c, const pa_sink_input_info *i, int eol,
892 void *userdata)
893 {
894 UserData *userData = reinterpret_cast<UserData*>(userdata);
895 PulseAudioServiceAdapterImpl *thiz = userData->thiz;
896
897 AUDIO_INFO_LOG("[PulseAudioServiceAdapterImpl] GetSinkInputInfoVolumeCb");
898 if (eol < 0) {
899 delete userData;
900 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Failed to get sink input information: %{public}s",
901 pa_strerror(pa_context_errno(c)));
902 return;
903 }
904
905 if (eol) {
906 pa_threaded_mainloop_signal(thiz->mMainLoop, 1);
907 delete userData;
908 return;
909 }
910
911 if (i->proplist == nullptr) {
912 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Invalid Proplist for sink input (%{public}d).", i->index);
913 return;
914 }
915
916 const char *streamtype = pa_proplist_gets(i->proplist, "stream.type");
917 const char *streamVolume = pa_proplist_gets(i->proplist, "stream.volumeFactor");
918 const char *streamPowerVolume = pa_proplist_gets(i->proplist, "stream.powerVolumeFactor");
919 const char *sessionCStr = pa_proplist_gets(i->proplist, "stream.sessionID");
920 if ((streamtype == nullptr) || (streamVolume == nullptr) || (streamPowerVolume == nullptr) ||
921 (sessionCStr == nullptr)) {
922 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Invalid Stream parameter info.");
923 return;
924 }
925
926 std::stringstream sessionStr;
927 uint32_t sessionID;
928 sessionStr << sessionCStr;
929 sessionStr >> sessionID;
930 AUDIO_INFO_LOG("PulseAudioServiceAdapterImpl: PaGetSinkInputInfoVolumeCb sessionID %{public}u", sessionID);
931
932 sinkIndexSessionIDMap[i->index] = sessionID;
933
934 string streamType(streamtype);
935 float volumeFactor = atof(streamVolume);
936 float powerVolumeFactor = atof(streamPowerVolume);
937 AudioStreamType streamID = thiz->GetIdByStreamType(streamType);
938 float volumeCb = g_audioServiceAdapterCallback->OnGetVolumeCb(streamtype);
939 float vol = volumeCb * volumeFactor * powerVolumeFactor;
940
941 pa_cvolume cv = i->volume;
942 uint32_t volume = pa_sw_volume_from_linear(vol);
943 pa_cvolume_set(&cv, i->channel_map.channels, volume);
944 pa_operation_unref(pa_context_set_sink_input_volume(c, i->index, &cv, nullptr, nullptr));
945
946 if (streamID == userData->streamType) {
947 if (i->mute) {
948 pa_operation_unref(pa_context_set_sink_input_mute(c, i->index, 0, nullptr, nullptr));
949 }
950 }
951 AUDIO_INFO_LOG("[PulseAudioServiceAdapterImpl]volume : %{public}f for stream : %{public}s, volumeInt%{public}d",
952 vol, i->name, volume);
953 HiviewDFX::HiSysEvent::Write("AUDIO", "AUDIO_VOLUME_CHANGE", HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
954 "ISOUTPUT", 1, "STREAMID", sessionID, "STREAMTYPE", streamID, "VOLUME", vol);
955 }
956
PaGetSinkInputInfoCorkStatusCb(pa_context * c,const pa_sink_input_info * i,int eol,void * userdata)957 void PulseAudioServiceAdapterImpl::PaGetSinkInputInfoCorkStatusCb(pa_context *c, const pa_sink_input_info *i, int eol,
958 void *userdata)
959 {
960 UserData *userData = reinterpret_cast<UserData*>(userdata);
961 PulseAudioServiceAdapterImpl *thiz = userData->thiz;
962
963 if (eol < 0) {
964 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Failed to get sink input information: %{public}s",
965 pa_strerror(pa_context_errno(c)));
966 return;
967 }
968
969 if (eol) {
970 pa_threaded_mainloop_signal(thiz->mMainLoop, 0);
971 return;
972 }
973
974 if (i->proplist == nullptr) {
975 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Invalid Proplist for sink input (%{public}d).", i->index);
976 return;
977 }
978
979 const char *streamtype = pa_proplist_gets(i->proplist, "stream.type");
980 if (streamtype == nullptr) {
981 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Invalid StreamType.");
982 return;
983 }
984
985 string streamType(streamtype);
986 if (!streamType.compare(thiz->GetNameByStreamType(userData->streamType))) {
987 userData->isCorked = i->corked;
988 AUDIO_INFO_LOG("[PulseAudioServiceAdapterImpl] corked : %{public}d for stream : %{public}s",
989 userData->isCorked, i->name);
990 }
991 }
992
993 template <typename T>
CastValue(T & a,const char * raw)994 inline void CastValue(T &a, const char *raw)
995 {
996 if (raw == nullptr) {
997 return;
998 }
999 std::stringstream valueStr;
1000 valueStr << raw;
1001 valueStr >> a;
1002 }
1003
PaGetAllSinkInputsCb(pa_context * c,const pa_sink_input_info * i,int eol,void * userdata)1004 void PulseAudioServiceAdapterImpl::PaGetAllSinkInputsCb(pa_context *c, const pa_sink_input_info *i, int eol,
1005 void *userdata)
1006 {
1007 AUDIO_INFO_LOG("[PaGetAllSinkInputsCb] in eol[%{public}d]", eol);
1008 UserData *userData = reinterpret_cast<UserData *>(userdata);
1009 PulseAudioServiceAdapterImpl *thiz = userData->thiz;
1010
1011 if (eol < 0) {
1012 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Failed to get sink input information: %{public}s",
1013 pa_strerror(pa_context_errno(c)));
1014 return;
1015 }
1016
1017 if (eol) {
1018 pa_threaded_mainloop_signal(thiz->mMainLoop, 0);
1019 return;
1020 }
1021
1022 if (i->proplist == nullptr) {
1023 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] Invalid Proplist for sink input (%{public}d).", i->index);
1024 return;
1025 }
1026
1027 AudioStreamType audioStreamType = STREAM_DEFAULT;
1028 const char *streamType = pa_proplist_gets(i->proplist, "stream.type");
1029 if (streamType != nullptr) {
1030 audioStreamType = thiz->GetIdByStreamType(streamType);
1031 }
1032
1033 SinkInput sinkInput = {};
1034 sinkInput.streamType = audioStreamType;
1035
1036 sinkInput.deviceSinkId = i->sink;
1037 for (auto sinkInfo : userData->sinkInfos) {
1038 if (sinkInput.deviceSinkId == sinkInfo.sinkId) {
1039 sinkInput.sinkName = sinkInfo.sinkName;
1040 break;
1041 }
1042 }
1043 sinkInput.paStreamId = i->index;
1044 CastValue<int32_t>(sinkInput.streamId, pa_proplist_gets(i->proplist, "stream.sessionID"));
1045 CastValue<int32_t>(sinkInput.uid, pa_proplist_gets(i->proplist, "stream.client.uid"));
1046 CastValue<int32_t>(sinkInput.pid, pa_proplist_gets(i->proplist, "stream.client.pid"));
1047 CastValue<uint64_t>(sinkInput.startTime, pa_proplist_gets(i->proplist, "stream.startTime"));
1048
1049 userData->sinkInputList.push_back(sinkInput);
1050 }
1051
PaGetAllSourceOutputsCb(pa_context * c,const pa_source_output_info * i,int eol,void * userdata)1052 void PulseAudioServiceAdapterImpl::PaGetAllSourceOutputsCb(pa_context *c, const pa_source_output_info *i, int eol,
1053 void *userdata)
1054 {
1055 AUDIO_INFO_LOG("[PaGetAllSourceOutputsCb] in eol[%{public}d]", eol);
1056 UserData *userData = reinterpret_cast<UserData *>(userdata);
1057 PulseAudioServiceAdapterImpl *thiz = userData->thiz;
1058
1059 if (eol < 0) {
1060 AUDIO_ERR_LOG("[PaGetAllSourceOutputsCb] Failed to get source output information: %{public}s",
1061 pa_strerror(pa_context_errno(c)));
1062 return;
1063 }
1064
1065 if (eol) {
1066 pa_threaded_mainloop_signal(thiz->mMainLoop, 0);
1067 return;
1068 }
1069
1070 if (i->proplist == nullptr) {
1071 AUDIO_ERR_LOG("[PaGetAllSourceOutputsCb] Invalid Proplist for source output (%{public}d).", i->index);
1072 return;
1073 }
1074
1075 uint32_t sessionID = 0;
1076 const char *sessionCStr = pa_proplist_gets(i->proplist, "stream.sessionID");
1077 if (sessionCStr != nullptr) {
1078 std::stringstream sessionStr;
1079 sessionStr << sessionCStr;
1080 sessionStr >> sessionID;
1081 }
1082
1083 AudioStreamType audioStreamType = STREAM_DEFAULT;
1084 const char *streamType = pa_proplist_gets(i->proplist, "stream.type");
1085 if (streamType != nullptr) {
1086 audioStreamType = thiz->GetIdByStreamType(streamType);
1087 }
1088
1089 SourceOutput sourceOutput = {};
1090 sourceOutput.streamId = sessionID;
1091 sourceOutput.streamType = audioStreamType;
1092
1093 sourceOutput.paStreamId = i->index;
1094 sourceOutput.deviceSourceId = i->source;
1095 CastValue<int32_t>(sourceOutput.uid, pa_proplist_gets(i->proplist, "stream.client.uid"));
1096 CastValue<int32_t>(sourceOutput.pid, pa_proplist_gets(i->proplist, "stream.client.pid"));
1097 CastValue<uint64_t>(sourceOutput.startTime, pa_proplist_gets(i->proplist, "stream.startTime"));
1098 userData->sourceOutputList.push_back(sourceOutput);
1099 }
1100
PaSubscribeCb(pa_context * c,pa_subscription_event_type_t t,uint32_t idx,void * userdata)1101 void PulseAudioServiceAdapterImpl::PaSubscribeCb(pa_context *c, pa_subscription_event_type_t t, uint32_t idx,
1102 void *userdata)
1103 {
1104 unique_ptr<UserData> userData = make_unique<UserData>();
1105 PulseAudioServiceAdapterImpl *thiz = reinterpret_cast<PulseAudioServiceAdapterImpl*>(userdata);
1106 userData->thiz = thiz;
1107 switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
1108 case PA_SUBSCRIPTION_EVENT_SINK:
1109 break;
1110
1111 case PA_SUBSCRIPTION_EVENT_SOURCE:
1112 break;
1113
1114 case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
1115 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
1116 pa_threaded_mainloop_lock(thiz->mMainLoop);
1117 pa_operation *operation = pa_context_get_sink_input_info(c, idx,
1118 PulseAudioServiceAdapterImpl::PaGetSinkInputInfoVolumeCb, reinterpret_cast<void*>(userData.get()));
1119 if (operation == nullptr) {
1120 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] pa_context_get_sink_input_info_list nullptr");
1121 pa_threaded_mainloop_unlock(thiz->mMainLoop);
1122 return;
1123 }
1124 userData.release();
1125 pa_threaded_mainloop_accept(thiz->mMainLoop);
1126 pa_operation_unref(operation);
1127 pa_threaded_mainloop_unlock(thiz->mMainLoop);
1128 } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
1129 uint32_t sessionID = sinkIndexSessionIDMap[idx];
1130 AUDIO_ERR_LOG("[PulseAudioServiceAdapterImpl] sessionID: %{public}d removed", sessionID);
1131 g_audioServiceAdapterCallback->OnSessionRemoved(sessionID);
1132 }
1133 break;
1134
1135 case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT:
1136 break;
1137
1138 default:
1139 break;
1140 }
1141 }
1142 } // namespace AudioStandard
1143 } // namespace OHOS
1144
1145 #endif // ST_PULSEAUDIO_AUDIO_SERVICE_ADAPTER_IMPL_H
1146