1 /*
2 * Copyright (c) 2025 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 #ifndef LOG_TAG
16 #define LOG_TAG "AudioServerHpaeDump"
17 #endif
18
19 #include "audio_server_hpae_dump.h"
20 #include <sstream>
21 #include "audio_utils.h"
22 #include "audio_errors.h"
23 #include "audio_service.h"
24 #include "audio_dump_pcm.h"
25 #include "audio_performance_monitor.h"
26 #include "manager/hdi_adapter_manager.h"
27 #include "i_hpae_manager.h"
28
29 using namespace std;
30 using namespace OHOS::AudioStandard::HPAE;
31 namespace OHOS {
32 namespace AudioStandard {
33 static const int32_t OPERATION_TIMEOUT_IN_MS = 1000; // 1000ms
34
AudioServerHpaeDump()35 AudioServerHpaeDump::AudioServerHpaeDump()
36 {
37 AUDIO_DEBUG_LOG("AudioServerHpaeDump construct");
38 InitDumpFuncMap();
39 }
40
~AudioServerHpaeDump()41 AudioServerHpaeDump::~AudioServerHpaeDump()
42 {}
43
InitDumpFuncMap()44 void AudioServerHpaeDump::InitDumpFuncMap()
45 {
46 dumpFuncMap[u"-h"] = &AudioServerHpaeDump::HelpInfoDump;
47 dumpFuncMap[u"-p"] = &AudioServerHpaeDump::PlaybackSinkDump;
48 dumpFuncMap[u"-r"] = &AudioServerHpaeDump::RecordSourceDump;
49 dumpFuncMap[u"-m"] = &AudioServerHpaeDump::HDFModulesDump;
50 dumpFuncMap[u"-ep"] = &AudioServerHpaeDump::PolicyHandlerDump;
51 dumpFuncMap[u"-ct"] = &AudioServerHpaeDump::AudioCacheTimeDump;
52 dumpFuncMap[u"-cm"] = &AudioServerHpaeDump::AudioCacheMemoryDump;
53 dumpFuncMap[u"-pm"] = &AudioServerHpaeDump::AudioPerformMonitorDump;
54 dumpFuncMap[u"-ha"] = &AudioServerHpaeDump::HdiAdapterDump;
55 }
56
AudioDataDump(std::string & dumpString,std::queue<std::u16string> & argQue)57 void AudioServerHpaeDump::AudioDataDump(std::string &dumpString, std::queue<std::u16string> &argQue)
58 {
59 ArgDataDump(dumpString, argQue);
60 }
61
ServerDataDump(string & dumpString)62 void AudioServerHpaeDump::ServerDataDump(string &dumpString)
63 {
64 PlaybackSinkDump(dumpString);
65 RecordSourceDump(dumpString);
66 HDFModulesDump(dumpString);
67 PolicyHandlerDump(dumpString);
68 }
69
GetDeviceSinkInfo(std::string & dumpString,std::string deviceName)70 void AudioServerHpaeDump::GetDeviceSinkInfo(std::string &dumpString, std::string deviceName)
71 {
72 lock_guard<mutex> lock(lock_);
73 AUDIO_INFO_LOG("GetDeviceSinkInfo %{public}s start.", deviceName.c_str());
74 isFinishGetSinkInfo_ = false;
75 IHpaeManager::GetHpaeManager().DumpSinkInfo(deviceName);
76 std::unique_lock<std::mutex> waitLock(callbackMutex_);
77 dumpHpaeSinkInfo_.clear();
78 bool stopWaiting = callbackCV_.wait_for(waitLock, std::chrono::milliseconds(OPERATION_TIMEOUT_IN_MS), [this] {
79 return isFinishGetSinkInfo_; // will be true when got notified.
80 });
81 if (!stopWaiting) {
82 AUDIO_ERR_LOG("GetDeviceSinkInfo timeout!");
83 return;
84 }
85 AUDIO_INFO_LOG("GetDeviceSinkInfo %{public}s end.", deviceName.c_str());
86 dumpString += dumpHpaeSinkInfo_;
87 }
88
PlaybackSinkDump(std::string & dumpString)89 void AudioServerHpaeDump::PlaybackSinkDump(std::string &dumpString)
90 {
91 dumpString += "Hpae AudioServer Playback sink Dump:\n\n";
92 for (auto it = devicesInfo_.sinkInfos.begin(); it != devicesInfo_.sinkInfos.end(); it++) {
93 dumpString += it->deviceName + ":\n";
94 GetDeviceSinkInfo(dumpString, it->deviceName);
95 dumpString += "\n";
96 }
97 dumpString += "\n";
98 PlaybackSinkInputDump(dumpString);
99 }
100
OnDumpSinkInfoCb(std::string & dumpStr,int32_t result)101 void AudioServerHpaeDump::OnDumpSinkInfoCb(std::string &dumpStr, int32_t result)
102 {
103 std::unique_lock<std::mutex> waitLock(callbackMutex_);
104 dumpHpaeSinkInfo_ = dumpStr;
105 isFinishGetSinkInfo_ = true;
106 AUDIO_INFO_LOG(
107 "AudioServerHpaeDump OnDumpSinkInfoCb %{public}s, result %{public}d", dumpHpaeSinkInfo_.c_str(), result);
108 callbackCV_.notify_all();
109 }
110
GetDeviceSourceInfo(std::string & dumpString,std::string deviceName)111 void AudioServerHpaeDump::GetDeviceSourceInfo(std::string &dumpString, std::string deviceName)
112 {
113 lock_guard<mutex> lock(lock_);
114 AUDIO_INFO_LOG("GetDeviceSourceInfo %{public}s start.", deviceName.c_str());
115 isFinishGetSourceInfo_ = false;
116 IHpaeManager::GetHpaeManager().DumpSourceInfo(deviceName);
117 std::unique_lock<std::mutex> waitLock(callbackMutex_);
118 dumpHpaeSourceInfo_.clear();
119 bool stopWaiting = callbackCV_.wait_for(waitLock, std::chrono::milliseconds(OPERATION_TIMEOUT_IN_MS), [this] {
120 return isFinishGetSourceInfo_; // will be true when got notified.
121 });
122 if (!stopWaiting) {
123 AUDIO_ERR_LOG("GetDeviceSourceInfo timeout!");
124 return;
125 }
126 AUDIO_INFO_LOG("GetDeviceSourceInfo %{public}s end.", deviceName.c_str());
127 dumpString += dumpHpaeSourceInfo_;
128 }
129
RecordSourceDump(std::string & dumpString)130 void AudioServerHpaeDump::RecordSourceDump(std::string &dumpString)
131 {
132 dumpString += "Hpae AudioServer Record source Dump:\n\n";
133 for (auto it = devicesInfo_.sourceInfos.begin(); it != devicesInfo_.sourceInfos.end(); it++) {
134 dumpString += it->deviceName + ":\n";
135 GetDeviceSourceInfo(dumpString, it->deviceName);
136 dumpString += "\n";
137 }
138 dumpString += "\n";
139 RecordSourceOutputDump(dumpString);
140 }
141
OnDumpSourceInfoCb(std::string & dumpStr,int32_t result)142 void AudioServerHpaeDump::OnDumpSourceInfoCb(std::string &dumpStr, int32_t result)
143 {
144 std::unique_lock<std::mutex> waitLock(callbackMutex_);
145 dumpHpaeSourceInfo_ = dumpStr;
146 isFinishGetSourceInfo_ = true;
147 AUDIO_INFO_LOG(
148 "AudioServerHpaeDump OnDumpSourceInfoCb %{public}s, result %{public}d", dumpHpaeSourceInfo_.c_str(), result);
149 callbackCV_.notify_all();
150 }
151
ArgDataDump(std::string & dumpString,std::queue<std::u16string> & argQue)152 void AudioServerHpaeDump::ArgDataDump(std::string &dumpString, std::queue<std::u16string> &argQue)
153 {
154 CHECK_AND_RETURN(GetDevicesInfo());
155 dumpString += "Hpae AudioServer Data Dump:\n\n";
156 if (argQue.empty()) {
157 ServerDataDump(dumpString);
158 return;
159 }
160 while (!argQue.empty()) {
161 std::u16string para = argQue.front();
162 if (para == u"-h") {
163 dumpString.clear();
164 (this->*dumpFuncMap[para])(dumpString);
165 return;
166 } else if (para == u"-p") {
167 dumpString.clear();
168 (this->*dumpFuncMap[para])(dumpString);
169 return;
170 } else if (dumpFuncMap.count(para) == 0) {
171 dumpString.clear();
172 AppendFormat(dumpString, "Please input correct param:\n");
173 HelpInfoDump(dumpString);
174 return;
175 } else {
176 (this->*dumpFuncMap[para])(dumpString);
177 }
178 argQue.pop();
179 }
180 }
181
HelpInfoDump(string & dumpString)182 void AudioServerHpaeDump::HelpInfoDump(string &dumpString)
183 {
184 AppendFormat(dumpString, "usage:\n");
185 AppendFormat(dumpString, " -h\t\t\t|help text for hidumper audio\n");
186 AppendFormat(dumpString, " -p\t\t\t|dump hpae playback streams\n");
187 AppendFormat(dumpString, " -r\t\t\t|dump hpae record streams\n");
188 }
189
Initialize()190 int32_t AudioServerHpaeDump::Initialize()
191 {
192 AUDIO_INFO_LOG("AudioServerHpaeDump Initialize");
193 IHpaeManager::GetHpaeManager().RegisterHpaeDumpCallback(weak_from_this());
194 return SUCCESS;
195 }
196
HDFModulesDump(std::string & dumpString)197 void AudioServerHpaeDump::HDFModulesDump(std::string &dumpString)
198 {
199 lock_guard<mutex> lock(lock_);
200 dumpHdfModulesInfo_ += "\nHDF Input Modules\n";
201 AppendFormat(dumpHdfModulesInfo_, "- %zu HDF Input Modules (s) available:\n", devicesInfo_.sourceInfos.size());
202
203 for (auto it = devicesInfo_.sourceInfos.begin(); it != devicesInfo_.sourceInfos.end(); it++) {
204 HpaeSinkSourceInfo &sourceInfo = *it;
205 AppendFormat(dumpHdfModulesInfo_, " Module %d\n", it - devicesInfo_.sourceInfos.begin() + 1);
206 AppendFormat(dumpHdfModulesInfo_, " - Module Name: %s\n", (sourceInfo.deviceName).c_str());
207 AppendFormat(dumpHdfModulesInfo_, " - Module Configuration: %s\n\n", sourceInfo.config.c_str());
208 }
209
210 dumpHdfModulesInfo_ += "HDF Output Modules\n";
211 AppendFormat(dumpHdfModulesInfo_, "- %zu HDF Output Modules (s) available:\n", devicesInfo_.sinkInfos.size());
212
213 for (auto it = devicesInfo_.sinkInfos.begin(); it != devicesInfo_.sinkInfos.end(); it++) {
214 HpaeSinkSourceInfo &sinkInfo = *it;
215 AppendFormat(dumpHdfModulesInfo_, " Module %d\n", it - devicesInfo_.sinkInfos.begin() + 1);
216 AppendFormat(dumpHdfModulesInfo_, " - Module Name: %s\n", (sinkInfo.deviceName).c_str());
217 AppendFormat(dumpHdfModulesInfo_, " - Module Configuration: %s\n\n", sinkInfo.config.c_str());
218 }
219
220 AUDIO_INFO_LOG("HDFModulesDump : \n%{public}s end", dumpHdfModulesInfo_.c_str());
221 dumpString += dumpHdfModulesInfo_;
222 }
223
GetDevicesInfo()224 bool AudioServerHpaeDump::GetDevicesInfo()
225 {
226 lock_guard<mutex> lock(lock_);
227 IHpaeManager::GetHpaeManager().DumpAllAvailableDevice(devicesInfo_);
228 std::unique_lock<std::mutex> waitLock(callbackMutex_);
229 isFinishGetHdfModulesInfo_ = false;
230 dumpHdfModulesInfo_.clear();
231 bool stopWaiting = callbackCV_.wait_for(waitLock, std::chrono::milliseconds(OPERATION_TIMEOUT_IN_MS), [this] {
232 return isFinishGetHdfModulesInfo_; // will be true when got notified.
233 });
234 CHECK_AND_RETURN_RET_LOG(stopWaiting, false, "DumpAllAvailableDevice timeout!");
235 return true;
236 }
237
OnDumpAllAvailableDeviceCb(int32_t result)238 void AudioServerHpaeDump::OnDumpAllAvailableDeviceCb(int32_t result)
239 {
240 std::unique_lock<std::mutex> waitLock(callbackMutex_);
241 isFinishGetHdfModulesInfo_ = true;
242 AUDIO_INFO_LOG(
243 "sink count %{public}zu, source count %{public}zu, result %{public}d",
244 devicesInfo_.sinkInfos.size(), devicesInfo_.sourceInfos.size(), result);
245 callbackCV_.notify_all();
246 }
247
PolicyHandlerDump(std::string & dumpString)248 void AudioServerHpaeDump::PolicyHandlerDump(std::string &dumpString)
249 {
250 AUDIO_INFO_LOG("PolicyHandlerDump");
251 AudioService::GetInstance()->Dump(dumpString);
252 }
253
AudioCacheTimeDump(std::string & dumpString)254 void AudioServerHpaeDump::AudioCacheTimeDump(std::string &dumpString)
255 {
256 AUDIO_INFO_LOG("AudioCacheTimeDump");
257 dumpString += "\nAudioCached Time\n";
258
259 int64_t startTime = 0;
260 int64_t endTime = 0;
261 AudioCacheMgr::GetInstance().GetCachedDuration(startTime, endTime);
262 dumpString += "Call dump get time: [ " + ClockTime::NanoTimeToString(startTime) + " ~ " +
263 ClockTime::NanoTimeToString(endTime) + " ], cur: [ " +
264 ClockTime::NanoTimeToString(ClockTime::GetRealNano()) + " ] \n";
265 }
266
AudioCacheMemoryDump(std::string & dumpString)267 void AudioServerHpaeDump::AudioCacheMemoryDump(std::string &dumpString)
268 {
269 AUDIO_INFO_LOG("AudioCacheMemoryDump");
270 dumpString += "\nAudioCached Memory\n";
271
272 size_t dataLength = 0;
273 size_t bufferLength = 0;
274 size_t structLength = 0;
275 AudioCacheMgr::GetInstance().GetCurMemoryCondition(dataLength, bufferLength, structLength);
276 dumpString += "dataLength: " + std::to_string(dataLength / BYTE_TO_KB_SIZE) + " KB, " +
277 "bufferLength: " + std::to_string(bufferLength / BYTE_TO_KB_SIZE) + " KB, " +
278 "structLength: " + std::to_string(structLength / BYTE_TO_KB_SIZE) + " KB \n";
279 }
280
AudioPerformMonitorDump(std::string & dumpString)281 void AudioServerHpaeDump::AudioPerformMonitorDump(std::string &dumpString)
282 {
283 AUDIO_INFO_LOG("AudioPerformMonitorDump");
284 dumpString += "\n Dump Audio Performance Monitor Record Infos\n";
285 AudioPerformanceMonitor::GetInstance().DumpMonitorInfo(dumpString);
286 }
287
HdiAdapterDump(std::string & dumpString)288 void AudioServerHpaeDump::HdiAdapterDump(std::string &dumpString)
289 {
290 AUDIO_INFO_LOG("HdiAdapterDump");
291 dumpString += "\nHdiAdapter Info\n";
292 HdiAdapterManager::GetInstance().DumpInfo(dumpString);
293 }
294
PlaybackSinkInputDump(std::string & dumpString)295 void AudioServerHpaeDump::PlaybackSinkInputDump(std::string &dumpString)
296 {
297 lock_guard<mutex> lock(lock_);
298 AUDIO_INFO_LOG("get sinkinputs dump info");
299 isFinishGetStreamInfo_ = false;
300 dumpSinkInputsInfo_.clear();
301 IHpaeManager::GetHpaeManager().DumpSinkInputsInfo();
302 std::unique_lock<std::mutex> waitLock(callbackMutex_);
303
304 bool stopWaiting = callbackCV_.wait_for(waitLock, std::chrono::milliseconds(OPERATION_TIMEOUT_IN_MS), [this] {
305 return isFinishGetStreamInfo_; // will be true when got notified.
306 });
307 if (!stopWaiting) {
308 AUDIO_ERR_LOG("PlaybackSinkInputDump timeout!");
309 return;
310 }
311 AUDIO_INFO_LOG("PlaybackSinkInputDump SUCCESS, info : \n%{public}s", dumpSinkInputsInfo_.c_str());
312 dumpString += dumpSinkInputsInfo_;
313 }
314
RecordSourceOutputDump(std::string & dumpString)315 void AudioServerHpaeDump::RecordSourceOutputDump(std::string &dumpString)
316 {
317 lock_guard<mutex> lock(lock_);
318 AUDIO_INFO_LOG("get sourceoutputs dump info");
319 isFinishGetStreamInfo_ = false;
320 dumpSourceOutputsInfo_.clear();
321 IHpaeManager::GetHpaeManager().DumpSourceOutputsInfo();
322 std::unique_lock<std::mutex> waitLock(callbackMutex_);
323
324 bool stopWaiting = callbackCV_.wait_for(waitLock, std::chrono::milliseconds(OPERATION_TIMEOUT_IN_MS), [this] {
325 return isFinishGetStreamInfo_; // will be true when got notified.
326 });
327 if (!stopWaiting) {
328 AUDIO_ERR_LOG("RecordSourceOutputDump timeout!");
329 return;
330 }
331 AUDIO_INFO_LOG("RecordSourceOutputDump SUCCESS, info : \n%{public}s", dumpSourceOutputsInfo_.c_str());
332 dumpString += dumpSourceOutputsInfo_;
333 }
334
TransTimeToString(uint64_t timetamp)335 static std::string TransTimeToString(uint64_t timetamp)
336 {
337 auto tp = std::chrono::system_clock::time_point(std::chrono::milliseconds(timetamp));
338 time_t time = std::chrono::system_clock::to_time_t(tp);
339 struct tm *timeinfo = localtime(&time);
340 if (!timeinfo) {
341 return "Invalid time";
342 }
343 char buffer[80];
344 CHECK_AND_RETURN_RET_LOG(strftime(buffer, sizeof(buffer), "%a %b %d %H:%M:%S %Y", timeinfo) != 0, "error time",
345 "strftime failed");
346 return buffer;
347 }
348
TransHpaeInputOutputInfoToStr(const HpaeInputOutputInfo & info,const size_t & idx,std::string & tempDumpStr)349 static void TransHpaeInputOutputInfoToStr(const HpaeInputOutputInfo &info, const size_t &idx, std::string &tempDumpStr)
350 {
351 std::ostringstream oss;
352 oss << " Stream " << idx << "\n"
353 << " - Stream Id: " << info.sessionId << "\n"
354 << " - Device Name: " << info.deviceName << "\n"
355 << " - Application Name: " << GetBundleNameByToken(info.tokenId) << "\n"
356 << " - Process Id: " << info.pid << "\n"
357 << " - User Id: " << info.uid << "\n"
358 << " - Offload Enable: " << (info.offloadEnable ? "true" : "false") << "\n"
359 << " - stream can be captured: " << (info.privacyType == 0 ? "true" : "false") << "\n"
360 << " - Stream Configuration: " << info.config << "\n"
361 << " - Status: " << (info.state == HPAE_SESSION_RUNNING ? "RUNNING" : "STOPPED/PAUSED") << "\n"
362 << " - Stream Start Time: " << TransTimeToString(info.startTime) << "\n\n";
363 tempDumpStr += oss.str();
364 }
365
OnDumpSinkInputsInfoCb(std::vector<HpaeInputOutputInfo> & sinkInputs,int32_t result)366 void AudioServerHpaeDump::OnDumpSinkInputsInfoCb(std::vector<HpaeInputOutputInfo> &sinkInputs, int32_t result)
367 {
368 std::unique_lock<std::mutex> waitLock(callbackMutex_);
369 if (result == SUCCESS) {
370 dumpSinkInputsInfo_ += "Playback Streams\n";
371 AppendFormat(dumpSinkInputsInfo_, "- %zu Playback stream (s) available:\n", sinkInputs.size());
372 for (auto it = sinkInputs.begin(); it != sinkInputs.end(); it++) {
373 HpaeInputOutputInfo info = *it;
374 TransHpaeInputOutputInfoToStr(info, it - sinkInputs.begin() + 1, dumpSinkInputsInfo_);
375 }
376 dumpSinkInputsInfo_ += "\n";
377 }
378 isFinishGetStreamInfo_ = true;
379 AUDIO_INFO_LOG("AudioServerHpaeDump OnDumpSinkInputsInfoCb result %{public}d", result);
380 callbackCV_.notify_all();
381 }
382
OnDumpSourceOutputsInfoCb(std::vector<HpaeInputOutputInfo> & sourceOutputs,int32_t result)383 void AudioServerHpaeDump::OnDumpSourceOutputsInfoCb(std::vector<HpaeInputOutputInfo> &sourceOutputs, int32_t result)
384 {
385 std::unique_lock<std::mutex> waitLock(callbackMutex_);
386 if (result == SUCCESS) {
387 dumpSourceOutputsInfo_ += "Record Streams\n";
388 AppendFormat(dumpSourceOutputsInfo_, "- %zu Record stream (s) available:\n", sourceOutputs.size());
389 for (auto it = sourceOutputs.begin(); it != sourceOutputs.end(); it++) {
390 HpaeInputOutputInfo info = *it;
391 TransHpaeInputOutputInfoToStr(info, it - sourceOutputs.begin() + 1, dumpSourceOutputsInfo_);
392 }
393 dumpSourceOutputsInfo_ += "\n";
394 }
395 isFinishGetStreamInfo_ = true;
396 AUDIO_INFO_LOG("AudioServerHpaeDump OnDumpSourceOutputsInfoCb result %{public}d", result);
397 callbackCV_.notify_all();
398 }
399 } // namespace AudioStandard
400 } // namespace OHOS
401