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