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 24using namespace std; 25 26namespace OHOS { 27namespace ConcurrentTask { 28namespace { 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 45bool 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 56bool 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 78bool 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 100void 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 120void 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 163bool 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 197void 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 215bool ConfigReader::IsUidAuth(pid_t uid) 216{ 217 if (authProcUidConfigs_.find(uid) != authProcUidConfigs_.end()) { 218 return true; 219 } 220 return false; 221} 222 223bool ConfigReader::IsBundleNameAuth(std::string& bundleName) 224{ 225 if (authProcBundleNameConfigs_.find(bundleName) != authProcBundleNameConfigs_.end()) { 226 return true; 227 } 228 return false; 229} 230 231bool ConfigReader::GetPowerModeSchedSwitch() 232{ 233 return powerModeSchedSwitch_; 234} 235 236int 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 244bool 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 252bool 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 264void 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}