• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cinttypes>
17 #include <mutex>
18 
19 #include "ability_manager_helper.h"
20 #include "account_helper.h"
21 #include "aging/aging_handler.h"
22 #include "app_log_wrapper.h"
23 #include "bundle_data_mgr.h"
24 #include "bundle_mgr_service.h"
25 #include "bundle_promise.h"
26 #include "event_report.h"
27 #include "install_param.h"
28 #include "installd_client.h"
29 
30 namespace OHOS {
31 namespace AppExecFwk {
32 namespace {
33 class AgingUninstallReceiveImpl : public StatusReceiverHost {
34 public:
35     AgingUninstallReceiveImpl() = default;
36     virtual ~AgingUninstallReceiveImpl() override = default;
37 
IsRunning()38     bool IsRunning()
39     {
40         std::lock_guard<std::mutex> lock(stateMutex_);
41         return isRunning_;
42     }
43 
MarkRunning()44     void MarkRunning()
45     {
46         std::lock_guard<std::mutex> lock(stateMutex_);
47         isRunning_ = true;
48     }
49 
SetAgingPromise(const std::shared_ptr<BundlePromise> & agingPromise)50     void SetAgingPromise(const std::shared_ptr<BundlePromise>& agingPromise)
51     {
52         agingPromise_ = agingPromise;
53     }
54 
OnStatusNotify(const int progress)55     virtual void OnStatusNotify(const int progress) override
56     {}
57 
OnFinished(const int32_t resultCode,const std::string & resultMsg)58     virtual void OnFinished(const int32_t resultCode, const std::string &resultMsg) override
59     {
60         std::lock_guard<std::mutex> lock(stateMutex_);
61         isRunning_ = false;
62         if (agingPromise_) {
63             APP_LOGD("Notify task end.");
64             agingPromise_->NotifyAllTasksExecuteFinished();
65         }
66     }
67 
68 private:
69     std::mutex stateMutex_;
70     bool isRunning_ = false;
71     std::shared_ptr<BundlePromise> agingPromise_ = nullptr;
72 };
73 }
74 
Process(AgingRequest & request) const75 bool RecentlyUnuseBundleAgingHandler::Process(AgingRequest &request) const
76 {
77     return ProcessBundle(request);
78 }
79 
ProcessBundle(AgingRequest & request) const80 bool RecentlyUnuseBundleAgingHandler::ProcessBundle(AgingRequest &request) const
81 {
82     APP_LOGD("aging handler start: cleanType: %{public}d, totalDataBytes: %{public}" PRId64,
83         static_cast<int32_t>(request.GetAgingCleanType()), request.GetTotalDataBytes());
84     for (const auto &agingBundle : request.GetAgingBundles()) {
85         bool isBundleRunning = AbilityManagerHelper::IsRunning(agingBundle.GetBundleName());
86         APP_LOGD("found matching bundle: %{public}s, isRunning: %{public}d.",
87             agingBundle.GetBundleName().c_str(), isBundleRunning);
88         if (isBundleRunning != AbilityManagerHelper::NOT_RUNNING) {
89             continue;
90         }
91 
92         bool result = AgingClean(agingBundle, request);
93         if (!result) {
94             continue;
95         }
96 
97         UpdateUsedTotalDataBytes(request);
98         if (!NeedContinue(request)) {
99             APP_LOGD("there is no need to continue now.");
100             return false;
101         }
102     }
103 
104     UpdateUsedTotalDataBytes(request);
105     return NeedContinue(request);
106 }
107 
NeedContinue(const AgingRequest & request) const108 bool RecentlyUnuseBundleAgingHandler::NeedContinue(const AgingRequest &request) const
109 {
110     return !request.IsReachEndAgingThreshold();
111 }
112 
UpdateUsedTotalDataBytes(AgingRequest & request) const113 bool RecentlyUnuseBundleAgingHandler::UpdateUsedTotalDataBytes(AgingRequest &request) const
114 {
115     auto dataMgr = OHOS::DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
116     if (dataMgr == nullptr) {
117         APP_LOGE("dataMgr is null");
118         return false;
119     }
120 
121     request.SetTotalDataBytes(dataMgr->GetAllFreeInstallBundleSpaceSize());
122     return true;
123 }
124 
AgingClean(const AgingBundleInfo & agingBundleInfo,AgingRequest & request) const125 bool RecentlyUnuseBundleAgingHandler::AgingClean(
126     const AgingBundleInfo &agingBundleInfo, AgingRequest &request) const
127 {
128     if (request.GetAgingCleanType() == AgingCleanType::CLEAN_CACHE) {
129         return CleanCache(agingBundleInfo);
130     }
131 
132     return UnInstallBundle(agingBundleInfo.GetBundleName());
133 }
134 
CleanCache(const AgingBundleInfo & agingBundle) const135 bool RecentlyUnuseBundleAgingHandler::CleanCache(const AgingBundleInfo &agingBundle) const
136 {
137     std::vector<std::string> caches;
138     if (!GetCachePath(agingBundle, caches)) {
139         APP_LOGW("Get cache path failed: %{public}s", agingBundle.GetBundleName().c_str());
140         EventReport::SendCleanCacheSysEvent(
141             agingBundle.GetBundleName(), Constants::ALL_USERID, true, true);
142         return false;
143     }
144 
145     bool hasCleanCache = false;
146     for (const auto &cache : caches) {
147         APP_LOGD("cache path: %{public}s", cache.c_str());
148         ErrCode ret = InstalldClient::GetInstance()->CleanBundleDataDir(cache);
149         if (ret != ERR_OK) {
150             APP_LOGE("CleanBundleDataDir failed, path: %{private}s", cache.c_str());
151             continue;
152         }
153 
154         hasCleanCache = true;
155     }
156 
157     EventReport::SendCleanCacheSysEvent(
158         agingBundle.GetBundleName(), Constants::ALL_USERID, true, !hasCleanCache);
159     return hasCleanCache;
160 }
161 
GetCachePath(const AgingBundleInfo & agingBundle,std::vector<std::string> & caches) const162 bool RecentlyUnuseBundleAgingHandler::GetCachePath(
163     const AgingBundleInfo &agingBundle, std::vector<std::string> &caches) const
164 {
165     auto dataMgr = OHOS::DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
166     if (dataMgr == nullptr) {
167         APP_LOGE("dataMgr is null");
168         return false;
169     }
170 
171     std::vector<InnerBundleUserInfo> innerBundleUserInfos;
172     if (!dataMgr->GetInnerBundleUserInfos(agingBundle.GetBundleName(), innerBundleUserInfos)) {
173         APP_LOGE("GetInnerBundleUserInfos failed bundle: %{public}s",
174             agingBundle.GetBundleName().c_str());
175         return false;
176     }
177 
178     std::vector<std::string> rootDir;
179     for (const auto &innerBundleUserInfo : innerBundleUserInfos) {
180         int32_t userId = innerBundleUserInfo.bundleUserInfo.userId;
181         for (const auto &el : Constants::BUNDLE_EL) {
182             std::string dataDir =
183                 Constants::BUNDLE_APP_DATA_BASE_DIR + el +
184                 Constants::PATH_SEPARATOR + std::to_string(userId) +
185                 Constants::BASE + agingBundle.GetBundleName();
186             rootDir.emplace_back(dataDir);
187         }
188     }
189 
190     for (const auto &st : rootDir) {
191         std::vector<std::string> cache;
192         if (InstalldClient::GetInstance()->GetBundleCachePath(st, cache) != ERR_OK) {
193             APP_LOGW("GetBundleCachePath failed, path: %{public}s", st.c_str());
194             continue;
195         }
196 
197         std::copy(cache.begin(), cache.end(), std::back_inserter(caches));
198     }
199 
200     return !caches.empty();
201 }
202 
UnInstallBundle(const std::string & bundleName) const203 bool RecentlyUnuseBundleAgingHandler::UnInstallBundle(const std::string &bundleName) const
204 {
205     auto bms = DelayedSingleton<BundleMgrService>::GetInstance();
206     if (bms == nullptr) {
207         return false;
208     }
209 
210     auto bundleInstaller = bms->GetBundleInstaller();
211     if (bundleInstaller == nullptr) {
212         APP_LOGE("bundleInstaller is null.");
213         return false;
214     }
215 
216     sptr<AgingUninstallReceiveImpl> unInstallReceiverImpl(new (std::nothrow) AgingUninstallReceiveImpl());
217     if (unInstallReceiverImpl == nullptr) {
218         return false;
219     }
220 
221     std::shared_ptr<BundlePromise> agingPromise = std::make_shared<BundlePromise>();
222     unInstallReceiverImpl->SetAgingPromise(agingPromise);
223     unInstallReceiverImpl->MarkRunning();
224     InstallParam installParam;
225     installParam.userId = Constants::ALL_USERID;
226     installParam.installFlag = InstallFlag::FREE_INSTALL;
227     installParam.isAgingUninstall = true;
228     installParam.noSkipsKill = false;
229     bundleInstaller->Uninstall(bundleName, installParam, unInstallReceiverImpl);
230     if (unInstallReceiverImpl->IsRunning()) {
231         APP_LOGD("Wait for UnInstallBundle end %{public}s.", bundleName.c_str());
232         agingPromise->WaitForAllTasksExecute();
233     }
234 
235     return true;
236 }
237 }  //  namespace AppExecFwk
238 }  //  namespace OHOS
239