1 /*
2 * Copyright (c) 2022-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
16 #include <media_dfx.h>
17
18 #include <cstdint>
19 #include <format>
20 #include <unistd.h>
21
22 #include "securec.h"
23 #include "hitrace_meter.h"
24 #include "hitrace/tracechain.h"
25 #include "ipc_skeleton.h"
26 #include "media_utils.h"
27 #include "hitrace/tracechain.h"
28 #include "common/log.h"
29 #include "common/media_core.h"
30 #include "meta/any.h"
31 #include "osal/utils/string_utils.h"
32
33 namespace {
34 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_SYSTEM_PLAYER, "MediaDFX" };
35
36 constexpr uint32_t MAX_STRING_SIZE = 256;
37 constexpr int64_t HOURS_BETWEEN_REPORTS = 4;
38 constexpr int64_t MAX_MAP_SIZE = 100;
39
40 std::mutex collectMut_;
41 std::mutex reportMut_;
42 std::map<OHOS::Media::CallType,
43 std::map<int32_t, std::list<std::pair<uint64_t, std::shared_ptr<OHOS::Media::Meta>>>>> mediaInfoMap_;
44 std::map<OHOS::Media::CallType,
45 std::map<int32_t, std::list<std::pair<uint64_t, std::shared_ptr<OHOS::Media::Meta>>>>> reportMediaInfoMap_;
46 std::map<uint64_t, std::pair<OHOS::Media::CallType, int32_t>> idMap_;
47 std::chrono::system_clock::time_point currentTime_ = std::chrono::system_clock::now();
48 bool g_reachMaxMapSize {false};
49
CollectReportMediaInfo(uint64_t instanceId)50 bool CollectReportMediaInfo(uint64_t instanceId)
51 {
52 OHOS::Media::CallType ct;
53 int32_t uid;
54 std::pair<uint64_t, std::shared_ptr<OHOS::Media::Meta>> metaAppIdPair;
55 {
56 std::lock_guard<std::mutex> lock(collectMut_);
57 MEDIA_LOG_I("CollectReportMediaInfo, instanceId is %{public}" PRIu64, instanceId);
58 auto idMapIt = idMap_.find(instanceId);
59 if (idMapIt == idMap_.end()) {
60 MEDIA_LOG_W("Not found instanceId in idMap, instanceId is : %{public}" PRIu64, instanceId);
61 return false;
62 }
63 ct = idMapIt->second.first;
64 uid = idMapIt->second.second;
65 idMap_.erase(idMapIt);
66 auto ctUidToMediaInfo = mediaInfoMap_.find(ct);
67 if (ctUidToMediaInfo == mediaInfoMap_.end()) {
68 MEDIA_LOG_W("Not found calltype, calltype is : %{public}d", static_cast<OHOS::Media::CallType>(ct));
69 return false;
70 }
71 auto uidToMediaInfo = ctUidToMediaInfo->second.find(uid);
72 if (uidToMediaInfo == ctUidToMediaInfo->second.end()) {
73 MEDIA_LOG_W("Not found uid in mediaInfoMap_, uid is : %{public}" PRId32, uid);
74 return false;
75 }
76 auto& instanceList = uidToMediaInfo->second;
77 for (const auto& instancePair : instanceList) {
78 if (instancePair.first == instanceId) {
79 metaAppIdPair = instancePair;
80 instanceList.remove(instancePair);
81 break;
82 }
83 }
84 }
85 std::lock_guard<std::mutex> lock(reportMut_);
86 auto reportCtUidToMediaInfo = reportMediaInfoMap_.find(ct);
87 if (reportCtUidToMediaInfo != reportMediaInfoMap_.end()) {
88 auto it = reportCtUidToMediaInfo->second.find(uid);
89 if (it != reportCtUidToMediaInfo->second.end()) {
90 it->second.push_back(metaAppIdPair);
91 } else {
92 reportCtUidToMediaInfo->second[uid].push_back(metaAppIdPair);
93 }
94 } else {
95 reportMediaInfoMap_[ct][uid].push_back(metaAppIdPair);
96 }
97 g_reachMaxMapSize = (reportMediaInfoMap_[ct].size() >= MAX_MAP_SIZE);
98 return true;
99 }
100
StatisticsEventReport()101 int32_t StatisticsEventReport()
102 {
103 MEDIA_LOG_I("StatisticsEventReport.");
104 if (reportMediaInfoMap_.empty()) {
105 MEDIA_LOG_I("reportMediaInfoMap_ is empty, can't report");
106 return OHOS::Media::MSERR_INVALID_OPERATION;
107 }
108 OHOS::Media::MediaEvent event;
109 for (const auto &it : reportMediaInfoMap_) {
110 event.CommonStatisicsEventWrite(it.first, OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, it.second);
111 }
112 auto currentTime = std::chrono::system_clock::now();
113 currentTime_ = currentTime;
114 reportMediaInfoMap_.clear();
115 return OHOS::Media::MSERR_OK;
116 }
117 }
118
119 namespace OHOS {
120 namespace Media {
121 using namespace OHOS::HiviewDFX;
CreateMsg(const char * format,...)122 bool MediaEvent::CreateMsg(const char *format, ...)
123 {
124 va_list args;
125 va_start(args, format);
126 char msg[MAX_STRING_SIZE] = {0};
127 auto ret = vsnprintf_s(msg, sizeof(msg), sizeof(msg) - 1, format, args);
128 va_end(args);
129 msg_ = msg;
130 return ret < 0 ? false : true;
131 }
132
EventWrite(std::string eventName,OHOS::HiviewDFX::HiSysEvent::EventType type,std::string module)133 void MediaEvent::EventWrite(std::string eventName, OHOS::HiviewDFX::HiSysEvent::EventType type,
134 std::string module)
135 {
136 int32_t pid = getpid();
137 uint32_t uid = getuid();
138 HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA, eventName, type,
139 "PID", pid,
140 "UID", uid,
141 "MODULE", module,
142 "MSG", msg_);
143 }
144
EventWriteWithAppInfo(std::string eventName,OHOS::HiviewDFX::HiSysEvent::EventType type,std::string module,std::string status,int32_t appUid,int32_t appPid)145 void MediaEvent::EventWriteWithAppInfo(std::string eventName, OHOS::HiviewDFX::HiSysEvent::EventType type,
146 std::string module, std::string status, int32_t appUid, int32_t appPid)
147 {
148 int32_t pid = getpid();
149 uint32_t uid = getuid();
150 HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA, eventName, type,
151 "PID", pid,
152 "UID", uid,
153 "MODULE", module,
154 "MSG", msg_,
155 "APP_PID", appPid,
156 "APP_UID", appUid,
157 "STATUS", status);
158 }
159
EventWriteBundleName(std::string eventName,OHOS::HiviewDFX::HiSysEvent::EventType type,std::string module,std::string status,int32_t appUid,int32_t appPid,std::string bundleName)160 void MediaEvent::EventWriteBundleName(std::string eventName, OHOS::HiviewDFX::HiSysEvent::EventType type,
161 std::string module, std::string status, int32_t appUid, int32_t appPid, std::string bundleName)
162 {
163 int32_t pid = getpid();
164 uint32_t uid = getuid();
165 HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA, eventName, type,
166 "PID", pid,
167 "UID", uid,
168 "MODULE", module,
169 "MSG", msg_,
170 "APP_PID", appPid,
171 "APP_UID", appUid,
172 "STATUS", status,
173 "BUNDLE", bundleName);
174 }
175
SourceEventWrite(const std::string & eventName,OHOS::HiviewDFX::HiSysEvent::EventType type,const std::string & appName,uint64_t instanceId,const std::string & callerType,int8_t sourceType,const std::string & sourceUrl,const std::string & errMsg)176 void MediaEvent::SourceEventWrite(const std::string& eventName, OHOS::HiviewDFX::HiSysEvent::EventType type,
177 const std::string& appName, uint64_t instanceId, const std::string& callerType, int8_t sourceType,
178 const std::string& sourceUrl, const std::string& errMsg)
179 {
180 std::string instanceIdStr = std::to_string(instanceId);
181 HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA, eventName, type,
182 "APP_NAME", appName,
183 "INSTANCE_ID", instanceIdStr,
184 "CALLER_TYPE", callerType,
185 "SOURCE_TYPE", sourceType,
186 "SOURCE_URI", sourceUrl,
187 "ERROR_MESG", errMsg);
188 }
189
ScreenCaptureEventWrite(const std::string & eventName,OHOS::HiviewDFX::HiSysEvent::EventType type,const std::string & appName,uint64_t instanceId,int8_t captureMode,int8_t dataMode,int32_t errorCode,const std::string & errorMessage)190 void MediaEvent::ScreenCaptureEventWrite(const std::string& eventName, OHOS::HiviewDFX::HiSysEvent::EventType type,
191 const std::string& appName, uint64_t instanceId, int8_t captureMode, int8_t dataMode, int32_t errorCode,
192 const std::string& errorMessage)
193 {
194 std::string instanceIdStr = std::to_string(instanceId);
195 HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA, eventName, type,
196 "APP_NAME", appName,
197 "INSTANCE_ID", instanceIdStr,
198 "CAPTURE_MODE", captureMode,
199 "DATA_MODE", dataMode,
200 "ERROR_CODE", errorCode,
201 "ERROR_MESG", errorMessage);
202 }
203
CommonStatisicsEventWrite(CallType callType,OHOS::HiviewDFX::HiSysEvent::EventType type,const std::map<int32_t,std::list<std::pair<uint64_t,std::shared_ptr<Meta>>>> & infoMap)204 void MediaEvent::CommonStatisicsEventWrite(CallType callType, OHOS::HiviewDFX::HiSysEvent::EventType type,
205 const std::map<int32_t, std::list<std::pair<uint64_t, std::shared_ptr<Meta>>>>& infoMap)
206 {
207 MEDIA_LOG_I("MediaEvent::CommonStatisicsEventWrite");
208 if (infoMap.empty()) {
209 MEDIA_LOG_I("Player infoMap is empty.");
210 return;
211 }
212 std::vector<std::string> infoArr;
213 #ifndef CROSS_PLATFORM
214 for (const auto& kv : infoMap) {
215 json jsonArray;
216 json eventInfoJson;
217 json mediaEvents;
218 for (const auto& listPair : kv.second) {
219 json metaInfoJson;
220 ParseOneEvent(listPair, metaInfoJson);
221 mediaEvents.push_back(metaInfoJson);
222 }
223 eventInfoJson["appName"] = GetClientBundleName(kv.first);
224 eventInfoJson["mediaEvents"] = mediaEvents;
225 jsonArray.push_back(eventInfoJson);
226 infoArr.push_back(jsonArray.dump());
227 }
228 #endif
229 StatisicsHiSysEventWrite(callType, type, infoArr);
230 }
231
232 #ifndef CROSS_PLATFORM
ParseOneEvent(const std::pair<uint64_t,std::shared_ptr<OHOS::Media::Meta>> & listPair,json & metaInfoJson)233 void MediaEvent::ParseOneEvent(const std::pair<uint64_t, std::shared_ptr<OHOS::Media::Meta>> &listPair,
234 json& metaInfoJson)
235 {
236 for (auto it = listPair.second->begin(); it != listPair.second->end(); ++it) {
237 Any valueType = OHOS::Media::GetDefaultAnyValue(it->first);
238 if (Any::IsSameTypeWith<int32_t>(valueType)) {
239 int32_t intVal;
240 if (listPair.second->GetData(it->first, intVal)) {
241 metaInfoJson[it->first] = std::to_string(intVal);
242 }
243 } else if (Any::IsSameTypeWith<uint32_t>(valueType)) {
244 uint32_t uintVal;
245 if (listPair.second->GetData(it->first, uintVal)) {
246 metaInfoJson[it->first] = std::to_string(uintVal);
247 }
248 } else if (Any::IsSameTypeWith<uint64_t>(valueType)) {
249 uint64_t uintVal;
250 if (listPair.second->GetData(it->first, uintVal)) {
251 metaInfoJson[it->first] = std::to_string(uintVal);
252 }
253 } else if (Any::IsSameTypeWith<std::string>(valueType)) {
254 metaInfoJson[it->first] = AnyCast<std::string>(it->second);
255 } else if (Any::IsSameTypeWith<int8_t>(valueType)) {
256 int8_t intVal;
257 if (listPair.second->GetData(it->first, intVal)) {
258 metaInfoJson[it->first] = std::to_string(intVal);
259 }
260 } else if (Any::IsSameTypeWith<bool>(valueType)) {
261 bool isTrue;
262 if (listPair.second->GetData(it->first, isTrue)) {
263 metaInfoJson[it->first] = isTrue ? "true" : "false";
264 }
265 } else if (Any::IsSameTypeWith<float>(valueType)) {
266 float floatVal = 0.0f;
267 if (listPair.second->GetData(it->first, floatVal)) {
268 metaInfoJson[it->first] = OSAL::FloatToString(floatVal);
269 }
270 } else {
271 MEDIA_LOG_I("not found type matched with it->first: %{public}s", it->first.c_str());
272 }
273 }
274 }
275 #endif
276
StatisicsHiSysEventWrite(CallType callType,OHOS::HiviewDFX::HiSysEvent::EventType type,const std::vector<std::string> & infoArr)277 void MediaEvent::StatisicsHiSysEventWrite(CallType callType, OHOS::HiviewDFX::HiSysEvent::EventType type,
278 const std::vector<std::string>& infoArr)
279 {
280 MEDIA_LOG_I("MediaEvent::StatisicsHiSysEventWrite");
281 std::string eventName;
282 switch (callType) {
283 case CallType::AVPLAYER:
284 eventName = "PLAYER_COMMON_STATISTICS";
285 break;
286 case CallType::AVRECORDER:
287 eventName = "RECORDER_STATISTICS";
288 break;
289 case CallType::SCREEN_CAPTRUER:
290 eventName = "SCREEN_CAPTURE_STATISTICS";
291 break;
292 case CallType::AVTRANSCODER:
293 eventName = "TRANSCODER_STATISTICS";
294 break;
295 default:
296 return;
297 }
298 HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA, eventName, type,
299 "EVENTS", infoArr);
300 }
301
BehaviorEventWrite(std::string status,std::string module)302 void BehaviorEventWrite(std::string status, std::string module)
303 {
304 MediaEvent event;
305 if (event.CreateMsg("%s, current state is: %s", "state change", status.c_str())) {
306 event.EventWrite("PLAYER_STATE", OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR, module);
307 }
308 }
309
BehaviorEventWriteForScreenCapture(std::string status,std::string module,int32_t appUid,int32_t appPid)310 void BehaviorEventWriteForScreenCapture(std::string status, std::string module, int32_t appUid, int32_t appPid)
311 {
312 MediaEvent event;
313 if (event.CreateMsg("%s, current state is: %s", "state change", status.c_str())) {
314 event.EventWriteWithAppInfo("PLAYER_STATE", OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
315 module, status, appUid, appPid);
316 }
317 }
318
StatisticEventWriteBundleName(std::string status,std::string module)319 void StatisticEventWriteBundleName(std::string status, std::string module)
320 {
321 MediaEvent event;
322 int32_t appUid = IPCSkeleton::GetCallingUid();
323 int32_t appPid = IPCSkeleton::GetCallingPid();
324 std::string bundleName = GetClientBundleName(appUid);
325 if (event.CreateMsg("%s is invoke %s", bundleName.c_str(), module.c_str())) {
326 event.EventWriteBundleName("PLAYER_STATISTICS", OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
327 module, status, appUid, appPid, bundleName);
328 }
329 }
330
FaultEventWrite(std::string msg,std::string module)331 void FaultEventWrite(std::string msg, std::string module)
332 {
333 MediaEvent event;
334 if (event.CreateMsg("%s", msg.c_str())) {
335 event.EventWrite("PLAYER_ERR", OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, module);
336 }
337 }
338
FaultSourceEventWrite(const std::string & appName,uint64_t instanceId,const std::string & callerType,int8_t sourceType,const std::string & sourceUrl,const std::string & errorMessage)339 void FaultSourceEventWrite(const std::string& appName, uint64_t instanceId, const std::string& callerType,
340 int8_t sourceType, const std::string& sourceUrl, const std::string& errorMessage)
341 {
342 MediaEvent event;
343 event.SourceEventWrite("SOURCE_FAILURE", OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, appName, instanceId,
344 callerType, sourceType, sourceUrl, errorMessage);
345 }
346
FaultScreenCaptureEventWrite(const std::string & appName,uint64_t instanceId,int8_t captureMode,int8_t dataMode,int32_t errorCode,const std::string & errorMessage)347 void FaultScreenCaptureEventWrite(const std::string& appName, uint64_t instanceId, int8_t captureMode, int8_t dataMode,
348 int32_t errorCode, const std::string& errorMessage)
349 {
350 MediaEvent event;
351 event.ScreenCaptureEventWrite("SCREEN_CAPTURE_FAILURE", OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, appName,
352 instanceId, captureMode, dataMode, errorCode, errorMessage);
353 }
354
CreateMediaInfo(CallType callType,int32_t uid,uint64_t instanceId)355 int32_t CreateMediaInfo(CallType callType, int32_t uid, uint64_t instanceId)
356 {
357 MEDIA_LOG_I("CreateMediaInfo uid is: %{public}" PRId32 " instanceId is: %{public}" PRIu64, uid, instanceId);
358 std::lock_guard<std::mutex> lock(collectMut_);
359 auto instanceIdMap = idMap_.find(instanceId);
360 if (instanceIdMap != idMap_.end()) {
361 MEDIA_LOG_I("instanceId already exists id idMap_");
362 return MSERR_INVALID_VAL;
363 } else {
364 MEDIA_LOG_I("CreateMediaInfo not found instanceId in idMap_, add the instanceId to idMap_");
365 std::pair<CallType, int32_t> insertToMapPair(callType, uid);
366 idMap_[instanceId] = insertToMapPair;
367 }
368 std::shared_ptr<Meta> meta = std::make_shared<Meta>();
369 std::pair<uint64_t, std::shared_ptr<Meta>> metaAppIdPair(instanceId, meta);
370 auto ctUidToMediaInfo = mediaInfoMap_.find(callType);
371 if (ctUidToMediaInfo != mediaInfoMap_.end()) {
372 auto it = ctUidToMediaInfo->second.find(uid);
373 if (it != ctUidToMediaInfo->second.end()) {
374 it->second.push_back(metaAppIdPair);
375 MEDIA_LOG_I("CreateMediaInfo: Successfully inserted metaAppIdPair for uid ");
376 } else {
377 ctUidToMediaInfo->second[uid].push_back(metaAppIdPair);
378 MEDIA_LOG_I("CreateMediaInfo: Successfully created new list for uid and inserted metaAppIdPair.");
379 }
380 } else {
381 mediaInfoMap_[callType][uid].push_back(metaAppIdPair);
382 MEDIA_LOG_I("CreateMediaInfo: Successfully created new list for callType and uid ");
383 }
384 return MSERR_OK;
385 }
386
AppendMediaInfo(const std::shared_ptr<Meta> & meta,uint64_t instanceId)387 int32_t AppendMediaInfo(const std::shared_ptr<Meta>& meta, uint64_t instanceId)
388 {
389 MEDIA_LOG_I("AppendMediaInfo.");
390 if (meta == nullptr || meta->Empty()) {
391 MEDIA_LOG_I("Insert meta is empty.");
392 return MSERR_INVALID_OPERATION;
393 }
394 std::lock_guard<std::mutex> lock(collectMut_);
395 auto idMapIt = idMap_.find(instanceId);
396 if (idMapIt == idMap_.end()) {
397 MEDIA_LOG_I("Not found instanceId when append meta, instanceId is : %{public}" PRIu64, instanceId);
398 return MSERR_INVALID_VAL;
399 }
400 CallType ct = idMapIt->second.first;
401 int32_t uid = idMapIt->second.second;
402 auto ctUidToMediaInfo = mediaInfoMap_.find(ct);
403 if (ctUidToMediaInfo == mediaInfoMap_.end()) {
404 MEDIA_LOG_I("Not found calltype when append meta, calltype is : %{public}d", static_cast<CallType>(ct));
405 return MSERR_INVALID_OPERATION;
406 }
407 auto it = ctUidToMediaInfo->second.find(uid);
408 if (it == ctUidToMediaInfo->second.end()) {
409 MEDIA_LOG_I("Not found uid when append meta, uid is : %{public}" PRId32, uid);
410 return MSERR_INVALID_OPERATION;
411 }
412 auto& instanceList = it->second;
413 for (const auto& instancePair : instanceList) {
414 if (instancePair.first == instanceId) {
415 auto arg = meta->begin();
416 while (arg != meta->end()) {
417 instancePair.second->SetData(arg->first, arg->second);
418 ++arg;
419 }
420 break;
421 }
422 }
423 return MSERR_OK;
424 }
425
ReportMediaInfo(uint64_t instanceId)426 int32_t ReportMediaInfo(uint64_t instanceId)
427 {
428 MEDIA_LOG_I("Report.");
429 MEDIA_LOG_I("Delete media info instanceId is: %{public}" PRIu64, instanceId);
430 if (!CollectReportMediaInfo(instanceId)) {
431 MEDIA_LOG_I("Collect media info fail.");
432 return MSERR_INVALID_OPERATION;
433 }
434 std::lock_guard<std::mutex> lock(reportMut_);
435 if (g_reachMaxMapSize) {
436 MEDIA_LOG_I("Event data size exceeds 100, report the event");
437 g_reachMaxMapSize = false;
438 return StatisticsEventReport();
439 }
440 auto currentTime = std::chrono::system_clock::now();
441 auto diff = currentTime - currentTime_;
442 auto hour = std::chrono::duration_cast<std::chrono::hours>(diff).count();
443 if (hour >= HOURS_BETWEEN_REPORTS) {
444 MEDIA_LOG_I("Over 4 hours, report the event");
445 return StatisticsEventReport();
446 }
447 return MSERR_OK;
448 }
449
MediaTrace(const std::string & funcName)450 MediaTrace::MediaTrace(const std::string &funcName)
451 {
452 StartTrace(HITRACE_TAG_ZMEDIA, funcName);
453 isSync_ = true;
454 }
455
TraceBegin(const std::string & funcName,int32_t taskId)456 void MediaTrace::TraceBegin(const std::string &funcName, int32_t taskId)
457 {
458 StartAsyncTrace(HITRACE_TAG_ZMEDIA, funcName, taskId);
459 }
460
TraceEnd(const std::string & funcName,int32_t taskId)461 void MediaTrace::TraceEnd(const std::string &funcName, int32_t taskId)
462 {
463 FinishAsyncTrace(HITRACE_TAG_ZMEDIA, funcName, taskId);
464 }
465
CounterTrace(const std::string & varName,int32_t val)466 void MediaTrace::CounterTrace(const std::string &varName, int32_t val)
467 {
468 CountTrace(HITRACE_TAG_ZMEDIA, varName, val);
469 }
470
~MediaTrace()471 MediaTrace::~MediaTrace()
472 {
473 if (isSync_) {
474 FinishTrace(HITRACE_TAG_ZMEDIA);
475 }
476 }
477 } // namespace Media
478 } // namespace OHOS
479