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