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