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