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