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 }