1 /*
2  * Copyright (c) 2024-2024 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     ConcurrentUidSet g_appUidSet{};
29 }
30 
31 const std::map<DfxEventType, DfxEventHandleFunc> DfxAgent::DFX_EVENT_HANDLERS_ = {
32     { DfxEventType::DFX_INFO_PLAYER_VIDEO_LAG, DfxAgent::ProcessVideoLagEvent },
33     { DfxEventType::DFX_INFO_PLAYER_AUDIO_LAG, DfxAgent::ProcessAudioLagEvent },
34     { DfxEventType::DFX_INFO_PLAYER_STREAM_LAG, DfxAgent::ProcessStreamLagEvent },
35     { DfxEventType::DFX_INFO_PLAYER_EOS_SEEK, DfxAgent::ProcessEosSeekEvent },
36 };
37 
38 
DfxAgent(const std::string & groupId,const std::string & appName)39 DfxAgent::DfxAgent(const std::string& groupId, const std::string& appName) : groupId_(groupId), appName_(appName)
40 {
41     dfxTask_ = std::make_unique<Task>("OS_Ply_Dfx", groupId_, TaskType::GLOBAL, TaskPriority::NORMAL, false);
42     MEDIA_LOG_I("DfxAgent create for app " PUBLIC_LOG_S, appName_.c_str());
43 }
44 
~DfxAgent()45 DfxAgent::~DfxAgent()
46 {
47     dfxTask_.reset();
48 }
49 
SetSourceType(PlayerDfxSourceType type)50 void DfxAgent::SetSourceType(PlayerDfxSourceType type)
51 {
52     FALSE_RETURN(dfxTask_ != nullptr);
53     std::weak_ptr<DfxAgent> agent = shared_from_this();
54     dfxTask_->SubmitJobOnce([agent, type] {
55         auto ptr = agent.lock();
56         FALSE_RETURN_MSG(ptr != nullptr, "DfxAgent is released");
57         ptr->sourceType_ = type;
58     });
59 }
60 
SetInstanceId(const std::string & instanceId)61 void DfxAgent::SetInstanceId(const std::string& instanceId)
62 {
63     FALSE_RETURN(dfxTask_ != nullptr);
64     std::weak_ptr<DfxAgent> agent = shared_from_this();
65     dfxTask_->SubmitJobOnce([agent, instanceId] {
66         auto ptr = agent.lock();
67         FALSE_RETURN_MSG(ptr != nullptr, "DfxAgent is released");
68         ptr->instanceId_ = instanceId;
69     });
70 }
71 
OnDfxEvent(const DfxEvent & event)72 void DfxAgent::OnDfxEvent(const DfxEvent &event)
73 {
74     auto ret = DfxAgent::DFX_EVENT_HANDLERS_.find(event.type);
75     FALSE_RETURN(ret != DfxAgent::DFX_EVENT_HANDLERS_.end());
76     FALSE_RETURN(dfxTask_ != nullptr);
77     std::weak_ptr<DfxAgent> agent = shared_from_this();
78     dfxTask_->SubmitJobOnce([agent, event, handler = ret->second] {
79         auto ptr = agent.lock();
80         FALSE_RETURN_MSG(ptr != nullptr, "DfxAgent is released");
81         handler(ptr, event);
82     });
83 }
84 
ReportLagEvent(int64_t lagDuration,const std::string & eventMsg)85 void DfxAgent::ReportLagEvent(int64_t lagDuration, const std::string& eventMsg)
86 {
87     FALSE_RETURN(dfxTask_ != nullptr);
88     std::weak_ptr<DfxAgent> agent = shared_from_this();
89     dfxTask_->SubmitJobOnce([agent, lagDuration, eventMsg] {
90         auto ptr = agent.lock();
91         FALSE_RETURN_MSG(ptr != nullptr, "DfxAgent is released");
92         FALSE_RETURN(!(ptr->hasReported_));
93         std::string msg = eventMsg;
94         MEDIA_LOG_W("PLAYER_LAG event reported, lagDuration=" PUBLIC_LOG_D64 ", msg=" PUBLIC_LOG_S,
95             lagDuration, eventMsg.c_str());
96         HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA,
97             "PLAYER_LAG",
98             OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
99             "APP_NAME", ptr->appName_,
100             "INSTANCE_ID", ptr->instanceId_,
101             "SOURCE_TYPE", static_cast<uint8_t>(ptr->sourceType_),
102             "LAG_DURATION", static_cast<int32_t>(lagDuration),
103             "MSG", msg);
104         ptr->hasReported_ = true;
105     });
106 }
107 
ReportEosSeek0Event(int32_t appUid)108 void DfxAgent::ReportEosSeek0Event(int32_t appUid)
109 {
110     FALSE_RETURN(dfxTask_ != nullptr);
111     dfxTask_->SubmitJobOnce([appUid, appName = appName_] {
112         FALSE_RETURN(g_appUidSet.IsAppFirstEvent(appUid));
113         MEDIA_LOG_I("EOS_SEEK_0 event reported, appName = %{public}s appUid = %{public}d", appName.c_str(), appUid);
114         HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::MULTI_MEDIA,
115             "EOS_SEEK_0",
116             OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
117             "APP_NAME", appName,
118             "APP_UID", appUid);
119     });
120 }
121 
ResetAgent()122 void DfxAgent::ResetAgent()
123 {
124     FALSE_RETURN(dfxTask_ != nullptr);
125     std::weak_ptr<DfxAgent> agent = shared_from_this();
126     dfxTask_->SubmitJobOnce([agent] {
127         auto ptr = agent.lock();
128         FALSE_RETURN_MSG(ptr != nullptr, "DfxAgent is released");
129         ptr->hasReported_ = false;
130     });
131 }
132 
ProcessVideoLagEvent(std::weak_ptr<DfxAgent> ptr,const DfxEvent & event)133 void DfxAgent::ProcessVideoLagEvent(std::weak_ptr<DfxAgent> ptr, const DfxEvent &event)
134 {
135     auto agent = ptr.lock();
136     FALSE_RETURN(agent != nullptr);
137     int64_t lagDuration = AnyCast<int64_t>(event.param);
138     FALSE_RETURN(lagDuration >= LAG_EVENT_THRESHOLD_MS);
139     std::string msg = "lagEvent=Video";
140     agent->ReportLagEvent(lagDuration, msg);
141 }
142 
ProcessAudioLagEvent(std::weak_ptr<DfxAgent> ptr,const DfxEvent & event)143 void DfxAgent::ProcessAudioLagEvent(std::weak_ptr<DfxAgent> ptr, const DfxEvent &event)
144 {
145     auto agent = ptr.lock();
146     FALSE_RETURN(agent != nullptr);
147     int64_t lagDuration = AnyCast<int64_t>(event.param);
148     FALSE_RETURN(lagDuration >= LAG_EVENT_THRESHOLD_MS);
149     std::string msg = "lagEvent=Audio";
150     agent->ReportLagEvent(lagDuration, msg);
151 }
152 
ProcessStreamLagEvent(std::weak_ptr<DfxAgent> ptr,const DfxEvent & event)153 void DfxAgent::ProcessStreamLagEvent(std::weak_ptr<DfxAgent> ptr, const DfxEvent &event)
154 {
155     auto agent = ptr.lock();
156     FALSE_RETURN(agent != nullptr);
157     int64_t lagDuration = AnyCast<int64_t>(event.param);
158     FALSE_RETURN(lagDuration >= LAG_EVENT_THRESHOLD_MS);
159     std::string msg = "lagEvent=Stream";
160     agent->ReportLagEvent(lagDuration, msg);
161 }
162 
ProcessEosSeekEvent(std::weak_ptr<DfxAgent> ptr,const DfxEvent & event)163 void DfxAgent::ProcessEosSeekEvent(std::weak_ptr<DfxAgent> ptr, const DfxEvent &event)
164 {
165     auto agent = ptr.lock();
166     FALSE_RETURN(agent != nullptr);
167     int64_t appUid = AnyCast<int32_t>(event.param);
168     agent->ReportEosSeek0Event(appUid);
169 }
170 }  // namespace Media
171 }  // namespace OHOS