1 /*
2 * Copyright (c) 2022 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 "quick_fix_deleter.h"
17
18 #include "app_log_tag_wrapper.h"
19 #include "bundle_mgr_service.h"
20 #include "installd_client.h"
21 #include "scope_guard.h"
22
23 namespace OHOS {
24 namespace AppExecFwk {
25 namespace {
26 const std::string PATCH_DIR = "patch";
27 }
QuickFixDeleter(const std::string & bundleName)28 QuickFixDeleter::QuickFixDeleter(const std::string &bundleName) : bundleName_(bundleName)
29 {
30 LOG_I(BMS_TAG_DEFAULT, "enter QuickFixDeleter");
31 }
32
Execute()33 ErrCode QuickFixDeleter::Execute()
34 {
35 LOG_I(BMS_TAG_DEFAULT, "start execute");
36 auto ret = DeleteQuickFix();
37 if (ret != ERR_OK) {
38 LOG_E(BMS_TAG_DEFAULT, "DeleteQuickFix is failed");
39 }
40 return ret;
41 }
42
DeleteQuickFix()43 ErrCode QuickFixDeleter::DeleteQuickFix()
44 {
45 LOG_I(BMS_TAG_DEFAULT, "DeleteQuickFix start");
46 if (bundleName_.empty()) {
47 LOG_E(BMS_TAG_DEFAULT, "InnerDeleteQuickFix failed due to empty bundleName");
48 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
49 }
50 if (GetQuickFixDataMgr() != ERR_OK) {
51 LOG_E(BMS_TAG_DEFAULT, "quickFixDataMgr is nullptr");
52 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
53 }
54 InnerAppQuickFix innerAppQuickFix;
55 // 1. query quick fix info form db
56 if (!quickFixDataMgr_->QueryInnerAppQuickFix(bundleName_, innerAppQuickFix)) {
57 LOG_I(BMS_TAG_DEFAULT, "no patch in the db");
58 return ERR_OK;
59 }
60 // 2. update quick fix status
61 if (!quickFixDataMgr_->UpdateQuickFixStatus(QuickFixStatus::DELETE_START, innerAppQuickFix)) {
62 LOG_E(BMS_TAG_DEFAULT, "update quickfix status %{public}d failed", QuickFixStatus::DELETE_START);
63 return ERR_BUNDLEMANAGER_QUICK_FIX_INVALID_PATCH_STATUS;
64 }
65 // 3. utilize stateGuard to rollback quick fix info status in db
66 ScopeGuard stateGuard([&] {
67 quickFixDataMgr_->UpdateQuickFixStatus(QuickFixStatus::SWITCH_END, innerAppQuickFix);
68 });
69
70 // 4. to delete patch path
71 ErrCode errCode = ToDeletePatchDir(innerAppQuickFix);
72 if (errCode != ERR_OK) {
73 LOG_E(BMS_TAG_DEFAULT, "ToDeletePatchDir failed");
74 return errCode;
75 }
76 // 5. to remove deployingAppqfInfo from cache
77 errCode = RemoveDeployingInfo(bundleName_);
78 if (errCode != ERR_OK) {
79 LOG_E(BMS_TAG_DEFAULT, "RemoveDeployingInfo failed");
80 return errCode;
81 }
82 // 6. to remove old patch info from db
83 if (!quickFixDataMgr_->DeleteInnerAppQuickFix(bundleName_)) {
84 LOG_E(BMS_TAG_DEFAULT, "InnerDeleteQuickFix failed");
85 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
86 }
87 stateGuard.Dismiss();
88 return ERR_OK;
89 }
90
ToDeletePatchDir(const InnerAppQuickFix & innerAppQuickFix)91 ErrCode QuickFixDeleter::ToDeletePatchDir(const InnerAppQuickFix &innerAppQuickFix)
92 {
93 LOG_I(BMS_TAG_DEFAULT, "start to delete patch dir");
94 std::string bundleName = innerAppQuickFix.GetAppQuickFix().bundleName;
95 auto res = InnerDeletePatchDir(innerAppQuickFix.GetAppQuickFix().deployedAppqfInfo, bundleName);
96 if (res != ERR_OK) {
97 LOG_E(BMS_TAG_DEFAULT, "delete patch dir of deployedAppqfInfo failed");
98 return res;
99 }
100 res = InnerDeletePatchDir(innerAppQuickFix.GetAppQuickFix().deployingAppqfInfo, bundleName);
101 if (res != ERR_OK) {
102 LOG_E(BMS_TAG_DEFAULT, "delete patch dir of deployingAppqfInfo failed");
103 return res;
104 }
105 return ERR_OK;
106 }
107
InnerDeletePatchDir(const AppqfInfo & appqfInfo,const std::string & bundleName)108 ErrCode QuickFixDeleter::InnerDeletePatchDir(const AppqfInfo &appqfInfo, const std::string &bundleName)
109 {
110 if (appqfInfo.hqfInfos.empty()) {
111 LOG_D(BMS_TAG_DEFAULT, "no patch info in bundleInfo");
112 return ERR_OK;
113 }
114
115 if (appqfInfo.type == QuickFixType::UNKNOWN) {
116 LOG_E(BMS_TAG_DEFAULT, "unknown quick fix type");
117 return ERR_BUNDLEMANAGER_QUICK_FIX_UNKNOWN_QUICK_FIX_TYPE;
118 }
119
120 std::string patchPath = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR +
121 bundleName + ServiceConstants::PATH_SEPARATOR;
122 if (appqfInfo.type == QuickFixType::PATCH) {
123 if (appqfInfo.nativeLibraryPath.substr(0,
124 appqfInfo.nativeLibraryPath.find(ServiceConstants::PATH_SEPARATOR)) == PATCH_DIR) {
125 patchPath += PATCH_DIR;
126 } else {
127 patchPath += ServiceConstants::PATCH_PATH + std::to_string(appqfInfo.versionCode);
128 }
129 }
130 if (appqfInfo.type == QuickFixType::HOT_RELOAD) {
131 patchPath += ServiceConstants::HOT_RELOAD_PATH + std::to_string(appqfInfo.versionCode);
132 }
133
134 LOG_D(BMS_TAG_DEFAULT, "patch path is %{public}s", patchPath.c_str());
135 if (InstalldClient::GetInstance()->RemoveDir(patchPath) != ERR_OK) {
136 LOG_E(BMS_TAG_DEFAULT, "RemoveDir patch path or hot reload path failed");
137 return ERR_BUNDLEMANAGER_QUICK_FIX_REMOVE_PATCH_PATH_FAILED;
138 }
139
140 return ERR_OK;
141 }
142
GetQuickFixDataMgr()143 ErrCode QuickFixDeleter::GetQuickFixDataMgr()
144 {
145 if (quickFixDataMgr_ == nullptr) {
146 quickFixDataMgr_ = DelayedSingleton<QuickFixDataMgr>::GetInstance();
147 if (quickFixDataMgr_ == nullptr) {
148 LOG_E(BMS_TAG_DEFAULT, "quickFix dataMgr is nullptr");
149 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
150 }
151 }
152 return ERR_OK;
153 }
154
GetDataMgr()155 ErrCode QuickFixDeleter::GetDataMgr()
156 {
157 if (dataMgr_ == nullptr) {
158 dataMgr_ = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
159 if (dataMgr_ == nullptr) {
160 LOG_E(BMS_TAG_DEFAULT, "dataMgr_ is nullptr");
161 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
162 }
163 }
164 return ERR_OK;
165 }
166
RemoveDeployingInfo(const std::string & bundleName)167 ErrCode QuickFixDeleter::RemoveDeployingInfo(const std::string &bundleName)
168 {
169 if (GetDataMgr() != ERR_OK) {
170 LOG_E(BMS_TAG_DEFAULT, "get data mar failed");
171 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
172 }
173 InnerBundleInfo innerBundleInfo;
174 auto isExisted = dataMgr_->GetInnerBundleInfo(bundleName, innerBundleInfo);
175 if (isExisted) {
176 AppQuickFix appQuickFix = innerBundleInfo.GetAppQuickFix();
177 if (appQuickFix.deployingAppqfInfo.hqfInfos.empty()) {
178 dataMgr_->EnableBundle(bundleName_);
179 return ERR_OK;
180 }
181 appQuickFix.deployingAppqfInfo = AppqfInfo();
182 innerBundleInfo.SetAppQuickFix(appQuickFix);
183 innerBundleInfo.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
184 if (!dataMgr_->UpdateQuickFixInnerBundleInfo(bundleName, innerBundleInfo)) {
185 LOG_E(BMS_TAG_DEFAULT, "update quickfix innerbundleInfo failed");
186 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
187 }
188 }
189 return ERR_OK;
190 }
191 } // AppExecFwk
192 } // OHOS