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 ¶m : 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 ¶m : 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 }