• 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     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