/* * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "window_manager_config.h" #include "config_policy_utils.h" #include "window_helper.h" #include "window_manager_hilog.h" namespace OHOS { namespace Rosen { namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowManagerConfig"}; } WindowManagerConfig::ConfigItem WindowManagerConfig::config_; const std::map WindowManagerConfig::configItemTypeMap_ = { { "maxAppWindowNumber", WindowManagerConfig::ValueType::INTS }, { "modeChangeHotZones", WindowManagerConfig::ValueType::INTS }, { "duration", WindowManagerConfig::ValueType::INTS }, { "durationIn", WindowManagerConfig::ValueType::INTS }, { "durationOut", WindowManagerConfig::ValueType::INTS }, { "defaultWindowMode", WindowManagerConfig::ValueType::INTS }, { "dragFrameGravity", WindowManagerConfig::ValueType::INTS }, { "floatingBottomPosY", WindowManagerConfig::ValueType::INTS }, { "defaultFloatingWindow", WindowManagerConfig::ValueType::INTS }, { "maxMainFloatingWindowNumber", WindowManagerConfig::ValueType::INTS }, { "maxFloatingWindowSize", WindowManagerConfig::ValueType::INTS }, { "defaultMaximizeMode", WindowManagerConfig::ValueType::INTS }, { "windowAnimation", WindowManagerConfig::ValueType::MAP }, { "keyboardAnimation", WindowManagerConfig::ValueType::MAP }, { "animationIn", WindowManagerConfig::ValueType::MAP }, { "animationOut", WindowManagerConfig::ValueType::MAP }, { "timing", WindowManagerConfig::ValueType::MAP }, { "windowEffect", WindowManagerConfig::ValueType::MAP }, { "appWindows", WindowManagerConfig::ValueType::MAP }, { "cornerRadius", WindowManagerConfig::ValueType::MAP }, { "shadow", WindowManagerConfig::ValueType::MAP }, { "focused", WindowManagerConfig::ValueType::MAP }, { "unfocused", WindowManagerConfig::ValueType::MAP }, { "decor", WindowManagerConfig::ValueType::MAP }, { "startWindowTransitionAnimation", WindowManagerConfig::ValueType::MAP }, { "curve", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, { "splitRatios", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, { "exitSplitRatios", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, { "scale", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, { "opacity", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, { "opacityStart", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, { "opacityEnd", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, { "elevation", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, { "alpha", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, { "rotation", WindowManagerConfig::ValueType::FLOATS }, { "translate", WindowManagerConfig::ValueType::FLOATS }, { "offsetX", WindowManagerConfig::ValueType::FLOATS }, { "offsetY", WindowManagerConfig::ValueType::FLOATS }, { "radius", WindowManagerConfig::ValueType::FLOATS }, { "fullScreen", WindowManagerConfig::ValueType::STRING }, { "split", WindowManagerConfig::ValueType::STRING }, { "float", WindowManagerConfig::ValueType::STRING }, { "color", WindowManagerConfig::ValueType::STRING }, { "supportedMode", WindowManagerConfig::ValueType::STRINGS }, { "minimizeByOther", WindowManagerConfig::ValueType::UNDIFINED }, { "stretchable", WindowManagerConfig::ValueType::UNDIFINED }, { "remoteAnimation", WindowManagerConfig::ValueType::UNDIFINED }, { "configMainFloatingWindowAbove", WindowManagerConfig::ValueType::UNDIFINED }, { "uiType", WindowManagerConfig::ValueType::STRING }, { "supportTypeFloatWindow", WindowManagerConfig::ValueType::STRING }, }; std::vector WindowManagerConfig::SplitNodeContent(const xmlNodePtr& node, const std::string& pattern) { xmlChar* content = xmlNodeGetContent(node); if (content == nullptr) { WLOGFE("[WmConfig] read xml node error: nodeName:(%{public}s)", node->name); return std::vector(); } std::string contentStr = reinterpret_cast(content); xmlFree(content); if (contentStr.size() == 0) { return std::vector(); } return WindowHelper::Split(contentStr, pattern); } std::string WindowManagerConfig::GetConfigPath(const std::string& configFileName) { char buf[PATH_MAX + 1]; char* configPath = GetOneCfgFile(configFileName.c_str(), buf, PATH_MAX + 1); char tmpPath[PATH_MAX + 1] = { 0 }; if (!configPath || strlen(configPath) == 0 || strlen(configPath) > PATH_MAX || !realpath(configPath, tmpPath)) { WLOGI("[WmConfig] can not get customization config file"); return "/system/" + configFileName; } return std::string(tmpPath); } void WindowManagerConfig::ReadConfig(const xmlNodePtr& rootPtr, std::map& mapValue) { for (xmlNodePtr curNodePtr = rootPtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) { if (!IsValidNode(*curNodePtr)) { WLOGFE("[WmConfig]: invalid node!"); continue; } std::string nodeName = reinterpret_cast(curNodePtr->name); if (configItemTypeMap_.count(nodeName)) { std::map property = ReadProperty(curNodePtr); if (property.size() > 0) { mapValue[reinterpret_cast(curNodePtr->name)].SetProperty(property); } switch (configItemTypeMap_.at(nodeName)) { case ValueType::INTS: { std::vector v = ReadIntNumbersConfigInfo(curNodePtr); mapValue[reinterpret_cast(curNodePtr->name)].SetValue(v); break; } case ValueType::FLOATS: { std::vector v = ReadFloatNumbersConfigInfo(curNodePtr, true); mapValue[reinterpret_cast(curNodePtr->name)].SetValue(v); break; } case ValueType::POSITIVE_FLOATS: { std::vector v = ReadFloatNumbersConfigInfo(curNodePtr, false); mapValue[reinterpret_cast(curNodePtr->name)].SetValue(v); break; } case ValueType::STRING: { std::string v = ReadStringConfigInfo(curNodePtr); mapValue[reinterpret_cast(curNodePtr->name)].SetValue(v); break; } case ValueType::STRINGS: { std::vector v = ReadStringsConfigInfo(curNodePtr); mapValue[reinterpret_cast(curNodePtr->name)].SetValue(v); break; } case ValueType::MAP: { std::map v; ReadConfig(curNodePtr, v); mapValue[reinterpret_cast(curNodePtr->name)].SetValue(v); break; } default: break; } } } } bool WindowManagerConfig::LoadConfigXml() { auto configFilePath = GetConfigPath("etc/window/resources/window_manager_config.xml"); xmlDocPtr docPtr = nullptr; { std::lock_guard lock(mutex_); docPtr = xmlReadFile(configFilePath.c_str(), nullptr, XML_PARSE_NOBLANKS); } WLOGI("[WmConfig] filePath: %{public}s", configFilePath.c_str()); if (docPtr == nullptr) { WLOGFE("[WmConfig] load xml error!"); return false; } xmlNodePtr rootPtr = xmlDocGetRootElement(docPtr); if (rootPtr == nullptr || rootPtr->name == nullptr || xmlStrcmp(rootPtr->name, reinterpret_cast("Configs"))) { WLOGFE("[WmConfig] get root element failed!"); xmlFreeDoc(docPtr); return false; } std::map configMap; config_.SetValue(configMap); ReadConfig(rootPtr, *config_.mapValue_); xmlFreeDoc(docPtr); return true; } bool WindowManagerConfig::IsValidNode(const xmlNode& currNode) { if (currNode.name == nullptr || currNode.type == XML_COMMENT_NODE) { return false; } return true; } std::map WindowManagerConfig::ReadProperty(const xmlNodePtr& currNode) { std::map property; xmlChar* propVal = xmlGetProp(currNode, reinterpret_cast("enable")); if (propVal != nullptr) { if (!xmlStrcmp(propVal, reinterpret_cast("true"))) { property["enable"].SetValue(true); } else if (!xmlStrcmp(propVal, reinterpret_cast("false"))) { property["enable"].SetValue(false); } xmlFree(propVal); } propVal = xmlGetProp(currNode, reinterpret_cast("name")); if (propVal != nullptr) { property["name"].SetValue(std::string(reinterpret_cast(propVal))); xmlFree(propVal); } return property; } std::vector WindowManagerConfig::ReadIntNumbersConfigInfo(const xmlNodePtr& currNode) { std::vector intsValue; auto numbers = SplitNodeContent(currNode); for (auto& num : numbers) { if (!WindowHelper::IsNumber(num)) { WLOGFE("[WmConfig] read int number error: nodeName:(%{public}s)", currNode->name); return {}; } intsValue.push_back(std::stoi(num)); } return intsValue; } std::vector WindowManagerConfig::ReadStringsConfigInfo(const xmlNodePtr& currNode) { return SplitNodeContent(currNode); } std::vector WindowManagerConfig::ReadFloatNumbersConfigInfo(const xmlNodePtr& currNode, bool allowNeg) { std::vector floatsValue; auto numbers = SplitNodeContent(currNode); for (auto& num : numbers) { if (!WindowHelper::IsFloatingNumber(num, allowNeg)) { WLOGFE("[WmConfig] read float number error: nodeName:(%{public}s)", currNode->name); return {}; } floatsValue.push_back(std::stof(num)); } return floatsValue; } std::string WindowManagerConfig::ReadStringConfigInfo(const xmlNodePtr& currNode) { std::string stringValue; xmlChar* context = xmlNodeGetContent(currNode); if (context == nullptr) { WLOGFE("[WmConfig] read xml node error: nodeName:(%{public}s)", currNode->name); return {}; } stringValue = std::string(reinterpret_cast(context)); xmlFree(context); return stringValue; } void WindowManagerConfig::DumpConfig(const std::map& config) { for (auto& conf : config) { WLOGI("[WmConfig] %{public}s", conf.first.c_str()); std::map propMap; if (conf.second.property_) { propMap = *conf.second.property_; } for (auto prop : propMap) { switch (prop.second.type_) { case ValueType::BOOL: WLOGI("[WmConfig] Prop: %{public}s %{public}u", prop.first.c_str(), prop.second.boolValue_); break; case ValueType::STRING: WLOGI("[WmConfig] Prop: %{public}s %{public}s", prop.first.c_str(), prop.second.stringValue_.c_str()); break; default: break; } } switch (conf.second.type_) { case ValueType::INTS: for (auto& num : *conf.second.intsValue_) { TLOGI(WmsLogTag::DEFAULT, "[WmConfig] Num: %{public}d", num); } break; case ValueType::MAP: if (conf.second.mapValue_) { DumpConfig(*conf.second.mapValue_); } break; case ValueType::STRING: TLOGI(WmsLogTag::DEFAULT, "[WmConfig] %{public}s", conf.second.stringValue_.c_str()); break; case ValueType::BOOL: TLOGI(WmsLogTag::DEFAULT, "[WmConfig] %{public}u", conf.second.boolValue_); break; case ValueType::FLOATS: for (auto& num : *conf.second.floatsValue_) { TLOGI(WmsLogTag::DEFAULT, "[WmConfig] Num: %{public}f", num); } break; default: break; } } } } // namespace Rosen } // namespace OHOS