1/* 2 * Copyright (c) 2022 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 "display_manager_config.h" 16 17#include <climits> 18#include <cstdint> 19#include <cstdlib> 20#include <libxml/globals.h> 21#include <libxml/xmlstring.h> 22#include <map> 23#include <string> 24#include <utility> 25#include <vector> 26 27#include "config_policy_utils.h" 28#include "window_manager_hilog.h" 29 30 31namespace OHOS::Rosen { 32namespace { 33constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerConfig"}; 34} 35 36std::map<std::string, bool> DisplayManagerConfig::enableConfig_; 37std::map<std::string, std::vector<int>> DisplayManagerConfig::intNumbersConfig_; 38std::map<std::string, std::string> DisplayManagerConfig::stringConfig_; 39 40std::vector<std::string> DisplayManagerConfig::Split(std::string str, std::string pattern) 41{ 42 std::vector<std::string> result; 43 str += pattern; 44 size_t length = str.size(); 45 for (size_t i = 0; i < length; i++) { 46 size_t position = str.find(pattern, i); 47 if (position < length) { 48 std::string tmp = str.substr(i, position - i); 49 result.push_back(tmp); 50 i = position + pattern.size() - 1; 51 } 52 } 53 return result; 54} 55 56bool inline DisplayManagerConfig::IsNumber(std::string str) 57{ 58 for (int32_t i = 0; i < static_cast<int32_t>(str.size()); i++) { 59 if (str.at(i) < '0' || str.at(i) > '9') { 60 return false; 61 } 62 } 63 return true; 64} 65 66std::string DisplayManagerConfig::GetConfigPath(const std::string& configFileName) 67{ 68 char buf[PATH_MAX + 1]; 69 char* configPath = GetOneCfgFile(configFileName.c_str(), buf, PATH_MAX + 1); 70 char tmpPath[PATH_MAX + 1] = { 0 }; 71 if (!configPath || strlen(configPath) == 0 || strlen(configPath) > PATH_MAX || !realpath(configPath, tmpPath)) { 72 WLOGFI("[DmConfig] can not get customization config file"); 73 return "/system/" + configFileName; 74 } 75 return std::string(tmpPath); 76} 77 78bool DisplayManagerConfig::LoadConfigXml() 79{ 80 auto configFilePath = GetConfigPath("etc/window/resources/display_manager_config.xml"); 81 xmlDocPtr docPtr = nullptr; 82 { 83 std::lock_guard<std::recursive_mutex> lock(mutex_); 84 docPtr = xmlReadFile(configFilePath.c_str(), nullptr, XML_PARSE_NOBLANKS); 85 } 86 WLOGFI("[DmConfig] filePath: %{public}s", configFilePath.c_str()); 87 if (docPtr == nullptr) { 88 WLOGFE("[DmConfig] load xml error!"); 89 return false; 90 } 91 92 xmlNodePtr rootPtr = xmlDocGetRootElement(docPtr); 93 if (rootPtr == nullptr || rootPtr->name == nullptr || 94 xmlStrcmp(rootPtr->name, reinterpret_cast<const xmlChar*>("Configs"))) { 95 WLOGFE("[DmConfig] get root element failed!"); 96 xmlFreeDoc(docPtr); 97 return false; 98 } 99 100 for (xmlNodePtr curNodePtr = rootPtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) { 101 if (!IsValidNode(*curNodePtr)) { 102 WLOGFE("DmConfig]: invalid node!"); 103 continue; 104 } 105 106 auto nodeName = curNodePtr->name; 107 if (!xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("isWaterfallDisplay")) || 108 !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("isWaterfallAreaCompressionEnableWhenHorizontal"))) { 109 ReadEnableConfigInfo(curNodePtr); 110 continue; 111 } 112 if (!xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("dpi")) || 113 !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("defaultDeviceRotationOffset")) || 114 !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("cutoutArea")) || 115 !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("curvedScreenBoundary")) || 116 !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("waterfallAreaCompressionSizeWhenHorzontal")) || 117 !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("buildInDefaultOrientation"))) { 118 ReadIntNumbersConfigInfo(curNodePtr); 119 continue; 120 } 121 if (!xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("defaultDisplayCutoutPath"))) { 122 ReadStringConfigInfo(curNodePtr); 123 continue; 124 } 125 } 126 xmlFreeDoc(docPtr); 127 return true; 128} 129 130bool DisplayManagerConfig::IsValidNode(const xmlNode& currNode) 131{ 132 if (currNode.name == nullptr || currNode.type == XML_COMMENT_NODE) { 133 return false; 134 } 135 return true; 136} 137 138void DisplayManagerConfig::ReadIntNumbersConfigInfo(const xmlNodePtr& currNode) 139{ 140 xmlChar* context = xmlNodeGetContent(currNode); 141 if (context == nullptr) { 142 WLOGFE("[DmConfig] read xml node error: nodeName:(%{public}s)", currNode->name); 143 return; 144 } 145 146 std::vector<int> numbersVec; 147 std::string numbersStr = reinterpret_cast<const char*>(context); 148 if (numbersStr.empty()) { 149 xmlFree(context); 150 return; 151 } 152 auto numbers = Split(numbersStr, " "); 153 for (auto& num : numbers) { 154 if (!IsNumber(num)) { 155 WLOGFE("[DmConfig] read number error: nodeName:(%{public}s)", currNode->name); 156 xmlFree(context); 157 return; 158 } 159 numbersVec.emplace_back(std::stoi(num)); 160 } 161 162 std::string nodeName = reinterpret_cast<const char *>(currNode->name); 163 intNumbersConfig_[nodeName] = numbersVec; 164 xmlFree(context); 165} 166 167void DisplayManagerConfig::ReadEnableConfigInfo(const xmlNodePtr& currNode) 168{ 169 xmlChar* enable = xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("enable")); 170 if (enable == nullptr) { 171 WLOGFE("[DmConfig] read xml node error: nodeName:(%{public}s)", currNode->name); 172 return; 173 } 174 175 std::string nodeName = reinterpret_cast<const char *>(currNode->name); 176 if (!xmlStrcmp(enable, reinterpret_cast<const xmlChar*>("true"))) { 177 enableConfig_[nodeName] = true; 178 } else { 179 enableConfig_[nodeName] = false; 180 } 181 xmlFree(enable); 182} 183 184void DisplayManagerConfig::ReadStringConfigInfo(const xmlNodePtr& currNode) 185{ 186 xmlChar* context = xmlNodeGetContent(currNode); 187 if (context == nullptr) { 188 WLOGFE("[DmConfig] read xml node error: nodeName:(%{public}s)", currNode->name); 189 return; 190 } 191 192 std::string inputString = reinterpret_cast<const char*>(context); 193 std::string nodeName = reinterpret_cast<const char*>(currNode->name); 194 stringConfig_[nodeName] = inputString; 195 xmlFree(context); 196} 197 198const std::map<std::string, bool>& DisplayManagerConfig::GetEnableConfig() 199{ 200 return enableConfig_; 201} 202 203const std::map<std::string, std::vector<int>>& DisplayManagerConfig::GetIntNumbersConfig() 204{ 205 return intNumbersConfig_; 206} 207 208const std::map<std::string, std::string>& DisplayManagerConfig::GetStringConfig() 209{ 210 return stringConfig_; 211} 212 213void DisplayManagerConfig::DumpConfig() 214{ 215 for (auto& enable : enableConfig_) { 216 WLOGFI("[DmConfig] Enable: %{public}s %{public}u", enable.first.c_str(), enable.second); 217 } 218 for (auto& numbers : intNumbersConfig_) { 219 WLOGFI("[DmConfig] Numbers: %{public}s %{public}zu", numbers.first.c_str(), numbers.second.size()); 220 for (auto& num : numbers.second) { 221 WLOGFI("[DmConfig] Num: %{public}d", num); 222 } 223 } 224 for (auto& string : stringConfig_) { 225 WLOGFI("[DmConfig] String: %{public}s", string.first.c_str()); 226 } 227} 228} // namespace OHOS::Rosen 229