1ba5c3796Sopenharmony_ci/*
2ba5c3796Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3ba5c3796Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4ba5c3796Sopenharmony_ci * you may not use this file except in compliance with the License.
5ba5c3796Sopenharmony_ci * You may obtain a copy of the License at
6ba5c3796Sopenharmony_ci *
7ba5c3796Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8ba5c3796Sopenharmony_ci *
9ba5c3796Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10ba5c3796Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11ba5c3796Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12ba5c3796Sopenharmony_ci * See the License for the specific language governing permissions and
13ba5c3796Sopenharmony_ci * limitations under the License.
14ba5c3796Sopenharmony_ci */
15ba5c3796Sopenharmony_ci
16ba5c3796Sopenharmony_ci#include "memmgr_log.h"
17ba5c3796Sopenharmony_ci#include "memmgr_ptr_util.h"
18ba5c3796Sopenharmony_ci#include "parameters.h"
19ba5c3796Sopenharmony_ci#include "kernel_interface.h"
20ba5c3796Sopenharmony_ci#include "nandlife_controller.h"
21ba5c3796Sopenharmony_ci
22ba5c3796Sopenharmony_cinamespace OHOS {
23ba5c3796Sopenharmony_cinamespace Memory {
24ba5c3796Sopenharmony_cinamespace {
25ba5c3796Sopenharmony_ciconst std::string TAG = "NandLifeController";
26ba5c3796Sopenharmony_ci
27ba5c3796Sopenharmony_ciconstexpr int TIMER_PEROID_MIN = 15;
28ba5c3796Sopenharmony_ciconstexpr int TIMER_PEROID_MS = TIMER_PEROID_MIN * 60 * 1000;
29ba5c3796Sopenharmony_ci
30ba5c3796Sopenharmony_ciconst std::string PARAM_VALUE_ZERO = "0";
31ba5c3796Sopenharmony_ciconst std::string PARAM_VALUE_ONE = "1";
32ba5c3796Sopenharmony_ciconst std::string PARAM_VALUE_UNKOWN = "-1";
33ba5c3796Sopenharmony_ci
34ba5c3796Sopenharmony_ciconst std::string PERMANENTLY_CLOSED_STATUS_PARAM = "persist.resourceschedule.memmgr.eswap.permanently.closed";
35ba5c3796Sopenharmony_ciconst std::string PERMANENTLY_CLOSED = PARAM_VALUE_ONE;
36ba5c3796Sopenharmony_ciconst std::string NOT_PERMANENTLY_CLOSED = PARAM_VALUE_ZERO;
37ba5c3796Sopenharmony_ci
38ba5c3796Sopenharmony_ciconst std::string MINS_TODAY_PARAM = "persist.resourceschedule.memmgr.eswap.minsToday";
39ba5c3796Sopenharmony_ci
40ba5c3796Sopenharmony_ciconst std::string SWAP_OUT_KB_TODAY_PARAM = "persist.resourceschedule.memmgr.eswap.swapOutKBToday";
41ba5c3796Sopenharmony_ci
42ba5c3796Sopenharmony_ciconst std::string MINS_FROM_BIRTH_PARAM = "persist.resourceschedule.memmgr.eswap.minsFromBirth";
43ba5c3796Sopenharmony_ci
44ba5c3796Sopenharmony_ciconst std::string SWAP_OUT_KB_FROM_BIRTH_PARAM = "persist.resourceschedule.memmgr.eswap.swapOutKBFromBirth";
45ba5c3796Sopenharmony_ci
46ba5c3796Sopenharmony_ciconst std::string params[] = {
47ba5c3796Sopenharmony_ci    PERMANENTLY_CLOSED_STATUS_PARAM,
48ba5c3796Sopenharmony_ci    MINS_TODAY_PARAM,
49ba5c3796Sopenharmony_ci    SWAP_OUT_KB_TODAY_PARAM,
50ba5c3796Sopenharmony_ci    MINS_FROM_BIRTH_PARAM,
51ba5c3796Sopenharmony_ci    SWAP_OUT_KB_FROM_BIRTH_PARAM,
52ba5c3796Sopenharmony_ci};
53ba5c3796Sopenharmony_ci
54ba5c3796Sopenharmony_ciconst std::string PSI_HEALTH_INFO_PATH = "/dev/memcg/memory.eswap_info";
55ba5c3796Sopenharmony_ciconst std::string SWAP_OUT_SIZE_TAG = "Total Swapout Size";
56ba5c3796Sopenharmony_ci
57ba5c3796Sopenharmony_ciconst std::string ESWAP_ENABLE_PATH = "/proc/sys/kernel/hyperhold/enable";
58ba5c3796Sopenharmony_ciconst std::string ENABLE_ESWAP = "enable";
59ba5c3796Sopenharmony_ciconst std::string DISABLE_ESWAP = "disable";
60ba5c3796Sopenharmony_ci
61ba5c3796Sopenharmony_ciconstexpr int RETRY_TIMES = 3;
62ba5c3796Sopenharmony_ci}
63ba5c3796Sopenharmony_ci
64ba5c3796Sopenharmony_ciIMPLEMENT_SINGLE_INSTANCE(NandLifeController);
65ba5c3796Sopenharmony_ci
66ba5c3796Sopenharmony_ciNandLifeController::NandLifeController()
67ba5c3796Sopenharmony_ci{
68ba5c3796Sopenharmony_ci}
69ba5c3796Sopenharmony_ci
70ba5c3796Sopenharmony_cibool NandLifeController::Init()
71ba5c3796Sopenharmony_ci{
72ba5c3796Sopenharmony_ci    if (!GetEventHandler()) {
73ba5c3796Sopenharmony_ci        CloseSwapOutTemporarily("init handler failed, nandlife controller cannot set timmer");
74ba5c3796Sopenharmony_ci        return false;
75ba5c3796Sopenharmony_ci    }
76ba5c3796Sopenharmony_ci    HILOGI("init handler successed");
77ba5c3796Sopenharmony_ci
78ba5c3796Sopenharmony_ci    // read nandlife config from xml, then check and set it.
79ba5c3796Sopenharmony_ci    // if the config does not meet the requirements, eswap will be closed temporarily.
80ba5c3796Sopenharmony_ci    if (!GetAndValidateNandLifeConfig()) {
81ba5c3796Sopenharmony_ci        CloseSwapOutTemporarily("get or validate nandlife config failed, controller will not work properly.");
82ba5c3796Sopenharmony_ci        return false;
83ba5c3796Sopenharmony_ci    }
84ba5c3796Sopenharmony_ci    HILOGI("get and validate nandlife config success. dailyQuotaMB=%{public}llu, totalQuotaMB=%{public}llu",
85ba5c3796Sopenharmony_ci        config_.GetDailySwapOutQuotaMb(), config_.GetTotalSwapOutQuotaMb());
86ba5c3796Sopenharmony_ci    if (config_.GetDailySwapOutQuotaMb() == 0 && config_.GetTotalSwapOutQuotaMb() == 0) {
87ba5c3796Sopenharmony_ci        HILOGE("will not limit swap-out!");
88ba5c3796Sopenharmony_ci        OpenSwapOutPermanently();
89ba5c3796Sopenharmony_ci        OpenSwapOutTemporarily("not limit swap-out in xml");
90ba5c3796Sopenharmony_ci        return true;
91ba5c3796Sopenharmony_ci    } else {
92ba5c3796Sopenharmony_ci        DAILY_SWAP_OUT_QUOTA_KB = config_.GetDailySwapOutQuotaMb() * 1024; // 1024: MB to KB
93ba5c3796Sopenharmony_ci        TOTAL_SWAP_OUT_QUOTA_KB = config_.GetTotalSwapOutQuotaMb() * 1024; // 1024: MB to KB
94ba5c3796Sopenharmony_ci    }
95ba5c3796Sopenharmony_ci
96ba5c3796Sopenharmony_ci    if (!LoadNandLifeParam()) {
97ba5c3796Sopenharmony_ci        CloseSwapOutTemporarily("load nandlife info file failed, controller will not work properly.");
98ba5c3796Sopenharmony_ci        return false;
99ba5c3796Sopenharmony_ci    }
100ba5c3796Sopenharmony_ci    HILOGI("load nandlife sys param success");
101ba5c3796Sopenharmony_ci
102ba5c3796Sopenharmony_ci    PrintNandLifeParam();
103ba5c3796Sopenharmony_ci
104ba5c3796Sopenharmony_ci    if (IsSwapOutClosedPermently()) {
105ba5c3796Sopenharmony_ci        CloseSwapOutTemporarily("swap-out has benn closed permently, nandlife controller no need work!");
106ba5c3796Sopenharmony_ci        return false;
107ba5c3796Sopenharmony_ci    }
108ba5c3796Sopenharmony_ci
109ba5c3796Sopenharmony_ci    unsigned long long swapOutKBSinceKernelBoot = 0;
110ba5c3796Sopenharmony_ci    if (GetSwapOutKBSinceKernelBoot(swapOutKBSinceKernelBoot)) {
111ba5c3796Sopenharmony_ci        HILOGI("swapOutKBSinceKernelBoot=%{public}llu KB", swapOutKBSinceKernelBoot);
112ba5c3796Sopenharmony_ci        lastSwapOutKB_ = swapOutKBSinceKernelBoot;
113ba5c3796Sopenharmony_ci        nowSwapOutKB_ = swapOutKBSinceKernelBoot;
114ba5c3796Sopenharmony_ci    } else {
115ba5c3796Sopenharmony_ci        CloseSwapOutTemporarily("invalid swapOutKBSinceKernelBoot");
116ba5c3796Sopenharmony_ci        return false;
117ba5c3796Sopenharmony_ci    }
118ba5c3796Sopenharmony_ci
119ba5c3796Sopenharmony_ci    // start check loop
120ba5c3796Sopenharmony_ci    SetTimer();
121ba5c3796Sopenharmony_ci
122ba5c3796Sopenharmony_ci    // check limit
123ba5c3796Sopenharmony_ci    if (CheckReachedTotalLimit() || CheckReachedDailyLimit()) {
124ba5c3796Sopenharmony_ci        return false;
125ba5c3796Sopenharmony_ci    }
126ba5c3796Sopenharmony_ci
127ba5c3796Sopenharmony_ci    OpenSwapOutTemporarily("pass all check when init");
128ba5c3796Sopenharmony_ci    return true;
129ba5c3796Sopenharmony_ci}
130ba5c3796Sopenharmony_ci
131ba5c3796Sopenharmony_ci// may throw exception due to number format
132ba5c3796Sopenharmony_ciunsigned long long ReadUnsignedLongLongParam(const std::string &paramName)
133ba5c3796Sopenharmony_ci{
134ba5c3796Sopenharmony_ci    std::string value = system::GetParameter(paramName, PARAM_VALUE_UNKOWN);
135ba5c3796Sopenharmony_ci    if (value == PARAM_VALUE_UNKOWN) {
136ba5c3796Sopenharmony_ci        HILOGI("param <%{public}s> not set", paramName.c_str());
137ba5c3796Sopenharmony_ci    }
138ba5c3796Sopenharmony_ci    return std::strtoull(value.c_str(), nullptr, 10); // 10:Decimal
139ba5c3796Sopenharmony_ci}
140ba5c3796Sopenharmony_ci
141ba5c3796Sopenharmony_cibool NandLifeController::LoadNandLifeParam()
142ba5c3796Sopenharmony_ci{
143ba5c3796Sopenharmony_ci    minsToday_ = ReadUnsignedLongLongParam(MINS_TODAY_PARAM);
144ba5c3796Sopenharmony_ci    if (errno == ERANGE || minsToday_ == ULLONG_MAX) {
145ba5c3796Sopenharmony_ci        HILOGI("[%{public}llu] invalid value of minsToday_", iter_);
146ba5c3796Sopenharmony_ci        return false;
147ba5c3796Sopenharmony_ci    } else {
148ba5c3796Sopenharmony_ci        HILOGI("[%{public}llu] minsToday_=%{public}llu", iter_, minsToday_);
149ba5c3796Sopenharmony_ci    }
150ba5c3796Sopenharmony_ci
151ba5c3796Sopenharmony_ci    swapOutKBToday_ = ReadUnsignedLongLongParam(SWAP_OUT_KB_TODAY_PARAM);
152ba5c3796Sopenharmony_ci    if (errno == ERANGE || swapOutKBToday_ == ULLONG_MAX) {
153ba5c3796Sopenharmony_ci        HILOGI("[%{public}llu] invalid value of swapOutKBToday_", iter_);
154ba5c3796Sopenharmony_ci        return false;
155ba5c3796Sopenharmony_ci    } else {
156ba5c3796Sopenharmony_ci        HILOGI("[%{public}llu] swapOutKBToday_=%{public}llu", iter_, swapOutKBToday_);
157ba5c3796Sopenharmony_ci    }
158ba5c3796Sopenharmony_ci
159ba5c3796Sopenharmony_ci    minsSinceBirth_ = ReadUnsignedLongLongParam(MINS_FROM_BIRTH_PARAM);
160ba5c3796Sopenharmony_ci    if (errno == ERANGE || minsSinceBirth_ == ULLONG_MAX) {
161ba5c3796Sopenharmony_ci        HILOGI("[%{public}llu] invalid value of minsSinceBirth_", iter_);
162ba5c3796Sopenharmony_ci        return false;
163ba5c3796Sopenharmony_ci    } else {
164ba5c3796Sopenharmony_ci        HILOGI("[%{public}llu] minsSinceBirth_=%{public}llu", iter_, minsSinceBirth_);
165ba5c3796Sopenharmony_ci    }
166ba5c3796Sopenharmony_ci
167ba5c3796Sopenharmony_ci    swapOutKBSinceBirth_ = ReadUnsignedLongLongParam(SWAP_OUT_KB_FROM_BIRTH_PARAM);
168ba5c3796Sopenharmony_ci    if (errno == ERANGE || swapOutKBSinceBirth_ == ULLONG_MAX) {
169ba5c3796Sopenharmony_ci        HILOGI("[%{public}llu] invalid value of swapOutKBSinceBirth_", iter_);
170ba5c3796Sopenharmony_ci        return false;
171ba5c3796Sopenharmony_ci    } else {
172ba5c3796Sopenharmony_ci        HILOGI("[%{public}llu] swapOutKBSinceBirth_=%{public}llu", iter_, swapOutKBSinceBirth_);
173ba5c3796Sopenharmony_ci    }
174ba5c3796Sopenharmony_ci
175ba5c3796Sopenharmony_ci    return true;
176ba5c3796Sopenharmony_ci}
177ba5c3796Sopenharmony_ci
178ba5c3796Sopenharmony_civoid NandLifeController::PrintNandLifeParam()
179ba5c3796Sopenharmony_ci{
180ba5c3796Sopenharmony_ci    HILOGI("[%{public}llu] begin print nandlife param-------------", iter_);
181ba5c3796Sopenharmony_ci    for (auto param : params) {
182ba5c3796Sopenharmony_ci        HILOGI("[%{public}llu] %{public}s=%{public}s", iter_, param.c_str(),
183ba5c3796Sopenharmony_ci            system::GetParameter(param, PARAM_VALUE_UNKOWN).c_str());
184ba5c3796Sopenharmony_ci    }
185ba5c3796Sopenharmony_ci    HILOGI("[%{public}llu] end print nandlife param --------------", iter_);
186ba5c3796Sopenharmony_ci}
187ba5c3796Sopenharmony_ci
188ba5c3796Sopenharmony_cibool NandLifeController::IsSwapOutClosedPermently()
189ba5c3796Sopenharmony_ci{
190ba5c3796Sopenharmony_ci    return system::GetParameter(PERMANENTLY_CLOSED_STATUS_PARAM, PARAM_VALUE_UNKOWN) == PERMANENTLY_CLOSED;
191ba5c3796Sopenharmony_ci}
192ba5c3796Sopenharmony_ci
193ba5c3796Sopenharmony_cibool NandLifeController::GetAndValidateNandLifeConfig()
194ba5c3796Sopenharmony_ci{
195ba5c3796Sopenharmony_ci    config_ = MemmgrConfigManager::GetInstance().GetNandLifeConfig();
196ba5c3796Sopenharmony_ci    return config_.GetDailySwapOutQuotaMb() >= 0 && config_.GetTotalSwapOutQuotaMb() >=0;
197ba5c3796Sopenharmony_ci}
198ba5c3796Sopenharmony_ci
199ba5c3796Sopenharmony_cibool NandLifeController::GetEventHandler()
200ba5c3796Sopenharmony_ci{
201ba5c3796Sopenharmony_ci    if (handler_ == nullptr) {
202ba5c3796Sopenharmony_ci        MAKE_POINTER(handler_, shared, AppExecFwk::EventHandler, "failed to create event handler", return false,
203ba5c3796Sopenharmony_ci            AppExecFwk::EventRunner::Create());
204ba5c3796Sopenharmony_ci    }
205ba5c3796Sopenharmony_ci    return true;
206ba5c3796Sopenharmony_ci}
207ba5c3796Sopenharmony_ci
208ba5c3796Sopenharmony_cibool NandLifeController::GetSwapOutKBSinceKernelBoot(unsigned long long &ret)
209ba5c3796Sopenharmony_ci{
210ba5c3796Sopenharmony_ci    for (auto i = 0; i < RETRY_TIMES; i ++) {
211ba5c3796Sopenharmony_ci        if (KernelInterface::GetInstance().ReadSwapOutKBSinceKernelBoot(PSI_HEALTH_INFO_PATH, SWAP_OUT_SIZE_TAG, ret)) {
212ba5c3796Sopenharmony_ci            return true;
213ba5c3796Sopenharmony_ci        }
214ba5c3796Sopenharmony_ci    }
215ba5c3796Sopenharmony_ci    return false;
216ba5c3796Sopenharmony_ci}
217ba5c3796Sopenharmony_ci
218ba5c3796Sopenharmony_civoid NandLifeController::SetTimer()
219ba5c3796Sopenharmony_ci{
220ba5c3796Sopenharmony_ci    // set timer and call CheckSwapOut each TIMER_PEROID_MIN min.
221ba5c3796Sopenharmony_ci    handler_->PostTask([this] { this->CheckSwapOut(); }, TIMER_PEROID_MS, AppExecFwk::EventQueue::Priority::HIGH);
222ba5c3796Sopenharmony_ci    HILOGI("[%{public}llu] set timer after %{public}d mins", iter_, TIMER_PEROID_MIN);
223ba5c3796Sopenharmony_ci}
224ba5c3796Sopenharmony_ci
225ba5c3796Sopenharmony_cibool NandLifeController::CheckReachedDailyLimit()
226ba5c3796Sopenharmony_ci{
227ba5c3796Sopenharmony_ci    bool reachedDailyLimit = swapOutKBToday_ >= DAILY_SWAP_OUT_QUOTA_KB;
228ba5c3796Sopenharmony_ci    HILOGI("[%{public}llu] swapOutKBToday_(%{public}llu) %{public}s DAILY_SWAP_OUT_QUOTA_KB(%{public}llu)",
229ba5c3796Sopenharmony_ci        iter_, swapOutKBToday_, (reachedDailyLimit ? ">=" : "<"), DAILY_SWAP_OUT_QUOTA_KB);
230ba5c3796Sopenharmony_ci    if (reachedDailyLimit) {
231ba5c3796Sopenharmony_ci        CloseSwapOutTemporarily("reach daily limit, close swap-out temporarily!");
232ba5c3796Sopenharmony_ci    } else {
233ba5c3796Sopenharmony_ci        HILOGI("[%{public}llu] unreach daily limit, swap-out is still opened!", iter_);
234ba5c3796Sopenharmony_ci    }
235ba5c3796Sopenharmony_ci    return reachedDailyLimit;
236ba5c3796Sopenharmony_ci}
237ba5c3796Sopenharmony_ci
238ba5c3796Sopenharmony_cibool NandLifeController::CheckReachedTotalLimit()
239ba5c3796Sopenharmony_ci{
240ba5c3796Sopenharmony_ci    bool reachedTotalLimit = swapOutKBSinceBirth_ >= TOTAL_SWAP_OUT_QUOTA_KB;
241ba5c3796Sopenharmony_ci    HILOGI("[%{public}llu] swapOutKBSinceBirth_(%{public}llu) %{public}s TOTAL_SWAP_OUT_QUOTA_KB(%{public}llu)",
242ba5c3796Sopenharmony_ci        iter_, swapOutKBSinceBirth_, (reachedTotalLimit ? ">=" : "<"), TOTAL_SWAP_OUT_QUOTA_KB);
243ba5c3796Sopenharmony_ci    if (reachedTotalLimit) {
244ba5c3796Sopenharmony_ci        HILOGE("[%{public}llu] reached total limit, close swap-out forever!", iter_);
245ba5c3796Sopenharmony_ci        CloseSwapOutPermanently();
246ba5c3796Sopenharmony_ci    } else {
247ba5c3796Sopenharmony_ci        HILOGI("[%{public}llu] unreach total limit!", iter_);
248ba5c3796Sopenharmony_ci    }
249ba5c3796Sopenharmony_ci    return reachedTotalLimit;
250ba5c3796Sopenharmony_ci}
251ba5c3796Sopenharmony_ci
252ba5c3796Sopenharmony_civoid NandLifeController::CheckSwapOut()
253ba5c3796Sopenharmony_ci{
254ba5c3796Sopenharmony_ci    ++iter_;
255ba5c3796Sopenharmony_ci
256ba5c3796Sopenharmony_ci    HILOGE("[%{public}llu] called", iter_);
257ba5c3796Sopenharmony_ci
258ba5c3796Sopenharmony_ci    if (IsSwapOutClosedPermently()) {
259ba5c3796Sopenharmony_ci        CloseSwapOutTemporarily("swap-out has benn closed permently!");
260ba5c3796Sopenharmony_ci        SetTimer();
261ba5c3796Sopenharmony_ci        return;
262ba5c3796Sopenharmony_ci    }
263ba5c3796Sopenharmony_ci
264ba5c3796Sopenharmony_ci    PrintNandLifeParam();
265ba5c3796Sopenharmony_ci
266ba5c3796Sopenharmony_ci    minsToday_ += TIMER_PEROID_MIN;
267ba5c3796Sopenharmony_ci    minsSinceBirth_ += TIMER_PEROID_MIN;
268ba5c3796Sopenharmony_ci
269ba5c3796Sopenharmony_ci    if (GetSwapOutKBSinceKernelBoot(nowSwapOutKB_)) {
270ba5c3796Sopenharmony_ci        HILOGI("[%{public}llu] swapOutKBSinceKernelBoot=%{public}llu KB", iter_, nowSwapOutKB_);
271ba5c3796Sopenharmony_ci    } else {
272ba5c3796Sopenharmony_ci        CloseSwapOutTemporarily("invalid swapOutKBSinceKernelBoot");
273ba5c3796Sopenharmony_ci        SetTimer();
274ba5c3796Sopenharmony_ci        return;
275ba5c3796Sopenharmony_ci    }
276ba5c3796Sopenharmony_ci    if (nowSwapOutKB_ < lastSwapOutKB_) {
277ba5c3796Sopenharmony_ci        CloseSwapOutTemporarily("deltaSwapOutMB < 0");
278ba5c3796Sopenharmony_ci        SetTimer();
279ba5c3796Sopenharmony_ci        return;
280ba5c3796Sopenharmony_ci    }
281ba5c3796Sopenharmony_ci    unsigned long long increasedSwapOutKB = nowSwapOutKB_ - lastSwapOutKB_;
282ba5c3796Sopenharmony_ci    HILOGE("[%{public}llu] lastSwapOutKB_=%{public}llu, nowSwapOutKB_=%{public}llu, increasedSwapOutKB=%{public}llu",
283ba5c3796Sopenharmony_ci        iter_, lastSwapOutKB_, nowSwapOutKB_, increasedSwapOutKB);
284ba5c3796Sopenharmony_ci    lastSwapOutKB_ = nowSwapOutKB_;
285ba5c3796Sopenharmony_ci    swapOutKBToday_ += increasedSwapOutKB;
286ba5c3796Sopenharmony_ci    swapOutKBSinceBirth_ += increasedSwapOutKB;
287ba5c3796Sopenharmony_ci
288ba5c3796Sopenharmony_ci    CheckReachedDailyLimit();
289ba5c3796Sopenharmony_ci
290ba5c3796Sopenharmony_ci    if (minsToday_ >= 24 * 60) { // 24: a day has 24 hours, 60: one hour has 60 min
291ba5c3796Sopenharmony_ci        HILOGI("[%{public}llu] enter a new day", iter_);
292ba5c3796Sopenharmony_ci        minsToday_ = 0;
293ba5c3796Sopenharmony_ci        swapOutKBToday_ = 0;
294ba5c3796Sopenharmony_ci        if (swapOutKBSinceBirth_ < TOTAL_SWAP_OUT_QUOTA_KB) { // swap-out is allowed
295ba5c3796Sopenharmony_ci            HILOGI("[%{public}llu] open swap-out since a new day", iter_);
296ba5c3796Sopenharmony_ci            OpenSwapOutTemporarily("enter a new day");
297ba5c3796Sopenharmony_ci        }
298ba5c3796Sopenharmony_ci    }
299ba5c3796Sopenharmony_ci
300ba5c3796Sopenharmony_ci    if (!UpdateNandLifeParam()) {
301ba5c3796Sopenharmony_ci        CloseSwapOutTemporarily("UpdateNandLifeParam failed!");
302ba5c3796Sopenharmony_ci    }
303ba5c3796Sopenharmony_ci
304ba5c3796Sopenharmony_ci    PrintNandLifeParam();
305ba5c3796Sopenharmony_ci
306ba5c3796Sopenharmony_ci    CheckReachedTotalLimit();
307ba5c3796Sopenharmony_ci
308ba5c3796Sopenharmony_ci    // set next timer
309ba5c3796Sopenharmony_ci    SetTimer();
310ba5c3796Sopenharmony_ci}
311ba5c3796Sopenharmony_ci
312ba5c3796Sopenharmony_cibool NandLifeController::SetParameterRetry(const std::string &paramName, const std::string &paramValue, int retryTimes)
313ba5c3796Sopenharmony_ci{
314ba5c3796Sopenharmony_ci    for (auto i = 0; i < retryTimes; i++) {
315ba5c3796Sopenharmony_ci        if (system::SetParameter(paramName, paramValue)) {
316ba5c3796Sopenharmony_ci            return true;
317ba5c3796Sopenharmony_ci        }
318ba5c3796Sopenharmony_ci    }
319ba5c3796Sopenharmony_ci    HILOGW("[%{public}llu] set [%{public}s] to [%{public}s] failed!", iter_, paramName.c_str(), paramValue.c_str());
320ba5c3796Sopenharmony_ci    return false;
321ba5c3796Sopenharmony_ci}
322ba5c3796Sopenharmony_ci
323ba5c3796Sopenharmony_cibool NandLifeController::UpdateNandLifeParam()
324ba5c3796Sopenharmony_ci{
325ba5c3796Sopenharmony_ci    if (!SetParameterRetry(MINS_TODAY_PARAM, std::to_string(minsToday_), RETRY_TIMES)) {
326ba5c3796Sopenharmony_ci        return false;
327ba5c3796Sopenharmony_ci    }
328ba5c3796Sopenharmony_ci    if (!SetParameterRetry(SWAP_OUT_KB_TODAY_PARAM, std::to_string(swapOutKBToday_), RETRY_TIMES)) {
329ba5c3796Sopenharmony_ci        return false;
330ba5c3796Sopenharmony_ci    }
331ba5c3796Sopenharmony_ci    if (!SetParameterRetry(MINS_FROM_BIRTH_PARAM, std::to_string(minsSinceBirth_), RETRY_TIMES)) {
332ba5c3796Sopenharmony_ci        return false;
333ba5c3796Sopenharmony_ci    }
334ba5c3796Sopenharmony_ci    if (!SetParameterRetry(SWAP_OUT_KB_FROM_BIRTH_PARAM, std::to_string(swapOutKBSinceBirth_), RETRY_TIMES)) {
335ba5c3796Sopenharmony_ci        return false;
336ba5c3796Sopenharmony_ci    }
337ba5c3796Sopenharmony_ci    HILOGW("[%{public}llu] all success!", iter_);
338ba5c3796Sopenharmony_ci    return true;
339ba5c3796Sopenharmony_ci}
340ba5c3796Sopenharmony_ci
341ba5c3796Sopenharmony_civoid NandLifeController::OpenSwapOutTemporarily(const std::string &reason)
342ba5c3796Sopenharmony_ci{
343ba5c3796Sopenharmony_ci    HILOGW("[%{public}llu] %{public}s", iter_, reason.c_str());
344ba5c3796Sopenharmony_ci    for (auto  i = 0; i < RETRY_TIMES; i++) {
345ba5c3796Sopenharmony_ci        if (KernelInterface::GetInstance().EchoToPath(ESWAP_ENABLE_PATH.c_str(), ENABLE_ESWAP.c_str())) {
346ba5c3796Sopenharmony_ci            HILOGI("[%{public}llu] open eswap temporarily success!", iter_);
347ba5c3796Sopenharmony_ci            return;
348ba5c3796Sopenharmony_ci        }
349ba5c3796Sopenharmony_ci    }
350ba5c3796Sopenharmony_ci    HILOGW("[%{public}llu] open eswap temporarily failed!", iter_);
351ba5c3796Sopenharmony_ci}
352ba5c3796Sopenharmony_ci
353ba5c3796Sopenharmony_civoid NandLifeController::CloseSwapOutTemporarily(const std::string &reason)
354ba5c3796Sopenharmony_ci{
355ba5c3796Sopenharmony_ci    HILOGW("[%{public}llu] %{public}s", iter_, reason.c_str());
356ba5c3796Sopenharmony_ci    for (auto  i = 0; i < RETRY_TIMES; i++) {
357ba5c3796Sopenharmony_ci        if (KernelInterface::GetInstance().EchoToPath(ESWAP_ENABLE_PATH.c_str(), DISABLE_ESWAP.c_str())) {
358ba5c3796Sopenharmony_ci            HILOGW("[%{public}llu] clsoe eswap temporarily success!", iter_);
359ba5c3796Sopenharmony_ci            return;
360ba5c3796Sopenharmony_ci        }
361ba5c3796Sopenharmony_ci    }
362ba5c3796Sopenharmony_ci    HILOGW("[%{public}llu] close eswap temporarily failed!", iter_);
363ba5c3796Sopenharmony_ci}
364ba5c3796Sopenharmony_ci
365ba5c3796Sopenharmony_civoid NandLifeController::OpenSwapOutPermanently()
366ba5c3796Sopenharmony_ci{
367ba5c3796Sopenharmony_ci    bool ret = SetParameterRetry(PERMANENTLY_CLOSED_STATUS_PARAM, NOT_PERMANENTLY_CLOSED, RETRY_TIMES);
368ba5c3796Sopenharmony_ci    HILOGW("[%{public}llu] open eswap permanently %{public}s!", iter_, ret ? "success" : "failed");
369ba5c3796Sopenharmony_ci}
370ba5c3796Sopenharmony_ci
371ba5c3796Sopenharmony_civoid NandLifeController::CloseSwapOutPermanently()
372ba5c3796Sopenharmony_ci{
373ba5c3796Sopenharmony_ci    CloseSwapOutTemporarily("CloseSwapOutPermanently close eswap temporarily first!");
374ba5c3796Sopenharmony_ci    bool ret = SetParameterRetry(PERMANENTLY_CLOSED_STATUS_PARAM, PERMANENTLY_CLOSED, RETRY_TIMES);
375ba5c3796Sopenharmony_ci    HILOGW("[%{public}llu] close eswap permanently %{public}s!", iter_, ret ? "success" : "failed");
376ba5c3796Sopenharmony_ci}
377ba5c3796Sopenharmony_ci} // namespace Memory
378ba5c3796Sopenharmony_ci} // namespace OHOS
379