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