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