• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-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 #define HST_LOG_TAG "DfxAgent"
17 
18 #include "dfx_agent.h"
19 #include "common/log.h"
20 #include "common/media_source.h"
21 #include "hisysevent.h"
22 
23 namespace OHOS {
24 namespace Media {
25 namespace {
26     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_PLAYER, "DfxAgent" };
27     constexpr int64_t LAG_EVENT_THRESHOLD_MS = 500; // Lag threshold is 500 ms
28     constexpr int64_t LAG_EVENT_UPPER_MS = 5000; // Lag upper threshold is 5000 ms
29     ConcurrentUidSet g_appUidSet{};
30     const std::string SOURCE = "SRC";
31     const std::string DEMUXER = "DEMUX";
32     const std::string VIDEO_SINK = "VSINK";
33     const std::string AUDIO_SINK = "ASINK";
34     const std::string VIDEO_RENDERER = "VRNDR";
35 }
36 
37 const std::map<DfxEventType, DfxEventHandleFunc> DfxAgent::DFX_EVENT_HANDLERS_ = {
38     { DfxEventType::DFX_INFO_PLAYER_VIDEO_LAG, DfxAgent::ProcessVideoLagEvent },
39     { DfxEventType::DFX_INFO_PLAYER_AUDIO_LAG, DfxAgent::ProcessAudioLagEvent },
40     { DfxEventType::DFX_INFO_PLAYER_STREAM_LAG, DfxAgent::ProcessStreamLagEvent },
41     { DfxEventType::DFX_INFO_PLAYER_EOS_SEEK, DfxAgent::ProcessEosSeekEvent },
42     { DfxEventType::DFX_INFO_PERF_REPORT, DfxAgent::ProcessPerfInfoEvent },
43 };
44 
45 const std::unordered_map<std::string, bool> PERF_ITEM_NECESSITY = {
46     { SOURCE, false },
47     { DEMUXER, false },
48     { VIDEO_SINK, true },
49     { AUDIO_SINK, false },
50     { VIDEO_RENDERER, true },
51 };
52 
53 
DfxAgent(const std::string & groupId,const std::string & appName)54 DfxAgent::DfxAgent(const std::string& groupId, const std::string& appName) : groupId_(groupId), appName_(appName)
55 {
56     dfxTask_ = std::make_unique<Task>("OS_Ply_Dfx", groupId_, TaskType::GLOBAL, TaskPriority::NORMAL, false);
57     MEDIA_LOG_I("DfxAgent create for app " PUBLIC_LOG_S, appName_.c_str());
58 }
59 
~DfxAgent()60 DfxAgent::~DfxAgent()
61 {
62     dfxTask_.reset();
63 }
64 
SetSourceType(PlayerDfxSourceType type)65 void DfxAgent::SetSourceType(PlayerDfxSourceType type)
66 {
67     FALSE_RETURN(dfxTask_ != nullptr);
68     std::weak_ptr<DfxAgent> agent = shared_from_this();
69     dfxTask_->SubmitJobOnce([agent, type] {
70         auto ptr = agent.lock();
71         FALSE_RETURN_MSG(ptr != nullptr, "DfxAgent is released");
72         ptr->sourceType_ = type;
73     });
74 }
75 
SetInstanceId(const std::string & instanceId)76 void DfxAgent::SetInstanceId(const std::string& instanceId)
77 {
78     FALSE_RETURN(dfxTask_ != nullptr);
79     std::weak_ptr<DfxAgent> agent = shared_from_this();
80     dfxTask_->SubmitJobOnce([agent, instanceId] {
81         auto ptr = agent.lock();
82         FALSE_RETURN_MSG(ptr != nullptr, "DfxAgent is released");
83         ptr->instanceId_ = instanceId;
84     });
85 }
86 
OnDfxEvent(const DfxEvent & event)87 void DfxAgent::OnDfxEvent(const DfxEvent &event)
88 {
89     auto ret = DfxAgent::DFX_EVENT_HANDLERS_.find(event.type);
90     FALSE_RETURN(ret != DfxAgent::DFX_EVENT_HANDLERS_.end());
91     FALSE_RETURN(dfxTask_ != nullptr);
92     std::weak_ptr<DfxAgent> agent = shared_from_this();
93     dfxTask_->SubmitJobOnce([agent, event, handler = ret->second] {
94         auto ptr = agent.lock();
95         FALSE_RETURN_MSG(ptr != nullptr, "DfxAgent is released");
96         handler(ptr, event);
97     });
98 }
99 
ReportLagEvent(int64_t lagDuration,const std::string & eventMsg)100 void DfxAgent::ReportLagEvent(int64_t lagDuration, const std::string& eventMsg)
101 {
102     FALSE_RETURN(dfxTask_ != nullptr);
103     std::weak_ptr<DfxAgent> agent = shared_from_this();
104     dfxTask_->SubmitJobOnce([agent, lagDuration, eventMsg] {
105         auto ptr = agent.lock();
106         FALSE_RETURN_MSG(ptr != nullptr, "DfxAgent is released");
107         FALSE_RETURN(!(ptr->hasReported_));
108         std::string msg = eventMsg;
109         MEDIA_LOG_W("PLAYER_LAG event reported, lagDuration=" PUBLIC_LOG_D64 ", msg=" PUBLIC_LOG_S,
110             lagDuration, eventMsg.c_str());
111         HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA,
112             "PLAYER_LAG",
113             OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
114             "APP_NAME", ptr->appName_,
115             "INSTANCE_ID", ptr->instanceId_,
116             "SOURCE_TYPE", static_cast<uint8_t>(ptr->sourceType_),
117             "LAG_DURATION", static_cast<int32_t>(lagDuration),
118             "MSG", msg);
119         ptr->hasReported_ = true;
120     });
121 }
122 
ReportEosSeek0Event(int32_t appUid)123 void DfxAgent::ReportEosSeek0Event(int32_t appUid)
124 {
125     FALSE_RETURN(dfxTask_ != nullptr);
126     dfxTask_->SubmitJobOnce([appUid, appName = appName_] {
127         FALSE_RETURN(g_appUidSet.IsAppFirstEvent(appUid));
128         MEDIA_LOG_I("EOS_SEEK_0 event reported, appName = %{public}s appUid = %{public}d", appName.c_str(), appUid);
129         HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA,
130             "EOS_SEEK_0",
131             OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
132             "APP_NAME", appName,
133             "APP_UID", appUid);
134     });
135 }
136 
ResetAgent()137 void DfxAgent::ResetAgent()
138 {
139     FALSE_RETURN(dfxTask_ != nullptr);
140     std::weak_ptr<DfxAgent> agent = shared_from_this();
141     dfxTask_->SubmitJobOnce([agent] {
142         auto ptr = agent.lock();
143         FALSE_RETURN_MSG(ptr != nullptr, "DfxAgent is released");
144         ptr->hasReported_ = false;
145     });
146 }
147 
ProcessVideoLagEvent(std::weak_ptr<DfxAgent> ptr,const DfxEvent & event)148 void DfxAgent::ProcessVideoLagEvent(std::weak_ptr<DfxAgent> ptr, const DfxEvent &event)
149 {
150     auto agent = ptr.lock();
151     FALSE_RETURN(agent != nullptr);
152     auto perfStr = agent->GetPerfStr(false);
153     MEDIA_LOG_W("%{public}s", perfStr.c_str());
154     agent->needPrintPerfLog_ = true;
155     int64_t lagDuration = AnyCast<int64_t>(event.param);
156     FALSE_RETURN(lagDuration >= LAG_EVENT_THRESHOLD_MS && lagDuration <= LAG_EVENT_UPPER_MS);
157     std::string msg = "lagEvent=Video ";
158     agent->ReportLagEvent(lagDuration, msg + perfStr);
159 }
160 
ProcessAudioLagEvent(std::weak_ptr<DfxAgent> ptr,const DfxEvent & event)161 void DfxAgent::ProcessAudioLagEvent(std::weak_ptr<DfxAgent> ptr, const DfxEvent &event)
162 {
163     auto agent = ptr.lock();
164     FALSE_RETURN(agent != nullptr);
165     int64_t lagDuration = AnyCast<int64_t>(event.param);
166     FALSE_RETURN(lagDuration >= LAG_EVENT_THRESHOLD_MS);
167     std::string msg = "lagEvent=Audio";
168     agent->ReportLagEvent(lagDuration, msg);
169 }
170 
ProcessStreamLagEvent(std::weak_ptr<DfxAgent> ptr,const DfxEvent & event)171 void DfxAgent::ProcessStreamLagEvent(std::weak_ptr<DfxAgent> ptr, const DfxEvent &event)
172 {
173     auto agent = ptr.lock();
174     FALSE_RETURN(agent != nullptr);
175     int64_t lagDuration = AnyCast<int64_t>(event.param);
176     FALSE_RETURN(lagDuration >= LAG_EVENT_THRESHOLD_MS);
177     std::string msg = "lagEvent=Stream";
178     agent->ReportLagEvent(lagDuration, msg);
179 }
180 
ProcessEosSeekEvent(std::weak_ptr<DfxAgent> ptr,const DfxEvent & event)181 void DfxAgent::ProcessEosSeekEvent(std::weak_ptr<DfxAgent> ptr, const DfxEvent &event)
182 {
183     auto agent = ptr.lock();
184     FALSE_RETURN(agent != nullptr);
185     int64_t appUid = AnyCast<int32_t>(event.param);
186     agent->ReportEosSeek0Event(appUid);
187 }
188 
ProcessPerfInfoEvent(std::weak_ptr<DfxAgent> ptr,const DfxEvent & event)189 void DfxAgent::ProcessPerfInfoEvent(std::weak_ptr<DfxAgent> ptr, const DfxEvent &event)
190 {
191     auto agent = ptr.lock();
192     FALSE_RETURN(agent != nullptr);
193     agent->UpdateDfxInfo(event);
194 }
195 
UpdateDfxInfo(const DfxEvent & event)196 void DfxAgent::UpdateDfxInfo(const DfxEvent &event)
197 {
198     auto data = AnyCast<MainPerfData>(event.param);
199     perfDataMap_.insert_or_assign(event.callerName, data);
200     FALSE_RETURN_NOLOG(needPrintPerfLog_);
201     MEDIA_LOG_W("%{public}s", GetPerfStr(true).c_str());
202 }
203 
GetPerfStr(const bool needWaitAllData)204 std::string DfxAgent::GetPerfStr(const bool needWaitAllData)
205 {
206     bool isAllDataReady = true;
207     std::string waitFor = "not all ready, wait for";
208     std::string perfStr = needPrintPerfLog_ ? "AfterLag\n" : "Lag\n";
209     for (auto it = PERF_ITEM_NECESSITY.begin(); it != PERF_ITEM_NECESSITY.end(); ++it) {
210         auto dataMapIt = perfDataMap_.find(it->first);
211         if (dataMapIt != perfDataMap_.end()) {
212             perfStr += "[" + it->first + " speed] max " + std::to_string(dataMapIt->second.max) + " min " +
213                 std::to_string(dataMapIt->second.min) + " avg " + std::to_string(dataMapIt->second.avg) + "\n";
214         } else if (!it->second) {
215             perfStr += "not enough data, but " + it->first + " is not bottleneck\n";
216         } else {
217             waitFor += " " + it->first;
218             isAllDataReady = false;
219         }
220     }
221     if (isAllDataReady) {
222         perfDataMap_.clear();
223     }
224     needPrintPerfLog_ = !isAllDataReady;
225     return (!isAllDataReady && needWaitAllData) ? waitFor : perfStr;
226 }
227 }  // namespace Media
228 }  // namespace OHOS