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
16 #include "updater_ui_config.h"
17 #include "common/screen.h"
18 #include "control/callback_manager.h"
19 #include "language/language_ui.h"
20 #include "layout/layout_parser.h"
21 #include "log/log.h"
22 #include "utils.h"
23
24 namespace Updater {
25 namespace Fs = std::filesystem;
26 namespace {
27 constexpr auto UI_CFG_FILE = "/resources/pages/config.json";
28 constexpr auto UI_CFG_KEY = "config";
29 constexpr auto WIDTH_KEY = "screenWidth";
30 constexpr auto HEIGHT_KEY = "screenHeight";
31 constexpr auto FOCUS_CFG_FIELD = "enableFoucs";
32
CanonicalPagePath(PagePath & pagePath)33 bool CanonicalPagePath(PagePath &pagePath)
34 {
35 if (!Utils::PathToRealPath(pagePath.dir, pagePath.dir)) {
36 LOG(ERROR) << "page path canonical failed, please check your config, dir = " << pagePath.dir;
37 return false;
38 }
39 for (auto &file : pagePath.pages) {
40 file = pagePath.dir + "/" + file;
41 }
42 return true;
43 }
44
operator <<(std::ostream & os,const UxViewCommonInfo & info)45 std::ostream &operator<<(std::ostream &os, const UxViewCommonInfo &info)
46 {
47 os << "x=" << info.x << ", y=" << info.y << ", w=" << info.w << ", h=" << info.h << ", id=";
48 os << info.id << ", type=" << info.type << ", visible=" << info.visible;
49 return os;
50 }
51
operator <<(std::ostream & os,const UxPageInfo & info)52 std::ostream &operator<<(std::ostream &os, const UxPageInfo &info)
53 {
54 LOG(INFO) << "page:" << info.id;
55 for (auto &it : info.viewInfos) {
56 LOG(INFO) << it.commonInfo;
57 }
58 return os;
59 }
60
PrintInfoVec(const std::vector<UxPageInfo> & infoVec)61 void PrintInfoVec(const std::vector<UxPageInfo> &infoVec)
62 {
63 LOG(INFO) << "=====print start=====";
64 for (auto &iter : infoVec) {
65 LOG(INFO) << iter;
66 }
67 LOG(INFO) << "=====print end=====";
68 }
69
SelectConfig(const JsonNode & node)70 std::string SelectConfig(const JsonNode &node)
71 {
72 using namespace OHOS;
73 for (const auto &iter : node) {
74 const JsonNode &subCfgPathNode = iter.get();
75 auto optStr = subCfgPathNode.As<std::string>();
76 if (!optStr.has_value()) {
77 LOG(ERROR) << "config array's element should be string";
78 return "";
79 }
80 std::string subConfigPath = *optStr;
81 const JsonNode &subCfg = JsonNode { Fs::path { subConfigPath }};
82 auto screenW = subCfg[WIDTH_KEY].As<int16_t>();
83 auto screenH = subCfg[HEIGHT_KEY].As<int16_t>();
84 if (!screenW.has_value() || !screenH.has_value()) {
85 LOG(ERROR) << "real config file should has screenW and screenH key";
86 return "";
87 }
88 if (screenW != Screen::GetInstance().GetWidth() || screenH != Screen::GetInstance().GetHeight()) {
89 LOG(INFO) << "screen size not matched" << subConfigPath;
90 continue;
91 }
92 LOG(INFO) << "select config: " << subConfigPath;
93 return subConfigPath;
94 }
95 LOG(ERROR) << "no config matched";
96 return "";
97 }
98 } // namespace
99
100 bool UpdaterUiConfig::isFocusEnable_ {false};
101
Init()102 bool UpdaterUiConfig::Init()
103 {
104 JsonNode node { Fs::path { UI_CFG_FILE }};
105 const JsonNode &cfgNode = node[UI_CFG_KEY];
106 switch (cfgNode.Type()) {
107 case NodeType::STRING: {
108 auto optString = cfgNode.As<std::string>();
109 if (!optString.has_value()) {
110 LOG(ERROR) << "config path should be string";
111 break;
112 }
113 JsonNode realNode { Fs::path { *optString }};
114 return Init(realNode);
115 }
116 case NodeType::ARRAY: {
117 std::string realConfig = SelectConfig(cfgNode);
118 if (realConfig.empty()) {
119 break;
120 }
121 JsonNode realNode { Fs::path { realConfig }};
122 return Init(realNode);
123 }
124 default:
125 break;
126 }
127 LOG(ERROR) << "config file parse failed: " << UI_CFG_FILE;
128 return false;
129 }
130
Init(const JsonNode & node)131 bool UpdaterUiConfig::Init(const JsonNode &node)
132 {
133 static bool res = [&node] () {
134 return LoadLangRes(node) && LoadStrategy(node) && LoadCallbacks(node) && LoadFocusCfg(node) && LoadPages(node);
135 } ();
136 return res;
137 }
138
GetStrategy()139 const std::unordered_map<UpdaterMode, UiStrategyCfg> &UpdaterUiConfig::GetStrategy()
140 {
141 return UiStrategy::GetStrategy();
142 }
143
GetFocusCfg()144 bool UpdaterUiConfig::GetFocusCfg()
145 {
146 return isFocusEnable_;
147 }
148
LoadPages(const JsonNode & node)149 bool UpdaterUiConfig::LoadPages(const JsonNode &node)
150 {
151 PagePath pagePath {};
152 if (!Visit<SETVAL>(node, pagePath)) {
153 LOG(ERROR) << "parse page path error: " << pagePath.dir;
154 return false;
155 }
156
157 if (!CanonicalPagePath(pagePath)) {
158 return false;
159 }
160
161 std::vector<UxPageInfo> pageInfos {};
162 if (!LayoutParser::GetInstance().LoadLayout(pagePath.pages, pageInfos)) {
163 LOG(ERROR) << "load layout error: " << UI_CFG_FILE;
164 return false;
165 }
166 if (!PageManager::GetInstance().Init(pageInfos, pagePath.entry)) {
167 LOG(ERROR) << "page manager init error";
168 return false;
169 }
170 PrintInfoVec(pageInfos);
171 return true;
172 }
173
LoadLangRes(const JsonNode & node)174 bool UpdaterUiConfig::LoadLangRes(const JsonNode &node)
175 {
176 return Lang::LanguageUI::GetInstance().LoadLangRes(node);
177 }
178
LoadStrategy(const JsonNode & node)179 bool UpdaterUiConfig::LoadStrategy(const JsonNode &node)
180 {
181 return UiStrategy::LoadStrategy(node);
182 }
183
LoadCallbacks(const JsonNode & node)184 bool UpdaterUiConfig::LoadCallbacks(const JsonNode &node)
185 {
186 return CallbackManager::LoadCallbacks(node);
187 }
188
LoadFocusCfg(const JsonNode & node)189 bool UpdaterUiConfig::LoadFocusCfg(const JsonNode &node)
190 {
191 // disable focus by default
192 isFocusEnable_ = node[FOCUS_CFG_FIELD].As<bool>().value_or(false);
193 return true;
194 }
195 } // namespace Updater