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