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 #include "reclaim_priority_constants.h"
16 #include "memmgr_log.h"
17 #include "xml_helper.h"
18 #include "kill_config.h"
19 
20 namespace OHOS {
21 namespace Memory {
22 namespace {
23     const std::string TAG = "KillConfig";
24     const unsigned int KILL_LEVEL_ITEMS__MAX_COUNT = 10;
25 }
26 
ClearKillLevelsMap()27 void KillConfig::ClearKillLevelsMap()
28 {
29     killLevelsMap_.clear();
30 }
31 
ParseConfig(const xmlNodePtr & rootNodePtr)32 void KillConfig::ParseConfig(const xmlNodePtr &rootNodePtr)
33 {
34     if (!XmlHelper::CheckNode(rootNodePtr) || !XmlHelper::HasChild(rootNodePtr)) {
35         HILOGD("Node exsist:%{public}d,has child node:%{public}d",
36                XmlHelper::CheckNode(rootNodePtr), XmlHelper::HasChild(rootNodePtr));
37         return;
38     }
39     for (xmlNodePtr currNode = rootNodePtr->xmlChildrenNode; currNode != nullptr; currNode = currNode->next) {
40         std::map<std::string, std::string> param;
41         XmlHelper::GetModuleParam(currNode, param);
42         if (!ParseKillLevelNode(currNode, param) || killLevelsMap_.size() > KILL_LEVEL_ITEMS__MAX_COUNT) {
43             /* if has error, clear set */
44             killLevelsMap_.clear();
45             break;
46         }
47     }
48     if (killLevelsMap_.empty()) {
49         return;
50     }
51     /* check if <memoryMB, minPriority> is increasing, if not, invalid. */
52     int lastPriority = RECLAIM_PRIORITY_MIN - 1;
53     for (auto it = killLevelsMap_.begin(); it != killLevelsMap_.end(); it++) {
54         HILOGD("KillConfig: memory:%{public}u prio:%{public}d lastPrio:%{public}d",
55                it->first, it->second, lastPriority);
56         if (it->second <= lastPriority) {
57             /* Priority list must be decreasing, if not, clear set */
58             HILOGE("KillConfig: memory:%{public}u prio:%{public}d invalid", it->first, it->second);
59             killLevelsMap_.clear();
60             break;
61         }
62         lastPriority = it->second;
63     }
64 }
65 
GetKillLevelsMap()66 const KillConfig::KillLevelsMap& KillConfig::GetKillLevelsMap()
67 {
68     return killLevelsMap_;
69 }
70 
ParseKillLevelNode(const xmlNodePtr & currNodePtr,std::map<std::string,std::string> & param)71 bool KillConfig::ParseKillLevelNode(const xmlNodePtr &currNodePtr,
72                                     std::map<std::string, std::string> &param)
73 {
74     std::string name = std::string(reinterpret_cast<const char *>(currNodePtr->name));
75     if (name.compare("comment") == 0) {
76         HILOGD("%{public}s comment skip :<%{public}s>", __func__, name.c_str());
77         return true;
78     }
79     if (name.compare("killLevel") != 0) {
80         HILOGW("%{public}s unknown node :<%{public}s>", __func__, name.c_str());
81         return false;
82     }
83     unsigned int memoryMB;
84     int minPriority;
85     XmlHelper::SetUnsignedIntParam(param, "memoryMB", memoryMB, 0);
86     XmlHelper::SetIntParam(param, "minPriority", minPriority, RECLAIM_PRIORITY_MAX + 1);
87     /* if read from xml fail, error */
88     if (memoryMB == 0 || minPriority == (RECLAIM_PRIORITY_MAX + 1)) {
89         HILOGE("node:<%{public}s> <%{public}u, %{public}d> read fail", name.c_str(), memoryMB, minPriority);
90         return false;
91     }
92     if ((memoryMB * KB_PER_MB) > UINT_MAX) {
93         HILOGE("<%{public}s> %{public}u MB to KB > UINT_MAX", name.c_str(), memoryMB);
94         return false;
95     }
96     unsigned int memoryKB = memoryMB * KB_PER_MB; /* MB to KB */
97     if (killLevelsMap_.count(memoryKB) > 0) { /* if key @memoryKB has exist, error */
98         HILOGE("node:<%{public}s> <%{public}u, %{public}d> key has exist, mapSize:%{public}zu",
99                name.c_str(), memoryKB, minPriority, killLevelsMap_.size());
100         return false;
101     }
102     killLevelsMap_.insert(std::make_pair(memoryKB, minPriority));
103     return true;
104 }
105 
Dump(int fd)106 void KillConfig::Dump(int fd)
107 {
108     dprintf(fd, "KillConfig:   \n");
109     for (auto it = killLevelsMap_.begin(); it != killLevelsMap_.end(); it++) {
110         dprintf(fd, "                   memory:%u  ---->  prio:%d \n", it->first, it->second);
111     }
112 }
113 } // namespace Memory
114 } // namespace OHOS
115