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