• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "export_json_file_writer.h"
17 
18 #include <chrono>
19 #include <cstdio>
20 #include <tuple>
21 #include <sstream>
22 
23 #include "file_util.h"
24 #include "focused_event_util.h"
25 #include "hiview_global.h"
26 #include "hiview_logger.h"
27 #include "hiview_zip_util.h"
28 #include "parameter.h"
29 #include "parameter_ex.h"
30 #include "string_util.h"
31 #include "time_util.h"
32 
33 namespace OHOS {
34 namespace HiviewDFX {
35 DEFINE_LOG_TAG("HiView-ExportJsonFileWriter");
36 namespace {
37 constexpr int64_t MB_TO_BYTE = 1024 * 1024;
38 constexpr int64_t INVALID_EVENT_SEQ = -1;
39 constexpr char SYSEVENT_EXPORT_TMP_DIR[] = "tmp";
40 constexpr char SYSEVENT_EXPORT_DIR[] = "sys_event_export";
41 constexpr char EXPORT_JSON_FILE_NAME[] = "HiSysEvent.json";
42 constexpr char SYS_EVENT_EXPORT_DIR_NAME[] = "sys_event_export";
43 constexpr char ZIP_FILE_DELIM[] = "_";
44 constexpr char CUR_HEADER_VERSION[] = "1.0";
45 constexpr char H_HEADER_KEY[] = "HEADER";
46 constexpr char H_VERSION_KEY[] = "VERSION";
47 constexpr char H_MSG_ID_KEY[] = "MESSAGE_ID";
48 constexpr char H_MANUFACTURE_KEY[] = "MANUFACTURER";
49 constexpr char H_NAME_KEY[] = "NAME";
50 constexpr char H_BRAND_KEY[] = "BRAND";
51 constexpr char H_DEVICE_KEY[] = "DEVICE";
52 constexpr char H_ID_KEY[] = "ID";
53 constexpr char H_MODEL_KEY[] = "MODEL";
54 constexpr char H_CATEGORY_KEY[] = "CATEGORY";
55 constexpr char H_SYSTEM_KEY[] = "SYSTEM";
56 constexpr char H_OHOS_VER_KEY[] = "OHOS_VER";
57 constexpr char DOMAINS_KEY[] = "DOMAINS";
58 constexpr char DOMAIN_INFO_KEY[] = "DOMAIN_INFO";
59 constexpr char EVENTS_KEY[] = "EVENTS";
60 constexpr char DATA_KEY[] = "DATA";
61 constexpr char DEFAULT_MSG_ID[] = "00000000000000000000000000000000";
62 constexpr mode_t EVENT_EXPORT_DIR_MODE = S_IRWXU | S_IROTH | S_IWOTH | S_IXOTH; // rwx---rwx
63 constexpr mode_t EVENT_EXPORT_FILE_MODE = S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH; // rw----rw-
64 
GenerateDeviceId()65 std::string GenerateDeviceId()
66 {
67     constexpr int32_t deviceIdLength = 65;
68     char id[deviceIdLength] = {0};
69     if (GetDevUdid(id, deviceIdLength) == 0) {
70         return std::string(id);
71     }
72     return "";
73 }
74 
GetDeviceId()75 std::string GetDeviceId()
76 {
77     static std::string deviceId = GenerateDeviceId();
78     return deviceId;
79 }
80 
CreateHeaderJsonObj()81 cJSON* CreateHeaderJsonObj()
82 {
83     cJSON* header = cJSON_CreateObject();
84     if (header == nullptr) {
85         HIVIEW_LOGE("failed to create header json object");
86         return nullptr;
87     }
88     cJSON_AddStringToObject(header, H_VERSION_KEY, CUR_HEADER_VERSION);
89     cJSON_AddStringToObject(header, H_MSG_ID_KEY, DEFAULT_MSG_ID);
90     return header;
91 }
92 
CreateManufacturerJsonObj()93 cJSON* CreateManufacturerJsonObj()
94 {
95     cJSON* manufacturer = cJSON_CreateObject();
96     if (manufacturer == nullptr) {
97         HIVIEW_LOGE("failed to create manufacturer json object");
98         return nullptr;
99     }
100     cJSON_AddStringToObject(manufacturer, H_NAME_KEY, Parameter::GetManufactureStr().c_str());
101     cJSON_AddStringToObject(manufacturer, H_BRAND_KEY, Parameter::GetBrandStr().c_str());
102     return manufacturer;
103 }
104 
CreateDeviceJsonObj()105 cJSON* CreateDeviceJsonObj()
106 {
107     cJSON* device = cJSON_CreateObject();
108     if (device == nullptr) {
109         HIVIEW_LOGE("failed to create device json object");
110         return nullptr;
111     }
112     cJSON_AddStringToObject(device, H_ID_KEY, GetDeviceId().c_str());
113     cJSON_AddStringToObject(device, H_MODEL_KEY, Parameter::GetProductModelStr().c_str());
114     cJSON_AddStringToObject(device, H_NAME_KEY, Parameter::GetMarketNameStr().c_str());
115     cJSON_AddStringToObject(device, H_CATEGORY_KEY, Parameter::GetDeviceTypeStr().c_str());
116     return device;
117 }
118 
CreateSystemObj(const std::string & sysVersion)119 cJSON* CreateSystemObj(const std::string& sysVersion)
120 {
121     cJSON* system = cJSON_CreateObject();
122     if (system == nullptr) {
123         HIVIEW_LOGE("failed to create system json object");
124         return nullptr;
125     }
126     cJSON_AddStringToObject(system, H_VERSION_KEY, sysVersion.c_str());
127     cJSON_AddStringToObject(system, H_OHOS_VER_KEY, Parameter::GetSysVersionDetailsStr().c_str());
128     return system;
129 }
130 
CreateJsonObjectByVersion(const std::string & sysVersion)131 cJSON* CreateJsonObjectByVersion(const std::string& sysVersion)
132 {
133     cJSON* root = cJSON_CreateObject();
134     if (root == nullptr) {
135         HIVIEW_LOGE("failed to create root json object");
136         return nullptr;
137     }
138     // add header
139     auto headerObj = CreateHeaderJsonObj();
140     if (headerObj != nullptr) {
141         cJSON_AddItemToObjectCS(root, H_HEADER_KEY, headerObj);
142     }
143     // add manufacturer
144     auto manufacturerObj = CreateManufacturerJsonObj();
145     if (manufacturerObj != nullptr) {
146         cJSON_AddItemToObjectCS(root, H_MANUFACTURE_KEY, manufacturerObj);
147     }
148     auto deviceObj = CreateDeviceJsonObj();
149     if (deviceObj != nullptr) {
150         cJSON_AddItemToObjectCS(root, H_DEVICE_KEY, deviceObj);
151     }
152     auto systemObj = CreateSystemObj(sysVersion);
153     if (systemObj != nullptr) {
154         cJSON_AddItemToObjectCS(root, H_SYSTEM_KEY, systemObj);
155     }
156     return root;
157 }
158 
CreateEventsJsonArray(const std::string & domain,const std::vector<std::pair<std::string,std::string>> & events)159 cJSON* CreateEventsJsonArray(const std::string& domain,
160     const std::vector<std::pair<std::string, std::string>>& events)
161 {
162     // events
163     cJSON* eventsJsonArray = cJSON_CreateArray();
164     if (eventsJsonArray == nullptr) {
165         HIVIEW_LOGE("failed to create events json array");
166         return nullptr;
167     }
168     cJSON* dataJsonArray = cJSON_CreateArray();
169     if (dataJsonArray == nullptr) {
170         HIVIEW_LOGE("failed to create data json array");
171         return nullptr;
172     }
173     for (const auto& event : events) {
174         cJSON* eventItem = cJSON_Parse(event.second.c_str());
175         if (FocusedEventUtil::IsFocusedEvent(domain, event.first)) {
176             HIVIEW_LOGI("write event to json: [%{public}s|%{public}s]", domain.c_str(),
177                 event.first.c_str());
178         }
179         cJSON_AddItemToArray(dataJsonArray, eventItem);
180     }
181     cJSON* anonymousJsonObj = cJSON_CreateObject();
182     if (anonymousJsonObj == nullptr) {
183         HIVIEW_LOGE("failed to create anonymousJsonObj json object");
184         return nullptr;
185     }
186     cJSON_AddItemToObjectCS(anonymousJsonObj, DATA_KEY, dataJsonArray);
187     cJSON_AddItemToArray(eventsJsonArray, anonymousJsonObj);
188     return eventsJsonArray;
189 }
190 
GetHiSysEventJsonTempDir(const std::string & moduleName,const std::string & version)191 std::string GetHiSysEventJsonTempDir(const std::string& moduleName, const std::string& version)
192 {
193     auto& context = HiviewGlobal::GetInstance();
194     if (context == nullptr) {
195         return "";
196     }
197     std::string tmpDir = context->GetHiViewDirectory(HiviewContext::DirectoryType::WORK_DIRECTORY);
198     tmpDir = FileUtil::IncludeTrailingPathDelimiter(tmpDir.append(SYSEVENT_EXPORT_DIR));
199     tmpDir = FileUtil::IncludeTrailingPathDelimiter(tmpDir.append(SYSEVENT_EXPORT_TMP_DIR));
200     tmpDir = FileUtil::IncludeTrailingPathDelimiter(tmpDir.append(moduleName));
201     tmpDir = FileUtil::IncludeTrailingPathDelimiter(tmpDir.append(version));
202     if (!FileUtil::IsDirectory(tmpDir) && !FileUtil::ForceCreateDirectory(tmpDir)) {
203         HIVIEW_LOGE("failed to init directory %{public}s.", tmpDir.c_str());
204         return "";
205     }
206     return tmpDir;
207 }
208 
ZipDbFile(const std::string & src,const std::string & dest)209 bool ZipDbFile(const std::string& src, const std::string& dest)
210 {
211     HiviewZipUnit zipUnit(dest);
212     if (int32_t ret = zipUnit.AddFileInZip(src, ZipFileLevel::KEEP_NONE_PARENT_PATH); ret != 0) {
213         HIVIEW_LOGW("zip db failed, ret: %{public}d.", ret);
214         return false;
215     }
216     if (bool ret = FileUtil::ChangeModeFile(dest, EVENT_EXPORT_FILE_MODE); !ret) {
217         HIVIEW_LOGE("failed to chmod file %{public}s.", StringUtil::HideDeviceIdInfo(dest).c_str());
218         return false;
219     }
220     // delete json file
221     FileUtil::RemoveFile(src);
222     return true;
223 }
224 
AppendZipFile(std::string & dir)225 void AppendZipFile(std::string& dir)
226 {
227     dir.append("HSE").append(ZIP_FILE_DELIM)
228         .append(Parameter::GetBrandStr()).append(std::string(ZIP_FILE_DELIM))
229         .append(Parameter::GetProductModelStr()).append(std::string(ZIP_FILE_DELIM))
230         .append(Parameter::GetSysVersionStr()).append(std::string(ZIP_FILE_DELIM))
231         .append(GetDeviceId()).append(std::string(ZIP_FILE_DELIM))
232         .append(TimeUtil::GetFormattedTimestampEndWithMilli()).append(std::string(".zip"));
233 }
234 
GetTmpZipFile(const std::string & baseDir,const std::string & moduleName,const std::string & version)235 std::string GetTmpZipFile(const std::string& baseDir, const std::string& moduleName,
236     const std::string& version)
237 {
238     std::string dir = FileUtil::IncludeTrailingPathDelimiter(baseDir);
239     dir = FileUtil::IncludeTrailingPathDelimiter(dir.append(SYSEVENT_EXPORT_TMP_DIR));
240     dir = FileUtil::IncludeTrailingPathDelimiter(dir.append(moduleName));
241     dir = FileUtil::IncludeTrailingPathDelimiter(dir.append(version));
242     if (!FileUtil::IsDirectory(dir) && !FileUtil::ForceCreateDirectory(dir)) {
243         HIVIEW_LOGE("failed to init directory %{public}s.", dir.c_str());
244         return "";
245     }
246     AppendZipFile(dir);
247     return dir;
248 }
249 
GetZipFile(const std::string & baseDir)250 std::string GetZipFile(const std::string& baseDir)
251 {
252     std::string dir = FileUtil::IncludeTrailingPathDelimiter(baseDir);
253     dir = FileUtil::IncludeTrailingPathDelimiter(dir.append(SYS_EVENT_EXPORT_DIR_NAME));
254     if (!FileUtil::IsDirectory(dir) && !FileUtil::ForceCreateDirectory(dir)) {
255         HIVIEW_LOGE("failed to init directory %{public}s.", dir.c_str());
256         return "";
257     }
258     if (!FileUtil::ChangeModeFile(dir, EVENT_EXPORT_DIR_MODE)) {
259         HIVIEW_LOGE("failed to change file mode of %{public}s.", dir.c_str());
260         return "";
261     }
262     AppendZipFile(dir);
263     return dir;
264 }
265 
PersistJsonStrToLocalFile(cJSON * root,const std::string & localFile)266 void PersistJsonStrToLocalFile(cJSON* root, const std::string& localFile)
267 {
268     if (root == nullptr) {
269         HIVIEW_LOGE("root of json is null");
270         return;
271     }
272     char* parsedJsonStr = cJSON_PrintUnformatted(root);
273     if (parsedJsonStr == nullptr) {
274         HIVIEW_LOGE("formatted json str is null");
275         return;
276     }
277     FILE* file = fopen(localFile.c_str(), "w+");
278     if (file == nullptr) {
279         HIVIEW_LOGE("failed to open file: %{public}s.", localFile.c_str());
280         cJSON_free(parsedJsonStr);
281         return;
282     }
283     (void)fprintf(file, "%s", parsedJsonStr);
284     (void)fclose(file);
285     cJSON_free(parsedJsonStr);
286 }
287 }
288 
Write()289 bool ExportJsonFileWriter::Write()
290 {
291     cJSON* root = CreateJsonObjectByVersion(eventVersion_);
292     if (root == nullptr) {
293         return false;
294     }
295     cJSON* domainsJsonArray = cJSON_CreateArray();
296     if (domainsJsonArray == nullptr) {
297         HIVIEW_LOGE("failed to create json array");
298         cJSON_Delete(root);
299         return false;
300     }
301     for (const auto& sysEvent : sysEventMap_) {
302         cJSON* domainJsonObj = cJSON_CreateObject();
303         if (domainJsonObj == nullptr) {
304             continue;
305         }
306         // domain info
307         cJSON* domainInfoJsonObj = cJSON_CreateObject();
308         if (domainInfoJsonObj == nullptr) {
309             HIVIEW_LOGE("failed to create domain info json object");
310             continue;
311         }
312         cJSON_AddStringToObject(domainInfoJsonObj, H_NAME_KEY, sysEvent.first.c_str());
313         cJSON_AddItemToObjectCS(domainJsonObj, DOMAIN_INFO_KEY, domainInfoJsonObj);
314         cJSON* eventsJsonObj = CreateEventsJsonArray(sysEvent.first, sysEvent.second);
315         if (eventsJsonObj == nullptr) {
316             continue;
317         }
318         cJSON_AddItemToObjectCS(domainJsonObj, EVENTS_KEY, eventsJsonObj);
319         cJSON_AddItemToArray(domainsJsonArray, domainJsonObj);
320     }
321     // add domains
322     cJSON_AddItemToObjectCS(root, DOMAINS_KEY, domainsJsonArray);
323     // create export json file HiSysEvent.json
324     auto packagedFile = GetHiSysEventJsonTempDir(moduleName_, eventVersion_).append(EXPORT_JSON_FILE_NAME);
325     HIVIEW_LOGD("packagedFile: %{public}s", packagedFile.c_str());
326     PersistJsonStrToLocalFile(root, packagedFile);
327     cJSON_Delete(root);
328     // zip json file into a temporary zip file
329     auto tmpZipFile = GetTmpZipFile(exportDir_, moduleName_, eventVersion_);
330     if (!ZipDbFile(packagedFile, tmpZipFile)) {
331         HIVIEW_LOGE("failed to zip %{public}s to %{public}s", packagedFile.c_str(),
332             StringUtil::HideDeviceIdInfo(tmpZipFile).c_str());
333         return false;
334     }
335     auto zipFile = GetZipFile(exportDir_);
336     HIVIEW_LOGD("zipFile: %{public}s", StringUtil::HideDeviceIdInfo(zipFile).c_str());
337     if (exportJsonFileZippedListener_ != nullptr) {
338         exportJsonFileZippedListener_(tmpZipFile, zipFile);
339     }
340     totalJsonStrSize_ = 0;
341     sysEventMap_.clear(); // clear cache;
342     return true;
343 }
344 
ExportJsonFileWriter(const std::string & moduleName,const std::string & eventVersion,const std::string & exportDir,int64_t maxFileSize)345 ExportJsonFileWriter::ExportJsonFileWriter(const std::string& moduleName, const std::string& eventVersion,
346     const std::string& exportDir, int64_t maxFileSize)
347 {
348     moduleName_ = moduleName;
349     eventVersion_ = eventVersion;
350     exportDir_ = exportDir;
351     maxFileSize_ = maxFileSize * MB_TO_BYTE;
352 }
353 
SetExportJsonFileZippedListener(ExportJsonFileZippedListener listener)354 void ExportJsonFileWriter::SetExportJsonFileZippedListener(ExportJsonFileZippedListener listener)
355 {
356     exportJsonFileZippedListener_ = listener;
357 }
358 
AppendEvent(const std::string & domain,const std::string & name,const std::string & eventStr)359 bool ExportJsonFileWriter::AppendEvent(const std::string& domain, const std::string& name,
360     const std::string& eventStr)
361 {
362     int64_t eventSize = static_cast<int64_t>(eventStr.size());
363     if (totalJsonStrSize_ + eventSize > maxFileSize_ && !Write()) {
364         HIVIEW_LOGE("failed to write export events");
365         return false;
366     }
367     auto iter = sysEventMap_.find(domain);
368     if (iter == sysEventMap_.end()) {
369         sysEventMap_.emplace(domain, std::vector<std::pair<std::string, std::string>> {
370             std::make_pair(name, eventStr),
371         });
372         totalJsonStrSize_ += eventSize;
373         return true;
374     }
375     iter->second.emplace_back(name, eventStr);
376     totalJsonStrSize_ += eventSize;
377     return true;
378 }
379 
ClearEventCache()380 void ExportJsonFileWriter::ClearEventCache()
381 {
382     sysEventMap_.clear();
383 }
384 } // HiviewDFX
385 } // OHOS