• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "uc_telemetry_callback.h"
16 
17 #include <chrono>
18 
19 #include "ffrt.h"
20 #include "hisysevent.h"
21 #include "parameter_ex.h"
22 #include "time_util.h"
23 #include "trace_flow_controller.h"
24 #include "hiview_logger.h"
25 #include "string_util.h"
26 #include "common_utils.h"
27 
28 namespace OHOS::HiviewDFX {
29 DEFINE_LOG_TAG("UcTelemetryCallback");
30 using namespace UCollectUtil;
31 namespace {
32 constexpr char TELEMETRY_DOMAIN[] = "TELEMETRY";
33 constexpr char LISTENER_KEY[] = "TelemetryCallback";
34 
OnSaParamChanged(const char * key,const char * value,void * context)35 void OnSaParamChanged(const char *key, const char *value, void *context)
36 {
37     if (key == nullptr || value == nullptr) {
38         HIVIEW_LOGW("invalid input");
39         return;
40     }
41     auto pid = static_cast<pid_t>(StringUtil::StrToInt(value));
42     if (pid < 0) {
43         HIVIEW_LOGW("pid get error");
44         return;
45     }
46     HIVIEW_LOGI("set new pid %{public}d", pid);
47     TraceStateMachine::GetInstance().SetFilterPidInfo(pid);
48 }
49 
HandTimeout()50 void HandTimeout()
51 {
52     // Avoid died lock
53     ffrt::submit([] {
54         TraceStateMachine::GetInstance().CloseTrace(TraceScenario::TRACE_TELEMETRY);
55     });
56 }
57 }
58 
OnTelemetryStart()59 void UcTelemetryCallback::OnTelemetryStart()
60 {
61     HiSysEventWrite(TELEMETRY_DOMAIN, "TASK_INFO", HiSysEvent::EventType::STATISTIC,
62         "ID", telemetryId_,
63         "STAGE", "TRACE_BEGIN");
64     HIVIEW_LOGI("telemetry start");
65 
66     // set app bundle names to kernel
67     if (!appFilterName_.empty()) {
68         int32_t ret = TraceStateMachine::GetInstance().SetAppFilterInfo(appFilterName_);
69         auto pid = CommonUtils::GetPidByName(appFilterName_);
70         HIVIEW_LOGI("set app package:%{public}s ret:%{public}d pid:%{public}d", appFilterName_.c_str(), ret, pid);
71         if (pid > 0) {
72             int32_t pidRet = TraceStateMachine::GetInstance().SetFilterPidInfo(pid);
73             HIVIEW_LOGI("app started ,set app pid:%{public}d ret:%{public}d", pid, pidRet);
74         }
75     }
76     if (saParams_.empty()) {
77         return;
78     }
79 
80     // set sa pids to kernel
81     for (const auto &param : saParams_) {
82         Parameter::WatchParamChange(param.c_str(), OnSaParamChanged, nullptr);
83         auto pid = static_cast<pid_t>(Parameter::GetInteger(param, -1));
84         if (pid < 0) {
85             HIVIEW_LOGE("pid invalid:%{public}s", param.c_str());
86             continue;
87         }
88         if (int32_t ret = TraceStateMachine::GetInstance().SetFilterPidInfo(pid); ret != 0) {
89             HIVIEW_LOGE("SetFilterPidInfo failed %{public}s ret:%{public}d", param.c_str(), ret);
90         }
91     }
92 }
93 
OnTelemetryFinish()94 void UcTelemetryCallback::OnTelemetryFinish()
95 {
96     HIVIEW_LOGI("telemetry finish");
97     HiSysEventWrite(TELEMETRY_DOMAIN, "TASK_INFO", HiSysEvent::EventType::STATISTIC,
98         "ID", telemetryId_,
99         "STAGE", "TRACE_END");
100     if (saParams_.empty()) {
101         return;
102     }
103     for (const auto &param : saParams_) {
104         Parameter::RemoveParameterWatcherEx(param.c_str(), OnSaParamChanged, nullptr);
105     }
106     std::lock_guard<std::mutex> lock(timeMutex_);
107     isTraceOn_ = false;
108 }
109 
UpdateAndCheckTimeOut(int64_t timeCost)110 bool UcTelemetryCallback::UpdateAndCheckTimeOut(int64_t timeCost)
111 {
112     TraceFlowController controller(BusinessName::TELEMETRY);
113     int64_t traceOnTime = 0;
114     if (!controller.QueryRunningTime(traceOnTime) || traceOnTime < 0) {
115         HIVIEW_LOGE("QueryTraceOnTime error");
116         return false;
117     }
118     traceOnTime += timeCost;
119     if (!controller.UpdateRunningTime(traceOnTime)) {
120         HIVIEW_LOGE("UpdateTraceOnTime error");
121         return false;
122     }
123     if (traceOnTime >= traceDuration_) {
124         HIVIEW_LOGI("timeout traceOnTime:%{public}" PRId64 " traceDuration:%{public}" PRId64 "", traceOnTime,
125             traceDuration_);
126         return false;
127     }
128     return true;
129 }
130 
RunTraceOnTimeTask()131 void UcTelemetryCallback::RunTraceOnTimeTask()
132 {
133     while (true) {
134         ffrt::this_task::sleep_for(std::chrono::seconds(60)); // 60s: collect period
135         std::lock_guard<std::mutex> lock(timeMutex_);
136         if (!isTraceOn_) {
137             HIVIEW_LOGE("exit RunTraceOnTime task");
138             isTaskOn_ = false;
139             break;
140         }
141         auto timeCost = TimeUtil::GetBootTimeMs() - traceOnStartTime_;
142         traceOnStartTime_ += timeCost;
143         if (!UpdateAndCheckTimeOut(static_cast<int64_t>(timeCost))) {
144             HandTimeout();
145             HIVIEW_LOGW("telemetry time out, exit RunTraceOnTime task");
146             isTaskOn_ = false;
147             break;
148         }
149     }
150 }
151 
OnTelemetryTraceOn()152 void UcTelemetryCallback::OnTelemetryTraceOn()
153 {
154     HIVIEW_LOGI("trace on");
155     std::lock_guard<std::mutex> lock(timeMutex_);
156     traceOnStartTime_ = TimeUtil::GetBootTimeMs();
157     isTraceOn_ = true;
158     if (isTaskOn_) {
159         HIVIEW_LOGW("old task still running do not need start again");
160         return;
161     }
162 
163     // start new task
164     auto task = [this] { this->RunTraceOnTimeTask(); };
165     ffrt::submit(task, {}, {}, ffrt::task_attr().name("telemetry_trace_on").qos(ffrt::qos_default));
166     isTaskOn_ = true;
167 }
168 
OnTelemetryTraceOff()169 void UcTelemetryCallback::OnTelemetryTraceOff()
170 {
171     HIVIEW_LOGI("trace off");
172     std::lock_guard<std::mutex> lock(timeMutex_);
173     isTraceOn_ = false;
174     auto timeCost = TimeUtil::GetBootTimeMs() - traceOnStartTime_;
175     traceOnStartTime_ += timeCost;
176     if (!UpdateAndCheckTimeOut(static_cast<int64_t>(timeCost))) {
177         HandTimeout();
178     }
179 }
180 
OnTelemetryStart()181 void PowerCallback::OnTelemetryStart()
182 {
183     UcTelemetryCallback::OnTelemetryStart();
184     PowerStatusManager::GetInstance().AddPowerListener(LISTENER_KEY, powerListener_);
185     bool isStatusOn = PowerStatusManager::GetInstance().GetPowerState() == UCollectUtil::SCREEN_ON;
186     TraceStateMachine::GetInstance().InitTelemetryStatus(isStatusOn);
187 }
188 
OnTelemetryFinish()189 void PowerCallback::OnTelemetryFinish()
190 {
191     UcTelemetryCallback::OnTelemetryFinish();
192     PowerStatusManager::GetInstance().RemovePowerListener(LISTENER_KEY);
193 }
194 
OnScreenOn()195 void PowerTelemetryListener::OnScreenOn()
196 {
197     HIVIEW_LOGI("power on");
198     auto ret = TraceStateMachine::GetInstance().PowerTelemetryOn();
199     if (!ret.IsSuccess()) {
200         HIVIEW_LOGW("PowerTelemetryListener failed");
201     }
202 }
203 
OnScreenOff()204 void PowerTelemetryListener::OnScreenOff()
205 {
206     HIVIEW_LOGI("power off");
207     auto ret = TraceStateMachine::GetInstance().PowerTelemetryOff();
208     if (!ret.IsSuccess()) {
209         HIVIEW_LOGW("PowerTelemetryListener failed");
210     }
211 }
212 
OnTelemetryStart()213 void ManualCallback::OnTelemetryStart()
214 {
215     UcTelemetryCallback::OnTelemetryStart();
216     TraceStateMachine::GetInstance().InitTelemetryStatus(false);
217 }
218 }