1 /*
2 * Copyright (C) 2023-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 "wifi_app_parser.h"
16 #include <unordered_map>
17 #include "wifi_common_def.h"
18 #include "wifi_config_file_impl.h"
19 #include <algorithm>
20 #include "wifi_logger.h"
21 #include "json/json.h"
22
23 namespace OHOS {
24 namespace Wifi {
25 DEFINE_WIFILOG_LABEL("WifiAppXmlParser");
26
27 constexpr auto WIFI_MONITOR_APP_FILE_PATH = "/system/etc/wifi/wifi_monitor_apps.xml";
28 constexpr auto WIFI_MONITOR_CLOUD_PUSH_INSTALL_PATH = "/data/service/el1/public/update/param_service/install/system/";
29 constexpr auto WIFI_MONITOR_CLOUD_PUSH_FILE_PATH = "etc/WifiHighTemSpeedLimit/";
30 constexpr auto WIFI_MONITOR_CLOUD_PUSH_VERIOSN_FILE_NAME = "version.txt";
31 constexpr auto WIFI_MONITOR_CLOUD_PUSH_FILE_NAME = "HighTemperatureSpeedLimit.json";
32 constexpr auto XML_TAG_SECTION_HEADER_MONITOR_APP = "MonitorAPP";
33 constexpr auto XML_TAG_SECTION_HEADER_GAME_INFO = "GameInfo";
34 constexpr auto XML_TAG_SECTION_HEADER_APP_WHITE_LIST = "AppWhiteList";
35 constexpr auto XML_TAG_SECTION_HEADER_APP_BLACK_LIST = "AppBlackList";
36 constexpr auto XML_TAG_SECTION_HEADER_MULTILINK_BLACK_LIST = "MultiLinkBlackList";
37 constexpr auto XML_TAG_SECTION_HEADER_CHARIOT_APP = "ChariotApp";
38 constexpr auto XML_TAG_SECTION_HEADER_HIGH_TEMP_LIMIT_SPEED_APP = "HighTempLimitSpeedApp";
39 constexpr auto XML_TAG_SECTION_KEY_GAME_NAME = "gameName";
40 constexpr auto XML_TAG_SECTION_KEY_PACKAGE_NAME = "packageName";
41 constexpr auto VERSION_FILE_MAX_LINE = 50;
42 constexpr auto VERSION_FILE_KEY_WORD = "version=";
43 const char* XML_VERSION_NODE_NAME = "HighTempLimitSpeedAppVersionInfo";
44
45 const std::unordered_map<std::string, AppType> appTypeMap = {
46 { XML_TAG_SECTION_HEADER_GAME_INFO, AppType::LOW_LATENCY_APP },
47 { XML_TAG_SECTION_HEADER_APP_WHITE_LIST, AppType::WHITE_LIST_APP },
48 { XML_TAG_SECTION_HEADER_APP_BLACK_LIST, AppType::BLACK_LIST_APP },
49 { XML_TAG_SECTION_HEADER_MULTILINK_BLACK_LIST, AppType::MULTILINK_BLACK_LIST_APP },
50 { XML_TAG_SECTION_HEADER_CHARIOT_APP, AppType::CHARIOT_APP },
51 {XML_TAG_SECTION_HEADER_HIGH_TEMP_LIMIT_SPEED_APP, AppType::HIGH_TEMP_LIMIT_SPEED_APP},
52 };
53
AppParser()54 AppParser::AppParser()
55 {
56 WIFI_LOGI("%{public}s enter", __FUNCTION__);
57 }
58
~AppParser()59 AppParser::~AppParser()
60 {
61 WIFI_LOGI("%{public}s enter", __FUNCTION__);
62 }
63
GetInstance()64 AppParser &AppParser::GetInstance()
65 {
66 static AppParser instance;
67 return instance;
68 }
69
Init()70 bool AppParser::Init()
71 {
72 if (!initFlag_) {
73 if (IsReadCloudConfig()) {
74 ReadPackageCloudFilterConfig();
75 }
76 if (InitAppParser(WIFI_MONITOR_APP_FILE_PATH)) {
77 initFlag_ = true;
78 WIFI_LOGD("%{public}s InitAppParser successful", __FUNCTION__);
79 } else {
80 WIFI_LOGE("%{public}s InitAppParser fail", __FUNCTION__);
81 };
82 }
83 return initFlag_;
84 }
85
IsLowLatencyApp(const std::string & bundleName) const86 bool AppParser::IsLowLatencyApp(const std::string &bundleName) const
87 {
88 return std::any_of(m_lowLatencyAppVec.begin(), m_lowLatencyAppVec.end(),
89 [bundleName](const LowLatencyAppInfo &app) { return app.packageName == bundleName; });
90 }
91
IsWhiteListApp(const std::string & bundleName) const92 bool AppParser::IsWhiteListApp(const std::string &bundleName) const
93 {
94 return std::any_of(m_whiteAppVec.begin(), m_whiteAppVec.end(),
95 [bundleName](const WhiteListAppInfo &app) { return app.packageName == bundleName; });
96 }
97
IsBlackListApp(const std::string & bundleName) const98 bool AppParser::IsBlackListApp(const std::string &bundleName) const
99 {
100 return std::any_of(m_blackAppVec.begin(), m_blackAppVec.end(),
101 [bundleName](const BlackListAppInfo &app) { return app.packageName == bundleName; });
102 }
103
IsMultiLinkApp(const std::string & bundleName) const104 bool AppParser::IsMultiLinkApp(const std::string &bundleName) const
105 {
106 return std::any_of(m_multilinkAppVec.begin(), m_multilinkAppVec.end(),
107 [bundleName](const MultiLinkAppInfo &app) { return app.packageName == bundleName; });
108 }
109
IsChariotApp(const std::string & bundleName) const110 bool AppParser::IsChariotApp(const std::string &bundleName) const
111 {
112 return std::any_of(m_chariotAppVec.begin(), m_chariotAppVec.end(),
113 [bundleName](const ChariotAppInfo &app) { return app.packageName == bundleName; });
114 }
115
IsHighTempLimitSpeedApp(const std::string & bundleName) const116 bool AppParser::IsHighTempLimitSpeedApp(const std::string &bundleName) const
117 {
118 if (mIshighTempLimitSpeedReadCloudPush) {
119 return std::any_of(m_highTempLimitSpeedAppVecCloudPush.begin(), m_highTempLimitSpeedAppVecCloudPush.end(),
120 [bundleName](const HighTempLimitSpeedAppInfo &app) { return app.packageName == bundleName; });
121 } else {
122 return std::any_of(m_highTempLimitSpeedAppVec.begin(), m_highTempLimitSpeedAppVec.end(),
123 [bundleName](const HighTempLimitSpeedAppInfo &app) { return app.packageName == bundleName; });
124 }
125 }
126
InitAppParser(const char * appXmlFilePath)127 bool AppParser::InitAppParser(const char *appXmlFilePath)
128 {
129 if (appXmlFilePath == nullptr) {
130 WIFI_LOGE("%{public}s appXmlFilePath is null", __FUNCTION__);
131 return false;
132 }
133 std::string xmlPath(appXmlFilePath);
134 std::filesystem::path pathName = xmlPath;
135 std::error_code code;
136 if (!std::filesystem::exists(pathName, code)) {
137 WIFI_LOGE("%{public}s %{public}s not exists", __FUNCTION__, appXmlFilePath);
138 return false;
139 }
140 bool ret = LoadConfiguration(appXmlFilePath);
141 if (!ret) {
142 WIFI_LOGE("%{public}s load failed", __FUNCTION__);
143 return ret;
144 }
145 ret = Parse();
146 if (!ret) {
147 WIFI_LOGE("%{public}s parse failed", __FUNCTION__);
148 return ret;
149 }
150 WIFI_LOGD("%{public}s, wifi monitor app xml parsed successfully", __FUNCTION__);
151 return ret;
152 }
153
ParseInternal(xmlNodePtr node)154 bool AppParser::ParseInternal(xmlNodePtr node)
155 {
156 if (node == nullptr) {
157 WIFI_LOGE("%{public}s node is null", __FUNCTION__);
158 return false;
159 }
160 ParseAppList(node);
161 return true;
162 }
163
ParseAppList(const xmlNodePtr & innode)164 void AppParser::ParseAppList(const xmlNodePtr &innode)
165 {
166 if (xmlStrcmp(innode->name, BAD_CAST(XML_TAG_SECTION_HEADER_MONITOR_APP)) != 0) {
167 WIFI_LOGE("innode name=%{public}s not equal MonitorAPP", innode->name);
168 return;
169 }
170 m_lowLatencyAppVec.clear();
171 m_whiteAppVec.clear();
172 m_blackAppVec.clear();
173 m_multilinkAppVec.clear();
174 m_chariotAppVec.clear();
175 m_highTempLimitSpeedAppVec.clear();
176 for (xmlNodePtr node = innode->children; node != nullptr; node = node->next) {
177 switch (GetAppTypeAsInt(node)) {
178 case AppType::LOW_LATENCY_APP:
179 m_lowLatencyAppVec.push_back(ParseLowLatencyAppInfo(node));
180 break;
181 case AppType::WHITE_LIST_APP:
182 m_whiteAppVec.push_back(ParseWhiteAppInfo(node));
183 break;
184 case AppType::BLACK_LIST_APP:
185 m_blackAppVec.push_back(ParseBlackAppInfo(node));
186 break;
187 case AppType::MULTILINK_BLACK_LIST_APP:
188 m_multilinkAppVec.push_back(ParseMultiLinkAppInfo(node));
189 break;
190 case AppType::CHARIOT_APP:
191 m_chariotAppVec.push_back(ParseChariotAppInfo(node));
192 break;
193 case AppType::HIGH_TEMP_LIMIT_SPEED_APP:
194 m_highTempLimitSpeedAppVec.push_back(ParseHighTempLimitSpeedAppInfo(node));
195 break;
196 default:
197 WIFI_LOGD("app type: %{public}s is not monitored", GetNodeValue(node).c_str());
198 break;
199 }
200 }
201 WIFI_LOGI("%{public}s out,m_highTempLimitSpeedAppVec count:%{public}d!",
202 __FUNCTION__, (int)m_highTempLimitSpeedAppVec.size());
203 WIFI_LOGI("%{public}s out,m_multilinkAppVec count:%{public}d!",
204 __FUNCTION__, (int)m_multilinkAppVec.size());
205 }
206
ParseLowLatencyAppInfo(const xmlNodePtr & innode)207 LowLatencyAppInfo AppParser::ParseLowLatencyAppInfo(const xmlNodePtr &innode)
208 {
209 LowLatencyAppInfo appInfo;
210 xmlChar *value = xmlGetProp(innode, BAD_CAST(XML_TAG_SECTION_KEY_GAME_NAME));
211 std::string gameName = std::string(reinterpret_cast<char *>(value));
212 appInfo.packageName = gameName;
213 xmlFree(value);
214 return appInfo;
215 }
216
ParseWhiteAppInfo(const xmlNodePtr & innode)217 WhiteListAppInfo AppParser::ParseWhiteAppInfo(const xmlNodePtr &innode)
218 {
219 WhiteListAppInfo appInfo;
220 xmlChar *value = xmlGetProp(innode, BAD_CAST(XML_TAG_SECTION_KEY_PACKAGE_NAME));
221 std::string packageName = std::string(reinterpret_cast<char *>(value));
222 appInfo.packageName = packageName;
223 xmlFree(value);
224 return appInfo;
225 }
226
ParseBlackAppInfo(const xmlNodePtr & innode)227 BlackListAppInfo AppParser::ParseBlackAppInfo(const xmlNodePtr &innode)
228 {
229 BlackListAppInfo appInfo;
230 xmlChar *value = xmlGetProp(innode, BAD_CAST(XML_TAG_SECTION_KEY_PACKAGE_NAME));
231 std::string packageName = std::string(reinterpret_cast<char *>(value));
232 appInfo.packageName = packageName;
233 xmlFree(value);
234 return appInfo;
235 }
236
ParseMultiLinkAppInfo(const xmlNodePtr & innode)237 MultiLinkAppInfo AppParser::ParseMultiLinkAppInfo(const xmlNodePtr &innode)
238 {
239 MultiLinkAppInfo appInfo;
240 xmlChar *value = xmlGetProp(innode, BAD_CAST(XML_TAG_SECTION_KEY_PACKAGE_NAME));
241 std::string packageName = std::string(reinterpret_cast<char *>(value));
242 appInfo.packageName = packageName;
243 WIFI_LOGD("%{public}s packageName:%{public}s", __FUNCTION__, packageName.c_str());
244 xmlFree(value);
245 return appInfo;
246 }
247
ParseChariotAppInfo(const xmlNodePtr & innode)248 ChariotAppInfo AppParser::ParseChariotAppInfo(const xmlNodePtr &innode)
249 {
250 ChariotAppInfo appInfo;
251 xmlChar *value = xmlGetProp(innode, BAD_CAST(XML_TAG_SECTION_KEY_PACKAGE_NAME));
252 std::string packageName = std::string(reinterpret_cast<char *>(value));
253 appInfo.packageName = packageName;
254 xmlFree(value);
255 return appInfo;
256 }
257
ParseHighTempLimitSpeedAppInfo(const xmlNodePtr & innode)258 HighTempLimitSpeedAppInfo AppParser::ParseHighTempLimitSpeedAppInfo(const xmlNodePtr &innode)
259 {
260 HighTempLimitSpeedAppInfo appInfo;
261 xmlChar *value = xmlGetProp(innode, BAD_CAST(XML_TAG_SECTION_KEY_PACKAGE_NAME));
262 std::string packageName = std::string(reinterpret_cast<char *>(value));
263 appInfo.packageName = packageName;
264 xmlFree(value);
265 return appInfo;
266 }
267
GetAppTypeAsInt(const xmlNodePtr & innode)268 AppType AppParser::GetAppTypeAsInt(const xmlNodePtr &innode)
269 {
270 std::string tagName = GetNodeValue(innode);
271 if (appTypeMap.find(tagName) != appTypeMap.end()) {
272 return appTypeMap.at(tagName);
273 }
274 WIFI_LOGD("%{public}s not find targName:%{public}s in appTypeMap", __FUNCTION__, tagName.c_str());
275 return AppType::OTHER_APP;
276 }
277
ReadPackageCloudFilterConfig()278 bool AppParser::ReadPackageCloudFilterConfig()
279 {
280 WIFI_LOGI("%{public}s enter!", __FUNCTION__);
281 std::ifstream ifs;
282 ifs.open(GetCloudPushJsonFilePath().c_str());
283 if (!ifs.is_open()) {
284 WIFI_LOGE("%{public}s json file not exist,%{public}s!", __FUNCTION__, GetCloudPushJsonFilePath().c_str());
285 return false;
286 }
287 std::stringstream buffer;
288 buffer << ifs.rdbuf();
289 std::string jsonString = buffer.str();
290 Json::Value root;
291 Json::Reader reader;
292 ifs.close();
293 bool success = reader.parse(jsonString, root);
294 if (!success) {
295 WIFI_LOGE("%{public}s Failed to parse JSON data!", __FUNCTION__);
296 return false;
297 }
298 if (!root.isMember("HighTemperatureSpeedLimit")) {
299 WIFI_LOGE("%{public}s Failed to parse JSON data,no member HighTemperatureSpeedLimit!", __FUNCTION__);
300 return false;
301 }
302 int nSize = 0;
303 m_highTempLimitSpeedAppVecCloudPush.clear();
304 Json::Value packageName = root["HighTemperatureSpeedLimit"];
305 if (packageName.isArray()) {
306 m_highTempLimitSpeedAppVecCloudPush.clear();
307 HighTempLimitSpeedAppInfo appInfo;
308 nSize = (int)packageName.size();
309 for (int i = 0; i < nSize; ++i) {
310 appInfo.packageName = packageName[i].asString();
311 m_highTempLimitSpeedAppVecCloudPush.push_back(appInfo);
312 }
313 } else {
314 WIFI_LOGE("%{public}s Failed , JSON data Not ARRAY!", __FUNCTION__);
315 return false;
316 }
317 WIFI_LOGI("%{public}s out,count:%{public}d!", __FUNCTION__, nSize);
318 return true;
319 }
320
IsReadCloudConfig()321 bool AppParser::IsReadCloudConfig()
322 {
323 std::string strLocal = GetLocalFileVersion(WIFI_MONITOR_APP_FILE_PATH);
324 std::string strCloud = GetCloudPushFileVersion(GetCloudPushVersionFilePath().c_str());
325 bool isReadCloudConfig = (strCloud > strLocal) || (strCloud.empty() && strLocal.empty());
326 WIFI_LOGI("%{public}s out,IsReadCloudConfig:%{public}d,strLocal=%{public}s,strCloud =%{public}s !", __FUNCTION__,
327 isReadCloudConfig, strLocal.c_str(), strCloud.c_str());
328 mIshighTempLimitSpeedReadCloudPush = isReadCloudConfig;
329 return isReadCloudConfig;
330 }
331
GetCloudPushFileVersion(const char * appVersionFilePath)332 std::string AppParser::GetCloudPushFileVersion(const char *appVersionFilePath)
333 {
334 if (appVersionFilePath == nullptr) {
335 return "";
336 }
337 std::string strFileVersion = "";
338 std::ifstream ifs;
339 ifs.open(appVersionFilePath);
340 bool isVersionFileExist = ifs.is_open();
341 if (!isVersionFileExist) {
342 WIFI_LOGE("%{public}s %{public}s not exists", __FUNCTION__, appVersionFilePath);
343 return strFileVersion;
344 }
345 int nLineCount = 0;
346 std::string strTemp = "";
347 while (getline(ifs, strTemp)) {
348 if (nLineCount > VERSION_FILE_MAX_LINE) {
349 WIFI_LOGE("%{public}s %{public}s Failed to parse local version data!", __FUNCTION__, appVersionFilePath);
350 break;
351 }
352 nLineCount++;
353 int nPos = strTemp.find(VERSION_FILE_KEY_WORD);
354 if (nPos != -1) {
355 strFileVersion = strTemp.substr(nPos + strlen(VERSION_FILE_KEY_WORD),
356 strTemp.length() - nPos - strlen(VERSION_FILE_KEY_WORD));
357 break;
358 }
359 }
360 ifs.close();
361 return strFileVersion;
362 }
363
GetLocalFileVersion(const char * appXmlVersionFilePath)364 std::string AppParser::GetLocalFileVersion(const char *appXmlVersionFilePath)
365 {
366 WIFI_LOGI("%{public}s enter!", __FUNCTION__);
367 std::string strFileVersion = "";
368 if (appXmlVersionFilePath == nullptr) {
369 WIFI_LOGE("%{public}s appXmlVersionFilePath null!", __FUNCTION__);
370 return strFileVersion;
371 }
372 std::string xmlPath(appXmlVersionFilePath);
373 std::filesystem::path pathName = xmlPath;
374 std::error_code code;
375 if (!std::filesystem::exists(xmlPath, code)) {
376 WIFI_LOGE("%{public}s %{public}s not exists", __FUNCTION__, appXmlVersionFilePath);
377 return strFileVersion;
378 }
379 xmlDoc *xmlObj = xmlReadFile(appXmlVersionFilePath, nullptr, XML_PARSE_NOBLANKS);
380 if (xmlObj == nullptr) {
381 WIFI_LOGE("%{public}s xmlReadFile failed", __FUNCTION__);
382 return strFileVersion;
383 }
384 do {
385 xmlNodePtr root = xmlDocGetRootElement(xmlObj);
386 if (root == nullptr) {
387 WIFI_LOGE("%{public}s Parse root null!", __FUNCTION__);
388 break;
389 }
390 xmlNodePtr cur = root;
391 xmlNodePtr pNode = nullptr;
392 cur = cur->xmlChildrenNode;
393 while (cur != NULL) {
394 if ((xmlStrcmp(cur->name, (const xmlChar *)XML_VERSION_NODE_NAME)==0)) {
395 pNode = cur;
396 break;
397 }
398 cur = cur->next;
399 }
400 if (pNode == nullptr) {
401 WIFI_LOGE("%{public}s VersionInfo not find", __FUNCTION__);
402 break;
403 }
404 strFileVersion = GetStringValue(pNode);
405 } while (0);
406
407 if (xmlObj != nullptr) {
408 xmlFreeDoc(xmlObj);
409 xmlCleanupParser();
410 xmlObj = nullptr;
411 }
412 return strFileVersion;
413 }
414
GetCloudPushVersionFilePath()415 std::string AppParser::GetCloudPushVersionFilePath()
416 {
417 std::string path = WIFI_MONITOR_CLOUD_PUSH_INSTALL_PATH;
418 path += WIFI_MONITOR_CLOUD_PUSH_FILE_PATH;
419 return path + WIFI_MONITOR_CLOUD_PUSH_VERIOSN_FILE_NAME;
420 }
421
GetCloudPushJsonFilePath()422 std::string AppParser::GetCloudPushJsonFilePath()
423 {
424 std::string path = WIFI_MONITOR_CLOUD_PUSH_INSTALL_PATH;
425 path += WIFI_MONITOR_CLOUD_PUSH_FILE_PATH;
426 return path + WIFI_MONITOR_CLOUD_PUSH_FILE_NAME;
427 }
428 } // namespace Wifi
429 } // namespace OHOS