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 "setting_observer_manager.h"
27 #include "sys_event_sequence_mgr.h"
28 
29 namespace OHOS {
30 namespace HiviewDFX {
31 DEFINE_LOG_TAG("HiView-EventExportEngine");
32 namespace {
33 constexpr char SYS_EVENT_EXPORT_DIR_NAME[] = "sys_event_export";
34 constexpr int REGISTER_RETRY_CNT = 100;
35 constexpr int REGISTER_LOOP_DURATION = 6;
GetExportDir(HiviewContext::DirectoryType type)36 std::string GetExportDir(HiviewContext::DirectoryType type)
37 {
38     auto& context = HiviewGlobal::GetInstance();
39     if (context == nullptr) {
40         HIVIEW_LOGW("faield to get export directory");
41         return "";
42     }
43     std::string configDir = context->GetHiViewDirectory(type);
44     return FileUtil::IncludeTrailingPathDelimiter(configDir.append(SYS_EVENT_EXPORT_DIR_NAME));
45 }
46 }
47 
GetInstance()48 EventExportEngine& EventExportEngine::GetInstance()
49 {
50     static EventExportEngine instance;
51     return instance;
52 }
53 
EventExportEngine()54 EventExportEngine::EventExportEngine()
55 {
56 }
57 
~EventExportEngine()58 EventExportEngine::~EventExportEngine()
59 {
60     for (auto& config : configs_) {
61         SettingObserverManager::GetInstance()->UnregisterObserver(config->exportSwitchParam.name);
62     }
63 }
64 
Start()65 void EventExportEngine::Start()
66 {
67     std::lock_guard<std::mutex> lock(mgrMutex_);
68     if (isTaskRunning_) {
69         HIVIEW_LOGW("tasks have been started.");
70         return;
71     }
72     isTaskRunning_ = true;
73     auto initTaskHandle = ffrt::submit_h([this] () {
74             Init();
75         }, {}, {}, ffrt::task_attr().name("dft_export_init").qos(ffrt::qos_default));
76     ffrt::submit([this] () {
77             InitAndRunTasks();
78         }, { initTaskHandle }, {}, ffrt::task_attr().name("dft_export_start").qos(ffrt::qos_default));
79 }
80 
Stop()81 void EventExportEngine::Stop()
82 {
83     std::lock_guard<std::mutex> lock(mgrMutex_);
84     if (!isTaskRunning_) {
85         HIVIEW_LOGW("tasks have been stopped");
86         return;
87     }
88     isTaskRunning_ = false;
89     HIVIEW_LOGE("succeed to stop all tasks");
90 }
91 
Init()92 void EventExportEngine::Init()
93 {
94     // init ExportConfigManager
95     std::string configFileStoreDir = GetExportDir(HiviewContext::DirectoryType::CONFIG_DIRECTORY);
96     HIVIEW_LOGI("directory for export config file to store: %{public}s", configFileStoreDir.c_str());
97     ExportConfigManager configMgr(configFileStoreDir);
98 
99     // init ExportDbManager
100     std::string dbStoreDir = GetExportDir(HiviewContext::DirectoryType::WORK_DIRECTORY);
101     HIVIEW_LOGI("directory for export db to store: %{public}s", dbStoreDir.c_str());
102     dbMgr_ = std::make_shared<ExportDbManager>(dbStoreDir);
103 
104     // build tasks for all modules
105     configMgr.GetExportConfigs(configs_);
106     HIVIEW_LOGD("count of configuration: %{public}zu", configs_.size());
107 }
108 
InitAndRunTasks()109 void EventExportEngine::InitAndRunTasks()
110 {
111     HIVIEW_LOGI("total count of module is %{public}zu", configs_.size());
112     for (const auto& config : configs_) {
113         auto task = std::bind(&EventExportEngine::InitAndRunTask, this, config);
114         ffrt::submit(task, {}, {}, ffrt::task_attr().name("dft_event_export").qos(ffrt::qos_default));
115     }
116 }
117 
RegistSettingObserver(std::shared_ptr<ExportConfig> config)118 bool EventExportEngine::RegistSettingObserver(std::shared_ptr<ExportConfig> config)
119 {
120     SettingObserver::ObserverCallback callback =
121         [this, &config] (const std::string& paramKey) {
122             std::string val = SettingObserverManager::GetInstance()->GetStringValue(paramKey);
123             HIVIEW_LOGI("value of param key[%{public}s] is %{public}s", paramKey.c_str(), val.c_str());
124             if (val == config->exportSwitchParam.enabledVal) {
125                 HandleExportSwitchOn(config->moduleName);
126             } else {
127                 HandleExportSwitchOff(config->moduleName);
128             }
129         };
130     bool regRet = false;
131     int retryCount = REGISTER_RETRY_CNT;
132     while (!regRet && retryCount > 0) {
133         regRet = SettingObserverManager::GetInstance()->RegisterObserver(config->exportSwitchParam.name,
134             callback);
135         if (regRet) {
136             break;
137         }
138         retryCount--;
139         ffrt::this_task::sleep_for(std::chrono::seconds(REGISTER_LOOP_DURATION));
140     }
141     if (!regRet) {
142         HIVIEW_LOGW("failed to regist setting db observer for module %{public}s", config->moduleName.c_str());
143         return regRet;
144     }
145     if (dbMgr_->IsUnrecordedModule(config->moduleName)) { // first time to export event for current module
146         auto upgradeParam = config->sysUpgradeParam;
147         if (!upgradeParam.name.empty() &&
148             SettingObserverManager::GetInstance()->GetStringValue(upgradeParam.name) == upgradeParam.enabledVal) {
149             HIVIEW_LOGI("reset enabled sequence to 0 for moudle %{public}s", config->moduleName.c_str());
150             dbMgr_->HandleExportSwitchChanged(config->moduleName, 0);
151         }
152     }
153     HIVIEW_LOGI("succeed to regist setting db observer for module %{public}s", config->moduleName.c_str());
154     return regRet;
155 }
156 
InitAndRunTask(std::shared_ptr<ExportConfig> config)157 void EventExportEngine::InitAndRunTask(std::shared_ptr<ExportConfig> config)
158 {
159     // reg setting db observer
160     auto regRet = RegistSettingObserver(config);
161     if (!regRet) {
162         return;
163     }
164     // init tasks of current config then run them
165     auto expireTask = std::make_shared<EventExpireTask>(config, dbMgr_);
166     auto exportTask = std::make_shared<EventExportTask>(config, dbMgr_);
167     while (isTaskRunning_) {
168         expireTask->Run();
169         exportTask->Run();
170         // sleep for a task cycle
171         ffrt::this_task::sleep_for(exportTask->GetExecutingCycle());
172     }
173 }
174 
HandleExportSwitchOn(const std::string & moduleName)175 void EventExportEngine::HandleExportSwitchOn(const std::string& moduleName)
176 {
177     int64_t enabledSeq = dbMgr_->GetExportEnabledSeq(moduleName);
178     if (enabledSeq == 0) {
179         // expport enabled sequence has been reset to 0, no need to update
180         return;
181     }
182     auto curEventSeq = EventStore::SysEventSequenceManager::GetInstance().GetSequence();
183     HIVIEW_LOGI("update enabled seq:%{public}" PRId64 " for moudle %{public}s", curEventSeq, moduleName.c_str());
184     dbMgr_->HandleExportSwitchChanged(moduleName, curEventSeq);
185 }
186 
HandleExportSwitchOff(const std::string & moduleName)187 void EventExportEngine::HandleExportSwitchOff(const std::string& moduleName)
188 {
189     dbMgr_->HandleExportSwitchChanged(moduleName, INVALID_SEQ_VAL);
190 }
191 } // HiviewDFX
192 } // OHOS