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 #include "event_export_engine.h"
17
18 #include <chrono>
19
20 #include "event_expire_task.h"
21 #include "event_export_task.h"
22 #include "event_export_util.h"
23 #include "ffrt.h"
24 #include "ffrt_util.h"
25 #include "file_util.h"
26 #include "hiview_global.h"
27 #include "hiview_logger.h"
28 #include "parameter_ex.h"
29 #include "setting_observer_manager.h"
30 #include "sys_event_sequence_mgr.h"
31
32 namespace OHOS {
33 namespace HiviewDFX {
34 DEFINE_LOG_TAG("HiView-EventExportFlow");
35 namespace {
36 constexpr int REGISTER_RETRY_CNT = 100;
37 constexpr int REGISTER_LOOP_DURATION = 6;
38
GenerateUuid()39 std::string GenerateUuid()
40 {
41 std::string uuid;
42 int8_t retryTimes = 3; // max retry 3 times
43 do {
44 FileUtil::LoadStringFromFile("/proc/sys/kernel/random/uuid", uuid);
45 if (!uuid.empty()) {
46 break;
47 }
48 --retryTimes;
49 } while (retryTimes > 0);
50
51 if (!uuid.empty() && uuid.back() == '\n') {
52 // remove line breaks at the end
53 uuid.pop_back();
54 }
55 uuid.erase(std::remove(uuid.begin(), uuid.end(), '-'), uuid.end()); // remove character '-'
56 return uuid;
57 }
58
HandleExportSwitchOn(const std::string & moduleName)59 void HandleExportSwitchOn(const std::string& moduleName)
60 {
61 auto& dbMgr = ExportDbManager::GetInstance();
62 if (FileUtil::FileExists(dbMgr.GetEventInheritFlagPath(moduleName))) {
63 // if inherit flag file exists, no need to update export enabled seq
64 return;
65 }
66 auto curEventSeq = EventStore::SysEventSequenceManager::GetInstance().GetSequence();
67 HIVIEW_LOGI("update enabled seq:%{public}" PRId64 " for module %{public}s", curEventSeq, moduleName.c_str());
68 dbMgr.HandleExportSwitchChanged(moduleName, curEventSeq);
69 }
70
HandleExportSwitchOff(const std::string & moduleName)71 void HandleExportSwitchOff(const std::string& moduleName)
72 {
73 auto& dbMgr = ExportDbManager::GetInstance();
74 dbMgr.HandleExportSwitchChanged(moduleName, INVALID_SEQ_VAL);
75 FileUtil::RemoveFile(dbMgr.GetEventInheritFlagPath(moduleName)); // remove inherit flag file if switch changes
76 }
77
RegisterSettingObserver(std::shared_ptr<ExportConfig> config)78 bool RegisterSettingObserver(std::shared_ptr<ExportConfig> config)
79 {
80 SettingObserver::ObserverCallback callback =
81 [&config] (const std::string& paramKey) {
82 std::string val = SettingObserverManager::GetInstance()->GetStringValue(paramKey);
83 HIVIEW_LOGI("value of param key[%{public}s] is %{public}s", paramKey.c_str(), val.c_str());
84 if (val == config->exportSwitchParam.enabledVal) {
85 HandleExportSwitchOn(config->moduleName);
86 } else {
87 HandleExportSwitchOff(config->moduleName);
88 }
89 };
90 bool regRet = false;
91 int retryCount = REGISTER_RETRY_CNT;
92 while (!regRet && retryCount > 0) {
93 regRet = SettingObserverManager::GetInstance()->RegisterObserver(config->exportSwitchParam.name,
94 callback);
95 if (regRet) {
96 break;
97 }
98 retryCount--;
99 ffrt::this_task::sleep_for(std::chrono::seconds(REGISTER_LOOP_DURATION));
100 }
101 if (!regRet) {
102 HIVIEW_LOGW("failed to regist setting db observer for module %{public}s", config->moduleName.c_str());
103 return regRet;
104 }
105 auto& dbMgr = ExportDbManager::GetInstance();
106 if (dbMgr.IsUnrecordedModule(config->moduleName)) { // first time to export event for current module
107 auto upgradeParam = config->sysUpgradeParam;
108 if (!upgradeParam.name.empty() &&
109 SettingObserverManager::GetInstance()->GetStringValue(upgradeParam.name) == upgradeParam.enabledVal) {
110 int64_t startSeq = EventStore::SysEventSequenceManager::GetInstance().GetStartSequence();
111 HIVIEW_LOGI("reset enabled sequence to %{public}" PRId64 " for moudle %{public}s",
112 startSeq, config->moduleName.c_str());
113 dbMgr.HandleExportSwitchChanged(config->moduleName, startSeq);
114 FileUtil::CreateFile(dbMgr.GetEventInheritFlagPath(config->moduleName)); // create inherit flag file
115 }
116 }
117 HIVIEW_LOGI("succeed to regist setting db observer for module %{public}s", config->moduleName.c_str());
118 return regRet;
119 }
120
UnregisterSettingObserver(std::vector<std::shared_ptr<ExportConfig>> & configs)121 void UnregisterSettingObserver(std::vector<std::shared_ptr<ExportConfig>>& configs)
122 {
123 for (auto& config : configs) {
124 SettingObserverManager::GetInstance()->UnregisterObserver(config->exportSwitchParam.name);
125 }
126 }
127 }
128
GetInstance()129 EventExportEngine& EventExportEngine::GetInstance()
130 {
131 static EventExportEngine instance;
132 return instance;
133 }
134
~EventExportEngine()135 EventExportEngine::~EventExportEngine()
136 {
137 std::vector<std::shared_ptr<ExportConfig>> configs;
138 ExportConfigManager::GetInstance().GetAllExportConfigs(configs);
139 UnregisterSettingObserver(configs);
140 }
141
Start()142 void EventExportEngine::Start()
143 {
144 std::lock_guard<std::mutex> lock(mgrMutex_);
145 if (isTaskRunning_) {
146 HIVIEW_LOGW("tasks have been started.");
147 return;
148 }
149 isTaskRunning_ = true;
150 ffrt::submit([this] () {
151 InitAndRunTasks();
152 }, { }, {}, ffrt::task_attr().name("dft_export_start").qos(ffrt::qos_default));
153 }
154
Stop()155 void EventExportEngine::Stop()
156 {
157 std::lock_guard<std::mutex> lock(mgrMutex_);
158 if (!isTaskRunning_) {
159 HIVIEW_LOGW("tasks have been stopped");
160 return;
161 }
162 isTaskRunning_ = false;
163 }
164
SetTaskDelayedSecond(int second)165 void EventExportEngine::SetTaskDelayedSecond(int second)
166 {
167 delayedSecond_ = second;
168 }
169
InitAndRunTasks()170 void EventExportEngine::InitAndRunTasks()
171 {
172 std::vector<std::shared_ptr<ExportConfig>> configs;
173 ExportConfigManager::GetInstance().GetAllExportConfigs(configs);
174 HIVIEW_LOGI("total count of periodic config is %{public}zu", configs.size());
175 for (const auto& config : configs) {
176 auto task = std::bind(&EventExportEngine::InitAndRunTask, this, config);
177 ffrt::submit(task, {}, {}, ffrt::task_attr().name("dft_event_export").qos(ffrt::qos_default));
178 }
179 }
180
InitAndRunTask(std::shared_ptr<ExportConfig> config)181 void EventExportEngine::InitAndRunTask(std::shared_ptr<ExportConfig> config)
182 {
183 // reg setting db observer
184 if (!RegisterSettingObserver(config)) {
185 return;
186 }
187 ffrt::this_task::sleep_for(std::chrono::seconds(delayedSecond_));
188 // init tasks of current config then run them
189 auto expireTask = std::make_shared<EventExpireTask>(config);
190 auto exportTask = std::make_shared<EventExportTask>(config);
191 while (isTaskRunning_) {
192 expireTask->Run();
193 exportTask->Run();
194 if (!EventExportUtil::CheckAndPostExportEvent(config)) {
195 HIVIEW_LOGW("failed to post export event");
196 }
197 // sleep for a task cycle
198 FfrtUtil::Sleep(config->taskCycle);
199 }
200 }
201
InitPackId()202 void EventExportEngine::InitPackId()
203 {
204 if (Parameter::GetUserType() != Parameter::USER_TYPE_OVERSEA_COMMERCIAL) {
205 return;
206 }
207 const std::string packIdProp = "persist.hiviewdfx.priv.packid";
208 if (!Parameter::GetString(packIdProp, "").empty()) {
209 return;
210 }
211 if (std::string packId = GenerateUuid(); packId.empty()) {
212 HIVIEW_LOGW("init packid failed.");
213 } else {
214 HIVIEW_LOGI("init packid success.");
215 Parameter::SetProperty(packIdProp, packId);
216 }
217 }
218 } // HiviewDFX
219 } // OHOS
220