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