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