• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "screen_scene_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 "include/core/SkMatrix.h"
29 #include "include/core/SkPath.h"
30 #include "include/core/SkPathMeasure.h"
31 #include "include/utils/SkParsePath.h"
32 #include "window_manager_hilog.h"
33 
34 namespace OHOS::Rosen {
35 namespace {
36 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "ScreenSceneConfig"};
37 constexpr char IS_WATERFALL_DISPLAY[] = "isWaterfallDisplay";
38 constexpr char CURVED_SCREEN_BOUNDARY[] = "curvedScreenBoundary";
39 constexpr char CURVED_AREA_IN_LANDSCAPE[] = "waterfallAreaCompressionSizeWhenHorzontal";
40 constexpr char IS_CURVED_COMPRESS_ENABLED[] = "isWaterfallAreaCompressionEnableWhenHorizontal";
41 constexpr uint32_t NO_WATERFALL_DISPLAY_COMPRESSION_SIZE = 0;
42 }
43 
44 std::map<std::string, bool> ScreenSceneConfig::enableConfig_;
45 std::map<std::string, std::vector<int>> ScreenSceneConfig::intNumbersConfig_;
46 std::map<std::string, std::string> ScreenSceneConfig::stringConfig_;
47 std::vector<DMRect> ScreenSceneConfig::cutoutBoundaryRect_;
48 bool ScreenSceneConfig::isWaterfallDisplay_ = false;
49 bool ScreenSceneConfig::isScreenCompressionEnableInLandscape_ = false;
50 uint32_t ScreenSceneConfig::curvedAreaInLandscape_ = 0;
51 
Split(std::string str,std::string pattern)52 std::vector<std::string> ScreenSceneConfig::Split(std::string str, std::string pattern)
53 {
54     std::vector<std::string> result;
55     str += pattern;
56     int32_t length = static_cast<int32_t>(str.size());
57     for (int32_t i = 0; i < length; i++) {
58         int32_t position = static_cast<int32_t>(str.find(pattern, i));
59         if (position < length) {
60             std::string tmp = str.substr(i, position - i);
61             result.push_back(tmp);
62             i = position + static_cast<int32_t>(pattern.size()) - 1;
63         }
64     }
65     return result;
66 }
67 
IsNumber(std::string str)68 bool ScreenSceneConfig::IsNumber(std::string str)
69 {
70     if (str.size() == 0) {
71         return false;
72     }
73     for (int32_t i = 0; i < static_cast<int32_t>(str.size()); i++) {
74         if (str.at(i) < '0' || str.at(i) > '9') {
75             return false;
76         }
77     }
78     return true;
79 }
80 
GetConfigPath(const std::string & configFileName)81 std::string ScreenSceneConfig::GetConfigPath(const std::string& configFileName)
82 {
83     char buf[PATH_MAX + 1];
84     char* configPath = GetOneCfgFile(configFileName.c_str(), buf, PATH_MAX + 1);
85     char tmpPath[PATH_MAX + 1] = { 0 };
86     if (!configPath || strlen(configPath) == 0 || strlen(configPath) > PATH_MAX || !realpath(configPath, tmpPath)) {
87         WLOGFI("[SsConfig] can not get customization config file");
88         return "/system/" + configFileName;
89     }
90     return std::string(tmpPath);
91 }
92 
LoadConfigXml()93 bool ScreenSceneConfig::LoadConfigXml()
94 {
95     auto configFilePath = GetConfigPath("etc/window/resources/display_manager_config.xml");
96     xmlDocPtr docPtr = nullptr;
97     {
98         std::lock_guard<std::recursive_mutex> lock(mutex_);
99         docPtr = xmlReadFile(configFilePath.c_str(), nullptr, XML_PARSE_NOBLANKS);
100     }
101     WLOGFI("[SsConfig] filePath: %{public}s", configFilePath.c_str());
102     if (docPtr == nullptr) {
103         WLOGFE("[SsConfig] load xml error!");
104         return false;
105     }
106 
107     xmlNodePtr rootPtr = xmlDocGetRootElement(docPtr);
108     if (rootPtr == nullptr || rootPtr->name == nullptr ||
109         xmlStrcmp(rootPtr->name, reinterpret_cast<const xmlChar*>("Configs"))) {
110         WLOGFE("[SsConfig] get root element failed!");
111         xmlFreeDoc(docPtr);
112         return false;
113     }
114 
115     for (xmlNodePtr curNodePtr = rootPtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) {
116         if (!IsValidNode(*curNodePtr)) {
117             WLOGFE("SsConfig]: invalid node!");
118             continue;
119         }
120 
121         auto nodeName = curNodePtr->name;
122         if (!xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>(IS_WATERFALL_DISPLAY)) ||
123             !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>(IS_CURVED_COMPRESS_ENABLED))) {
124             ReadEnableConfigInfo(curNodePtr);
125             continue;
126         }
127         if (!xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("dpi")) ||
128             !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("defaultDeviceRotationOffset")) ||
129             !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>(CURVED_SCREEN_BOUNDARY)) ||
130             !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>(CURVED_AREA_IN_LANDSCAPE)) ||
131             !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("buildInDefaultOrientation"))) {
132             ReadIntNumbersConfigInfo(curNodePtr);
133             continue;
134         }
135         if (!xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("defaultDisplayCutoutPath"))) {
136             ReadStringConfigInfo(curNodePtr);
137             continue;
138         }
139     }
140     xmlFreeDoc(docPtr);
141     return true;
142 }
143 
IsValidNode(const xmlNode & currNode)144 bool ScreenSceneConfig::IsValidNode(const xmlNode& currNode)
145 {
146     if (currNode.name == nullptr || currNode.type == XML_COMMENT_NODE) {
147         return false;
148     }
149     return true;
150 }
151 
ReadIntNumbersConfigInfo(const xmlNodePtr & currNode)152 void ScreenSceneConfig::ReadIntNumbersConfigInfo(const xmlNodePtr& currNode)
153 {
154     xmlChar* context = xmlNodeGetContent(currNode);
155     if (context == nullptr) {
156         WLOGFE("[SsConfig] read xml node error: nodeName:(%{public}s)", currNode->name);
157         return;
158     }
159 
160     std::vector<int> numbersVec;
161     std::string numbersStr = reinterpret_cast<const char*>(context);
162     if (numbersStr.empty()) {
163         xmlFree(context);
164         return;
165     }
166     auto numbers = Split(numbersStr, " ");
167     for (auto& num : numbers) {
168         if (!IsNumber(num)) {
169             WLOGFE("[SsConfig] read number error: nodeName:(%{public}s)", currNode->name);
170             xmlFree(context);
171             return;
172         }
173         numbersVec.emplace_back(std::stoi(num));
174     }
175 
176     std::string nodeName = reinterpret_cast<const char *>(currNode->name);
177     intNumbersConfig_[nodeName] = numbersVec;
178     xmlFree(context);
179 }
180 
ReadEnableConfigInfo(const xmlNodePtr & currNode)181 void ScreenSceneConfig::ReadEnableConfigInfo(const xmlNodePtr& currNode)
182 {
183     xmlChar* enable = xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("enable"));
184     if (enable == nullptr) {
185         WLOGFE("[SsConfig] read xml node error: nodeName:(%{public}s)", currNode->name);
186         return;
187     }
188 
189     std::string nodeName = reinterpret_cast<const char *>(currNode->name);
190     if (!xmlStrcmp(enable, reinterpret_cast<const xmlChar*>("true"))) {
191         enableConfig_[nodeName] = true;
192         if (IS_WATERFALL_DISPLAY == nodeName) {
193             isWaterfallDisplay_ = true;
194         } else if (IS_CURVED_COMPRESS_ENABLED == nodeName) {
195             isScreenCompressionEnableInLandscape_ = true;
196         }
197     } else {
198         enableConfig_[nodeName] = false;
199     }
200     xmlFree(enable);
201 }
202 
ReadStringConfigInfo(const xmlNodePtr & currNode)203 void ScreenSceneConfig::ReadStringConfigInfo(const xmlNodePtr& currNode)
204 {
205     xmlChar* context = xmlNodeGetContent(currNode);
206     if (context == nullptr) {
207         WLOGFE("[SsConfig] read xml node error: nodeName:(%{public}s)", currNode->name);
208         return;
209     }
210 
211     std::string inputString = reinterpret_cast<const char*>(context);
212     std::string nodeName = reinterpret_cast<const char*>(currNode->name);
213     stringConfig_[nodeName] = inputString;
214     xmlFree(context);
215 }
216 
GetEnableConfig()217 const std::map<std::string, bool>& ScreenSceneConfig::GetEnableConfig()
218 {
219     return enableConfig_;
220 }
221 
GetIntNumbersConfig()222 const std::map<std::string, std::vector<int>>& ScreenSceneConfig::GetIntNumbersConfig()
223 {
224     return intNumbersConfig_;
225 }
226 
GetStringConfig()227 const std::map<std::string, std::string>& ScreenSceneConfig::GetStringConfig()
228 {
229     return stringConfig_;
230 }
231 
DumpConfig()232 void ScreenSceneConfig::DumpConfig()
233 {
234     for (auto& enable : enableConfig_) {
235         WLOGFI("[SsConfig] Enable: %{public}s %{public}u", enable.first.c_str(), enable.second);
236     }
237     for (auto& numbers : intNumbersConfig_) {
238         WLOGFI("[SsConfig] Numbers: %{public}s %{public}zu", numbers.first.c_str(), numbers.second.size());
239         for (auto& num : numbers.second) {
240             WLOGFI("[SsConfig] Num: %{public}d", num);
241         }
242     }
243     for (auto& string : stringConfig_) {
244         WLOGFI("[SsConfig] String: %{public}s", string.first.c_str());
245     }
246 }
247 
SetCutoutSvgPath(const std::string & svgPath)248 void ScreenSceneConfig::SetCutoutSvgPath(const std::string& svgPath)
249 {
250     cutoutBoundaryRect_.clear();
251     cutoutBoundaryRect_.emplace_back(CalcCutoutBoundaryRect(svgPath));
252 }
253 
CalcCutoutBoundaryRect(std::string svgPath)254 DMRect ScreenSceneConfig::CalcCutoutBoundaryRect(std::string svgPath)
255 {
256     DMRect emptyRect = { 0, 0, 0, 0 };
257     SkPath skCutoutSvgPath;
258     if (!SkParsePath::FromSVGString(svgPath.c_str(), &skCutoutSvgPath)) {
259         WLOGFE("Parse svg string path failed.");
260         return emptyRect;
261     }
262     SkRect skRect = skCutoutSvgPath.computeTightBounds();
263     if (skRect.isEmpty()) {
264         WLOGFW("Get empty skRect");
265         return emptyRect;
266     }
267     SkIRect skiRect = skRect.roundOut();
268     if (skiRect.isEmpty()) {
269         WLOGFW("Get empty skiRect");
270         return emptyRect;
271     }
272     int32_t left = static_cast<int32_t>(skiRect.left());
273     int32_t top = static_cast<int32_t>(skiRect.top());
274     uint32_t width = static_cast<uint32_t>(skiRect.width());
275     uint32_t height = static_cast<uint32_t>(skiRect.height());
276     WLOGFI("calc cutout boundary rect - left: [%{public}d top: %{public}d width: %{public}u height: %{public}u]", left,
277         top, width, height);
278     DMRect cutoutMinOuterRect = {
279         .posX_ = left,
280         .posY_ = top,
281         .width_ = width,
282         .height_ = height
283     };
284     return cutoutMinOuterRect;
285 }
286 
GetCutoutBoundaryRect()287 std::vector<DMRect> ScreenSceneConfig::GetCutoutBoundaryRect()
288 {
289     return cutoutBoundaryRect_;
290 }
291 
IsWaterfallDisplay()292 bool ScreenSceneConfig::IsWaterfallDisplay()
293 {
294     return isWaterfallDisplay_;
295 }
296 
SetCurvedCompressionAreaInLandscape()297 void ScreenSceneConfig::SetCurvedCompressionAreaInLandscape()
298 {
299     if (intNumbersConfig_[CURVED_AREA_IN_LANDSCAPE].size() > 0) {
300         curvedAreaInLandscape_ = static_cast<uint32_t>(intNumbersConfig_[CURVED_AREA_IN_LANDSCAPE][0]);
301     } else {
302         WLOGFW("waterfallAreaCompressionSizeWhenHorzontal value is not exist");
303     }
304 }
305 
GetCurvedScreenBoundaryConfig()306 std::vector<int> ScreenSceneConfig::GetCurvedScreenBoundaryConfig()
307 {
308     return intNumbersConfig_[CURVED_SCREEN_BOUNDARY];
309 }
310 
GetCurvedCompressionAreaInLandscape()311 uint32_t ScreenSceneConfig::GetCurvedCompressionAreaInLandscape()
312 {
313     if (!isWaterfallDisplay_ || !isScreenCompressionEnableInLandscape_) {
314         WLOGFW("noy waterfall screen or waterfall compression is not enabled");
315         return NO_WATERFALL_DISPLAY_COMPRESSION_SIZE;
316     }
317     return curvedAreaInLandscape_;
318 }
319 } // namespace OHOS::Rosen
320