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 (!CreateEventHandler()) {
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
CreateEventHandler()60 bool ReclaimStrategyManager::CreateEventHandler()
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
GetEventHandler() const69 std::shared_ptr<AppExecFwk::EventHandler> ReclaimStrategyManager::GetEventHandler() const
70 {
71 return handler_;
72 }
73
InitProcessBeforeMemmgr()74 void ReclaimStrategyManager::InitProcessBeforeMemmgr()
75 {
76 std::vector<unsigned int> pids;
77 if (!KernelInterface::GetInstance().GetAllProcPids(pids)) {
78 HILOGI("GetAllProcPids failed");
79 return;
80 }
81 unsigned int uid = 0;
82 int userId = 0;
83 bool ret = false;
84 for (auto pid : pids) {
85 if (!KernelInterface::GetInstance().GetUidByPid(pid, uid)) {
86 continue;
87 }
88 userId = GetOsAccountIdByUid(static_cast<int>(uid));
89 if (userId < VALID_USER_ID_MIN) { // invalid userId
90 continue;
91 }
92 ret = MemcgMgr::GetInstance().AddProcToMemcg(pid, userId);
93 HILOGD("add pid=%{public}u to userId=%{public}u, %{public}s", pid, userId, ret ? "succ" : "fail");
94 }
95 }
96
NotifyAppStateChanged(std::shared_ptr<ReclaimParam> reclaimPara)97 void ReclaimStrategyManager::NotifyAppStateChanged(std::shared_ptr<ReclaimParam> reclaimPara)
98 {
99 if (!Initailized()) {
100 HILOGE("has not been initialized_, skiped!");
101 return;
102 }
103 handler_->PostImmediateTask([this, reclaimPara] { this->HandleAppStateChanged_(reclaimPara); });
104 }
105
HandleAppStateChanged_(std::shared_ptr<ReclaimParam> reclaimPara)106 bool ReclaimStrategyManager::HandleAppStateChanged_(std::shared_ptr<ReclaimParam> reclaimPara)
107 {
108 if (reclaimPara == nullptr) {
109 HILOGE("reclaimPara nullptr");
110 return false;
111 }
112 if (reclaimPara->accountId_ < VALID_USER_ID_MIN) {
113 HILOGE("invalid userId %{public}d, less than MIN_VALUE(%{public}d)",
114 reclaimPara->accountId_, VALID_USER_ID_MIN);
115 return false;
116 }
117 HILOGI("%{public}s", reclaimPara->ToString().c_str());
118 bool ret = false;
119 switch (reclaimPara->action_) {
120 case AppAction::CREATE_PROCESS_AND_APP:
121 case AppAction::CREATE_PROCESS_ONLY: {
122 HandleProcessCreate_(reclaimPara);
123 break;
124 }
125 case AppAction::APP_DIED:
126 case AppAction::APP_FOREGROUND:
127 case AppAction::APP_BACKGROUND:
128 case AppAction::OTHERS: {
129 HILOGI("others app action! %{public}s", ReclaimParam::GetAppActionStr(reclaimPara->action_).c_str());
130 break;
131 }
132 default:
133 break;
134 }
135 reclaimPara.reset();
136 return ret;
137 }
138
HandleProcessCreate_(std::shared_ptr<ReclaimParam> reclaimPara)139 bool ReclaimStrategyManager::HandleProcessCreate_(std::shared_ptr<ReclaimParam> reclaimPara)
140 {
141 bool ret = MemcgMgr::GetInstance().AddProcToMemcg(reclaimPara->pid_, reclaimPara->accountId_);
142 HILOGI("%{public}s, %{public}s", ret ? "succ" : "fail", reclaimPara->ToString().c_str());
143 return ret;
144 }
145
NotifyAccountDied(int accountId)146 void ReclaimStrategyManager::NotifyAccountDied(int accountId)
147 {
148 if (!Initailized()) {
149 HILOGE("has not been initialized, skiped! accountId=%{public}d", accountId);
150 return;
151 }
152 if (accountId < VALID_USER_ID_MIN) {
153 HILOGE("invalid userId %{public}d, less than MIN_VALUE(%{public}d)",
154 accountId, VALID_USER_ID_MIN);
155 return;
156 }
157 handler_->PostImmediateTask([this, accountId] { this->HandleAccountDied_(accountId); });
158 }
159
NotifyAccountPriorityChanged(int accountId,int priority)160 void ReclaimStrategyManager::NotifyAccountPriorityChanged(int accountId, int priority)
161 {
162 if (!Initailized()) {
163 HILOGE("has not been initialized, skiped! accountId=%{public}d, priority=%{public}d", accountId, priority);
164 return;
165 }
166 if (accountId < VALID_USER_ID_MIN) {
167 HILOGE("invalid userId %{public}d, less than MIN_VALUE(%{public}d)",
168 accountId, VALID_USER_ID_MIN);
169 return;
170 }
171 handler_->PostImmediateTask([this, accountId, priority] {
172 this->HandleAccountPriorityChanged_(accountId, priority);
173 });
174 }
175
HandleAccountDied_(int accountId)176 bool ReclaimStrategyManager::HandleAccountDied_(int accountId)
177 {
178 return MemcgMgr::GetInstance().RemoveUserMemcg(accountId);
179 }
180
HandleAccountPriorityChanged_(int accountId,int priority)181 bool ReclaimStrategyManager::HandleAccountPriorityChanged_(int accountId, int priority)
182 {
183 if (MemcgMgr::GetInstance().GetUserMemcg(accountId) == nullptr) {
184 HILOGI("account %{public}d not exist.", accountId);
185 return false;
186 }
187 GetValidScore_(priority);
188 std::unique_ptr<ReclaimRatios> ratios = nullptr;
189 try {
190 ratios = std::make_unique<ReclaimRatios>();
191 } catch (...) {
192 HILOGE("new ratios obj failed!");
193 return false;
194 }
195 if (ratios == nullptr || !GetReclaimRatiosByScore_(priority, *ratios)) {
196 HILOGE("get config ratios failed, will not update memcg ratio, userId=%{public}d", accountId);
197 ratios = nullptr;
198 return false;
199 }
200 bool ret = MemcgMgr::GetInstance().UpdateMemcgScoreAndReclaimRatios(accountId, priority, *ratios);
201 HILOGI("UpdateMemcgScoreAndReclaimRatios %{public}s, userId=%{public}d score=%{public}d %{public}s",
202 ret ? "succ" : "fail", accountId, priority, ratios->ToString().c_str());
203 ratios = nullptr;
204 return ret;
205 }
206
GetReclaimRatiosByScore_(int score,ReclaimRatios & ratios)207 bool ReclaimStrategyManager::GetReclaimRatiosByScore_(int score, ReclaimRatios& ratios)
208 {
209 HILOGD("before get ratios from MemmgrConfigManager %{public}s", ratios.NumsToString().c_str());
210 ReclaimConfig::ReclaimConfigSet reclaimConfigSet =
211 MemmgrConfigManager::GetInstance().GetReclaimConfigSet();
212 for (auto i = reclaimConfigSet.begin(); i != reclaimConfigSet.end(); ++i) {
213 if ((*i)->GetMinScore() <= score && (*i)->GetMaxScore() >= score) {
214 ratios.SetRatiosByValue((*i)->GetMem2zramRatio(), (*i)->GetZram2ufsRatio(), (*i)->GetRefaultThreshold());
215 HILOGI("get ratios from MemmgrConfigManager %{public}s", ratios.NumsToString().c_str());
216 return true;
217 }
218 }
219 HILOGD("can not get ratios from MemmgrConfigManager");
220 return false;
221 }
222
GetValidScore_(int & priority)223 void ReclaimStrategyManager::GetValidScore_(int& priority)
224 {
225 if (priority < RECLAIM_SCORE_MIN) {
226 priority = RECLAIM_SCORE_MIN;
227 } else if (priority > RECLAIM_SCORE_MAX) {
228 priority = RECLAIM_SCORE_MAX;
229 }
230 }
231 } // namespace Memory
232 } // namespace OHOS
233