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