• 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         case STREAM_WAKEUP:
175             return true;
176         default:
177             return false;
178     }
179 }
180 
GetStreamName(AudioStreamType streamType)181 const std::string AudioServiceDump::GetStreamName(AudioStreamType streamType)
182 {
183     string name;
184     switch (streamType) {
185         case STREAM_VOICE_ASSISTANT:
186             name = "VOICE_ASSISTANT";
187             break;
188         case STREAM_VOICE_CALL:
189             name = "VOICE_CALL";
190             break;
191         case STREAM_SYSTEM:
192             name = "SYSTEM";
193             break;
194         case STREAM_RING:
195             name = "RING";
196             break;
197         case STREAM_MUSIC:
198             name = "MUSIC";
199             break;
200         case STREAM_ALARM:
201             name = "ALARM";
202             break;
203         case STREAM_NOTIFICATION:
204             name = "NOTIFICATION";
205             break;
206         case STREAM_BLUETOOTH_SCO:
207             name = "BLUETOOTH_SCO";
208             break;
209         case STREAM_DTMF:
210             name = "DTMF";
211             break;
212         case STREAM_TTS:
213             name = "TTS";
214             break;
215         case STREAM_ACCESSIBILITY:
216             name = "ACCESSIBILITY";
217             break;
218         case STREAM_ULTRASONIC:
219             name = "ULTRASONIC";
220             break;
221         case STREAM_WAKEUP:
222             name = "WAKEUP";
223             break;
224         default:
225             name = "UNKNOWN";
226     }
227 
228     const string streamName = name;
229     return streamName;
230 }
231 
GetSourceName(SourceType sourceType)232 const std::string AudioServiceDump::GetSourceName(SourceType sourceType)
233 {
234     string name;
235     switch (sourceType) {
236         case SOURCE_TYPE_INVALID:
237             name = "INVALID";
238             break;
239         case SOURCE_TYPE_MIC:
240             name = "MIC";
241             break;
242         case SOURCE_TYPE_VOICE_RECOGNITION:
243             name = "VOICE_RECOGNITION";
244             break;
245         case SOURCE_TYPE_ULTRASONIC:
246             name = "ULTRASONIC";
247             break;
248         case SOURCE_TYPE_VOICE_COMMUNICATION:
249             name = "VOICE_COMMUNICATION";
250             break;
251         case SOURCE_TYPE_WAKEUP:
252             name = "WAKEUP";
253             break;
254         default:
255             name = "UNKNOWN";
256     }
257 
258     const string sourceName = name;
259     return sourceName;
260 }
261 
GetStreamUsgaeName(StreamUsage streamUsage)262 const std::string AudioServiceDump::GetStreamUsgaeName(StreamUsage streamUsage)
263 {
264     string usage;
265     switch (streamUsage) {
266         case STREAM_USAGE_MEDIA:
267             usage = "MEDIA";
268             break;
269         case STREAM_USAGE_VOICE_COMMUNICATION:
270             usage = "VOICE_COMMUNICATION";
271             break;
272         case STREAM_USAGE_NOTIFICATION_RINGTONE:
273             usage = "NOTIFICATION_RINGTONE";
274             break;
275         case STREAM_USAGE_VOICE_ASSISTANT:
276             usage = "VOICE_ASSISTANT";
277             break;
278         default:
279             usage = "STREAM_USAGE_UNKNOWN";
280     }
281 
282     const string streamUsageName = usage;
283     return streamUsageName;
284 }
285 
GetContentTypeName(ContentType contentType)286 const std::string AudioServiceDump::GetContentTypeName(ContentType contentType)
287 {
288     string content;
289     switch (contentType) {
290         case CONTENT_TYPE_SPEECH:
291             content = "SPEECH";
292             break;
293         case CONTENT_TYPE_MUSIC:
294             content = "MUSIC";
295             break;
296         case CONTENT_TYPE_MOVIE:
297             content = "MOVIE";
298             break;
299         case CONTENT_TYPE_SONIFICATION:
300             content = "SONIFICATION";
301             break;
302         case CONTENT_TYPE_RINGTONE:
303             content = "RINGTONE";
304             break;
305         default:
306             content = "UNKNOWN";
307     }
308 
309     const string contentTypeName = content;
310     return contentTypeName;
311 }
312 
GetDeviceTypeName(DeviceType deviceType)313 const std::string AudioServiceDump::GetDeviceTypeName(DeviceType deviceType)
314 {
315     string device;
316     switch (deviceType) {
317         case DEVICE_TYPE_EARPIECE:
318             device = "EARPIECE";
319             break;
320         case DEVICE_TYPE_SPEAKER:
321             device = "SPEAKER";
322             break;
323         case DEVICE_TYPE_WIRED_HEADSET:
324             device = "WIRED_HEADSET";
325             break;
326         case DEVICE_TYPE_WIRED_HEADPHONES:
327             device = "WIRED_HEADPHONES";
328             break;
329         case DEVICE_TYPE_BLUETOOTH_SCO:
330              device = "BLUETOOTH_SCO";
331             break;
332         case DEVICE_TYPE_BLUETOOTH_A2DP:
333             device = "BLUETOOTH_A2DP";
334             break;
335         case DEVICE_TYPE_MIC:
336             device = "MIC";
337             break;
338         case DEVICE_TYPE_WAKEUP:
339             device = "WAKEUP";
340             break;
341         case DEVICE_TYPE_NONE:
342             device = "NONE";
343             break;
344         case DEVICE_TYPE_INVALID:
345             device = "INVALID";
346             break;
347         default:
348             device = "UNKNOWN";
349     }
350 
351     const string deviceTypeName = device;
352     return deviceTypeName;
353 }
354 
GetConnectTypeName(ConnectType connectType)355 const std::string AudioServiceDump::GetConnectTypeName(ConnectType connectType)
356 {
357     string connectName;
358     switch (connectType) {
359         case OHOS::AudioStandard::CONNECT_TYPE_LOCAL:
360             connectName = "LOCAL";
361             break;
362         case OHOS::AudioStandard::CONNECT_TYPE_DISTRIBUTED:
363             connectName = "REMOTE";
364             break;
365         default:
366             connectName = "UNKNOWN";
367             break;
368     }
369     const string connectTypeName = connectName;
370     return connectTypeName;
371 }
372 
GetDeviceVolumeTypeName(DeviceVolumeType deviceType)373 const std::string AudioServiceDump::GetDeviceVolumeTypeName(DeviceVolumeType deviceType)
374 {
375     string device;
376     switch (deviceType) {
377         case EARPIECE_VOLUME_TYPE:
378             device = "EARPIECE";
379             break;
380         case SPEAKER_VOLUME_TYPE:
381             device = "SPEAKER";
382             break;
383         case HEADSET_VOLUME_TYPE:
384             device = "HEADSET";
385             break;
386         default:
387             device = "UNKNOWN";
388     }
389 
390     const string deviceTypeName = device;
391     return deviceTypeName;
392 }
393 
PlaybackStreamDump(std::string & dumpString)394 void AudioServiceDump::PlaybackStreamDump(std::string &dumpString)
395 {
396     char s[PA_SAMPLE_SPEC_SNPRINT_MAX];
397 
398     dumpString += "Audio Data Dump:\n\n";
399     dumpString += "Playback Streams\n";
400 
401     AppendFormat(dumpString, "%d  Playback stream (s) available:\n\n", audioData_.streamData.sinkInputs.size());
402 
403     for (auto it = audioData_.streamData.sinkInputs.begin(); it != audioData_.streamData.sinkInputs.end(); it++) {
404         InputOutputInfo sinkInputInfo = *it;
405 
406         AppendFormat(dumpString, "Stream Id: %s\n", (sinkInputInfo.sessionId).c_str());
407         AppendFormat(dumpString, "Application Name: %s\n", ((sinkInputInfo.applicationName).c_str()));
408         AppendFormat(dumpString, "Process Id: %s\n", (sinkInputInfo.processId).c_str());
409         AppendFormat(dumpString, "User Id: %u\n", sinkInputInfo.userId);
410 
411         char *inputSampleSpec = pa_sample_spec_snprint(s, sizeof(s), &(sinkInputInfo.sampleSpec));
412         AppendFormat(dumpString, "Stream Configuration: %s\n", inputSampleSpec);
413         dumpString += "Status:";
414         dumpString += (sinkInputInfo.corked) ? "STOPPED/PAUSED" : "RUNNING";
415         AppendFormat(dumpString, "\nStream Start Time: %s\n", (sinkInputInfo.sessionStartTime).c_str());
416         dumpString += "\n";
417     }
418 }
419 
RecordStreamDump(std::string & dumpString)420 void AudioServiceDump::RecordStreamDump(std::string &dumpString)
421 {
422     char s[PA_SAMPLE_SPEC_SNPRINT_MAX];
423     dumpString += "Record Streams \n";
424     AppendFormat(dumpString, "%d  Record stream (s) available:\n\n", audioData_.streamData.sourceOutputs.size());
425 
426     for (auto it = audioData_.streamData.sourceOutputs.begin(); it != audioData_.streamData.sourceOutputs.end(); it++) {
427         InputOutputInfo sourceOutputInfo = *it;
428         AppendFormat(dumpString, "Stream Id: %s\n", (sourceOutputInfo.sessionId).c_str());
429         AppendFormat(dumpString, "Application Name: %s\n", (sourceOutputInfo.applicationName).c_str());
430         AppendFormat(dumpString, "Process Id: %s\n", sourceOutputInfo.processId.c_str());
431         AppendFormat(dumpString, "User Id: %d\n", sourceOutputInfo.userId);
432 
433         char *outputSampleSpec = pa_sample_spec_snprint(s, sizeof(s), &(sourceOutputInfo.sampleSpec));
434         AppendFormat(dumpString, "Stream Configuration: %s\n", outputSampleSpec);
435         dumpString += "Status:";
436         dumpString += (sourceOutputInfo.corked) ? "STOPPED/PAUSED" : "RUNNING";
437         AppendFormat(dumpString, "\nStream Start Time: %s\n", (sourceOutputInfo.sessionStartTime).c_str());
438         dumpString += "\n";
439     }
440 }
441 
HDFModulesDump(std::string & dumpString)442 void AudioServiceDump::HDFModulesDump(std::string &dumpString)
443 {
444     char s[PA_SAMPLE_SPEC_SNPRINT_MAX];
445 
446     dumpString += "\nHDF Input Modules\n";
447     AppendFormat(dumpString, "%d  HDF Input Modules (s) available:\n\n", audioData_.streamData.sourceDevices.size());
448 
449     for (auto it = audioData_.streamData.sourceDevices.begin(); it != audioData_.streamData.sourceDevices.end(); it++) {
450         SinkSourceInfo sourceInfo = *it;
451 
452         AppendFormat(dumpString, "Module Name: %s\n", (sourceInfo.name).c_str());
453         char *hdfOutSampleSpec = pa_sample_spec_snprint(s, sizeof(s), &(sourceInfo.sampleSpec));
454         AppendFormat(dumpString, "Module Configuration: %s\n\n", hdfOutSampleSpec);
455     }
456 
457     dumpString += "HDF Output Modules\n";
458     AppendFormat(dumpString, "%d  HDF Output Modules (s) available:\n\n", audioData_.streamData.sinkDevices.size());
459 
460     for (auto it = audioData_.streamData.sinkDevices.begin(); it != audioData_.streamData.sinkDevices.end(); it++) {
461         SinkSourceInfo sinkInfo = *it;
462         AppendFormat(dumpString, "Module Name: %s\n", (sinkInfo.name).c_str());
463         char *hdfInSampleSpec = pa_sample_spec_snprint(s, sizeof(s), &(sinkInfo.sampleSpec));
464         AppendFormat(dumpString, "Module Configuration: %s\n\n", hdfInSampleSpec);
465     }
466 }
467 
CallStatusDump(std::string & dumpString)468 void AudioServiceDump::CallStatusDump(std::string &dumpString)
469 {
470     dumpString += "\nAudio Scene:";
471     switch (audioData_.policyData.callStatus) {
472         case AUDIO_SCENE_DEFAULT:
473             dumpString += "DEFAULT";
474             break;
475         case AUDIO_SCENE_RINGING:
476             dumpString += "RINGING";
477             break;
478         case AUDIO_SCENE_PHONE_CALL:
479             dumpString += "PHONE_CALL";
480             break;
481         case AUDIO_SCENE_PHONE_CHAT:
482             dumpString += "PHONE_CHAT";
483             break;
484         default:
485             dumpString += "UNKNOWN";
486     }
487     dumpString += "\n";
488 }
489 
RingerModeDump(std::string & dumpString)490 void AudioServiceDump::RingerModeDump(std::string &dumpString)
491 {
492     dumpString += "Ringer Mode:";
493     switch (audioData_.policyData.ringerMode) {
494         case RINGER_MODE_NORMAL:
495             dumpString += "NORMAL";
496             break;
497         case RINGER_MODE_SILENT:
498             dumpString += "SILENT";
499             break;
500         case RINGER_MODE_VIBRATE:
501             dumpString += "VIBRATE";
502             break;
503         default:
504             dumpString += "UNKNOWN";
505     }
506     dumpString += "\n";
507 }
508 
StreamVolumesDump(string & dumpString)509 void AudioServiceDump::StreamVolumesDump (string &dumpString)
510 {
511     dumpString += "\nStream: Volumes\n";
512     for (auto it = audioData_.policyData.streamVolumes.cbegin(); it != audioData_.policyData.streamVolumes.cend();
513         ++it) {
514         AppendFormat(dumpString, "%s: %d\n", GetStreamName(it->first).c_str(), it->second);
515     }
516 
517     return;
518 }
519 
AudioFocusInfoDump(string & dumpString)520 void AudioServiceDump::AudioFocusInfoDump(string &dumpString)
521 {
522     dumpString += "\nAudio In Focus Info:\n";
523     uint32_t invalidSessionID = static_cast<uint32_t>(-1);
524 
525     std::list<std::pair<AudioInterrupt, AudioFocuState>> audioFocusInfoList = audioData_.policyData.audioFocusInfoList;
526 
527     for (auto iter = audioFocusInfoList.begin(); iter != audioFocusInfoList.end(); ++iter) {
528         if ((iter->first).sessionID == invalidSessionID) {
529             continue;
530         }
531         AppendFormat(dumpString, "Session Id: %d\n", (iter->first).sessionID);
532         AppendFormat(dumpString, "AudioFocus isPlay Id: %d\n", (iter->first).audioFocusType.isPlay);
533         AppendFormat(dumpString, "Stream Name: %s\n",
534             GetStreamName((iter->first).audioFocusType.streamType).c_str());
535         AppendFormat(dumpString, "Source Name: %s\n",
536             GetSourceName((iter->first).audioFocusType.sourceType).c_str());
537         AppendFormat(dumpString, "AudioFocus State: %d\n", iter->second);
538     }
539 
540 	return;
541 }
542 
GroupInfoDump(std::string & dumpString)543 void AudioServiceDump::GroupInfoDump(std::string& dumpString)
544 {
545     dumpString += "\nGroupInfo:\n";
546     AppendFormat(dumpString, "%d  Group Infos (s) available :\n\n", audioData_.policyData.groupInfos.size());
547 
548     for (auto it = audioData_.policyData.groupInfos.begin(); it != audioData_.policyData.groupInfos.end(); it++) {
549         GroupInfo groupInfo = *it;
550         AppendFormat(dumpString, "ConnectType(0 for Local, 1 for Remote): %d\n", groupInfo.type);
551         AppendFormat(dumpString, "Name: %s\n", groupInfo.groupName.c_str());
552         AppendFormat(dumpString, "Id: %d\n", groupInfo.groupId);
553     }
554 }
555 
DevicesInfoDump(string & dumpString)556 void AudioServiceDump::DevicesInfoDump(string& dumpString)
557 {
558     dumpString += "\nInput Devices:\n";
559     AppendFormat(dumpString, "%d  Input Devices (s) available :\n\n", audioData_.policyData.inputDevices.size());
560 
561     for (auto it = audioData_.policyData.inputDevices.begin(); it != audioData_.policyData.inputDevices.end(); it++) {
562         DevicesInfo devicesInfo = *it;
563         AppendFormat(dumpString, "device type:%s ", GetDeviceTypeName(devicesInfo.deviceType).c_str());
564         AppendFormat(dumpString, "connect type:%s\n", GetConnectTypeName(devicesInfo.conneceType).c_str());
565     }
566 
567     dumpString += "\nOutput Devices:\n";
568     AppendFormat(dumpString, "%d  Output Devices (s) available :\n\n", audioData_.policyData.outputDevices.size());
569 
570     for (auto it = audioData_.policyData.outputDevices.begin(); it != audioData_.policyData.outputDevices.end(); it++) {
571         DevicesInfo devicesInfo = *it;
572         AppendFormat(dumpString, "device type:%s ", GetDeviceTypeName(devicesInfo.deviceType).c_str());
573         AppendFormat(dumpString, "connect type:%s\n", GetConnectTypeName(devicesInfo.conneceType).c_str());
574     }
575 
576     AppendFormat(dumpString, "\nHighest priority output device: %s",
577         GetDeviceTypeName(audioData_.policyData.priorityOutputDevice).c_str());
578     AppendFormat(dumpString, "\nHighest priority input device: %s \n\n",
579         GetDeviceTypeName(audioData_.policyData.priorityInputDevice).c_str());
580 }
581 
EffectManagerInfoDumpPart(string & dumpString,const AudioData & audioData_)582 static void EffectManagerInfoDumpPart(string& dumpString, const AudioData &audioData_)
583 {
584     int32_t count;
585    // xml -- Preprocess
586     for (Preprocess x : audioData_.policyData.oriEffectConfig.preProcess) {
587         AppendFormat(dumpString, "preProcess stream = %s \n", x.stream.c_str());
588         count = 0;
589         for (string modeName : x.mode) {
590             count++;
591             AppendFormat(dumpString, "  modeName%d = %s \n", count, modeName.c_str());
592             for (Device deviceInfo : x.device[count - 1]) {
593                 AppendFormat(dumpString, "      device type = %s \n", deviceInfo.type.c_str());
594                 AppendFormat(dumpString, "      device chain = %s \n", deviceInfo.chain.c_str());
595             }
596         }
597     }
598 
599     // xml -- Postprocess
600     for (Postprocess x : audioData_.policyData.oriEffectConfig.postProcess) {
601         AppendFormat(dumpString, "postprocess stream = %s \n", x.stream.c_str());
602         count = 0;
603         for (string modeName : x.mode) {
604             count++;
605             AppendFormat(dumpString, "  modeName%d = %s \n", count, modeName.c_str());
606             for (Device deviceInfo : x.device[count - 1]) {
607                 AppendFormat(dumpString, "      device type = %s \n", deviceInfo.type.c_str());
608                 AppendFormat(dumpString, "      device chain = %s \n", deviceInfo.chain.c_str());
609             }
610         }
611     }
612 }
613 
EffectManagerInfoDump(string & dumpString)614 void AudioServiceDump::EffectManagerInfoDump(string& dumpString)
615 {
616     int count = 0;
617     dumpString += "\n Effect Manager INFO: \n";
618     AppendFormat(dumpString, "XML version:%f \n", audioData_.policyData.oriEffectConfig.version);
619     // xml -- Library
620     for (Library x : audioData_.policyData.oriEffectConfig.libraries) {
621         count++;
622         AppendFormat(dumpString, "library%d name = %s \n", count, x.name.c_str());
623         AppendFormat(dumpString, "library%d path = %s \n", count, x.path.c_str());
624     }
625     // xml -- effect
626     count = 0;
627     for (Effect x : audioData_.policyData.oriEffectConfig.effects) {
628         count++;
629         AppendFormat(dumpString, "effect%d name = %s \n", count, x.name.c_str());
630         AppendFormat(dumpString, "effect%d libraryName = %s \n", count, x.libraryName.c_str());
631     }
632 
633     // xml -- effectChain
634     for (EffectChain x : audioData_.policyData.oriEffectConfig.effectChains) {
635         AppendFormat(dumpString, "effectChain name = %s \n", x.name.c_str());
636         count = 0;
637         for (string effectUnit : x.apply) {
638             count++;
639             AppendFormat(dumpString, "  effectUnit%d = %s \n", count, effectUnit.c_str());
640         }
641     }
642 
643     EffectManagerInfoDumpPart(dumpString, audioData_);
644 
645     // successful lib
646     count = 0;
647     for (Effect x : audioData_.policyData.availableEffects) {
648         count++;
649         AppendFormat(dumpString, "available Effect%d name = %s \n", count, x.name.c_str());
650         AppendFormat(dumpString, "available Effect%d libraryName = %s \n", count, x.libraryName.c_str());
651     }
652 }
653 
DataDump(string & dumpString)654 void AudioServiceDump::DataDump(string &dumpString)
655 {
656     PlaybackStreamDump(dumpString);
657     RecordStreamDump(dumpString);
658     HDFModulesDump(dumpString);
659     DevicesInfoDump(dumpString);
660     CallStatusDump(dumpString);
661     RingerModeDump(dumpString);
662     StreamVolumesDump(dumpString);
663     AudioFocusInfoDump(dumpString);
664     GroupInfoDump(dumpString);
665     EffectManagerInfoDump(dumpString);
666     StreamVolumeInfosDump(dumpString);
667 }
668 
AudioDataDump(PolicyData & policyData,string & dumpString)669 void AudioServiceDump::AudioDataDump(PolicyData &policyData, string &dumpString)
670 {
671     if (mainLoop == nullptr || context == nullptr) {
672         AUDIO_ERR_LOG("Audio Service Not running");
673         return;
674     }
675 
676     pa_threaded_mainloop_lock(mainLoop);
677     pa_operation *operation = nullptr;
678     operation = pa_context_get_sink_info_list(context, AudioServiceDump::PASinkInfoCallback, (void *)(this));
679 
680     while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
681         pa_threaded_mainloop_wait(mainLoop);
682     }
683 
684     pa_operation_unref(operation);
685     operation = pa_context_get_sink_input_info_list(context, AudioServiceDump::PASinkInputInfoCallback, (void *)this);
686 
687     while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
688         pa_threaded_mainloop_wait(mainLoop);
689     }
690 
691     pa_operation_unref(operation);
692     operation = pa_context_get_source_info_list(context, AudioServiceDump::PASourceInfoCallback, (void *)this);
693 
694     while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
695         pa_threaded_mainloop_wait(mainLoop);
696     }
697 
698     pa_operation_unref(operation);
699     operation = pa_context_get_source_output_info_list(context,
700         AudioServiceDump::PASourceOutputInfoCallback, (void *)this);
701 
702     while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
703         pa_threaded_mainloop_wait(mainLoop);
704     }
705 
706     pa_operation_unref(operation);
707     pa_threaded_mainloop_unlock(mainLoop);
708 
709     audioData_.policyData = policyData;
710     DataDump(dumpString);
711 
712     return;
713 }
714 
PAContextStateCb(pa_context * context,void * userdata)715 void AudioServiceDump::PAContextStateCb(pa_context *context, void *userdata)
716 {
717     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)userdata;
718 
719     switch (pa_context_get_state(context)) {
720         case PA_CONTEXT_READY:
721         case PA_CONTEXT_TERMINATED:
722         case PA_CONTEXT_FAILED:
723             pa_threaded_mainloop_signal(mainLoop, 0);
724             break;
725 
726         case PA_CONTEXT_UNCONNECTED:
727         case PA_CONTEXT_CONNECTING:
728         case PA_CONTEXT_AUTHORIZING:
729         case PA_CONTEXT_SETTING_NAME:
730         default:
731             break;
732     }
733     return;
734 }
735 
PASinkInfoCallback(pa_context * c,const pa_sink_info * i,int eol,void * userdata)736 void AudioServiceDump::PASinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
737 {
738     AudioServiceDump *asDump = (AudioServiceDump *)userdata;
739     if (asDump == nullptr) {
740         AUDIO_ERR_LOG("Failed to get sink information");
741         return;
742     }
743 
744     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)asDump->mainLoop;
745 
746     if (eol < 0) {
747         AUDIO_ERR_LOG("Failed to get sink information: %{public}s", pa_strerror(pa_context_errno(c)));
748         return;
749     }
750 
751     if (eol) {
752         pa_threaded_mainloop_signal(mainLoop, 0);
753         return;
754     }
755 
756     SinkSourceInfo sinkInfo;
757 
758     if (i->name != nullptr) {
759         string sinkName(i->name);
760         if (IsValidModule(sinkName)) {
761             (sinkInfo.name).assign(sinkName);
762             sinkInfo.sampleSpec = i->sample_spec;
763             asDump->audioData_.streamData.sinkDevices.push_back(sinkInfo);
764         }
765     }
766 }
767 
PASinkInputInfoCallback(pa_context * c,const pa_sink_input_info * i,int eol,void * userdata)768 void AudioServiceDump::PASinkInputInfoCallback(pa_context *c, const pa_sink_input_info *i, int eol, void *userdata)
769 {
770     AudioServiceDump *asDump = (AudioServiceDump *)userdata;
771     if (asDump == nullptr) {
772         AUDIO_ERR_LOG("Failed to get sink input information");
773         return;
774     }
775 
776     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)asDump->mainLoop;
777 
778     if (eol < 0) {
779         AUDIO_ERR_LOG("Failed to get sink input information: %{public}s", pa_strerror(pa_context_errno(c)));
780         return;
781     }
782 
783     if (eol) {
784         pa_threaded_mainloop_signal(mainLoop, 0);
785         return;
786     }
787 
788     InputOutputInfo sinkInputInfo;
789 
790     sinkInputInfo.sampleSpec = i->sample_spec;
791     sinkInputInfo.corked = i->corked;
792 
793     if (i->proplist !=nullptr) {
794         const char *applicationname = pa_proplist_gets(i->proplist, "application.name");
795         const char *processid = pa_proplist_gets(i->proplist, "application.process.id");
796         const char *user = pa_proplist_gets(i->proplist, "application.process.user");
797         const char *sessionid = pa_proplist_gets(i->proplist, "stream.sessionID");
798         const char *sessionstarttime = pa_proplist_gets(i->proplist, "stream.startTime");
799 
800         if (applicationname != nullptr) {
801             string applicationName(applicationname);
802             (sinkInputInfo.applicationName).assign(applicationName);
803         }
804 
805         if (processid != nullptr) {
806             string processId(processid);
807             (sinkInputInfo.processId).assign(processId);
808         }
809 
810         if (user != nullptr) {
811             struct passwd *p;
812             if ((p = getpwnam(user)) != nullptr) {
813                 sinkInputInfo.userId = uint32_t(p->pw_uid);
814             }
815         }
816 
817         if (sessionid != nullptr) {
818             string sessionId(sessionid);
819             (sinkInputInfo.sessionId).assign(sessionId);
820         }
821 
822         if (sessionstarttime != nullptr) {
823             string sessionStartTime(sessionstarttime);
824             (sinkInputInfo.sessionStartTime).assign(sessionStartTime);
825         }
826     }
827     asDump->audioData_.streamData.sinkInputs.push_back(sinkInputInfo);
828 }
829 
PASourceInfoCallback(pa_context * c,const pa_source_info * i,int eol,void * userdata)830 void AudioServiceDump::PASourceInfoCallback(pa_context *c, const pa_source_info *i, int eol, void *userdata)
831 {
832     AudioServiceDump *asDump = (AudioServiceDump *)userdata;
833     if (asDump == nullptr) {
834         AUDIO_ERR_LOG("Failed to get source information");
835         return;
836     }
837 
838     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)asDump->mainLoop;
839 
840     if (eol < 0) {
841         AUDIO_ERR_LOG("Failed to get source information: %{public}s", pa_strerror(pa_context_errno(c)));
842         return;
843     }
844 
845     if (eol) {
846         pa_threaded_mainloop_signal(mainLoop, 0);
847         return;
848     }
849 
850     SinkSourceInfo sourceInfo;
851 
852     if (i->name != nullptr) {
853         string sourceName(i->name);
854         if (IsValidModule(sourceName)) {
855             (sourceInfo.name).assign(sourceName);
856             sourceInfo.sampleSpec = i->sample_spec;
857             asDump->audioData_.streamData.sourceDevices.push_back(sourceInfo);
858         }
859     }
860 }
861 
PASourceOutputInfoCallback(pa_context * c,const pa_source_output_info * i,int eol,void * userdata)862 void AudioServiceDump::PASourceOutputInfoCallback(pa_context *c, const pa_source_output_info *i, int eol,
863     void *userdata)
864 {
865     AudioServiceDump *asDump = (AudioServiceDump *)userdata;
866     if (asDump == nullptr) {
867         AUDIO_ERR_LOG("Failed to get source output information");
868         return;
869     }
870 
871     pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)asDump->mainLoop;
872 
873     if (eol < 0) {
874         AUDIO_ERR_LOG("Failed to get source output information: %{public}s", pa_strerror(pa_context_errno(c)));
875         return;
876     }
877 
878     if (eol) {
879         pa_threaded_mainloop_signal(mainLoop, 0);
880         return;
881     }
882 
883     InputOutputInfo sourceOutputInfo;
884     sourceOutputInfo.sampleSpec = i->sample_spec;
885     sourceOutputInfo.corked = i->corked;
886 
887     if (i->proplist !=nullptr) {
888         const char *applicationname = pa_proplist_gets(i->proplist, "application.name");
889         const char *processid = pa_proplist_gets(i->proplist, "application.process.id");
890         const char *user = pa_proplist_gets(i->proplist, "application.process.user");
891         const char *sessionid = pa_proplist_gets(i->proplist, "stream.sessionID");
892         const char *sessionstarttime = pa_proplist_gets(i->proplist, "stream.startTime");
893 
894         if (applicationname != nullptr) {
895             string applicationName(applicationname);
896             (sourceOutputInfo.applicationName).assign(applicationName);
897         }
898 
899         if (processid != nullptr) {
900             string processId(processid);
901             (sourceOutputInfo.processId).assign(processId);
902         }
903 
904         if (user != nullptr) {
905             struct passwd *p;
906             if ((p = getpwnam(user)) != nullptr) {
907                 sourceOutputInfo.userId = uint32_t(p->pw_uid);
908             }
909         }
910 
911         if (sessionid != nullptr) {
912             string sessionId(sessionid);
913             (sourceOutputInfo.sessionId).assign(sessionId);
914         }
915 
916         if (sessionstarttime != nullptr) {
917             string sessionStartTime(sessionstarttime);
918             (sourceOutputInfo.sessionStartTime).assign(sessionStartTime);
919         }
920     }
921     asDump->audioData_.streamData.sourceOutputs.push_back(sourceOutputInfo);
922 }
923 
DeviceVolumeInfosDump(std::string & dumpString,DeviceVolumeInfoMap & deviceVolumeInfos)924 void AudioServiceDump::DeviceVolumeInfosDump(std::string& dumpString, DeviceVolumeInfoMap &deviceVolumeInfos)
925 {
926     AppendFormat(dumpString, "    volume points:\n");
927     for (auto iter = deviceVolumeInfos.cbegin(); iter != deviceVolumeInfos.cend(); ++iter) {
928         AppendFormat(dumpString, "      device:%s \n", GetDeviceVolumeTypeName(iter->first).c_str());
929         auto volumePoints = iter->second->volumePoints;
930         for (auto volPoint = volumePoints.cbegin(); volPoint != volumePoints.cend(); ++volPoint) {
931             AppendFormat(dumpString, "        [%d, %d]\n", volPoint->index, volPoint->dbValue);
932         }
933     }
934     AppendFormat(dumpString, "\n");
935 }
936 
StreamVolumeInfosDump(std::string & dumpString)937 void AudioServiceDump::StreamVolumeInfosDump(std::string& dumpString)
938 {
939     dumpString += "\nVolume config of streams:\n";
940 
941     for (auto it = audioData_.policyData.streamVolumeInfos.cbegin();
942         it != audioData_.policyData.streamVolumeInfos.cend(); ++it) {
943         AppendFormat(dumpString, "  %s:  ", GetStreamName(it->first).c_str());
944         auto streamVolumeInfo = it->second;
945         AppendFormat(dumpString, "minLevel = %d  ", streamVolumeInfo->minLevel);
946         AppendFormat(dumpString, "maxLevel = %d  ", streamVolumeInfo->maxLevel);
947         AppendFormat(dumpString, "defaultLevel = %d\n", streamVolumeInfo->defaultLevel);
948         DeviceVolumeInfosDump(dumpString, streamVolumeInfo->deviceVolumeInfos);
949     }
950 }
951 } // namespace AudioStandard
952 } // namespace OHOS
953