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 #include <cstdlib>
16 #include <string>
17 #include <climits>
18 
19 #include "config_reader.h"
20 #include "config_policy_utils.h"
21 #include "concurrent_task_log.h"
22 #include "parameters.h"
23 
24 using namespace std;
25 
26 namespace OHOS {
27 namespace ConcurrentTask {
28 namespace {
29     const std::string XML_TAG_QOS_CONFIG = "qosconfig";
30     const std::string XML_TAG_QOS_AUTH = "auth";
31     const std::string XML_TAG_UIDLIST = "uidlist";
32     const std::string XML_TAG_UID = "uid";
33     const std::string XML_TAG_BUNDLENAMELIST = "bundlenamelist";
34     const std::string XML_TAG_BUNDLENAME = "bundlename";
35     const std::string XML_TAG_POWER_MODE = "powermode";
36     const std::string XML_TAG_SWITCH = "switch";
37     const std::string XML_TAG_FPS = "fps";
38     const std::string XML_TAG_DEGRADATION_FPS = "degradationfps";
39 }
40 
IsValidNode(const xmlNode * currNode)41 bool ConfigReader::IsValidNode(const xmlNode* currNode)
42 {
43     if (!currNode) {
44         return false;
45     }
46     if (!currNode->name || currNode->type == XML_COMMENT_NODE) {
47         return false;
48     }
49     return true;
50 }
51 
FillinUidInfo(const xmlNode * currNode)52 bool ConfigReader::FillinUidInfo(const xmlNode* currNode)
53 {
54     if (!IsValidNode(currNode)) {
55         CONCUR_LOGE("FillinUidInfo:: currNode is nullptr!");
56         return false;
57     }
58     xmlNodePtr currNodePtr = currNode->xmlChildrenNode;
59     for (; currNodePtr; currNodePtr = currNodePtr->next) {
60         if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_UID.c_str())) == 0) {
61             xmlChar *attrValue = xmlGetProp(currNodePtr, reinterpret_cast<const xmlChar*>(XML_TAG_UID.c_str()));
62             if (!attrValue) {
63                 CONCUR_LOGE("FillinUidInfo:: uid null!");
64                 return false;
65             }
66             int64_t uid = atoi(reinterpret_cast<const char*>(attrValue));
67             authProcUidConfigs_.insert(uid);
68             xmlFree(attrValue);
69         }
70     }
71     return true;
72 }
73 
FillinBundleNameInfo(const xmlNode * currNode)74 bool ConfigReader::FillinBundleNameInfo(const xmlNode* currNode)
75 {
76     if (!IsValidNode(currNode)) {
77         CONCUR_LOGE("FillinBundleNameInfo:: currNode is nullptr!");
78         return false;
79     }
80     xmlNodePtr currNodePtr = currNode->xmlChildrenNode;
81     for (; currNodePtr; currNodePtr = currNodePtr->next) {
82         if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_BUNDLENAME.c_str())) == 0) {
83             xmlChar *attrValue = xmlGetProp(currNodePtr, reinterpret_cast<const xmlChar*>(XML_TAG_BUNDLENAME.c_str()));
84             if (!attrValue) {
85                 CONCUR_LOGE("FillinBundleNameInfo:: bundleName null!");
86                 return false;
87             }
88             std::string bundleName = reinterpret_cast<const char*>(attrValue);
89             authProcBundleNameConfigs_.insert(bundleName);
90             xmlFree(attrValue);
91         }
92     }
93     return true;
94 }
95 
ParseAuth(const xmlNode * currNode)96 void ConfigReader::ParseAuth(const xmlNode* currNode)
97 {
98     xmlNodePtr currNodePtr = currNode->xmlChildrenNode;
99     for (; currNodePtr; currNodePtr = currNodePtr->next) {
100         if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_UIDLIST.c_str())) == 0) {
101             if (!FillinUidInfo(currNodePtr)) {
102                 CONCUR_LOGE("ParseAuth:: uid fill in authProcUidConfigs_ error!");
103                 continue;
104             }
105         }
106 
107         if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_BUNDLENAMELIST.c_str())) == 0) {
108             if (!FillinBundleNameInfo(currNodePtr)) {
109                 CONCUR_LOGE("ParseAuth:: bundleName fill in authProcBundleNameConfigs_ error!");
110                 continue;
111             }
112         }
113     }
114 }
115 
ParsePowerMode(const xmlNode * currNode)116 void ConfigReader::ParsePowerMode(const xmlNode* currNode)
117 {
118     if (!IsValidNode(currNode)) {
119         CONCUR_LOGE("ParsePowerMode:: currNode is nullptr!");
120         return;
121     }
122     xmlNodePtr currNodePtr = currNode->xmlChildrenNode;
123     for (; currNodePtr; currNodePtr = currNodePtr->next) {
124         if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_SWITCH.c_str())) == 0) {
125             char* switchValue = reinterpret_cast<char*>(xmlNodeGetContent(currNode));
126             if (!switchValue) {
127                 CONCUR_LOGE("ParsePowerMode:: switch is null!");
128                 continue;
129             }
130             if (strcmp(switchValue, "1") == 0) {
131                 powerModeSchedSwitch_ = true;
132             } else if (strcmp(switchValue, "0") == 0) {
133                 powerModeSchedSwitch_ = false;
134             } else {
135                 CONCUR_LOGE("ParsePowerMode:: invalid switch value!");
136             }
137             xmlFree(switchValue);
138         }
139 
140         if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_DEGRADATION_FPS.c_str())) == 0) {
141             char* fpsValue = reinterpret_cast<char*>(xmlGetProp(currNodePtr,
142                 reinterpret_cast<const xmlChar*>(XML_TAG_FPS.c_str())));
143             char* deFpsValue = reinterpret_cast<char*>(xmlNodeGetContent(currNode));
144             if (!fpsValue || !deFpsValue) {
145                 CONCUR_LOGE("ParsePowerMode:: fps is null!");
146                 continue;
147             }
148             if (IsValidFps(fpsValue) && IsPositiveInt(deFpsValue)) {
149                 degradationFpsMap_.insert(std::make_pair(atoi(fpsValue), atoi(deFpsValue)));
150             } else {
151                 CONCUR_LOGE("ParsePowerMode:: invalid fps value!");
152             }
153             xmlFree(fpsValue);
154             xmlFree(deFpsValue);
155         }
156     }
157 }
158 
LoadFromConfigFile(const std::string & configFile)159 bool ConfigReader::LoadFromConfigFile(const std::string& configFile)
160 {
161     // skip the empty string, else you will get empty node
162     xmlDocPtr xmlDocPtr = xmlReadFile(configFile.c_str(), nullptr,
163         XML_PARSE_NOBLANKS | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
164     if (!xmlDocPtr) {
165         CONCUR_LOGE("LoadFromConfigFile:: xmlReadFile error!");
166         return false;
167     }
168     xmlNodePtr rootNodePtr = xmlDocGetRootElement(xmlDocPtr);
169     if (!rootNodePtr || !rootNodePtr->name ||
170         xmlStrcmp(rootNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_QOS_CONFIG.c_str())) != 0) {
171         CONCUR_LOGE("LoadFromConfigFile:: root element tag error!");
172         xmlFreeDoc(xmlDocPtr);
173         return false;
174     }
175     xmlNodePtr currNodePtr = rootNodePtr->xmlChildrenNode;
176     for (; currNodePtr; currNodePtr = currNodePtr->next) {
177         if (!IsValidNode(currNodePtr)) {
178             CONCUR_LOGE("LoadFromConfigFile:: IsInvalidNode!");
179             continue;
180         }
181         if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_QOS_AUTH.c_str())) == 0) {
182             ParseAuth(currNodePtr);
183         }
184         if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_POWER_MODE.c_str())) == 0) {
185             ParsePowerMode(currNodePtr);
186         }
187     }
188     ConfigHilog();
189     xmlFreeDoc(xmlDocPtr);
190     return true;
191 }
192 
GetRealConfigPath(const char * configName,std::string & configPath)193 void ConfigReader::GetRealConfigPath(const char* configName, std::string& configPath)
194 {
195     if (!configName) {
196         CONCUR_LOGE("GetRealConfigPath:: configName is nullptr!");
197         return;
198     }
199     char buf[PATH_MAX] = {0};
200     char* configFilePath = GetOneCfgFile(configName, buf, PATH_MAX);
201     char tmpPath[PATH_MAX] = {0};
202     if (!configFilePath || strlen(configFilePath) == 0 || strlen(configFilePath) > PATH_MAX ||
203         !realpath(configFilePath, tmpPath)) {
204         CONCUR_LOGE("GetRealConfigPath:: get config file path error!");
205         configPath = "";
206         return;
207     }
208     configPath = tmpPath;
209 }
210 
IsUidAuth(pid_t uid)211 bool ConfigReader::IsUidAuth(pid_t uid)
212 {
213     if (authProcUidConfigs_.find(uid) != authProcUidConfigs_.end()) {
214         return true;
215     }
216     return false;
217 }
218 
IsBundleNameAuth(std::string & bundleName)219 bool ConfigReader::IsBundleNameAuth(std::string& bundleName)
220 {
221     if (authProcBundleNameConfigs_.find(bundleName) != authProcBundleNameConfigs_.end()) {
222         return true;
223     }
224     return false;
225 }
226 
GetPowerModeSchedSwitch()227 bool ConfigReader::GetPowerModeSchedSwitch()
228 {
229     return powerModeSchedSwitch_;
230 }
231 
GetDegratationFps(int fps)232 int ConfigReader::GetDegratationFps(int fps)
233 {
234     if (degradationFpsMap_.find(fps) == degradationFpsMap_.end()) {
235         return fps;
236     }
237     return degradationFpsMap_[fps];
238 }
239 
IsValidFps(const std::string & fps)240 bool ConfigReader::IsValidFps(const std::string& fps)
241 {
242     if (fps == "120" || fps == "90" || fps == "60") {
243         return true;
244     }
245     return false;
246 }
247 
IsPositiveInt(const std::string & intStr)248 bool  ConfigReader::IsPositiveInt(const std::string& intStr)
249 {
250     int num = 0;
251     try {
252         num = stoi(intStr);
253     } catch (...) {
254         CONCUR_LOGE("Unexpected number format!");
255         return false;
256     }
257     return num > 0;
258 }
259 
ConfigHilog()260 void ConfigReader::ConfigHilog()
261 {
262     bool getConfigRead = OHOS::system::GetBoolParameter("persist.qos.configreadlog", false);
263     if (getConfigRead) {
264         for (auto iter : authProcUidConfigs_) {
265             CONCUR_LOGI("authProcUidConfigs_ contain uid = %{public}d", (int32_t)iter);
266         }
267         for (auto iter : authProcBundleNameConfigs_) {
268             CONCUR_LOGI("authProcBundleNameConfigs_ contain bundleName = %{public}s", iter.c_str());
269         }
270         CONCUR_LOGI("powerModeSchedSwitch_ = %{public}d", powerModeSchedSwitch_);
271         for (auto iter : degradationFpsMap_) {
272             CONCUR_LOGI("fps = %{public}d degradationFps = %{public}d", iter.first, iter.second);
273         }
274     }
275 }
276 }
277 }