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 }