• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #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