• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_config.h"
17 #include "hilog_wrapper.h"
18 
19 namespace {
20 constexpr const char *SYSTEM_PERIPHERAL_FAULT_NOTIFIER_CONFIG_PATH =
21     "/system/etc/peripheral/peripheral_fault_notifier_config.json";
22 constexpr const char *SYS_PROD_PERIPHERAL_FAULT_NOTIFIER_CONFIG_PATH =
23     "/sys_prod/etc/peripheral/peripheral_fault_notifier_config.json";
24 } // namespace
25 namespace OHOS {
26 namespace ExternalDeviceManager {
27 std::shared_ptr<EventConfig> EventConfig::instance_ = nullptr;
28 std::mutex EventConfig::mutex_;
GetInstance()29 EventConfig &EventConfig::GetInstance()
30 {
31     std::lock_guard<std::mutex> lock(mutex_);
32     if (instance_ == nullptr) {
33         instance_ = std::make_shared<EventConfig>();
34     }
35     return *(instance_.get());
36 }
37 
GetFaultsInfoByDomain(const std::string & domain)38 std::vector<FaultInfo> EventConfig::GetFaultsInfoByDomain(const std::string &domain)
39 {
40     std::vector<FaultInfo> faults;
41     if (peripheralFaultsMap_.find(domain) == peripheralFaultsMap_.end()) {
42         EDM_LOGE(MODULE_SERVICE, "fail to get faults info by domain %{public}s", domain.c_str());
43         return faults;
44     }
45     return peripheralFaultsMap_[domain];
46 }
47 
ExtractFaultInfo(const cJSON * faultItem)48 FaultInfo EventConfig::ExtractFaultInfo(const cJSON *faultItem)
49 {
50     FaultInfo faultInfo;
51     cJSON *nameObj = cJSON_GetObjectItemCaseSensitive(faultItem, "faultName");
52     if (nameObj && cJSON_IsString(nameObj) && (strlen(nameObj->valuestring) > 0)) {
53         faultInfo.faultName = nameObj->valuestring;
54     }
55 
56     cJSON *typeObj = cJSON_GetObjectItemCaseSensitive(faultItem, "type");
57     if (typeObj && cJSON_IsString(typeObj) && (strlen(typeObj->valuestring) > 0)) {
58         faultInfo.type = typeObj->valuestring;
59     }
60 
61     cJSON *titleObj = cJSON_GetObjectItemCaseSensitive(faultItem, "title");
62     if (titleObj && cJSON_IsString(titleObj) && (strlen(titleObj->valuestring) > 0)) {
63         faultInfo.title = titleObj->valuestring;
64     }
65 
66     cJSON *msgObj = cJSON_GetObjectItemCaseSensitive(faultItem, "msg");
67     if (msgObj && cJSON_IsString(msgObj) && (strlen(msgObj->valuestring) > 0)) {
68         faultInfo.msg = msgObj->valuestring;
69     }
70 
71     cJSON *uriObj = cJSON_GetObjectItemCaseSensitive(faultItem, "uri");
72     if (uriObj && cJSON_IsString(uriObj) && (strlen(uriObj->valuestring) > 0)) {
73         faultInfo.uri = uriObj->valuestring;
74     }
75     return faultInfo;
76 }
77 
DeleteJsonObj(cJSON * obj)78 void EventConfig::DeleteJsonObj(cJSON *obj)
79 {
80     if (obj &&!cJSON_IsNull(obj)) {
81         cJSON_Delete(obj);
82         obj = nullptr;
83     }
84 }
85 
ParseJsonFile(const std::string & targetPath,DomainFaultsMap & peripheralFaultMap)86 bool EventConfig::ParseJsonFile(const std::string &targetPath, DomainFaultsMap &peripheralFaultMap)
87 {
88     if (access(targetPath.c_str(), F_OK) != 0) {
89         EDM_LOGE(MODULE_SERVICE, "targetPath %{public}s invalid", targetPath.c_str());
90         return false;
91     }
92 
93     std::ifstream file(targetPath.c_str(), std::ios::in | std::ios::binary);
94     std::string content(std::istreambuf_iterator<char> {file}, std::istreambuf_iterator<char> {});
95     file.close();
96 
97     cJSON *root = cJSON_Parse(content.c_str());
98     if (!root) {
99         EDM_LOGE(MODULE_SERVICE, "%{public}s json parse error.", targetPath.c_str());
100         return false;
101     }
102 
103     if (cJSON_IsNull(root) || !cJSON_IsArray(root)) {
104         EDM_LOGE(MODULE_SERVICE, "%{public}s json root error", targetPath.c_str());
105         DeleteJsonObj(root);
106         return false;
107     }
108 
109     cJSON *item = nullptr;
110     cJSON_ArrayForEach(item, root)
111     {
112         std::string domain;
113         cJSON *domainObj = cJSON_GetObjectItemCaseSensitive(item, "domain");
114         if (!domainObj || !cJSON_IsString(domainObj) || (strlen(domainObj->valuestring) == 0)) {
115             EDM_LOGE(MODULE_SERVICE, "domain %{public}s is invalid.", targetPath.c_str());
116             DeleteJsonObj(root);
117             return false;
118         }
119 
120         domain = domainObj->valuestring;
121         cJSON *faultArray = cJSON_GetObjectItemCaseSensitive(item, "fault");
122         if (!faultArray || cJSON_IsNull(faultArray) || !cJSON_IsArray(faultArray)) {
123             EDM_LOGE(MODULE_SERVICE, "%{public}s faultArray invalid.", targetPath.c_str());
124             DeleteJsonObj(root);
125             return false;
126         }
127 
128         cJSON *faultItem = nullptr;
129         std::vector<FaultInfo> faults;
130         cJSON_ArrayForEach(faultItem, faultArray)
131         {
132             faults.push_back(ExtractFaultInfo(faultItem));
133         }
134 
135         peripheralFaultMap[domain] = faults;
136     }
137 
138     DeleteJsonObj(root);
139     return true;
140 }
141 
FillFaultsMap(const DomainFaultsMap & ccmMap,const DomainFaultsMap & localMap)142 DomainFaultsMap EventConfig::FillFaultsMap(const DomainFaultsMap &ccmMap, const DomainFaultsMap &localMap)
143 {
144     DomainFaultsMap resMap;
145     DomainFaultsMap tempMap(localMap);
146 
147     for (const auto &[domain, ccmFaults] : ccmMap) {
148         auto localIt = tempMap.find(domain);
149         if (localIt == tempMap.end()) {
150             EDM_LOGE(MODULE_SERVICE, "domain %{public}s has been configured in CCMMap but not configured in localMap",
151                 domain.c_str());
152             continue;
153         }
154         const auto& localFaults = localIt->second;
155         std::vector<FaultInfo> matchedFaults;
156         for (const auto& ccmFault : ccmFaults) {
157             auto it = std::find_if(localFaults.begin(), localFaults.end(),
158                 [&ccmFault](const FaultInfo& localFault) {
159                     return localFault.faultName == ccmFault.faultName;
160                 });
161             if (it != localFaults.end()) {
162                 matchedFaults.push_back(*it);
163             } else {
164                 EDM_LOGE(MODULE_SERVICE,
165                     "domain %{public}s and faultName %{public}s has been configured in CCMMap but not configured in "
166                     "localMap",
167                     domain.c_str(), ccmFault.faultName.c_str());
168             }
169         }
170         if (matchedFaults.size() < localFaults.size()) {
171             EDM_LOGE(MODULE_SERVICE, "localConfig has different faults with CCM for domain %{public}s", domain.c_str());
172         }
173         if (!matchedFaults.empty()) {
174             resMap[domain] = std::move(matchedFaults);
175         }
176         tempMap.erase(localIt);
177     }
178     if (!tempMap.empty()) {
179         EDM_LOGE(MODULE_SERVICE, "localMap contains %{public}lu domains that are not present in CCMMap",
180             static_cast<unsigned long>(tempMap.size()));
181     }
182     return resMap;
183 }
184 
ParseJsonFile()185 bool EventConfig::ParseJsonFile()
186 {
187     peripheralFaultsMap_.clear();
188     DomainFaultsMap ccmMap;
189     DomainFaultsMap localMap;
190     bool bRet = ParseJsonFile(SYS_PROD_PERIPHERAL_FAULT_NOTIFIER_CONFIG_PATH, ccmMap);
191     if (!bRet || ccmMap.size() == 0) {
192         EDM_LOGE(MODULE_SERVICE, "Failed to parse the CCM configuration file");
193         return false;
194     }
195     bRet = ParseJsonFile(SYSTEM_PERIPHERAL_FAULT_NOTIFIER_CONFIG_PATH, localMap);
196     if (!bRet || localMap.size() == 0) {
197         EDM_LOGE(MODULE_SERVICE, "Failed to parse the local configuration file");
198         return false;
199     }
200     peripheralFaultsMap_ = FillFaultsMap(ccmMap, localMap);
201     if (peripheralFaultsMap_.empty()) {
202         EDM_LOGE(MODULE_SERVICE, "Failed to ParseJsonFile and peripheralFaultsMap_ is empty");
203         return false;
204     }
205     return true;
206 }
207 
GetFaultInfo(const std::string & domain,const std::string & faultName) const208 FaultInfo EventConfig::GetFaultInfo(const std::string &domain, const std::string &faultName) const
209 {
210     FaultInfo faultInfo;
211     auto it = peripheralFaultsMap_.find(domain);
212     if (it != peripheralFaultsMap_.end()) {
213         for (const auto &fault : it->second) {
214             if (fault.faultName == faultName) {
215                 return fault;
216             }
217         }
218     }
219     return faultInfo;
220 }
221 } // namespace ExternalDeviceManager
222 } // namespace OHOS
223