• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "memmgr_log.h"
17 #include "memmgr_ptr_util.h"
18 #include "default_multi_account_strategy.h"
19 #include "reclaim_strategy_manager.h"
20 #include "kernel_interface.h"
21 #include "oom_score_adj_utils.h"
22 #include "reclaim_priority_constants.h"
23 #include "multi_account_manager.h"
24 
25 namespace OHOS {
26 namespace Memory {
27 namespace {
28 const std::string TAG = "MultiAccountManager";
29 const int MAX_RETRY_TIMES = 10;
30 const int SLEEP_TIME = 3000;
31 }
32 
33 IMPLEMENT_SINGLE_INSTANCE(MultiAccountManager);
34 
MultiAccountManager()35 MultiAccountManager::MultiAccountManager()
36 {
37     MAKE_POINTER(strategy_, shared, DefaultMultiAccountStrategy, "make shared failed", return, /* no param */);
38     MAKE_POINTER(handler_, shared, AppExecFwk::EventHandler, "failed to create event handler", return,
39         AppExecFwk::EventRunner::Create());
40 }
41 
~MultiAccountManager()42 MultiAccountManager::~MultiAccountManager()
43 {
44     if (strategy_) {
45         strategy_ = nullptr;
46     }
47 }
48 
Init()49 void MultiAccountManager::Init()
50 {
51     retryTimes_++;
52     initialized_ = false;
53     do {
54         oldActiveAccountIds_.clear();
55         ErrCode errCode = AccountSA::OsAccountManager::QueryActiveOsAccountIds(oldActiveAccountIds_);
56         if (errCode != ERR_OK) {
57             HILOGI("The manager initial failed, err = %{public}d.", static_cast<int>(errCode));
58             break;
59         }
60 
61         if (!UpdateAccountPriorityInfo(oldActiveAccountIds_)) {
62             HILOGI("The manager initial failed.");
63             break;
64         }
65 
66         initialized_ = true;
67     } while (0);
68 
69     if (initialized_) {
70         HILOGI("The manager initial succeed, accountCount = %{public}zu.", oldActiveAccountIds_.size());
71         return;
72     }
73 
74     if (retryTimes_ < MAX_RETRY_TIMES) {
75         if (handler_ == nullptr) {
76             HILOGE("The manager initial failed and couldn't retry, because the handler is null.");
77             return;
78         }
79 
80         std::function<void()> initMultiAccountManagerFunc = std::bind(&MultiAccountManager::Init, this);
81         handler_->PostTask(initMultiAccountManagerFunc, SLEEP_TIME, AppExecFwk::EventQueue::Priority::LOW);
82         HILOGE("Manager initial failed, try again after 3s!, retryTimes = %{public}d/10", retryTimes_);
83     }
84 }
85 
SetAccountPriority(int accountId,std::string accountName,AccountSA::OsAccountType accountType,bool isActived)86 bool MultiAccountManager::SetAccountPriority(int accountId, std::string accountName,
87                                              AccountSA::OsAccountType accountType, bool isActived)
88 {
89     std::shared_ptr<AccountPriorityInfo> accountInfo = GetAccountPriorityInfo(accountId);
90     if (accountInfo == nullptr) {
91         MAKE_POINTER(accountInfo, shared, AccountPriorityInfo, "make shared failed", return false,
92             accountId, accountName, accountType, isActived);
93         AddAccountPriorityInfo(accountInfo);
94     } else {
95         accountInfo->SetName(accountName);
96         accountInfo->SetType(accountType);
97         accountInfo->SetIsActived(isActived);
98     }
99 
100     if (strategy_ == nullptr) {
101         HILOGI("Set account priority failed, strategy is null.");
102         return false;
103     }
104 
105     int oldPriority = accountInfo->GetPriority();
106     if (!strategy_->SetAccountPriority(accountInfo)) {
107         HILOGI("Set account priority failed, accountId = %{public}d.", accountId);
108         return false;
109     }
110 
111     HILOGI("Set acccount priority succeed, accountId = %{public}d, old = %{public}d, new = %{public}d.",
112            accountId, oldPriority, accountInfo->GetPriority());
113     ReclaimStrategyManager::GetInstance().NotifyAccountPriorityChanged(accountId, accountInfo->GetPriority());
114     return true;
115 }
116 
RecalcBundlePriority(int accountId,int bundlePriority)117 int MultiAccountManager::RecalcBundlePriority(int accountId, int bundlePriority)
118 {
119     std::shared_ptr<AccountPriorityInfo> accountInfo = GetAccountPriorityInfo(accountId);
120     if (accountInfo == nullptr) {
121         HILOGI("Repeat calculate bundle priority failed, account non-exist, accountId = %{public}d.", accountId);
122         return RECLAIM_PRIORITY_MAX;
123     }
124 
125     if (strategy_ == nullptr) {
126         HILOGI("Repeat calculate bundle priority failed, strategy is null.");
127         return RECLAIM_PRIORITY_MAX;
128     }
129 
130     int recalcPriority = strategy_->RecalcBundlePriority(accountInfo, bundlePriority);
131     if (recalcPriority > RECLAIM_PRIORITY_MAX) {
132         recalcPriority = RECLAIM_PRIORITY_MAX;
133     }
134     if (recalcPriority < RECLAIM_PRIORITY_FOREGROUND) {
135         recalcPriority = RECLAIM_PRIORITY_FOREGROUND;
136     }
137     return recalcPriority;
138 }
139 
AddAccountPriorityInfo(std::shared_ptr<AccountPriorityInfo> accountPriorityInfo)140 void MultiAccountManager::AddAccountPriorityInfo(std::shared_ptr<AccountPriorityInfo> accountPriorityInfo)
141 {
142     accountMap_.insert(std::pair<int, std::shared_ptr<AccountPriorityInfo>>(accountPriorityInfo->GetId(),
143                                                                             accountPriorityInfo));
144     HILOGI("Add account information succeed, accountId = %{public}d.", accountPriorityInfo->GetId());
145 }
146 
GetAccountPriorityInfo(int accountId)147 std::shared_ptr<AccountPriorityInfo> MultiAccountManager::GetAccountPriorityInfo(int accountId)
148 {
149     std::map<int, std::shared_ptr<AccountPriorityInfo>>::iterator iter = accountMap_.find(accountId);
150     if (iter != accountMap_.end()) {
151         return iter->second;
152     }
153     return nullptr;
154 }
155 
GetMultiAccountStratgy()156 std::shared_ptr<MultiAccountStrategy> MultiAccountManager::GetMultiAccountStratgy()
157 {
158     return strategy_;
159 }
160 
SetMultiAccountStrategy(std::shared_ptr<MultiAccountStrategy> strategy)161 bool MultiAccountManager::SetMultiAccountStrategy(std::shared_ptr<MultiAccountStrategy> strategy)
162 {
163     if (strategy == nullptr) {
164         HILOGI("Set the multiple account strategy failed because the strategy is null.");
165         return false;
166     }
167 
168     strategy_ = strategy;
169     return true;
170 }
171 
GetSwitchedAccountIds(std::vector<int> & accountIds)172 bool MultiAccountManager::GetSwitchedAccountIds(std::vector<int> &accountIds)
173 {
174     std::vector<int> newActiveAccountIds;
175     ErrCode errCode = AccountSA::OsAccountManager::QueryActiveOsAccountIds(newActiveAccountIds);
176     if (errCode != ERR_OK) {
177         HILOGI("Query active os accountIds failed, err = %{public}d.", static_cast<int>(errCode));
178         return false;
179     }
180 
181     for (int oldId : oldActiveAccountIds_) {
182         if (std::find(newActiveAccountIds.begin(), newActiveAccountIds.end(), oldId) == newActiveAccountIds.end()) {
183             accountIds.push_back(oldId);
184             HILOGI("Get the switched account succeed, accountId = %{public}d.", oldId);
185         }
186     }
187 
188     oldActiveAccountIds_ = newActiveAccountIds;
189     return true;
190 }
191 
UpdateAccountPriorityInfo(std::vector<int> & accountIds)192 bool MultiAccountManager::UpdateAccountPriorityInfo(std::vector<int> &accountIds)
193 {
194     for (int accountId : accountIds) {
195         AccountSA::OsAccountInfo osAccountInfo;
196         ErrCode errCode = AccountSA::OsAccountManager::QueryOsAccountById(accountId, osAccountInfo);
197         if (errCode != ERR_OK) {
198             HILOGI("Get os account failed, accountId = %{public}d, err = %{public}d.",
199                    accountId, static_cast<int>(errCode));
200             return false;
201         }
202         if (!SetAccountPriority(accountId, osAccountInfo.GetLocalName(), osAccountInfo.GetType(),
203                                 osAccountInfo.GetIsActived())) {
204             HILOGI("Set account priority failed, accountId = %{public}d.", accountId);
205             return false;
206         }
207     }
208     return true;
209 }
210 
GetAccountBundleInfo(int accountId,std::map<int,std::shared_ptr<AccountBundleInfo>> & osAccountsInfoMap_)211 std::shared_ptr<AccountBundleInfo> MultiAccountManager::GetAccountBundleInfo(int accountId,
212     std::map<int, std::shared_ptr<AccountBundleInfo>> &osAccountsInfoMap_)
213 {
214     std::map<int, std::shared_ptr<AccountBundleInfo>>::iterator iter = osAccountsInfoMap_.find(accountId);
215     if (iter != osAccountsInfoMap_.end()) {
216         return iter->second;
217     }
218     return nullptr;
219 }
220 
KillProcessesOfAccount(int accountId,std::map<int,std::shared_ptr<AccountBundleInfo>> & osAccountsInfoMap_)221 void MultiAccountManager::KillProcessesOfAccount(int accountId,
222     std::map<int, std::shared_ptr<AccountBundleInfo>> &osAccountsInfoMap_)
223 {
224     std::shared_ptr<AccountBundleInfo> accountBundleInfo = GetAccountBundleInfo(accountId, osAccountsInfoMap_);
225     if (accountBundleInfo == nullptr) {
226         HILOGI("Kill proccess of the account failed because the account non-exist, accountId = %{public}d.", accountId);
227         return;
228     }
229 
230     for (auto iter1 : accountBundleInfo->bundleIdInfoMapping_) {
231         for (auto iter2 : iter1.second->procs_) {
232             pid_t pid = iter2.first;
233             if (!KernelInterface::GetInstance().KillOneProcessByPid(pid)) {
234                 HILOGI("Kill the process failed, pid = %{public}d.", pid);
235                 continue;
236             }
237             HILOGI("Kill the process succeed, pid = %{public}d.", pid);
238         }
239     }
240 }
241 
HandleAccountColdSwitch(std::vector<int> & switchedAccountIds,std::map<int,std::shared_ptr<AccountBundleInfo>> & osAccountsInfoMap_)242 bool MultiAccountManager::HandleAccountColdSwitch(std::vector<int> &switchedAccountIds,
243     std::map<int, std::shared_ptr<AccountBundleInfo>> &osAccountsInfoMap_)
244 {
245     for (int accountId : switchedAccountIds) {
246         HILOGI("Account cold switch account = %{public}d.", accountId);
247         KillProcessesOfAccount(accountId, osAccountsInfoMap_);
248         ReclaimStrategyManager::GetInstance().NotifyAccountDied(accountId);
249     }
250     return true;
251 }
252 
HandleAccountHotSwitch(std::vector<int> & updatedAccountIds,std::map<int,std::shared_ptr<AccountBundleInfo>> & osAccountsInfoMap_)253 bool MultiAccountManager::HandleAccountHotSwitch(std::vector<int> &updatedAccountIds,
254     std::map<int, std::shared_ptr<AccountBundleInfo>> &osAccountsInfoMap_)
255 {
256     for (int accountId : updatedAccountIds) {
257         std::shared_ptr<AccountBundleInfo> accountBundleInfo = GetAccountBundleInfo(accountId, osAccountsInfoMap_);
258         if (accountBundleInfo == nullptr) {
259             HILOGI("Search account bundle info failed, accountId = %{public}d.", accountId);
260             continue;
261         }
262 
263         if (accountBundleInfo->bundleIdInfoMapping_.empty()) {
264             HILOGI("The bundle list of the account = %{public}d is empty.", accountId);
265             continue;
266         }
267 
268         for (auto iter : accountBundleInfo->bundleIdInfoMapping_) {
269             std::shared_ptr<BundlePriorityInfo> bundleInfo = iter.second;
270             int oldPriority = bundleInfo->priority_;
271             bundleInfo->priority_ = RecalcBundlePriority(accountId, oldPriority);
272             HILOGI("account = %{public}d bundle = %{public}d old = %{public}d new = %{public}d.",
273                    accountId, iter.first, oldPriority, bundleInfo->priority_);
274             bundleInfo->IncreaseProcsPriority(bundleInfo->priority_ - oldPriority);
275             OomScoreAdjUtils::WriteOomScoreAdjToKernel(bundleInfo);
276         }
277     }
278     return true;
279 }
280 
HandleOsAccountsChanged(int accountId,AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod,std::map<int,std::shared_ptr<AccountBundleInfo>> & osAccountsInfoMap_)281 bool MultiAccountManager::HandleOsAccountsChanged(int accountId, AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod,
282                                                   std::map<int, std::shared_ptr<AccountBundleInfo>> &osAccountsInfoMap_)
283 {
284     if (!initialized_) {
285         HILOGI("The MultiAccountManager uninitialized.");
286         return false;
287     }
288 
289     std::vector<int> switchedAccountIds;
290     if (!GetSwitchedAccountIds(switchedAccountIds)) {
291         HILOGI("Get switched accountIds failed.");
292         return false;
293     }
294 
295     std::vector<int> updatedAccountIds = switchedAccountIds;
296     updatedAccountIds.push_back(accountId);
297     if (!UpdateAccountPriorityInfo(updatedAccountIds)) {
298         HILOGI("Update account priority information failed.");
299         return false;
300     }
301 
302     switch (switchMod) {
303         case AccountSA::COLD_SWITCH:
304             return HandleAccountColdSwitch(switchedAccountIds, osAccountsInfoMap_);
305         case AccountSA::HOT_SWITCH:
306             return HandleAccountHotSwitch(updatedAccountIds, osAccountsInfoMap_);
307         default:
308             HILOGI("Switch mode incorrect, mode = %{public}d.", static_cast<int>(switchMod));
309             return false;
310     }
311 }
312 } // namespace Memory
313 } // namespace OHOS
314