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