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 
16 #include "rs_round_corner_config.h"
17 #include <algorithm>
18 #include <chrono>
19 #include <regex>
20 
21 using std::chrono::high_resolution_clock;
22 using std::chrono::microseconds;
23 
24 namespace OHOS {
25 namespace Rosen {
26 namespace rs_rcd {
27 const char REG_NUM[] = "^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$"; // regular expression of check number
28 
RegexMatch(const std::string & str,const std::string & pattern)29 bool XMLReader::RegexMatch(const std::string& str, const std::string& pattern)
30 {
31     std::smatch result;
32     std::regex r(pattern);
33     return std::regex_match(str, result, r);
34 }
35 
RegexMatchNum(std::string & str)36 bool XMLReader::RegexMatchNum(std::string& str)
37 {
38     // remove space from string before match
39     str.erase(remove(str.begin(), str.end(), ' '), str.end());
40     return RegexMatch(str, std::string(REG_NUM));
41 }
42 
FindNode(const xmlNodePtr & src,const std::string & index)43 xmlNodePtr XMLReader::FindNode(const xmlNodePtr& src, const std::string& index)
44 {
45     xmlNodePtr startPtr = src->children;
46     while (startPtr != nullptr) {
47         auto name = startPtr->name;
48         if (xmlStrEqual(name, BAD_CAST(index.c_str())) == 1) {
49             return startPtr;
50         }
51         startPtr = startPtr->next;
52     }
53     RS_LOGD_IF(DEBUG_PIPELINE, "[%{public}s] can not found node %{public}s! \n", __func__, index.c_str());
54     return nullptr;
55 }
56 
ReadAttrStr(const xmlNodePtr & src,const std::string & attr)57 std::string XMLReader::ReadAttrStr(const xmlNodePtr& src, const std::string& attr)
58 {
59     auto result = reinterpret_cast<char*>((xmlGetProp(src, BAD_CAST(attr.c_str()))));
60     if (result == nullptr) {
61         RS_LOGE("[%{public}s] can not found attribute %{public}s! \n", __func__, attr.c_str());
62         return std::string("");
63     }
64     std::string str(result);
65     xmlFree(result);
66     return str;
67 }
68 
ReadAttrInt(const xmlNodePtr & src,const std::string & attr)69 int XMLReader::ReadAttrInt(const xmlNodePtr& src, const std::string& attr)
70 {
71     auto result = reinterpret_cast<char*>((xmlGetProp(src, BAD_CAST(attr.c_str()))));
72     if (result == nullptr) {
73         RS_LOGE("[%{public}s] can not found attribute %{public}s! \n", __func__, attr.c_str());
74         return 0;
75     }
76     std::string num(result);
77     xmlFree(result);
78     if (RegexMatchNum(num)) {
79         return std::atoi(num.c_str());
80     }
81     RS_LOGE("[%{public}s] attribute %{public}s can not convert to int! \n", __func__, attr.c_str());
82     return 0;
83 }
84 
ReadAttrFloat(const xmlNodePtr & src,const std::string & attr)85 float XMLReader::ReadAttrFloat(const xmlNodePtr& src, const std::string& attr)
86 {
87     auto result = reinterpret_cast<char*>((xmlGetProp(src, BAD_CAST(attr.c_str()))));
88     if (result == nullptr) {
89         RS_LOGE("[%{public}s] can not found attribute %{public}s! \n", __func__, attr.c_str());
90         return 0.0f;
91     }
92     std::string num(result);
93     xmlFree(result);
94     if (RegexMatchNum(num)) {
95         return std::atof(num.c_str());
96     }
97     RS_LOGE("[%{public}s] attribute %{public}s can not convert to float! \n", __func__, attr.c_str());
98     return 0;
99 }
100 
ReadAttrBool(const xmlNodePtr & src,const std::string & attr)101 bool XMLReader::ReadAttrBool(const xmlNodePtr& src, const std::string& attr)
102 {
103     auto result = reinterpret_cast<char*>((xmlGetProp(src, BAD_CAST(attr.c_str()))));
104     if (result == nullptr) {
105         RS_LOGE("[%{public}s] can not found attribute %{public}s! \n", __func__, attr.c_str());
106         return false;
107     }
108     auto istrue = strcmp(result, "true") == 0 ? true : false;
109     xmlFree(result);
110     return istrue;
111 }
112 
ReadXmlNode(const xmlNodePtr & ptr,const std::string & supportAttr,const std::string & modeAttr)113 bool SupportConfig::ReadXmlNode(const xmlNodePtr& ptr, const std::string& supportAttr, const std::string& modeAttr)
114 {
115     auto a1 = xmlGetProp(ptr, BAD_CAST(supportAttr.c_str()));
116     if (a1 == nullptr) {
117         RS_LOGE("[%{public}s] can not found supportAttr %{public}s! \n", __func__, supportAttr.c_str());
118         return false;
119     }
120     support = XMLReader::ReadAttrBool(ptr, supportAttr);
121     mode = XMLReader::ReadAttrInt(ptr, modeAttr);
122     xmlFree(a1);
123     return true;
124 }
125 
ReadXmlNode(const xmlNodePtr & ptr,const std::vector<std::string> & attrArray)126 bool RoundCornerLayer::ReadXmlNode(const xmlNodePtr& ptr, const std::vector<std::string>& attrArray)
127 {
128     const int layerAttrSize = 7;
129     if (attrArray.size() < layerAttrSize || ptr == nullptr) {
130         RS_LOGE("[%{public}s] attribute size less than 7! \n", __func__);
131         return false;
132     }
133     const int fileIndex = 0;
134     const int offsetXIndex = 1;
135     const int offsetYIndex = 2;
136     const int binFileIndex = 3;
137     const int bufferSizeIndex = 4;
138     const int cldWidthIndex = 5;
139     const int cldHeightIndex = 6;
140     fileName = XMLReader::ReadAttrStr(ptr, attrArray[fileIndex]);
141     offsetX = XMLReader::ReadAttrInt(ptr, attrArray[offsetXIndex]);
142     offsetY = XMLReader::ReadAttrInt(ptr, attrArray[offsetYIndex]);
143     binFileName = XMLReader::ReadAttrStr(ptr, attrArray[binFileIndex]);
144     bufferSize = XMLReader::ReadAttrInt(ptr, attrArray[bufferSizeIndex]);
145     cldWidth = XMLReader::ReadAttrInt(ptr, attrArray[cldWidthIndex]);
146     cldHeight = XMLReader::ReadAttrInt(ptr, attrArray[cldHeightIndex]);
147     return true;
148 }
149 
ReadXmlNode(const xmlNodePtr & portraitNodePtr)150 bool RogPortrait::ReadXmlNode(const xmlNodePtr& portraitNodePtr)
151 {
152     if (portraitNodePtr == nullptr) {
153         RS_LOGE("[%{public}s] input node is null! \n", __func__);
154         return false;
155     }
156     std::vector<std::string> attrList = { ATTR_FILENAME, ATTR_OFFSET_X, ATTR_OFFSET_Y,
157         ATTR_BINFILENAME, ATTR_BUFFERSIZE, ATTR_CLDWIDTH, ATTR_CLDHEIGHT };
158 
159     auto layerUpPtr = XMLReader::FindNode(portraitNodePtr, std::string(NODE_LAYERUP));
160     if (layerUpPtr == nullptr) {
161         RS_LOGE("[%{public}s] layerUpPtr node is null! \n", __func__);
162         return false;
163     }
164     layerUp.ReadXmlNode(layerUpPtr, attrList);
165 
166     auto layerDownPtr = XMLReader::FindNode(portraitNodePtr, std::string(NODE_LAYERDOWN));
167     if (layerDownPtr == nullptr) {
168         RS_LOGE("[%{public}s] layerDownPtr node is null! \n", __func__);
169         return false;
170     }
171     layerDown.ReadXmlNode(layerDownPtr, attrList);
172 
173     auto layerHidePtr = XMLReader::FindNode(portraitNodePtr, std::string(NODE_LAYERHIDE));
174     if (layerHidePtr == nullptr) {
175         RS_LOGE("[%{public}s] layerHidePtr node is null! \n", __func__);
176         return false;
177     }
178     layerHide.ReadXmlNode(layerHidePtr, attrList);
179     return true;
180 }
181 
ReadXmlNode(const xmlNodePtr & landNodePtr)182 bool RogLandscape::ReadXmlNode(const xmlNodePtr& landNodePtr)
183 {
184     if (landNodePtr == nullptr) {
185         RS_LOGE("[%{public}s] landNodePtr node is null! \n", __func__);
186         return false;
187     }
188     std::vector<std::string> attrList = { ATTR_FILENAME, ATTR_OFFSET_X, ATTR_OFFSET_Y,
189         ATTR_BINFILENAME, ATTR_BUFFERSIZE, ATTR_CLDWIDTH, ATTR_CLDHEIGHT };
190     auto layerUpPtr = XMLReader::FindNode(landNodePtr, std::string(NODE_LAYERUP));
191     if (layerUpPtr == nullptr) {
192         RS_LOGE("[%{public}s] layerUpPtr node is null! \n", __func__);
193         return false;
194     }
195     layerUp.ReadXmlNode(layerUpPtr, attrList);
196     return true;
197 }
198 
ReadXmlNode(const xmlNodePtr & rogNodePtr)199 bool ROGSetting::ReadXmlNode(const xmlNodePtr& rogNodePtr)
200 {
201     if (rogNodePtr == nullptr) {
202         RS_LOGE("[%{public}s] rogNodePtr node is null! \n", __func__);
203         return false;
204     }
205     width = XMLReader::ReadAttrInt(rogNodePtr, std::string(ATTR_WIDTH));
206     height = XMLReader::ReadAttrInt(rogNodePtr, std::string(ATTR_HEIGHT));
207 
208     auto portPtr = XMLReader::FindNode(rogNodePtr, NODE_PORTRAIT);
209     if (portPtr != nullptr) {
210         RogPortrait p;
211         p.ReadXmlNode(portPtr);
212         portraitMap[NODE_PORTRAIT] = p;
213     }
214 
215     auto portSidePtr = XMLReader::FindNode(rogNodePtr, NODE_PORTRAIT_SIDEREGION);
216     if (portSidePtr != nullptr) {
217         RogPortrait p;
218         p.ReadXmlNode(portSidePtr);
219         portraitMap[NODE_PORTRAIT_SIDEREGION] = p;
220     }
221 
222     auto landPtr = XMLReader::FindNode(rogNodePtr, NODE_LANDSCAPE);
223     if (landPtr != nullptr) {
224         RogLandscape p;
225         p.ReadXmlNode(landPtr);
226         landscapeMap[NODE_LANDSCAPE] = p;
227     }
228 
229     auto landSidePtr = XMLReader::FindNode(rogNodePtr, NODE_LANDSCAPE_SIDEREGION);
230     if (landSidePtr != nullptr) {
231         RogLandscape p;
232         p.ReadXmlNode(landSidePtr);
233         landscapeMap[NODE_LANDSCAPE_SIDEREGION] = p;
234     }
235     return true;
236 }
237 
HavePortrait(const std::string & name) const238 bool ROGSetting::HavePortrait(const std::string& name) const
239 {
240     if (portraitMap.count(name) < 1) {
241         RS_LOGD_IF(DEBUG_PIPELINE, "[%{public}s] PORTRAIT layerUp %{public}s do not configured \n", __func__,
242             name.c_str());
243         return false;
244     }
245     return true;
246 }
247 
HaveLandscape(const std::string & name) const248 bool ROGSetting::HaveLandscape(const std::string& name) const
249 {
250     if (landscapeMap.count(name) < 1) {
251         RS_LOGD_IF(DEBUG_PIPELINE, "[%{public}s] LANDSACPE layerUp %{public}s do not configured \n", __func__,
252             name.c_str());
253         return false;
254     }
255     return true;
256 }
257 
GetPortrait(const std::string & name) const258 std::optional<RogPortrait> ROGSetting::GetPortrait(const std::string& name) const
259 {
260     if (!HavePortrait(name)) {
261         return std::nullopt;
262     }
263     return portraitMap.at(name);
264 }
265 
GetLandscape(const std::string & name) const266 std::optional<RogLandscape> ROGSetting::GetLandscape(const std::string& name) const
267 {
268     if (!HaveLandscape(name)) {
269         return std::nullopt;
270     }
271     return landscapeMap.at(name);
272 }
273 
ReadXmlNode(const xmlNodePtr & surfaceConfigNodePtr)274 bool SurfaceConfig::ReadXmlNode(const xmlNodePtr& surfaceConfigNodePtr)
275 {
276     if (surfaceConfigNodePtr == nullptr) {
277         RS_LOGE("[%{public}s] surfaceConfigNodePtr node is null! \n", __func__);
278         return false;
279     }
280 
281     auto topSurfacePtr = XMLReader::FindNode(surfaceConfigNodePtr, std::string(NODE_TOPSURFACE));
282     if (topSurfacePtr == nullptr) {
283         RS_LOGE("[%{public}s] topSurfacePtr node is null! \n", __func__);
284         return false;
285     }
286     topSurface.ReadXmlNode(topSurfacePtr, std::string(ATTR_SUPPORT), std::string(ATTR_DISPLAYMODE));
287 
288     auto bottomSurfacePtr = XMLReader::FindNode(surfaceConfigNodePtr, std::string(NODE_BOTTOMSURFACE));
289     if (bottomSurfacePtr == nullptr) {
290         RS_LOGE("[%{public}s] bottomSurfacePtr node is null! \n", __func__);
291         return false;
292     }
293     bottomSurface.ReadXmlNode(bottomSurfacePtr, std::string(ATTR_SUPPORT), std::string(ATTR_DISPLAYMODE));
294     return true;
295 }
296 
ReadXmlNode(const xmlNodePtr & sideRegionNodePtr)297 bool SideRegionConfig::ReadXmlNode(const xmlNodePtr& sideRegionNodePtr)
298 {
299     if (sideRegionNodePtr == nullptr) {
300         RS_LOGE("[%{public}s] sideRegionNodePtr node is null! \n", __func__);
301         return false;
302     }
303     auto sideRegionPtr = XMLReader::FindNode(sideRegionNodePtr, std::string(NODE_SIDEREGION));
304     if (sideRegionPtr == nullptr) {
305         RS_LOGE("[%{public}s] sideRegionPtr node is null! \n", __func__);
306         return false;
307     }
308     sideRegion.ReadXmlNode(sideRegionPtr, std::string(ATTR_SUPPORT), std::string(ATTR_DISPLAYMODE));
309     return true;
310 }
311 
ReadXmlNode(const xmlNodePtr & ptr,const std::string & supportAttr)312 bool HardwareComposer::ReadXmlNode(const xmlNodePtr& ptr, const std::string& supportAttr)
313 {
314     auto a1 = xmlGetProp(ptr, BAD_CAST(supportAttr.c_str()));
315     if (a1 == nullptr) {
316         RS_LOGE("[%{public}s] supportAttr node is null! \n", __func__);
317         return false;
318     }
319     support = XMLReader::ReadAttrBool(ptr, supportAttr);
320     xmlFree(a1);
321     return true;
322 }
323 
ReadXmlNode(const xmlNodePtr & hardwareComposerNodeptr)324 bool HardwareComposerConfig::ReadXmlNode(const xmlNodePtr& hardwareComposerNodeptr)
325 {
326     if (hardwareComposerNodeptr == nullptr) {
327         RS_LOGE("[%{public}s] hardwareComposerNodeptr node is null! \n", __func__);
328         return false;
329     }
330     auto hardwareComposerPtr = XMLReader::FindNode(hardwareComposerNodeptr, std::string(NODE_HARDWARECOMPOSER));
331     if (hardwareComposerPtr == nullptr) {
332         RS_LOGE("[%{public}s] hardwareComposerPtr node is null! \n", __func__);
333         return false;
334     }
335     hardwareComposer.ReadXmlNode(hardwareComposerPtr, std::string(ATTR_SUPPORT));
336     return true;
337 }
338 
~LCDModel()339 LCDModel::~LCDModel()
340 {
341     for (auto& rog : rogs) {
342         if (rog != nullptr) {
343             delete rog;
344             rog = nullptr;
345         }
346     }
347 }
348 
ReadXmlNode(const xmlNodePtr & lcdNodePtr)349 bool LCDModel::ReadXmlNode(const xmlNodePtr& lcdNodePtr)
350 {
351     if (lcdNodePtr == nullptr) {
352         RS_LOGE("[%{public}s] input lcdNodePtr node is null! \n", __func__);
353         return false;
354     }
355     name = XMLReader::ReadAttrStr(lcdNodePtr, std::string(ATTR_NAME));
356     auto surfaceConfigPtr = XMLReader::FindNode(lcdNodePtr, std::string(NODE_SURFACECONFIG));
357     if (surfaceConfigPtr == nullptr) {
358         RS_LOGW("no surfaceConfig found \n");
359     }
360     surfaceConfig.ReadXmlNode(surfaceConfigPtr);
361 
362     auto sideRegionConfigPtr = XMLReader::FindNode(lcdNodePtr, std::string(NODE_SIDEREGIONCONFIG));
363     if (sideRegionConfigPtr == nullptr) {
364         RS_LOGW("no sideRegionConfig found \n");
365     }
366     sideRegionConfig.ReadXmlNode(sideRegionConfigPtr);
367 
368     auto hardwareComposerConfigPtr = XMLReader::FindNode(lcdNodePtr, std::string(NODE_HARDWARECOMPOSERCONFIG));
369     if (hardwareComposerConfigPtr == nullptr) {
370         RS_LOGW("no harewareComposer found \n");
371     }
372     hardwareConfig.ReadXmlNode(hardwareComposerConfigPtr);
373 
374     xmlNodePtr startPtr = lcdNodePtr->children;
375     while (startPtr != nullptr) {
376         auto name = startPtr->name;
377         if (xmlStrEqual(name, BAD_CAST(NODE_ROG)) == 1) {
378             ROGSetting *rog = new ROGSetting();
379             if (rog->ReadXmlNode(startPtr)) {
380                 rogs.push_back(rog);
381             } else {
382                 delete rog;
383                 rog = nullptr;
384             }
385         }
386         startPtr = startPtr->next;
387     }
388     return true;
389 }
390 
GetSurfaceConfig() const391 SurfaceConfig LCDModel::GetSurfaceConfig() const
392 {
393     return surfaceConfig;
394 }
395 
GetSideRegionConfig() const396 SideRegionConfig LCDModel::GetSideRegionConfig() const
397 {
398     return sideRegionConfig;
399 }
400 
GetHardwareComposerConfig() const401 HardwareComposerConfig LCDModel::GetHardwareComposerConfig() const
402 {
403     return hardwareConfig;
404 }
405 
GetRog(const int w,const int h) const406 ROGSetting* LCDModel::GetRog(const int w, const int h) const
407 {
408     for (auto rog : rogs) {
409         if (rog == nullptr) {
410             continue;
411         }
412         if (rog->width == w && rog->height == h) {
413             return rog;
414         }
415     }
416     return nullptr;
417 }
418 
PrintLayer(const std::string & name,const rs_rcd::RoundCornerLayer & layer)419 void RCDConfig::PrintLayer(const std::string& name, const rs_rcd::RoundCornerLayer& layer)
420 {
421     RS_LOGD_IF(DEBUG_PIPELINE, "%{public}s->Filename: %{public}s, Offset: %{public}d, %{public}d \n",
422         name.c_str(), layer.fileName.c_str(), layer.offsetX, layer.offsetY);
423     RS_LOGD_IF(DEBUG_PIPELINE, "BinFilename: %{public}s, BufferSize: %{public}d, cldSize:%{public}d, %{public}d \n",
424         layer.binFileName.c_str(), layer.bufferSize, layer.cldWidth, layer.cldHeight);
425 }
426 
PrintParseRog(rs_rcd::ROGSetting * rog)427 void RCDConfig::PrintParseRog(rs_rcd::ROGSetting* rog)
428 {
429     if (rog == nullptr) {
430         RS_LOGE("no model input \n");
431         return;
432     }
433     for (auto kv : rog->portraitMap) {
434         auto port = kv.second;
435         RS_LOGD_IF(DEBUG_PIPELINE, "rog: %{public}d, %{public}d, %{public}s: \n", rog->width, rog->height,
436             kv.first.c_str());
437         PrintLayer(std::string("layerUp  "), port.layerUp);
438         PrintLayer(std::string("layerDown"), port.layerDown);
439         PrintLayer(std::string("layerHide"), port.layerHide);
440     }
441     for (auto kv : rog->landscapeMap) {
442         auto port = kv.second;
443         RS_LOGD_IF(DEBUG_PIPELINE, "rog: %{public}d, %{public}d, %{public}s: \n", rog->width, rog->height,
444             kv.first.c_str());
445         PrintLayer(std::string("layerUp  "), port.layerUp);
446     }
447 }
448 
Load(const std::string & configFile)449 bool RCDConfig::Load(const std::string& configFile)
450 {
451     std::lock_guard<std::mutex> lock(xmlMut);
452     if (isLoadData) {
453         return true;
454     }
455     isLoadData = true;
456     auto begin = high_resolution_clock::now();
457     Clear();
458     xmlKeepBlanksDefault(0);
459     pDoc = xmlReadFile(configFile.c_str(), "", XML_PARSE_RECOVER);
460     if (pDoc == nullptr) {
461         RS_LOGE("RoundCornerDisplay read xml failed \n");
462         CloseXML();
463         return false;
464     }
465     RS_LOGI("RoundCornerDisplay read xml ok \n");
466     pRoot = xmlDocGetRootElement(pDoc);
467     if (pRoot == nullptr) {
468         RS_LOGE("RoundCornerDisplay get xml root failed \n");
469         CloseXML();
470         return false;
471     }
472     xmlNodePtr startPtr = pRoot->children;
473     while (startPtr != nullptr) {
474         auto name = startPtr->name;
475         if (xmlStrEqual(name, BAD_CAST(NODE_LCDMODEL)) == 1) {
476             LCDModel* lcdModel = new LCDModel();
477             if (lcdModel->ReadXmlNode(startPtr)) {
478                 lcdModels.push_back(lcdModel);
479             } else {
480                 delete lcdModel;
481                 lcdModel = nullptr;
482             }
483         }
484         startPtr = startPtr->next;
485     }
486     CloseXML();
487     auto interval = std::chrono::duration_cast<microseconds>(high_resolution_clock::now() - begin);
488     RS_LOGI("RoundCornerDisplay read xml time cost %{public}lld us \n", interval.count());
489     return true;
490 }
491 
GetLcdModel(const std::string & name) const492 LCDModel* RCDConfig::GetLcdModel(const std::string& name) const
493 {
494     if (name.empty()) {
495         RS_LOGE("[%{public}s] name is null! \n", __func__);
496         return nullptr;
497     }
498     for (auto model : lcdModels) {
499         if (model == nullptr) {
500             continue;
501         }
502         if (model->name.compare(name) == 0) {
503             return model;
504         }
505     }
506     RS_LOGE("[%{public}s] lcd not found in name %{public}s! \n", __func__, name.c_str());
507     return nullptr;
508 }
509 
CloseXML()510 void RCDConfig::CloseXML()
511 {
512     if (pDoc != nullptr) {
513         xmlFreeDoc(pDoc);
514         pDoc = nullptr;
515     }
516 }
517 
Clear()518 void RCDConfig::Clear()
519 {
520     for (auto& modelPtr : lcdModels) {
521         if (modelPtr != nullptr) {
522             delete modelPtr;
523             modelPtr = nullptr;
524         }
525     }
526 }
527 
~RCDConfig()528 RCDConfig::~RCDConfig()
529 {
530     Clear();
531 }
532 } // namespace rs_rcd
533 } // namespace Rosen
534 } // OHOS