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
17 #include "avail_buffer_manager.h"
18 #include "memmgr_config_manager.h"
19 #include "memmgr_log.h"
20 #include "memmgr_ptr_util.h"
21 #include "reclaim_priority_constants.h"
22 #include "reclaim_strategy_constants.h"
23 #include "reclaim_strategy_manager.h"
24
25 namespace OHOS {
26 namespace Memory {
27 namespace {
28 const std::string TAG = "ReclaimStrategyManager";
29 }
30
31 IMPLEMENT_SINGLE_INSTANCE(ReclaimStrategyManager);
32
ReclaimStrategyManager()33 ReclaimStrategyManager::ReclaimStrategyManager()
34 {
35 }
36
Init()37 bool ReclaimStrategyManager::Init()
38 {
39 initialized_ = false;
40 do {
41 if (!GetEventHandler_()) {
42 break;
43 }
44 AvailBufferManager::GetInstance().Init();
45 if (!MemcgMgr::GetInstance().SetRootMemcgPara()) {
46 break;
47 }
48 initialized_ = true;
49 } while (0);
50
51 if (!initialized_) {
52 HILOGE("init failed");
53 return false;
54 }
55 InitProcessBeforeMemmgr(); // add the process (which started before memmgr) to memcg
56 HILOGI("init success");
57 return initialized_;
58 }
59
GetEventHandler_()60 bool ReclaimStrategyManager::GetEventHandler_()
61 {
62 if (handler_ == nullptr) {
63 MAKE_POINTER(handler_, shared, AppExecFwk::EventHandler, "failed to create event handler", return false,
64 AppExecFwk::EventRunner::Create());
65 }
66 return true;
67 }
68
InitProcessBeforeMemmgr()69 void ReclaimStrategyManager::InitProcessBeforeMemmgr()
70 {
71 std::vector<unsigned int> pids;
72 if (!KernelInterface::GetInstance().GetAllProcPids(pids)) {
73 HILOGI("GetAllProcPids failed");
74 return;
75 }
76 unsigned int uid = 0;
77 unsigned int userId = 0;
78 bool ret = false;
79 for (auto pid : pids) {
80 if (!KernelInterface::GetInstance().GetUidByPid(pid, uid)) {
81 continue;
82 }
83 userId = GET_OS_ACCOUNT_ID_BY_UID(uid);
84 if (userId < VALID_USER_ID_MIN) { // invalid userId
85 continue;
86 }
87 ret = MemcgMgr::GetInstance().AddProcToMemcg(pid, userId);
88 HILOGD("add pid=%{public}u to userId=%{public}u, %{public}s", pid, userId, ret ? "succ" : "fail");
89 }
90 }
91
NotifyAppStateChanged(std::shared_ptr<ReclaimParam> reclaimPara)92 void ReclaimStrategyManager::NotifyAppStateChanged(std::shared_ptr<ReclaimParam> reclaimPara)
93 {
94 if (!Initailized()) {
95 HILOGE("has not been initialized_, skiped!");
96 return;
97 }
98 std::function<bool()> func = std::bind(
99 &ReclaimStrategyManager::HandleAppStateChanged_, this, reclaimPara);
100 handler_->PostImmediateTask(func);
101 }
102
HandleAppStateChanged_(std::shared_ptr<ReclaimParam> reclaimPara)103 bool ReclaimStrategyManager::HandleAppStateChanged_(std::shared_ptr<ReclaimParam> reclaimPara)
104 {
105 if (reclaimPara == nullptr) {
106 HILOGE("reclaimPara nullptr");
107 return false;
108 }
109 if (reclaimPara->accountId_ < VALID_USER_ID_MIN) {
110 HILOGE("invalid userId %{public}d, less than MIN_VALUE(%{public}d)",
111 reclaimPara->accountId_, VALID_USER_ID_MIN);
112 return false;
113 }
114 HILOGI("%{public}s", reclaimPara->ToString().c_str());
115 bool ret = false;
116 bool (ReclaimStrategyManager::*funcPtr)(std::shared_ptr<ReclaimParam>) = nullptr;
117 switch (reclaimPara->action_) {
118 case AppAction::CREATE_PROCESS_AND_APP:
119 case AppAction::CREATE_PROCESS_ONLY: {
120 funcPtr = &ReclaimStrategyManager::HandleProcessCreate_;
121 break;
122 }
123 case AppAction::APP_DIED:
124 case AppAction::APP_FOREGROUND:
125 case AppAction::APP_BACKGROUND:
126 case AppAction::OTHERS: {
127 HILOGI("others app action! %{public}s", ReclaimParam::GetAppActionStr(reclaimPara->action_).c_str());
128 break;
129 }
130 default:
131 break;
132 }
133 if (funcPtr != nullptr) {
134 ret = (this->*funcPtr)(reclaimPara);
135 }
136 reclaimPara.reset();
137 return ret;
138 }
139
HandleProcessCreate_(std::shared_ptr<ReclaimParam> reclaimPara)140 bool ReclaimStrategyManager::HandleProcessCreate_(std::shared_ptr<ReclaimParam> reclaimPara)
141 {
142 bool ret = MemcgMgr::GetInstance().AddProcToMemcg(reclaimPara->pid_, reclaimPara->accountId_);
143 HILOGI("%{public}s, %{public}s", ret ? "succ" : "fail", reclaimPara->ToString().c_str());
144 return ret;
145 }
146
NotifyAccountDied(int accountId)147 void ReclaimStrategyManager::NotifyAccountDied(int accountId)
148 {
149 if (!Initailized()) {
150 HILOGE("has not been initialized, skiped! accountId=%{public}d", accountId);
151 return;
152 }
153 if (accountId < VALID_USER_ID_MIN) {
154 HILOGE("invalid userId %{public}d, less than MIN_VALUE(%{public}d)",
155 accountId, VALID_USER_ID_MIN);
156 return;
157 }
158 std::function<bool()> func = std::bind(
159 &ReclaimStrategyManager::HandleAccountDied_, this, accountId);
160 handler_->PostImmediateTask(func);
161 }
162
NotifyAccountPriorityChanged(int accountId,int priority)163 void ReclaimStrategyManager::NotifyAccountPriorityChanged(int accountId, int priority)
164 {
165 if (!Initailized()) {
166 HILOGE("has not been initialized, skiped! accountId=%{public}d, priority=%{public}d", accountId, priority);
167 return;
168 }
169 if (accountId < VALID_USER_ID_MIN) {
170 HILOGE("invalid userId %{public}d, less than MIN_VALUE(%{public}d)",
171 accountId, VALID_USER_ID_MIN);
172 return;
173 }
174 std::function<bool()> func = std::bind(
175 &ReclaimStrategyManager::HandleAccountPriorityChanged_, this, accountId, priority);
176 handler_->PostImmediateTask(func);
177 }
178
HandleAccountDied_(int accountId)179 bool ReclaimStrategyManager::HandleAccountDied_(int accountId)
180 {
181 return MemcgMgr::GetInstance().RemoveUserMemcg(accountId);
182 }
183
HandleAccountPriorityChanged_(int accountId,int priority)184 bool ReclaimStrategyManager::HandleAccountPriorityChanged_(int accountId, int priority)
185 {
186 if (MemcgMgr::GetInstance().GetUserMemcg(accountId) == nullptr) {
187 HILOGI("account %{public}d not exist.", accountId);
188 return false;
189 }
190 GetValidScore_(priority);
191 std::unique_ptr<ReclaimRatios> ratios = nullptr;
192 try {
193 ratios = std::make_unique<ReclaimRatios>();
194 } catch (...) {
195 HILOGE("new ratios obj failed!");
196 return false;
197 }
198 if (ratios == nullptr || !GetReclaimRatiosByScore_(priority, *ratios)) {
199 HILOGE("get config ratios failed, will not update memcg ratio, userId=%{public}d", accountId);
200 ratios = nullptr;
201 return false;
202 }
203 bool ret = MemcgMgr::GetInstance().UpdateMemcgScoreAndReclaimRatios(accountId, priority, *ratios);
204 HILOGI("UpdateMemcgScoreAndReclaimRatios %{public}s, userId=%{public}d score=%{public}d %{public}s",
205 ret ? "succ" : "fail", accountId, priority, ratios->ToString().c_str());
206 ratios = nullptr;
207 return ret;
208 }
209
GetReclaimRatiosByScore_(int score,ReclaimRatios & ratios)210 bool ReclaimStrategyManager::GetReclaimRatiosByScore_(int score, ReclaimRatios& ratios)
211 {
212 HILOGD("before get ratios from MemmgrConfigManager %{public}s", ratios.NumsToString().c_str());
213 ReclaimConfig::ReclaimConfigSet reclaimConfigSet =
214 MemmgrConfigManager::GetInstance().GetReclaimConfigSet();
215 for (auto i = reclaimConfigSet.begin(); i != reclaimConfigSet.end(); ++i) {
216 if ((*i)->GetMinScore() <= score && (*i)->GetMaxScore() >= score) {
217 ratios.SetRatiosByValue((*i)->GetMem2zramRatio(), (*i)->GetZram2ufsRatio(), (*i)->GetRefaultThreshold());
218 HILOGI("get ratios from MemmgrConfigManager %{public}s", ratios.NumsToString().c_str());
219 return true;
220 }
221 }
222 HILOGD("can not get ratios from MemmgrConfigManager");
223 return false;
224 }
225
GetValidScore_(int & priority)226 void ReclaimStrategyManager::GetValidScore_(int& priority)
227 {
228 if (priority < RECLAIM_SCORE_MIN) {
229 priority = RECLAIM_SCORE_MIN;
230 } else if (priority > RECLAIM_SCORE_MAX) {
231 priority = RECLAIM_SCORE_MAX;
232 }
233 }
234 } // namespace Memory
235 } // namespace OHOS
236