1020a203aSopenharmony_ci/* 2020a203aSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4020a203aSopenharmony_ci * you may not use this file except in compliance with the License. 5020a203aSopenharmony_ci * You may obtain a copy of the License at 6020a203aSopenharmony_ci * 7020a203aSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8020a203aSopenharmony_ci * 9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12020a203aSopenharmony_ci * See the License for the specific language governing permissions and 13020a203aSopenharmony_ci * limitations under the License. 14020a203aSopenharmony_ci */ 15020a203aSopenharmony_ci 16020a203aSopenharmony_ci#include "rule_cluster.h" 17020a203aSopenharmony_ci 18020a203aSopenharmony_ci#include <sstream> 19020a203aSopenharmony_ci#include <sys/stat.h> 20020a203aSopenharmony_ci#include <unistd.h> 21020a203aSopenharmony_ci 22020a203aSopenharmony_ci#include "hiview_logger.h" 23020a203aSopenharmony_ci 24020a203aSopenharmony_cinamespace OHOS { 25020a203aSopenharmony_cinamespace HiviewDFX { 26020a203aSopenharmony_ciDEFINE_LOG_LABEL(0xD002D01, "FreezeDetector"); 27020a203aSopenharmony_cinamespace { 28020a203aSopenharmony_ci static constexpr const char* const DEFAULT_RULE_FILE = "/system/etc/hiview/freeze_rules.xml"; 29020a203aSopenharmony_ci static constexpr const char* const TAG_FREEZE = "freeze"; 30020a203aSopenharmony_ci static constexpr const char* const TAG_RULES = "rules"; 31020a203aSopenharmony_ci static constexpr const char* const TAG_RULE = "rule"; 32020a203aSopenharmony_ci static constexpr const char* const TAG_LINKS = "links"; 33020a203aSopenharmony_ci static constexpr const char* const TAG_EVENT = "event"; 34020a203aSopenharmony_ci static constexpr const char* const TAG_RESULT = "result"; 35020a203aSopenharmony_ci static constexpr const char* const TAG_RELEVANCE = "relevance"; 36020a203aSopenharmony_ci static constexpr const char* const ATTRIBUTE_ID = "id"; 37020a203aSopenharmony_ci static constexpr const char* const ATTRIBUTE_WINDOW = "window"; 38020a203aSopenharmony_ci static constexpr const char* const ATTRIBUTE_DOMAIN = "domain"; 39020a203aSopenharmony_ci static constexpr const char* const ATTRIBUTE_STRINGID = "stringid"; 40020a203aSopenharmony_ci static constexpr const char* const ATTRIBUTE_TYPE = "type"; 41020a203aSopenharmony_ci static constexpr const char* const ATTRIBUTE_USER = "user"; 42020a203aSopenharmony_ci static constexpr const char* const ATTRIBUTE_WATCHPOINT = "watchpoint"; 43020a203aSopenharmony_ci static constexpr const char* const ATTRIBUTE_CODE = "code"; 44020a203aSopenharmony_ci static constexpr const char* const ATTRIBUTE_SCOPE = "scope"; 45020a203aSopenharmony_ci static constexpr const char* const ATTRIBUTE_SAME_PACKAGE = "samePackage"; 46020a203aSopenharmony_ci static constexpr const char* const ATTRIBUTE_ACTION = "action"; 47020a203aSopenharmony_ci static constexpr const char* const ATTRIBUTE_APPLICATION = "application"; 48020a203aSopenharmony_ci static constexpr const char* const ATTRIBUTE_SYSTEM = "system"; 49020a203aSopenharmony_ci static const int MAX_FILE_SIZE = 512 * 1024; 50020a203aSopenharmony_ci} 51020a203aSopenharmony_ci 52020a203aSopenharmony_ciFreezeRuleCluster::FreezeRuleCluster() 53020a203aSopenharmony_ci{ 54020a203aSopenharmony_ci rules_.clear(); 55020a203aSopenharmony_ci} 56020a203aSopenharmony_ci 57020a203aSopenharmony_ciFreezeRuleCluster::~FreezeRuleCluster() 58020a203aSopenharmony_ci{ 59020a203aSopenharmony_ci rules_.clear(); 60020a203aSopenharmony_ci} 61020a203aSopenharmony_ci 62020a203aSopenharmony_cibool FreezeRuleCluster::Init() 63020a203aSopenharmony_ci{ 64020a203aSopenharmony_ci if (access(DEFAULT_RULE_FILE, R_OK) != 0) { 65020a203aSopenharmony_ci HIVIEW_LOGE("cannot access rule file."); 66020a203aSopenharmony_ci return false; 67020a203aSopenharmony_ci } 68020a203aSopenharmony_ci 69020a203aSopenharmony_ci if (CheckFileSize(DEFAULT_RULE_FILE) == false) { 70020a203aSopenharmony_ci HIVIEW_LOGE("bad rule file size."); 71020a203aSopenharmony_ci return false; 72020a203aSopenharmony_ci } 73020a203aSopenharmony_ci 74020a203aSopenharmony_ci if (ParseRuleFile(DEFAULT_RULE_FILE) == false) { 75020a203aSopenharmony_ci HIVIEW_LOGE("failed to parse rule file."); 76020a203aSopenharmony_ci return false; 77020a203aSopenharmony_ci } 78020a203aSopenharmony_ci 79020a203aSopenharmony_ci if (rules_.size() == 0) { 80020a203aSopenharmony_ci HIVIEW_LOGE("no rule in rule file."); 81020a203aSopenharmony_ci return false; 82020a203aSopenharmony_ci } 83020a203aSopenharmony_ci 84020a203aSopenharmony_ci return true; 85020a203aSopenharmony_ci} 86020a203aSopenharmony_ci 87020a203aSopenharmony_cibool FreezeRuleCluster::CheckFileSize(const std::string& path) 88020a203aSopenharmony_ci{ 89020a203aSopenharmony_ci struct stat st; 90020a203aSopenharmony_ci if (stat(path.c_str(), &st) != 0) { 91020a203aSopenharmony_ci return false; 92020a203aSopenharmony_ci } 93020a203aSopenharmony_ci if (st.st_size > MAX_FILE_SIZE) { 94020a203aSopenharmony_ci return false; 95020a203aSopenharmony_ci } 96020a203aSopenharmony_ci return true; 97020a203aSopenharmony_ci} 98020a203aSopenharmony_ci 99020a203aSopenharmony_cibool FreezeRuleCluster::ParseRuleFile(const std::string& file) 100020a203aSopenharmony_ci{ 101020a203aSopenharmony_ci xmlDoc* doc = xmlReadFile(file.c_str(), nullptr, 0); 102020a203aSopenharmony_ci if (doc == nullptr) { 103020a203aSopenharmony_ci HIVIEW_LOGE("failed to read rule file."); 104020a203aSopenharmony_ci return false; 105020a203aSopenharmony_ci } 106020a203aSopenharmony_ci 107020a203aSopenharmony_ci xmlNode* root = xmlDocGetRootElement(doc); 108020a203aSopenharmony_ci if (root == nullptr) { 109020a203aSopenharmony_ci HIVIEW_LOGE("failed to get root element in rule file."); 110020a203aSopenharmony_ci xmlFreeDoc(doc); 111020a203aSopenharmony_ci doc = nullptr; 112020a203aSopenharmony_ci return false; 113020a203aSopenharmony_ci } 114020a203aSopenharmony_ci 115020a203aSopenharmony_ci for (xmlNode* node = root; node; node = node->next) { 116020a203aSopenharmony_ci if (node->type != XML_ELEMENT_NODE) { 117020a203aSopenharmony_ci continue; 118020a203aSopenharmony_ci } 119020a203aSopenharmony_ci if (TAG_FREEZE == std::string((char*)(node->name))) { 120020a203aSopenharmony_ci ParseTagFreeze(node); 121020a203aSopenharmony_ci break; 122020a203aSopenharmony_ci } 123020a203aSopenharmony_ci } 124020a203aSopenharmony_ci 125020a203aSopenharmony_ci xmlFreeDoc(doc); 126020a203aSopenharmony_ci doc = nullptr; 127020a203aSopenharmony_ci return true; 128020a203aSopenharmony_ci} 129020a203aSopenharmony_ci 130020a203aSopenharmony_civoid FreezeRuleCluster::ParseTagFreeze(xmlNode* tag) 131020a203aSopenharmony_ci{ 132020a203aSopenharmony_ci for (xmlNode* node = tag->children; node; node = node->next) { 133020a203aSopenharmony_ci if (TAG_RULES == std::string((char*)(node->name))) { 134020a203aSopenharmony_ci ParseTagRules(node); 135020a203aSopenharmony_ci } 136020a203aSopenharmony_ci } 137020a203aSopenharmony_ci} 138020a203aSopenharmony_ci 139020a203aSopenharmony_civoid FreezeRuleCluster::ParseTagRules(xmlNode* tag) 140020a203aSopenharmony_ci{ 141020a203aSopenharmony_ci for (xmlNode* node = tag->children; node; node = node->next) { 142020a203aSopenharmony_ci if (TAG_RULE == std::string((char*)(node->name))) { 143020a203aSopenharmony_ci ParseTagRule(node); 144020a203aSopenharmony_ci } 145020a203aSopenharmony_ci } 146020a203aSopenharmony_ci} 147020a203aSopenharmony_ci 148020a203aSopenharmony_civoid FreezeRuleCluster::ParseTagRule(xmlNode* tag) 149020a203aSopenharmony_ci{ 150020a203aSopenharmony_ci std::string domain = GetAttributeValue<std::string>(tag, ATTRIBUTE_DOMAIN); 151020a203aSopenharmony_ci if (domain == "") { 152020a203aSopenharmony_ci HIVIEW_LOGE("null rule attribute:domain."); 153020a203aSopenharmony_ci return; 154020a203aSopenharmony_ci } 155020a203aSopenharmony_ci std::string stringId = GetAttributeValue<std::string>(tag, ATTRIBUTE_STRINGID); 156020a203aSopenharmony_ci if (stringId == "") { 157020a203aSopenharmony_ci HIVIEW_LOGE("null rule attribute:stringid."); 158020a203aSopenharmony_ci return; 159020a203aSopenharmony_ci } 160020a203aSopenharmony_ci 161020a203aSopenharmony_ci FreezeRule rule = FreezeRule(domain, stringId); 162020a203aSopenharmony_ci 163020a203aSopenharmony_ci for (xmlNode* node = tag->children; node; node = node->next) { 164020a203aSopenharmony_ci if (TAG_LINKS == std::string((char*)(node->name))) { 165020a203aSopenharmony_ci ParseTagLinks(node, rule); 166020a203aSopenharmony_ci } 167020a203aSopenharmony_ci } 168020a203aSopenharmony_ci 169020a203aSopenharmony_ci if (rules_.find(domain + stringId) != rules_.end()) { 170020a203aSopenharmony_ci HIVIEW_LOGE("skip duplicated rule, stringid:%{public}s.", stringId.c_str()); 171020a203aSopenharmony_ci return; 172020a203aSopenharmony_ci } 173020a203aSopenharmony_ci 174020a203aSopenharmony_ci rules_[domain + stringId] = rule; 175020a203aSopenharmony_ci} 176020a203aSopenharmony_ci 177020a203aSopenharmony_civoid FreezeRuleCluster::ParseTagLinks(xmlNode* tag, FreezeRule& rule) 178020a203aSopenharmony_ci{ 179020a203aSopenharmony_ci for (xmlNode* node = tag->children; node; node = node->next) { 180020a203aSopenharmony_ci if (TAG_EVENT == std::string((char*)(node->name))) { 181020a203aSopenharmony_ci std::string domain = GetAttributeValue<std::string>(node, ATTRIBUTE_DOMAIN); 182020a203aSopenharmony_ci if (domain == "") { 183020a203aSopenharmony_ci HIVIEW_LOGE("null event attribute:domain."); 184020a203aSopenharmony_ci return; 185020a203aSopenharmony_ci } 186020a203aSopenharmony_ci std::string stringId = GetAttributeValue<std::string>(node, ATTRIBUTE_STRINGID); 187020a203aSopenharmony_ci if (stringId == "") { 188020a203aSopenharmony_ci HIVIEW_LOGE("null event attribute:stringid."); 189020a203aSopenharmony_ci return; 190020a203aSopenharmony_ci } 191020a203aSopenharmony_ci 192020a203aSopenharmony_ci long window = GetAttributeValue<long>(node, ATTRIBUTE_WINDOW); 193020a203aSopenharmony_ci 194020a203aSopenharmony_ci FreezeResult result = FreezeResult(window, domain, stringId); 195020a203aSopenharmony_ci ParseTagEvent(node, result); 196020a203aSopenharmony_ci rule.AddResult(domain, stringId, result); 197020a203aSopenharmony_ci 198020a203aSopenharmony_ci bool principalPoint = false; 199020a203aSopenharmony_ci if (rule.GetDomain() == domain && rule.GetStringId() == stringId) { 200020a203aSopenharmony_ci principalPoint = true; 201020a203aSopenharmony_ci } 202020a203aSopenharmony_ci if (result.GetScope() == "app") { 203020a203aSopenharmony_ci applicationPairs_[stringId] = std::pair<std::string, bool>(domain, principalPoint); 204020a203aSopenharmony_ci } else if (result.GetScope() == "sys") { 205020a203aSopenharmony_ci systemPairs_[stringId] = std::pair<std::string, bool>(domain, principalPoint); 206020a203aSopenharmony_ci } else { 207020a203aSopenharmony_ci sysWarningPairs_[stringId] = std::pair<std::string, bool>(domain, principalPoint); 208020a203aSopenharmony_ci } 209020a203aSopenharmony_ci } 210020a203aSopenharmony_ci } 211020a203aSopenharmony_ci} 212020a203aSopenharmony_ci 213020a203aSopenharmony_civoid FreezeRuleCluster::ParseTagEvent(xmlNode* tag, FreezeResult& result) 214020a203aSopenharmony_ci{ 215020a203aSopenharmony_ci for (xmlNode* node = tag->children; node; node = node->next) { 216020a203aSopenharmony_ci if (TAG_RESULT == std::string((char*)(node->name))) { 217020a203aSopenharmony_ci ParseTagResult(node, result); 218020a203aSopenharmony_ci break; 219020a203aSopenharmony_ci } 220020a203aSopenharmony_ci } 221020a203aSopenharmony_ci} 222020a203aSopenharmony_ci 223020a203aSopenharmony_civoid FreezeRuleCluster::ParseTagResult(xmlNode* tag, FreezeResult& result) 224020a203aSopenharmony_ci{ 225020a203aSopenharmony_ci unsigned long code = GetAttributeValue<unsigned long>(tag, ATTRIBUTE_CODE); 226020a203aSopenharmony_ci std::string scope = GetAttributeValue<std::string>(tag, ATTRIBUTE_SCOPE); 227020a203aSopenharmony_ci std::string samePackage = GetAttributeValue<std::string>(tag, ATTRIBUTE_SAME_PACKAGE); 228020a203aSopenharmony_ci std::string action = GetAttributeValue<std::string>(tag, ATTRIBUTE_ACTION); 229020a203aSopenharmony_ci 230020a203aSopenharmony_ci result.SetId(code); 231020a203aSopenharmony_ci result.SetScope(scope); 232020a203aSopenharmony_ci result.SetSamePackage(samePackage); 233020a203aSopenharmony_ci result.SetAction(action); 234020a203aSopenharmony_ci} 235020a203aSopenharmony_ci 236020a203aSopenharmony_citemplate<typename T> 237020a203aSopenharmony_ciT FreezeRuleCluster::GetAttributeValue(xmlNode* node, const std::string& name) 238020a203aSopenharmony_ci{ 239020a203aSopenharmony_ci xmlChar* prop = xmlGetProp(node, (xmlChar*)(name.c_str())); 240020a203aSopenharmony_ci std::string propa = ""; 241020a203aSopenharmony_ci if (prop != nullptr) { 242020a203aSopenharmony_ci propa = (char*)prop; 243020a203aSopenharmony_ci } 244020a203aSopenharmony_ci std::istringstream istr(propa); 245020a203aSopenharmony_ci T value; 246020a203aSopenharmony_ci istr >> value; 247020a203aSopenharmony_ci xmlFree(prop); 248020a203aSopenharmony_ci return value; 249020a203aSopenharmony_ci} 250020a203aSopenharmony_ci 251020a203aSopenharmony_cibool FreezeRuleCluster::GetResult(const WatchPoint& watchPoint, std::vector<FreezeResult>& list) 252020a203aSopenharmony_ci{ 253020a203aSopenharmony_ci std::string domain = watchPoint.GetDomain(); 254020a203aSopenharmony_ci std::string stringId = watchPoint.GetStringId(); 255020a203aSopenharmony_ci if (rules_.find(domain + stringId) == rules_.end()) { 256020a203aSopenharmony_ci return false; 257020a203aSopenharmony_ci } 258020a203aSopenharmony_ci auto map = rules_[domain + stringId].GetMap(); 259020a203aSopenharmony_ci for (auto& i : map) { 260020a203aSopenharmony_ci list.push_back(i.second); 261020a203aSopenharmony_ci } 262020a203aSopenharmony_ci 263020a203aSopenharmony_ci if (list.empty()) { 264020a203aSopenharmony_ci return false; 265020a203aSopenharmony_ci } 266020a203aSopenharmony_ci return true; 267020a203aSopenharmony_ci} 268020a203aSopenharmony_ci 269020a203aSopenharmony_cistd::map<std::string, std::pair<std::string, bool>> FreezeRuleCluster::GetApplicationPairs() const 270020a203aSopenharmony_ci{ 271020a203aSopenharmony_ci return applicationPairs_; 272020a203aSopenharmony_ci} 273020a203aSopenharmony_ci 274020a203aSopenharmony_cistd::map<std::string, std::pair<std::string, bool>> FreezeRuleCluster::GetSystemPairs() const 275020a203aSopenharmony_ci{ 276020a203aSopenharmony_ci return systemPairs_; 277020a203aSopenharmony_ci} 278020a203aSopenharmony_ci 279020a203aSopenharmony_cistd::map<std::string, std::pair<std::string, bool>> FreezeRuleCluster::GetSysWarningPairs() const 280020a203aSopenharmony_ci{ 281020a203aSopenharmony_ci return sysWarningPairs_; 282020a203aSopenharmony_ci} 283020a203aSopenharmony_ci 284020a203aSopenharmony_cistd::string FreezeResult::GetDomain() const 285020a203aSopenharmony_ci{ 286020a203aSopenharmony_ci return domain_; 287020a203aSopenharmony_ci} 288020a203aSopenharmony_ci 289020a203aSopenharmony_cistd::string FreezeResult::GetStringId() const 290020a203aSopenharmony_ci{ 291020a203aSopenharmony_ci return stringId_; 292020a203aSopenharmony_ci} 293020a203aSopenharmony_ci 294020a203aSopenharmony_ciunsigned long FreezeResult::GetId() const 295020a203aSopenharmony_ci{ 296020a203aSopenharmony_ci return code_; 297020a203aSopenharmony_ci} 298020a203aSopenharmony_ci 299020a203aSopenharmony_civoid FreezeResult::SetId(unsigned long code) 300020a203aSopenharmony_ci{ 301020a203aSopenharmony_ci code_ = code; 302020a203aSopenharmony_ci} 303020a203aSopenharmony_ci 304020a203aSopenharmony_cistd::string FreezeResult::GetScope() const 305020a203aSopenharmony_ci{ 306020a203aSopenharmony_ci return scope_; 307020a203aSopenharmony_ci} 308020a203aSopenharmony_ci 309020a203aSopenharmony_civoid FreezeResult::SetScope(const std::string& scope) 310020a203aSopenharmony_ci{ 311020a203aSopenharmony_ci scope_ = scope; 312020a203aSopenharmony_ci} 313020a203aSopenharmony_ci 314020a203aSopenharmony_cilong FreezeResult::GetWindow() const 315020a203aSopenharmony_ci{ 316020a203aSopenharmony_ci return window_; 317020a203aSopenharmony_ci} 318020a203aSopenharmony_ci 319020a203aSopenharmony_cistd::string FreezeResult::GetSamePackage() const 320020a203aSopenharmony_ci{ 321020a203aSopenharmony_ci return samePackage_; 322020a203aSopenharmony_ci} 323020a203aSopenharmony_ci 324020a203aSopenharmony_civoid FreezeResult::SetSamePackage(const std::string& samePackage) 325020a203aSopenharmony_ci{ 326020a203aSopenharmony_ci samePackage_ = samePackage; 327020a203aSopenharmony_ci} 328020a203aSopenharmony_ci 329020a203aSopenharmony_cistd::string FreezeResult::GetAction() const 330020a203aSopenharmony_ci{ 331020a203aSopenharmony_ci return action_; 332020a203aSopenharmony_ci} 333020a203aSopenharmony_ci 334020a203aSopenharmony_civoid FreezeResult::SetAction(const std::string& action) 335020a203aSopenharmony_ci{ 336020a203aSopenharmony_ci action_ = action; 337020a203aSopenharmony_ci} 338020a203aSopenharmony_ci 339020a203aSopenharmony_cistd::string FreezeRule::GetDomain() const 340020a203aSopenharmony_ci{ 341020a203aSopenharmony_ci return domain_; 342020a203aSopenharmony_ci} 343020a203aSopenharmony_ci 344020a203aSopenharmony_civoid FreezeRule::SetDomain(const std::string& domain) 345020a203aSopenharmony_ci{ 346020a203aSopenharmony_ci domain_ = domain; 347020a203aSopenharmony_ci} 348020a203aSopenharmony_ci 349020a203aSopenharmony_cistd::string FreezeRule::GetStringId() const 350020a203aSopenharmony_ci{ 351020a203aSopenharmony_ci return stringId_; 352020a203aSopenharmony_ci} 353020a203aSopenharmony_ci 354020a203aSopenharmony_civoid FreezeRule::SetStringId(const std::string& stringId) 355020a203aSopenharmony_ci{ 356020a203aSopenharmony_ci stringId_ = stringId; 357020a203aSopenharmony_ci} 358020a203aSopenharmony_ci 359020a203aSopenharmony_cistd::map<std::string, FreezeResult> FreezeRule::GetMap() const 360020a203aSopenharmony_ci{ 361020a203aSopenharmony_ci return results_; 362020a203aSopenharmony_ci} 363020a203aSopenharmony_ci 364020a203aSopenharmony_civoid FreezeRule::AddResult(const std::string& domain, const std::string& stringId, const FreezeResult& result) 365020a203aSopenharmony_ci{ 366020a203aSopenharmony_ci if (results_.find(domain + stringId) != results_.end()) { 367020a203aSopenharmony_ci HIVIEW_LOGE("skip duplicated event tag, stringid:%{public}s.", stringId.c_str()); 368020a203aSopenharmony_ci return; 369020a203aSopenharmony_ci } 370020a203aSopenharmony_ci 371020a203aSopenharmony_ci results_[domain + stringId] = result; 372020a203aSopenharmony_ci} 373020a203aSopenharmony_ci 374020a203aSopenharmony_cibool FreezeRule::GetResult(const std::string& domain, const std::string& stringId, FreezeResult& result) 375020a203aSopenharmony_ci{ 376020a203aSopenharmony_ci if (results_.find(domain + stringId) == results_.end()) { 377020a203aSopenharmony_ci HIVIEW_LOGE("failed to find rule result, domain:%{public}s stringid:%{public}s.", 378020a203aSopenharmony_ci domain.c_str(), stringId.c_str()); 379020a203aSopenharmony_ci return false; 380020a203aSopenharmony_ci } 381020a203aSopenharmony_ci 382020a203aSopenharmony_ci result = results_[domain + stringId]; // take result back 383020a203aSopenharmony_ci return true; 384020a203aSopenharmony_ci} 385020a203aSopenharmony_ci} // namespace HiviewDFX 386020a203aSopenharmony_ci} // namespace OHOS 387