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