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 "memory_level_manager.h"
16
17 #include "app_mem_info.h"
18 #include "app_mgr_client.h"
19 #include "if_system_ability_manager.h"
20 #include "iservice_registry.h"
21 #include "kernel_interface.h"
22 #include "memmgr_config_manager.h"
23 #include "memmgr_log.h"
24 #include "memmgr_ptr_util.h"
25 #include "reclaim_priority_manager.h"
26 #ifdef USE_PURGEABLE_MEMORY
27 #include "purgeable_mem_manager.h"
28 #endif
29
30 namespace OHOS {
31 namespace Memory {
32 namespace {
33 const std::string TAG = "MemoryLevelManager";
34 }
35
36 IMPLEMENT_SINGLE_INSTANCE(MemoryLevelManager);
37
MemoryLevelManager()38 MemoryLevelManager::MemoryLevelManager()
39 {
40 initialized_ = GetEventHandler();
41 if (initialized_) {
42 HILOGI("init succeeded");
43 } else {
44 HILOGE("init failed");
45 }
46 }
47
GetEventHandler()48 bool MemoryLevelManager::GetEventHandler()
49 {
50 if (!handler_) {
51 MAKE_POINTER(handler_, shared, AppExecFwk::EventHandler, "failed to create event handler", return false,
52 AppExecFwk::EventRunner::Create());
53 }
54 return true;
55 }
56
CalcSystemMemoryLevel(SystemMemoryInfo & info)57 bool MemoryLevelManager::CalcSystemMemoryLevel(SystemMemoryInfo &info)
58 {
59 int currentBuffer = KernelInterface::GetInstance().GetCurrentBuffer();
60 std::shared_ptr<SystemMemoryLevelConfig> config =
61 std::make_shared<SystemMemoryLevelConfig>(MemmgrConfigManager::GetInstance().GetSystemMemoryLevelConfig());
62 if (config == nullptr) {
63 HILOGE("The SystemMemoryLevelConfig is NULL.");
64 return false;
65 }
66
67 if (currentBuffer <= config->GetCritical()) {
68 info.level = SystemMemoryLevel::MEMORY_LEVEL_CRITICAL;
69 } else if (currentBuffer <= config->GetLow()) {
70 info.level = SystemMemoryLevel::MEMORY_LEVEL_LOW;
71 } else if (currentBuffer <= config->GetModerate()) {
72 info.level = SystemMemoryLevel::MEMORY_LEVEL_MODERATE;
73 } else if (currentBuffer <= config->GetPurgeable()) {
74 info.level = SystemMemoryLevel::MEMORY_LEVEL_PURGEABLE;
75 } else {
76 return false;
77 }
78
79 HILOGI("critical:%{public}d low:%{public}d moderate:%{public}d purgeable:%{public}d in config, curBuf:%{public}dKB,"
80 "level:%{public}d.",
81 config->GetCritical(), config->GetLow(), config->GetModerate(), config->GetPurgeable(), currentBuffer,
82 static_cast<int>(info.level));
83 return true;
84 }
85
CalcReclaimAppList(std::vector<std::shared_ptr<AppEntity>> & appList)86 bool MemoryLevelManager::CalcReclaimAppList(std::vector<std::shared_ptr<AppEntity>> &appList)
87 {
88 ReclaimPriorityManager::BunldeCopySet bundleSet;
89 ReclaimPriorityManager::GetInstance().GetBundlePrioSet(bundleSet);
90 for (auto bundleInfo : bundleSet) {
91 std::shared_ptr<AppEntity> app;
92 MAKE_POINTER(app, shared, AppEntity, "make shared failed", return false, bundleInfo.uid_, bundleInfo.name_);
93 appList.push_back(app);
94 HILOGI("The app will be reclaimed, uid:%{public}d, name:%{public}s.", app->uid_, app->name_.c_str());
95 }
96 return true;
97 }
98
NotifyMemoryLevel(SystemMemoryInfo & info)99 void MemoryLevelManager::NotifyMemoryLevel(SystemMemoryInfo &info)
100 {
101 HILOGD("called!");
102 DECLARE_UNIQUE_POINTER(AppExecFwk::AppMgrClient, appMgrClient_);
103 MAKE_POINTER(appMgrClient_, unique, AppExecFwk::AppMgrClient, "make unique failed", return,
104 /* no param */);
105 bool isNotifyMemoryLevelToSaMgr = false;
106 switch (info.level) {
107 case SystemMemoryLevel::MEMORY_LEVEL_PURGEABLE: {
108 // no need notify appMgrClient_
109 break;
110 }
111 case SystemMemoryLevel::MEMORY_LEVEL_MODERATE: {
112 isNotifyMemoryLevelToSaMgr = true;
113 appMgrClient_->NotifyMemoryLevel(AppExecFwk::MemoryLevel::MEMORY_LEVEL_MODERATE);
114 break;
115 }
116 case SystemMemoryLevel::MEMORY_LEVEL_LOW: {
117 isNotifyMemoryLevelToSaMgr = true;
118 appMgrClient_->NotifyMemoryLevel(AppExecFwk::MemoryLevel::MEMORY_LEVEL_LOW);
119 break;
120 }
121 case SystemMemoryLevel::MEMORY_LEVEL_CRITICAL: {
122 isNotifyMemoryLevelToSaMgr = true;
123 appMgrClient_->NotifyMemoryLevel(AppExecFwk::MemoryLevel::MEMORY_LEVEL_CRITICAL);
124 break;
125 }
126 default:
127 return;
128 }
129 if (isNotifyMemoryLevelToSaMgr) {
130 NotifyMemoryLevelToSystemAbilityManager();
131 }
132 #ifdef USE_PURGEABLE_MEMORY
133 PurgeableMemManager::GetInstance().NotifyMemoryLevel(info);
134 #endif
135 }
136
NotifyMemoryLevelToSystemAbilityManager()137 void MemoryLevelManager::NotifyMemoryLevelToSystemAbilityManager()
138 {
139 sptr<ISystemAbilityManager> systemAbilityManager =
140 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
141 if (!systemAbilityManager) {
142 HILOGE("get system ability manager failed!");
143 return;
144 }
145
146 int32_t ret = systemAbilityManager->UnloadAllIdleSystemAbility();
147 if (ret != ERR_OK) {
148 HILOGE("notify system ability manager failed!");
149 return;
150 }
151 HILOGI("notify system ability manager succ!");
152 }
153
TriggerMemoryLevelByDump(SystemMemoryInfo & info)154 void MemoryLevelManager::TriggerMemoryLevelByDump(SystemMemoryInfo &info)
155 {
156 HILOGD("called!");
157 if (info.source != MemorySource::MANUAL_DUMP) {
158 HILOGE("error: trigger not by dump!");
159 return;
160 }
161 NotifyMemoryLevel(info);
162 }
163
PsiHandlerInner()164 void MemoryLevelManager::PsiHandlerInner()
165 {
166 HILOGD("[%{public}ld] called", ++calledCount_);
167
168 /* Calculate the system memory level */
169 SystemMemoryInfo info = {MemorySource::PSI_MEMORY, SystemMemoryLevel::UNKNOWN};
170 if (!CalcSystemMemoryLevel(info)) {
171 return;
172 }
173 NotifyMemoryLevel(info);
174 }
175
PsiHandler()176 void MemoryLevelManager::PsiHandler()
177 {
178 if (!initialized_) {
179 HILOGE("is not initialized, return!");
180 return;
181 }
182 handler_->PostImmediateTask([this] { this->PsiHandlerInner(); });
183 }
184 } // namespace Memory
185 } // namespace OHOS
186