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