• 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 #include "audio_service_dump.h"
17 
18 using namespace std;
19 
20 namespace OHOS {
21 namespace AudioStandard {
22 
23 constexpr int STRING_BUFFER_SIZE = 4096;
24 
25 template <typename...Args>
AppendFormat(std::string & out,const char * fmt,Args &&...args)26 void AppendFormat(std::string& out, const char* fmt, Args&& ... args)
27 {
28     char buf[STRING_BUFFER_SIZE] = {0};
29     int len = ::sprintf_s(buf, sizeof(buf), fmt, args...);
30     if (len <= 0) {
31         AUDIO_ERR_LOG("snprintf_s error : buffer allocation fails");
32         return;
33     }
34     out += buf;
35 }
36 
AudioServiceDump()37 AudioServiceDump::AudioServiceDump() : mainLoop(nullptr),
38                                        api(nullptr),
39                                        context(nullptr),
40                                        isMainLoopStarted(false),
41                                        isContextConnected(false)
42 {
43     AUDIO_DEBUG_LOG("AudioServiceDump ctor");
44 }
45 
~AudioServiceDump()46 AudioServiceDump::~AudioServiceDump()
47 {
48     ResetPAAudioDump();
49 }
50 
ResetPAAudioDump()51 void AudioServiceDump::ResetPAAudioDump()
52 {
53     lock_guard<mutex> lock(ctrlMutex);
54     if (mainLoop && (isMainLoopStarted == true)) {
55         pa_threaded_mainloop_stop(mainLoop);
56     }
57 
58     if (context) {
59         pa_context_set_state_callback(context, nullptr, nullptr);
60         if (isContextConnected == true) {
61             AUDIO_INFO_LOG("[AudioServiceDump] disconnect context!");
62             pa_context_disconnect(context);
63         }
64         pa_context_unref(context);
65     }
66 
67     if (mainLoop) {
68         pa_threaded_mainloop_free(mainLoop);
69     }
70 
71     isMainLoopStarted  = false;
72     isContextConnected = false;
73     mainLoop = nullptr;
74     context  = nullptr;
75     api      = nullptr;
76 }
77 
Initialize()78 int32_t AudioServiceDump::Initialize()
79 {
80     int error = PA_ERR_INTERNAL;
81     mainLoop = pa_threaded_mainloop_new();
82     if (mainLoop == nullptr) {
83         return AUDIO_DUMP_INIT_ERR;
84     }
85 
86     api = pa_threaded_mainloop_get_api(mainLoop);
87     if (api == nullptr) {
88         ResetPAAudioDump();
89         return AUDIO_DUMP_INIT_ERR;
90     }
91 
92     context = pa_context_new(api, "AudioServiceDump");
93     if (context == nullptr) {
94         ResetPAAudioDump();
95         return AUDIO_DUMP_INIT_ERR;
96     }
97 
98     pa_context_set_state_callback(context, PAContextStateCb, mainLoop);
99 
100     if (pa_context_connect(context, nullptr, PA_CONTEXT_NOFAIL, nullptr) < 0) {
101         error = pa_context_errno(context);
102         AUDIO_ERR_LOG("context connect error: %{public}s", pa_strerror(error));
103         ResetPAAudioDump();
104         return AUDIO_DUMP_INIT_ERR;
105     }
106 
107     isContextConnected = true;
108     pa_threaded_mainloop_lock(mainLoop);
109 
110     if (pa_threaded_mainloop_start(mainLoop) < 0) {
111         AUDIO_ERR_LOG("Audio Service not started");
112         pa_threaded_mainloop_unlock(mainLoop);
113         ResetPAAudioDump();
114         return AUDIO_DUMP_INIT_ERR;
115     }
116 
117     isMainLoopStarted = true;
118     while (true) {
119         pa_context_state_t state = pa_context_get_state(context);
120         if (state == PA_CONTEXT_READY) {
121             break;
122         }
123 
124         if (!PA_CONTEXT_IS_GOOD(state)) {
125             error = pa_context_errno(context);
126             AUDIO_ERR_LOG("context bad state error: %{public}s", pa_strerror(error));
127             pa_threaded_mainloop_unlock(mainLoop);
128             ResetPAAudioDump();
129             return AUDIO_DUMP_INIT_ERR;
130         }
131 
132         pa_threaded_mainloop_wait(mainLoop);
133     }
134 
135     pa_threaded_mainloop_unlock(mainLoop);
136     return AUDIO_DUMP_SUCCESS;
137 }
138 
OnTimeOut()139 void AudioServiceDump::OnTimeOut()
140 {
141     pa_threaded_mainloop_lock(mainLoop);
142     pa_threaded_mainloop_signal(mainLoop, 0);
143     pa_threaded_mainloop_unlock(mainLoop);
144 }
145 
IsEndWith(const std::string & mainStr,const std::string & toMatch)146 bool AudioServiceDump::IsEndWith(const std::string &mainStr, const std::string &toMatch)
147 {
148     if (mainStr.size() >= toMatch.size() &&
149         mainStr.compare(mainStr.size() - toMatch.size(), toMatch.size(), toMatch) == 0) {
150         return true;
151     }
152     return false;
153 }
154 
IsValidModule(const std::string moduleName)155 bool AudioServiceDump::IsValidModule(const std::string moduleName)
156 {
157     if (moduleName.rfind("fifo", 0) == SUCCESS) {
158         return false; // Module starts with fifo, Not valid module
159     }
160 
161     if (IsEndWith(moduleName, "monitor")) {
162         return false; // Module ends with monitor, Not valid module
163     }
164     return true;
165 }
166 
IsStreamSupported(AudioStreamType streamType)167 bool AudioServiceDump::IsStreamSupported(AudioStreamType streamType)
168 {
169     switch (streamType) {
170         case STREAM_MUSIC:
171         case STREAM_RING:
172         case STREAM_VOICE_CALL:
173         case STREAM_VOICE_ASSISTANT:
174             return true;
175         default:
176             return false;
177     }
178 }
179 
GetStreamName(AudioStreamType audioType)180 const std::string AudioServiceDump::GetStreamName(AudioStreamType audioType)
181 {
182     string name;
183     switch (audioType) {
184         case STREAM_VOICE_ASSISTANT:
185             name = "VOICE_ASSISTANT";
186             break;
187         case STREAM_VOICE_CALL:
188             name = "VOICE_CALL";
189             break;
190         case STREAM_SYSTEM:
191             name = "SYSTEM";
192             break;
193         case STREAM_RING:
194             name = "RING";
195             break;
196         case STREAM_MUSIC:
197             name = "MUSIC";
198             break;
199         case STREAM_ALARM:
200             name = "ALARM";
201             break;
202         case STREAM_NOTIFICATION:
203             name = "NOTIFICATION";
204             break;
205         case STREAM_BLUETOOTH_SCO:
206             name = "BLUETOOTH_SCO";
207             break;
208         case STREAM_DTMF:
209             name = "DTMF";
210             break;
211         case STREAM_TTS:
212             name = "TTS";
213             break;
214         default:
215             name = "UNKNOWN";
216     }
217 
218     const string streamName = name;
219     return streamName;
220 }
221 
GetStreamUsgaeName(StreamUsage streamUsage)222 const std::string AudioServiceDump::GetStreamUsgaeName(StreamUsage streamUsage)
223 {
224     string usage;
225     switch (streamUsage) {
226         case STREAM_USAGE_MEDIA:
227             usage = "MEDIA";
228             break;
229         case STREAM_USAGE_VOICE_COMMUNICATION:
230             usage = "VOICE_COMMUNICATION";
231             break;
232         case STREAM_USAGE_NOTIFICATION_RINGTONE:
233             usage = "NOTIFICATION_RINGTONE";
234             break;
235         case STREAM_USAGE_VOICE_ASSISTANT:
236             usage = "VOICE_ASSISTANT";
237             break;
238         default:
239             usage = "STREAM_USAGE_UNKNOWN";
240     }
241 
242     const string streamUsageName = usage;
243     return streamUsageName;
244 }
245 
GetContentTypeName(ContentType contentType)246 const std::string AudioServiceDump::GetContentTypeName(ContentType contentType)
247 {
248     string content;
249     switch (contentType) {
250         case CONTENT_TYPE_SPEECH:
251             content = "SPEECH";
252             break;
253         case CONTENT_TYPE_MUSIC:
254             content = "MUSIC";
255             break;
256         case CONTENT_TYPE_MOVIE:
257             content = "MOVIE";
258             break;
259         case CONTENT_TYPE_SONIFICATION:
260             content = "SONIFICATION";
261             break;
262         case CONTENT_TYPE_RINGTONE:
263             content = "RINGTONE";
264             break;
265         default:
266             content = "UNKNOWN";
267     }
268 
269     const string contentTypeName = content;
270     return contentTypeName;
271 }
272 
GetDeviceTypeName(DeviceType deviceType)273 const std::string AudioServiceDump::GetDeviceTypeName(DeviceType deviceType)
274 {
275     string device;
276     switch (deviceType) {
277         case DEVICE_TYPE_EARPIECE:
278             device = "EARPIECE";
279             break;
280         case DEVICE_TYPE_SPEAKER:
281             device = "SPEAKER";
282             break;
283         case DEVICE_TYPE_WIRED_HEADSET:
284             device = "WIRED_HEADSET";
285             break;
286         case DEVICE_TYPE_WIRED_HEADPHONES:
287             device = "WIRED_HEADPHONES";
288             break;
289         case DEVICE_TYPE_BLUETOOTH_SCO:
290              device = "BLUETOOTH_SCO";
291             break;
292         case DEVICE_TYPE_BLUETOOTH_A2DP:
293             device = "BLUETOOTH_A2DP";
294             break;
295         case DEVICE_TYPE_MIC:
296             device = "MIC";
297             break;
298         case DEVICE_TYPE_NONE:
299             device = "NONE";
300             break;
301         case DEVICE_TYPE_INVALID:
302             device = "INVALID";
303             break;
304         default:
305             device = "UNKNOWN";
306     }
307 
308     const string deviceTypeName = device;
309     return deviceTypeName;
310 }
311 
GetConnectTypeName(ConnectType connectType)312 const std::string AudioServiceDump::GetConnectTypeName(ConnectType connectType)
313 {
314     string connectName;
315     switch (connectType) {
316         case OHOS::AudioStandard::CONNECT_TYPE_LOCAL:
317             connectName = "LOCAL";
318             break;
319         case OHOS::AudioStandard::CONNECT_TYPE_DISTRIBUTED:
320             connectName = "REMOTE";
321             break;
322         default:
323             connectName = "UNKNOWN";
324             break;
325     }
326     const string connectTypeName = connectName;
327     return connectTypeName;
328 }
329 
PlaybackStreamDump(std::string & dumpString)330 void AudioServiceDump::PlaybackStreamDump(std::string &dumpString)
331 {
332     char s[PA_SAMPLE_SPEC_SNPRINT_MAX];
333 
334     dumpString += "Audio Data Dump:\n\n";
335     dumpString += "Playback Streams\n";
336 
337     AppendFormat(dumpString, "%d  Playback stream (s) available:\n\n", audioData_.streamData.sinkInputs.size());
338 
339     for (auto it = audioData_.streamData.sinkInputs.begin(); it != audioData_.streamData.sinkInputs.end(); it++) {
340         InputOutputInfo sinkInputInfo = *it;
341 
342         AppendFormat(dumpString, "Stream Id: %s\n", (sinkInputInfo.sessionId).c_str());
343         AppendFormat(dumpString, "Application Name: %s\n", ((sinkInputInfo.applicationName).c_str()));
344         AppendFormat(dumpString, "Process Id: %s\n", (sinkInputInfo.processId).c_str());
345         AppendFormat(dumpString, "User Id: %u\n", sinkInputInfo.userId);
346 
347         char *inputSampleSpec = pa_sample_spec_snprint(s, sizeof(s), &(sinkInputInfo.sampleSpec));
348         AppendFormat(dumpString, "Stream Configuration: %s\n", inputSampleSpec);
349         dumpString += "Status:";
350         dumpString += (sinkInputInfo.corked) ? "STOPPED/PAUSED" : "RUNNING";
351         AppendFormat(dumpString, "\nStream Start Time: %s\n", (sinkInputInfo.sessionStartTime).c_str());
352         dumpString += "\n";
353     }
354 }
355 
RecordStreamDump(std::string & dumpString)356 void AudioServiceDump::RecordStreamDump(std::string &dumpString)
357 {
358     char s[PA_SAMPLE_SPEC_SNPRINT_MAX];
359     dumpString += "Record Streams \n";
360     AppendFormat(dumpString, "%d  Record stream (s) available:\n\n", audioData_.streamData.sourceOutputs.size());
361 
362     for (auto it = audioData_.streamData.sourceOutputs.begin(); it != audioData_.streamData.sourceOutputs.end(); it++) {
363         InputOutputInfo sourceOutputInfo = *it;
364         AppendFormat(dumpString, "Stream Id: %s\n", (sourceOutputInfo.sessionId).c_str());
365         AppendFormat(dumpString, "Application Name: %s\n", (sourceOutputInfo.applicationName).c_str());
366         AppendFormat(dumpString, "Process Id: %s\n", sourceOutputInfo.processId.c_str());
367         AppendFormat(dumpString, "User Id: %d\n", sourceOutputInfo.userId);
368 
369         char *outputSampleSpec = pa_sample_spec_snprint(s, sizeof(s), &(sourceOutputInfo.sampleSpec));
370         AppendFormat(dumpString, "Stream Configuration: %s\n", outputSampleSpec);
371         dumpString += "Status:";
372         dumpString += (sourceOutputInfo.corked) ? "STOPPED/PAUSED" : "RUNNING";
373         AppendFormat(dumpString, "\nStream Start Time: %s\n", (sourceOutputInfo.sessionStartTime).c_str());
374         dumpString += "\n";
375     }
376 }
377 
HDFModulesDump(std::string & dumpString)378 void AudioServiceDump::HDFModulesDump(std::string &dumpString)
379 {
380     char s[PA_SAMPLE_SPEC_SNPRINT_MAX];
381 
382     dumpString += "\nHDF Input Modules\n";
383     AppendFormat(dumpString, "%d  HDF Input Modules (s) available:\n\n", audioData_.streamData.sourceDevices.size());
384 
385     for (auto it = audioData_.streamData.sourceDevices.begin(); it != audioData_.streamData.sourceDevices.end(); it++) {
386         SinkSourceInfo sourceInfo = *it;
387 
388         AppendFormat(dumpString, "Module Name: %s\n", (sourceInfo.name).c_str());
389         char *hdfOutSampleSpec = pa_sample_spec_snprint(s, sizeof(s), &(sourceInfo.sampleSpec));
390         AppendFormat(dumpString, "Module Configuration: %s\n\n", hdfOutSampleSpec);
391     }
392 
393     dumpString += "HDF Output Modules\n";
394     AppendFormat(dumpString, "%d  HDF Output Modules (s) available:\n\n", audioData_.streamData.sinkDevices.size());
395 
396     for (auto it = audioData_.streamData.sinkDevices.begin(); it != audioData_.streamData.sinkDevices.end(); it++) {
397         SinkSourceInfo sinkInfo = *it;
398         AppendFormat(dumpString, "Module Name: %s\n", (sinkInfo.name).c_str());
399         char *hdfInSampleSpec = pa_sample_spec_snprint(s, sizeof(s), &(sinkInfo.sampleSpec));
400         AppendFormat(dumpString, "Module Configuration: %s\n\n", hdfInSampleSpec);
401     }
402 }
403 
CallStatusDump(std::string & dumpString)404 void AudioServiceDump::CallStatusDump(std::string &dumpString)
405 {
406     dumpString += "\nAudio Scene:";
407     switch (audioData_.policyData.callStatus) {
408         case AUDIO_SCENE_DEFAULT:
409             dumpString += "DEFAULT";
410             break;
411         case AUDIO_SCENE_RINGING:
412             dumpString += "RINGING";
413             break;
414         case AUDIO_SCENE_PHONE_CALL:
415             dumpString += "PHONE_CALL";
416             break;
417         case AUDIO_SCENE_PHONE_CHAT:
418             dumpString += "PHONE_CHAT";
419             break;
420         default:
421             dumpString += "UNKNOWN";
422     }
423     dumpString += "\n";
424 }
425 
RingerModeDump(std::string & dumpString)426 void AudioServiceDump::RingerModeDump(std::string &dumpString)
427 {
428     dumpString += "Ringer Mode:";
429     switch (audioData_.policyData.ringerMode) {
430         case RINGER_MODE_NORMAL:
431             dumpString += "NORMAL";
432             break;
433         case RINGER_MODE_SILENT:
434             dumpString += "SILENT";
435             break;
436         case RINGER_MODE_VIBRATE:
437             dumpString += "VIBRATE";
438             break;
439         default:
440             dumpString += "UNKNOWN";
441     }
442     dumpString += "\n";
443 }
444 
StreamVolumesDump(string & dumpString)445 void AudioServiceDump::StreamVolumesDump (string &dumpString)
446 {
447     dumpString += "\nStream: Volumes\n";
448     for (auto it = audioData_.policyData.streamVolumes.cbegin(); it != audioData_.policyData.streamVolumes.cend();
449         ++it) {
450         AppendFormat(dumpString, "%s: %d\n", GetStreamName(it->first).c_str(), it->second);
451     }
452 }
453 
AudioFocusInfoDump(string & dumpString)454 void AudioServiceDump::AudioFocusInfoDump(string &dumpString)
455 {
456     dumpString += "\nAudio In Focus Info:\n";
457     uint32_t invalidSessionID = static_cast<uint32_t>(-1);
458 
459     if (audioData_.policyData.audioFocusInfo.sessionID == invalidSessionID) {
460         AUDIO_DEBUG_LOG("No streams in focus");
461         dumpString += "Not available\n";
462         return;
463     }
464 
465     AppendFormat(dumpString, "Stream Id: %d\n", audioData_.policyData.audioFocusInfo.sessionID);
466     AppendFormat(dumpString, "Stream Usage: %s\n",
467         GetStreamUsgaeName(audioData_.policyData.audioFocusInfo.streamUsage).c_str());
468     AppendFormat(dumpString, "Content Type: %s\n",
469         GetContentTypeName(audioData_.policyData.audioFocusInfo.contentType).c_str());
470     AppendFormat(dumpString, "Stream Name: %s\n",
471         GetStreamName(audioData_.policyData.audioFocusInfo.streamType).c_str());
472 
473 	return;
474 }
475 
GroupInfoDump(std::string & dumpString)476 void AudioServiceDump::GroupInfoDump(std::string& dumpString)
477 {
478     dumpString += "\nGroupInfo:\n";
479     AppendFormat(dumpString, "%d  Group Infos (s) available :\n\n", audioData_.policyData.groupInfos.size());
480 
481     for (auto it = audioData_.policyData.groupInfos.begin(); it != audioData_.policyData.groupInfos.end(); it++) {
482         GroupInfo groupInfo = *it;
483         AppendFormat(dumpString, "ConnectType(0 for Local, 1 for Remote): %d\n", groupInfo.type);
484         AppendFormat(dumpString, "Name: %s\n", groupInfo.groupName.c_str());
485         AppendFormat(dumpString, "Id: %d\n", groupInfo.groupId);
486     }
487 }
488 
DevicesInfoDump(string & dumpString)489 void AudioServiceDump::DevicesInfoDump(string& dumpString)
490 {
491     dumpString += "\nInput Devices:\n";
492     AppendFormat(dumpString, "%d  Input Devices (s) available :\n\n", audioData_.policyData.inputDevices.size());
493 
494     for (auto it = audioData_.policyData.inputDevices.begin(); it != audioData_.policyData.inputDevices.end(); it++) {
495         DevicesInfo devicesInfo = *it;
496         AppendFormat(dumpString, "device type:%s ", GetDeviceTypeName(devicesInfo.deviceType).c_str());
497         AppendFormat(dumpString, "connect type:%s\n", GetConnectTypeName(devicesInfo.conneceType).c_str());
498     }
499 
500     dumpString += "\nOutput Devices:\n";
501     AppendFormat(dumpString, "%d  Output Devices (s) available :\n\n", audioData_.policyData.outputDevices.size());
502 
503     for (auto it = audioData_.policyData.outputDevices.begin(); it != audioData_.policyData.outputDevices.end(); it++) {
504         DevicesInfo devicesInfo = *it;
505         AppendFormat(dumpString, "device type:%s ", GetDeviceTypeName(devicesInfo.deviceType).c_str());
506         AppendFormat(dumpString, "connect type:%s\n", GetConnectTypeName(devicesInfo.conneceType).c_str());
507     }
508 }
509 
DataDump(string & dumpString)510 void AudioServiceDump::DataDump(string &dumpString)
511 {
512     PlaybackStreamDump(dumpString);
513     RecordStreamDump(dumpString);
514     HDFModulesDump(dumpString);
515     DevicesInfoDump(dumpString);
516     CallStatusDump(dumpString);
517     RingerModeDump(dumpString);
518     StreamVolumesDump(dumpString);
519     AudioFocusInfoDump(dumpString);
520     GroupInfoDump(dumpString);
521 }
522 
AudioDataDump(PolicyData & policyData,string & dumpString)523 void AudioServiceDump::AudioDataDump(PolicyData &policyData, string &dumpString)
524 {
525     if (mainLoop == nullptr || context == nullptr) {
526         AUDIO_ERR_LOG("Audio Service Not running");
527         return;
528     }
529 
530     pa_threaded_mainloop_lock(mainLoop);
531     pa_operation *operation = nullptr;
532     operation = pa_context_get_sink_info_list(context, AudioServiceDump::PASinkInfoCallback, (void *)(this));
533 
534     while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
535         pa_threaded_mainloop_wait(mainLoop);
536     }
537 
538     pa_operation_unref(operation);
539     operation = pa_context_get_sink_input_info_list(context, AudioServiceDump::PASinkInputInfoCallback, (void *)this);
540 
541     while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
542         pa_threaded_mainloop_wait(mainLoop);
543     }
544 
545     pa_operation_unref(operation);
546     operation = pa_context_get_source_info_list(context, AudioServiceDump::PASourceInfoCallback, (void *)this);
547 
548     while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
549         pa_threaded_mainloop_wait(mainLoop);
550     }
551 
552     pa_operation_unref(operation);
553     operation = pa_context_get_source_output_info_list(context,
554         AudioServiceDump::PASourceOutputInfoCallback, (void *)this);
555 
556     while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
557         pa_threaded_mainloop_wait(mainLoop);
558     }
559 
560     pa_operation_unref(operation);
561     pa_threaded_mainloop_unlock(mainLoop);
562 
563     audioData_.policyData = policyData;
564     DataDump(dumpString);
565 
566     return;
567 }
568 
PAContextStateCb(pa_context * context,void * userdata)569 void AudioServiceDump::PAContextStateCb(pa_context *context, void *userdata)
570 {
571     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)userdata;
572 
573     switch (pa_context_get_state(context)) {
574         case PA_CONTEXT_READY:
575         case PA_CONTEXT_TERMINATED:
576         case PA_CONTEXT_FAILED:
577             pa_threaded_mainloop_signal(mainLoop, 0);
578             break;
579 
580         case PA_CONTEXT_UNCONNECTED:
581         case PA_CONTEXT_CONNECTING:
582         case PA_CONTEXT_AUTHORIZING:
583         case PA_CONTEXT_SETTING_NAME:
584         default:
585             break;
586     }
587     return;
588 }
589 
PASinkInfoCallback(pa_context * c,const pa_sink_info * i,int eol,void * userdata)590 void AudioServiceDump::PASinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
591 {
592     AudioServiceDump *asDump = (AudioServiceDump *)userdata;
593     if (asDump == nullptr) {
594         AUDIO_ERR_LOG("Failed to get sink information");
595         return;
596     }
597 
598     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)asDump->mainLoop;
599 
600     if (eol < 0) {
601         AUDIO_ERR_LOG("Failed to get sink information: %{public}s", pa_strerror(pa_context_errno(c)));
602         return;
603     }
604 
605     if (eol) {
606         pa_threaded_mainloop_signal(mainLoop, 0);
607         return;
608     }
609 
610     SinkSourceInfo sinkInfo;
611 
612     if (i->name != nullptr) {
613         string sinkName(i->name);
614         if (IsValidModule(sinkName)) {
615             (sinkInfo.name).assign(sinkName);
616             sinkInfo.sampleSpec = i->sample_spec;
617             asDump->audioData_.streamData.sinkDevices.push_back(sinkInfo);
618         }
619     }
620 }
621 
PASinkInputInfoCallback(pa_context * c,const pa_sink_input_info * i,int eol,void * userdata)622 void AudioServiceDump::PASinkInputInfoCallback(pa_context *c, const pa_sink_input_info *i, int eol, void *userdata)
623 {
624     AudioServiceDump *asDump = (AudioServiceDump *)userdata;
625     if (asDump == nullptr) {
626         AUDIO_ERR_LOG("Failed to get sink input information");
627         return;
628     }
629 
630     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)asDump->mainLoop;
631 
632     if (eol < 0) {
633         AUDIO_ERR_LOG("Failed to get sink input information: %{public}s", pa_strerror(pa_context_errno(c)));
634         return;
635     }
636 
637     if (eol) {
638         pa_threaded_mainloop_signal(mainLoop, 0);
639         return;
640     }
641 
642     InputOutputInfo sinkInputInfo;
643 
644     sinkInputInfo.sampleSpec = i->sample_spec;
645     sinkInputInfo.corked = i->corked;
646 
647     if (i->proplist !=nullptr) {
648         const char *applicationname = pa_proplist_gets(i->proplist, "application.name");
649         const char *processid = pa_proplist_gets(i->proplist, "application.process.id");
650         const char *user = pa_proplist_gets(i->proplist, "application.process.user");
651         const char *sessionid = pa_proplist_gets(i->proplist, "stream.sessionID");
652         const char *sessionstarttime = pa_proplist_gets(i->proplist, "stream.startTime");
653 
654         if (applicationname != nullptr) {
655             string applicationName(applicationname);
656             (sinkInputInfo.applicationName).assign(applicationName);
657         }
658 
659         if (processid != nullptr) {
660             string processId(processid);
661             (sinkInputInfo.processId).assign(processId);
662         }
663 
664         if (user != nullptr) {
665             struct passwd *p;
666             if ((p = getpwnam(user)) != nullptr) {
667                 sinkInputInfo.userId = uint32_t(p->pw_uid);
668             }
669         }
670 
671         if (sessionid != nullptr) {
672             string sessionId(sessionid);
673             (sinkInputInfo.sessionId).assign(sessionId);
674         }
675 
676         if (sessionstarttime != nullptr) {
677             string sessionStartTime(sessionstarttime);
678             (sinkInputInfo.sessionStartTime).assign(sessionStartTime);
679         }
680     }
681     asDump->audioData_.streamData.sinkInputs.push_back(sinkInputInfo);
682 }
683 
PASourceInfoCallback(pa_context * c,const pa_source_info * i,int eol,void * userdata)684 void AudioServiceDump::PASourceInfoCallback(pa_context *c, const pa_source_info *i, int eol, void *userdata)
685 {
686     AudioServiceDump *asDump = (AudioServiceDump *)userdata;
687     if (asDump == nullptr) {
688         AUDIO_ERR_LOG("Failed to get source information");
689         return;
690     }
691 
692     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)asDump->mainLoop;
693 
694     if (eol < 0) {
695         AUDIO_ERR_LOG("Failed to get source information: %{public}s", pa_strerror(pa_context_errno(c)));
696         return;
697     }
698 
699     if (eol) {
700         pa_threaded_mainloop_signal(mainLoop, 0);
701         return;
702     }
703 
704     SinkSourceInfo sourceInfo;
705 
706     if (i->name != nullptr) {
707         string sourceName(i->name);
708         if (IsValidModule(sourceName)) {
709             (sourceInfo.name).assign(sourceName);
710             sourceInfo.sampleSpec = i->sample_spec;
711             asDump->audioData_.streamData.sourceDevices.push_back(sourceInfo);
712         }
713     }
714 }
715 
PASourceOutputInfoCallback(pa_context * c,const pa_source_output_info * i,int eol,void * userdata)716 void AudioServiceDump::PASourceOutputInfoCallback(pa_context *c, const pa_source_output_info *i, int eol,
717     void *userdata)
718 {
719     AudioServiceDump *asDump = (AudioServiceDump *)userdata;
720     if (asDump == nullptr) {
721         AUDIO_ERR_LOG("Failed to get source output information");
722         return;
723     }
724 
725     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)asDump->mainLoop;
726 
727     if (eol < 0) {
728         AUDIO_ERR_LOG("Failed to get source output information: %{public}s", pa_strerror(pa_context_errno(c)));
729         return;
730     }
731 
732     if (eol) {
733         pa_threaded_mainloop_signal(mainLoop, 0);
734         return;
735     }
736 
737     InputOutputInfo sourceOutputInfo;
738     sourceOutputInfo.sampleSpec = i->sample_spec;
739     sourceOutputInfo.corked = i->corked;
740 
741     if (i->proplist !=nullptr) {
742         const char *applicationname = pa_proplist_gets(i->proplist, "application.name");
743         const char *processid = pa_proplist_gets(i->proplist, "application.process.id");
744         const char *user = pa_proplist_gets(i->proplist, "application.process.user");
745         const char *sessionid = pa_proplist_gets(i->proplist, "stream.sessionID");
746         const char *sessionstarttime = pa_proplist_gets(i->proplist, "stream.startTime");
747 
748         if (applicationname != nullptr) {
749             string applicationName(applicationname);
750             (sourceOutputInfo.applicationName).assign(applicationName);
751         }
752 
753         if (processid != nullptr) {
754             string processId(processid);
755             (sourceOutputInfo.processId).assign(processId);
756         }
757 
758         if (user != nullptr) {
759             struct passwd *p;
760             if ((p = getpwnam(user)) != nullptr) {
761                 sourceOutputInfo.userId = uint32_t(p->pw_uid);
762             }
763         }
764 
765         if (sessionid != nullptr) {
766             string sessionId(sessionid);
767             (sourceOutputInfo.sessionId).assign(sessionId);
768         }
769 
770         if (sessionstarttime != nullptr) {
771             string sessionStartTime(sessionstarttime);
772             (sourceOutputInfo.sessionStartTime).assign(sessionStartTime);
773         }
774     }
775     asDump->audioData_.streamData.sourceOutputs.push_back(sourceOutputInfo);
776 }
777 } // namespace AudioStandard
778 } // namespace OHOS
779