1 /*
2 * Copyright (c) 2021-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_json_parser.h"
17
18 #include <cctype>
19 #include <cinttypes>
20 #include <fstream>
21 #include <map>
22
23 #include "hiview_config_util.h"
24 #include "hiview_logger.h"
25 #include "parameter_ex.h"
26 #include "privacy_manager.h"
27
28 namespace OHOS {
29 namespace HiviewDFX {
30 namespace {
31 DEFINE_LOG_TAG("Event-JsonParser");
32
33 constexpr char BASE[] = "__BASE";
34 constexpr char LEVEL[] = "level";
35 constexpr char TAG[] = "tag";
36 constexpr char TYPE[] = "type";
37 constexpr char PRIVACY[] = "privacy";
38 constexpr char PRESERVE[] = "preserve";
39 constexpr char COLLECT[] = "collect";
40 const std::map<std::string, uint8_t> EVENT_TYPE_MAP = {
41 {"FAULT", 1}, {"STATISTIC", 2}, {"SECURITY", 3}, {"BEHAVIOR", 4}
42 };
43
ReadSysEventDefFromFile(const std::string & path,Json::Value & hiSysEventDef)44 bool ReadSysEventDefFromFile(const std::string& path, Json::Value& hiSysEventDef)
45 {
46 std::ifstream fin(path, std::ifstream::binary);
47 if (!fin.is_open()) {
48 HIVIEW_LOGW("failed to open file, path: %{public}s.", path.c_str());
49 return false;
50 }
51 Json::CharReaderBuilder jsonRBuilder;
52 Json::CharReaderBuilder::strictMode(&jsonRBuilder.settings_);
53 JSONCPP_STRING errs;
54 return parseFromStream(jsonRBuilder, fin, &hiSysEventDef, &errs);
55 }
56
AddEventToExportList(ExportEventList & list,const std::string & domain,const std::string & name,const BaseInfo & baseInfo)57 void AddEventToExportList(ExportEventList& list, const std::string& domain, const std::string& name,
58 const BaseInfo& baseInfo)
59 {
60 if (baseInfo.keyConfig.preserve != DEFAULT_PERSERVE_VAL || baseInfo.keyConfig.collect == DEFAULT_COLLECT_VAL) {
61 return;
62 }
63 auto foundRet = list.find(domain);
64 if (foundRet == list.end()) {
65 list.emplace(domain, std::vector<std::string> { name });
66 return;
67 }
68 foundRet->second.emplace_back(name);
69 }
70 }
71
EventJsonParser()72 EventJsonParser::EventJsonParser()
73 {
74 }
75
~EventJsonParser()76 EventJsonParser::~EventJsonParser()
77 {
78 }
79
GetTagByDomainAndName(const std::string & domain,const std::string & name)80 std::string EventJsonParser::GetTagByDomainAndName(const std::string& domain, const std::string& name)
81 {
82 return GetDefinedBaseInfoByDomainName(domain, name).tag;
83 }
84
GetTypeByDomainAndName(const std::string & domain,const std::string & name)85 uint8_t EventJsonParser::GetTypeByDomainAndName(const std::string& domain, const std::string& name)
86 {
87 return GetDefinedBaseInfoByDomainName(domain, name).keyConfig.type;
88 }
89
GetPreserveByDomainAndName(const std::string & domain,const std::string & name)90 bool EventJsonParser::GetPreserveByDomainAndName(const std::string& domain, const std::string& name)
91 {
92 return GetDefinedBaseInfoByDomainName(domain, name).keyConfig.preserve;
93 }
94
GetDefinedBaseInfoByDomainName(const std::string & domain,const std::string & name)95 BaseInfo EventJsonParser::GetDefinedBaseInfoByDomainName(const std::string& domain, const std::string& name)
96 {
97 std::unique_lock<ffrt::mutex> uniqueLock(defMtx_);
98 if (sysEventDefMap_ == nullptr) {
99 HIVIEW_LOGD("sys def map is null");
100 return BaseInfo();
101 }
102 auto domainIter = sysEventDefMap_->find(domain);
103 if (domainIter == sysEventDefMap_->end()) {
104 HIVIEW_LOGD("domain %{public}s is not defined.", domain.c_str());
105 return BaseInfo();
106 }
107 auto domainNames = sysEventDefMap_->at(domain);
108 auto nameIter = domainNames.find(name);
109 if (nameIter == domainNames.end()) {
110 HIVIEW_LOGD("%{public}s is not defined in domain %{public}s, or privacy not allowed.",
111 name.c_str(), domain.c_str());
112 return BaseInfo();
113 }
114 return nameIter->second;
115 }
116
HasUIntMember(const Json::Value & jsonObj,const std::string & name) const117 bool EventJsonParser::HasUIntMember(const Json::Value& jsonObj, const std::string& name) const
118 {
119 return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isUInt();
120 }
121
HasStringMember(const Json::Value & jsonObj,const std::string & name) const122 bool EventJsonParser::HasStringMember(const Json::Value& jsonObj, const std::string& name) const
123 {
124 return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isString();
125 }
126
HasBoolMember(const Json::Value & jsonObj,const std::string & name) const127 bool EventJsonParser::HasBoolMember(const Json::Value& jsonObj, const std::string& name) const
128 {
129 return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isBool();
130 }
131
InitEventInfoMapRef(const Json::Value & eventJson,JSON_VALUE_LOOP_HANDLER handler) const132 void EventJsonParser::InitEventInfoMapRef(const Json::Value& eventJson, JSON_VALUE_LOOP_HANDLER handler) const
133 {
134 if (!eventJson.isObject()) {
135 return;
136 }
137 auto attrList = eventJson.getMemberNames();
138 for (auto it = attrList.cbegin(); it != attrList.cend(); it++) {
139 std::string key = *it;
140 if (key.empty()) {
141 continue;
142 }
143 if (handler != nullptr) {
144 handler(key, eventJson[key]);
145 }
146 }
147 }
148
ParseBaseConfig(const Json::Value & eventNameJson) const149 BaseInfo EventJsonParser::ParseBaseConfig(const Json::Value& eventNameJson) const
150 {
151 BaseInfo baseInfo;
152 if (!eventNameJson.isObject() || !eventNameJson[BASE].isObject()) {
153 HIVIEW_LOGD("__BASE definition is invalid.");
154 return baseInfo;
155 }
156
157 Json::Value baseJsonInfo = eventNameJson[BASE];
158 if (!baseJsonInfo.isObject() || !HasStringMember(baseJsonInfo, TYPE)) {
159 HIVIEW_LOGD("type is not defined in __BASE.");
160 return baseInfo;
161 }
162 std::string typeDes = baseJsonInfo[TYPE].asString();
163 if (EVENT_TYPE_MAP.find(typeDes) == EVENT_TYPE_MAP.end()) {
164 HIVIEW_LOGD("type is defined as %{public}s, but a valid type must be FAULT, STATISTIC, SECURITY, or BEHAVIOR",
165 typeDes.c_str());
166 return baseInfo;
167 }
168 baseInfo.keyConfig.type = EVENT_TYPE_MAP.at(typeDes);
169
170 if (!HasStringMember(baseJsonInfo, LEVEL)) {
171 HIVIEW_LOGD("level is not defined in __BASE.");
172 return baseInfo;
173 }
174 baseInfo.level = baseJsonInfo[LEVEL].asString();
175
176 if (HasStringMember(baseJsonInfo, TAG)) {
177 baseInfo.tag = baseJsonInfo[TAG].asString();
178 }
179
180 if (HasUIntMember(baseJsonInfo, PRIVACY)) {
181 baseInfo.keyConfig.privacy = static_cast<uint8_t>(baseJsonInfo[PRIVACY].asUInt());
182 }
183
184 if (HasBoolMember(baseJsonInfo, PRESERVE)) {
185 baseInfo.keyConfig.preserve = baseJsonInfo[PRESERVE].asBool() ? 1 : 0;
186 }
187
188 if (HasBoolMember(baseJsonInfo, COLLECT)) {
189 baseInfo.keyConfig.collect = baseJsonInfo[COLLECT].asBool() ? 1 : 0;
190 }
191
192 return baseInfo;
193 }
194
ParseSysEventDef(const Json::Value & hiSysEventDef,std::shared_ptr<DOMAIN_INFO_MAP> sysDefMap)195 void EventJsonParser::ParseSysEventDef(const Json::Value& hiSysEventDef, std::shared_ptr<DOMAIN_INFO_MAP> sysDefMap)
196 {
197 InitEventInfoMapRef(hiSysEventDef, [this, sysDefMap] (const std::string& domain, const Json::Value& value) {
198 sysDefMap->insert(std::make_pair(domain, this->ParseEventNameConfig(domain, value)));
199 });
200 }
201
ParseEventNameConfig(const std::string & domain,const Json::Value & domainJson) const202 NAME_INFO_MAP EventJsonParser::ParseEventNameConfig(const std::string& domain, const Json::Value& domainJson) const
203 {
204 NAME_INFO_MAP allNames;
205 InitEventInfoMapRef(domainJson,
206 [this, &domain, &allNames] (const std::string& eventName, const Json::Value& eventContent) {
207 BaseInfo baseInfo = ParseBaseConfig(eventContent);
208 if (PrivacyManager::IsAllowed(domain, baseInfo.keyConfig.type, baseInfo.level, baseInfo.keyConfig.privacy)) {
209 baseInfo.disallowParams = ParseEventParamInfo(eventContent);
210 allNames[eventName] = baseInfo;
211 } else {
212 HIVIEW_LOGD("not allowed event: %{public}s | %{public}s", domain.c_str(), eventName.c_str());
213 }
214 });
215 return allNames;
216 }
217
ParseEventParamInfo(const Json::Value & eventContent) const218 PARAM_INFO_MAP_PTR EventJsonParser::ParseEventParamInfo(const Json::Value& eventContent) const
219 {
220 PARAM_INFO_MAP_PTR paramMaps = nullptr;
221 auto attrList = eventContent.getMemberNames();
222 if (attrList.empty()) {
223 return paramMaps;
224 }
225 for (const auto& paramName : attrList) {
226 if (paramName.empty() || paramName == BASE) {
227 // skip the definition of event, only care about the params
228 continue;
229 }
230 Json::Value paramContent = eventContent[paramName];
231 if (!paramContent.isObject()) {
232 continue;
233 }
234 if (!HasUIntMember(paramContent, PRIVACY)) {
235 // no privacy configured for this param, follow the event
236 continue;
237 }
238 uint8_t privacy = static_cast<uint8_t>(paramContent[PRIVACY].asUInt());
239 if (PrivacyManager::IsPrivacyAllowed(privacy)) {
240 // the privacy level of param is ok, no need to be recorded
241 continue;
242 }
243 if (paramMaps == nullptr) {
244 // if all params meet the privacy, no need to create the param instance
245 paramMaps = std::make_shared<std::map<std::string, std::shared_ptr<EventParamInfo>>>();
246 }
247 std::shared_ptr<EventParamInfo> paramInfo = nullptr;
248 if (Parameter::IsOversea() &&
249 HasStringMember(paramContent, "allowlist") && HasUIntMember(paramContent, "throwtype")) {
250 std::string allowListFile = paramContent["allowlist"].asString();
251 uint8_t throwType = static_cast<uint8_t>(paramContent["throwtype"].asUInt());
252 paramInfo = std::make_shared<EventParamInfo>(allowListFile, throwType);
253 }
254 paramMaps->insert(std::make_pair(paramName, paramInfo));
255 }
256 return paramMaps;
257 }
258
ReadDefFile()259 void EventJsonParser::ReadDefFile()
260 {
261 auto defFilePath = HiViewConfigUtil::GetConfigFilePath("hisysevent.zip", "sys_event_def", "hisysevent.def");
262 HIVIEW_LOGI("read event def file path: %{public}s", defFilePath.c_str());
263 Json::Value hiSysEventDef;
264 if (!ReadSysEventDefFromFile(defFilePath, hiSysEventDef)) {
265 HIVIEW_LOGE("parse json file failed, please check the style of json file: %{public}s", defFilePath.c_str());
266 return;
267 }
268
269 std::unique_lock<ffrt::mutex> uniqueLock(defMtx_);
270 if (sysEventDefMap_ == nullptr) {
271 sysEventDefMap_ = std::make_shared<DOMAIN_INFO_MAP>();
272 } else {
273 sysEventDefMap_->clear();
274 }
275 ParseSysEventDef(hiSysEventDef, sysEventDefMap_);
276 }
277
OnConfigUpdate()278 void EventJsonParser::OnConfigUpdate()
279 {
280 // update privacy at first, because event define file depends on privacy config
281 PrivacyManager::OnConfigUpdate();
282 ReadDefFile();
283 }
284
GetAllCollectEvents(ExportEventList & list)285 void EventJsonParser::GetAllCollectEvents(ExportEventList& list)
286 {
287 std::unique_lock<ffrt::mutex> uniqueLock(defMtx_);
288 if (sysEventDefMap_ == nullptr) {
289 return;
290 }
291 for (auto iter = sysEventDefMap_->cbegin(); iter != sysEventDefMap_->cend(); ++iter) {
292 for (const auto& eventDef : iter->second) {
293 AddEventToExportList(list, iter->first, eventDef.first, eventDef.second);
294 }
295 }
296 }
297 } // namespace HiviewDFX
298 } // namespace OHOS
299