1 /*
2 * Copyright (c) 2022-2023 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 "aging/bundle_aging_mgr.h"
16
17 #include "account_helper.h"
18 #include "battery_srv_client.h"
19 #include "bundle_active_period_stats.h"
20 #include "bundle_memory_guard.h"
21 #include "bundle_mgr_service.h"
22 #include "bundle_util.h"
23 #include "display_power_mgr_client.h"
24 #include "ffrt.h"
25 #include "parameter.h"
26
27 namespace OHOS {
28 namespace AppExecFwk {
29 namespace {
30 const int32_t PERIOD_ANNUALLY = 4;
31 const std::string SYSTEM_PARAM_AGING_TIMER_INTERVAL = "persist.sys.bms.aging.policy.timer.interval";
32 const std::string SYSTEM_PARAM_AGING_BATTER_THRESHOLD = "persist.sys.bms.aging.policy.battery.threshold";
33 const std::string AGING_TASK = "AgingTask";
34
StatisticsUsageStats(const std::vector<DeviceUsageStats::BundleActivePackageStats> & useStats,std::vector<DeviceUsageStats::BundleActivePackageStats> & results)35 void StatisticsUsageStats(
36 const std::vector<DeviceUsageStats::BundleActivePackageStats> &useStats,
37 std::vector<DeviceUsageStats::BundleActivePackageStats> &results)
38 {
39 for (const auto &useStat : useStats) {
40 auto ret = std::any_of(results.begin(), results.end(),
41 [&useStat](auto &result) {
42 if (useStat.bundleName_ == result.bundleName_) {
43 result.startCount_ += useStat.startCount_;
44 if (result.lastTimeUsed_ < useStat.lastTimeUsed_) {
45 result.lastTimeUsed_ = useStat.lastTimeUsed_;
46 }
47
48 return true;
49 }
50
51 return false;
52 });
53 if (!ret) {
54 results.emplace_back(useStat);
55 }
56 }
57 }
58 }
59
BundleAgingMgr()60 BundleAgingMgr::BundleAgingMgr()
61 {
62 InitAgingHandlerChain();
63 APP_LOGI("BundleAgingMgr is created.");
64 }
65
~BundleAgingMgr()66 BundleAgingMgr::~BundleAgingMgr()
67 {
68 APP_LOGI("BundleAgingMgr is destroyed");
69 }
70
InitAgingTimerInterval()71 void BundleAgingMgr::InitAgingTimerInterval()
72 {
73 char szTimerThresold[AgingConstants::THRESHOLD_VAL_LEN] = {0};
74 int32_t ret = GetParameter(SYSTEM_PARAM_AGING_TIMER_INTERVAL.c_str(), "", szTimerThresold,
75 AgingConstants::THRESHOLD_VAL_LEN);
76 APP_LOGD("ret is %{public}d, szTimerThresold is %{public}d", ret, atoi(szTimerThresold));
77 if (ret <= 0) {
78 APP_LOGD("GetParameter failed");
79 return;
80 }
81
82 if (strcmp(szTimerThresold, "") != 0) {
83 agingTimerInterval_ = atoi(szTimerThresold);
84 APP_LOGD("BundleAgingMgr init aging timer success");
85 }
86 }
87
InitAgingBatteryThresold()88 void BundleAgingMgr::InitAgingBatteryThresold()
89 {
90 char szBatteryThresold[AgingConstants::THRESHOLD_VAL_LEN] = {0};
91 int32_t ret = GetParameter(SYSTEM_PARAM_AGING_BATTER_THRESHOLD.c_str(), "", szBatteryThresold,
92 AgingConstants::THRESHOLD_VAL_LEN);
93 APP_LOGD("ret is %{public}d, szBatteryThresold is %{public}d", ret, atoi(szBatteryThresold));
94 if (ret <= 0) {
95 APP_LOGD("GetParameter failed");
96 return;
97 }
98
99 if (strcmp(szBatteryThresold, "") != 0) {
100 agingBatteryThresold_ = atoi(szBatteryThresold);
101 APP_LOGD("BundleAgingMgr init battery threshold success");
102 }
103 }
104
InitAgingtTimer()105 void BundleAgingMgr::InitAgingtTimer()
106 {
107 InitAgingBatteryThresold();
108 InitAgingTimerInterval();
109 ScheduleLoopTask();
110 }
111
ScheduleLoopTask()112 void BundleAgingMgr::ScheduleLoopTask()
113 {
114 std::weak_ptr<BundleAgingMgr> weakPtr = shared_from_this();
115 auto task = [weakPtr]() {
116 BundleMemoryGuard memoryGuard;
117 while (true) {
118 auto sharedPtr = weakPtr.lock();
119 if (sharedPtr == nullptr) {
120 APP_LOGD("stop aging task");
121 break;
122 }
123 ffrt::this_task::sleep_for(std::chrono::milliseconds(sharedPtr->agingTimerInterval_));
124 APP_LOGD("begin to run aging task");
125 sharedPtr->Start(AgingTriggertype::PREIOD);
126 }
127 APP_LOGD("aging task done");
128 };
129 if (agingTimerInterval_ >= 0) {
130 APP_LOGD("submit aging task");
131 ffrt::submit(task, {}, {}, ffrt::task_attr().name(AGING_TASK.c_str()));
132 }
133 }
134
ResetRequest()135 bool BundleAgingMgr::ResetRequest()
136 {
137 auto dataMgr = OHOS::DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
138 if (dataMgr == nullptr) {
139 APP_LOGE("dataMgr is null");
140 return false;
141 }
142
143 request_.ResetRequest();
144 request_.SetTotalDataBytes(dataMgr->GetAllFreeInstallBundleSpaceSize());
145 return true;
146 }
147
IsReachStartAgingThreshold()148 bool BundleAgingMgr::IsReachStartAgingThreshold()
149 {
150 return request_.IsReachStartAgingThreshold();
151 }
152
QueryBundleStatsInfoByInterval(std::vector<DeviceUsageStats::BundleActivePackageStats> & results)153 bool BundleAgingMgr::QueryBundleStatsInfoByInterval(
154 std::vector<DeviceUsageStats::BundleActivePackageStats> &results)
155 {
156 auto dataMgr = OHOS::DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
157 if (dataMgr == nullptr) {
158 APP_LOGE("dataMgr is null");
159 return false;
160 }
161
162 int64_t startTime = 0;
163 int64_t endTime = AgingUtil::GetNowSysTimeMs();
164 std::vector<DeviceUsageStats::BundleActivePackageStats> useStats;
165 for (const auto &userId : dataMgr->GetAllUser()) {
166 DeviceUsageStats::BundleActiveClient::GetInstance().QueryBundleStatsInfoByInterval(
167 useStats, PERIOD_ANNUALLY, startTime, endTime, userId);
168 StatisticsUsageStats(useStats, results);
169 useStats.clear();
170 }
171
172 APP_LOGD("activeBundleRecord size %{public}zu", results.size());
173 return !results.empty();
174 }
175
InitAgingRequest()176 bool BundleAgingMgr::InitAgingRequest()
177 {
178 auto dataMgr = OHOS::DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
179 if (dataMgr == nullptr) {
180 APP_LOGE("dataMgr is null");
181 return false;
182 }
183
184 if (!ResetRequest()) {
185 APP_LOGE("Reset Request failed");
186 return false;
187 }
188
189 if (!IsReachStartAgingThreshold()) {
190 APP_LOGI("Not reach agingThreshold and not need aging.");
191 return false;
192 }
193
194 std::vector<DeviceUsageStats::BundleActivePackageStats> activeBundleRecord;
195 if (!QueryBundleStatsInfoByInterval(activeBundleRecord)) {
196 APP_LOGE("InitAgingRequest: can not get bundle active bundle record");
197 return false;
198 }
199 auto bundleInfos = dataMgr->GetAllInnerBundleInfos();
200 for (const auto &item : bundleInfos) {
201 if (!item.second.IsBundleRemovable()) {
202 continue;
203 }
204
205 int64_t installTime = item.second.GetLastInstallationTime();
206 auto bundleName = item.first;
207 DeviceUsageStats::BundleActivePackageStats bundleRecord;
208 bundleRecord.bundleName_ = bundleName;
209 bundleRecord.lastTimeUsed_ = installTime;
210 std::any_of(activeBundleRecord.begin(), activeBundleRecord.end(),
211 [&bundleRecord](const auto &record) {
212 if (record.bundleName_ == bundleRecord.bundleName_) {
213 bundleRecord = record;
214 return true;
215 }
216
217 return false;
218 });
219 AgingBundleInfo agingBundleInfo(bundleName, bundleRecord.lastTimeUsed_, bundleRecord.startCount_);
220 request_.AddAgingBundle(agingBundleInfo);
221 }
222
223 bool ret = request_.SortAgingBundles() > 0;
224 request_.Dump();
225 return ret;
226 }
227
Process(const std::shared_ptr<BundleDataMgr> & dataMgr)228 void BundleAgingMgr::Process(const std::shared_ptr<BundleDataMgr> &dataMgr)
229 {
230 APP_LOGD("BundleAging begin to process.");
231 if (InitAgingRequest()) {
232 chain_.Process(request_);
233 }
234
235 {
236 std::lock_guard<std::mutex> lock(mutex_);
237 running_ = false;
238 }
239
240 APP_LOGD("BundleAgingMgr Process done");
241 }
242
Start(AgingTriggertype type)243 void BundleAgingMgr::Start(AgingTriggertype type)
244 {
245 APP_LOGD("aging start, AgingTriggertype: %{public}d", type);
246 if (!CheckPrerequisite(type)) {
247 APP_LOGE("BundleAgingMgr aging Prerequisite is not satisfied");
248 return;
249 }
250
251 auto dataMgr = OHOS::DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
252 if (dataMgr == nullptr) {
253 APP_LOGE("dataMgr is null");
254 return;
255 }
256
257 {
258 std::lock_guard<std::mutex> lock(mutex_);
259 if (running_) {
260 APP_LOGD("BundleAgingMgr is running, no need to start is again");
261 return;
262 }
263 running_ = true;
264 }
265
266 auto task = [&, dataMgr]() {
267 BundleMemoryGuard memoryGuard;
268 Process(dataMgr);
269 };
270 ffrt::task_handle task_handle = ffrt::submit_h(task);
271 if (task_handle == nullptr) {
272 APP_LOGE("submit_h return null, execute Process failed");
273 std::lock_guard<std::mutex> lock(mutex_);
274 running_ = false;
275 }
276 }
277
CheckPrerequisite(AgingTriggertype type) const278 bool BundleAgingMgr::CheckPrerequisite(AgingTriggertype type) const
279 {
280 if (type != AgingTriggertype::PREIOD) {
281 return true;
282 }
283
284 DisplayPowerMgr::DisplayState state = DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().GetDisplayState();
285 if (state == DisplayPowerMgr::DisplayState::DISPLAY_ON) {
286 APP_LOGD("current Displaystate is DisplayState::DISPLAY_ON");
287 return false;
288 }
289
290 int32_t currentBatteryCap = OHOS::PowerMgr::BatterySrvClient::GetInstance().GetCapacity();
291 APP_LOGD("current GetCapacity is %{public}d agingBatteryThresold: %{public}" PRId64,
292 currentBatteryCap, agingBatteryThresold_);
293 return currentBatteryCap > agingBatteryThresold_;
294 }
295
InitAgingHandlerChain()296 void BundleAgingMgr::InitAgingHandlerChain()
297 {
298 chain_ = AgingHandlerChain();
299 chain_.AddHandler(std::make_shared<RecentlyUnuseBundleAgingHandler>());
300 }
301 } // namespace AppExecFwk
302 } // namespace OHOS
303