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_deployer.h"
17
18 #include "app_log_wrapper.h"
19 #include "appexecfwk_errors.h"
20 #include "bundle_constants.h"
21 #include "bundle_mgr_service.h"
22 #include "bundle_util.h"
23 #include "installd_client.h"
24 #include "patch_extractor.h"
25 #include "patch_parser.h"
26 #include "scope_guard.h"
27
28 namespace OHOS {
29 namespace AppExecFwk {
QuickFixDeployer(const std::vector<std::string> & bundleFilePaths)30 QuickFixDeployer::QuickFixDeployer(const std::vector<std::string> &bundleFilePaths) : patchPaths_(bundleFilePaths)
31 {}
32
Execute()33 ErrCode QuickFixDeployer::Execute()
34 {
35 ErrCode ret = DeployQuickFix();
36 if (ret != ERR_OK) {
37 APP_LOGE("QuickFixDeployer errcode %{public}d", ret);
38 }
39 return ret;
40 }
41
DeployQuickFix()42 ErrCode QuickFixDeployer::DeployQuickFix()
43 {
44 if (patchPaths_.empty() || (GetQuickFixDataMgr() != ERR_OK)) {
45 APP_LOGE("DeployQuickFix wrong parms");
46 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
47 }
48
49 std::vector<std::string> realFilePaths;
50 ErrCode ret = ProcessBundleFilePaths(patchPaths_, realFilePaths);
51 if (ret != ERR_OK) {
52 return ret;
53 }
54 ScopeGuard guardRemovePath([realFilePaths] {
55 for (const auto &path: realFilePaths) {
56 std::string tempPath = path.substr(0, path.rfind(Constants::PATH_SEPARATOR));
57 if (InstalldClient::GetInstance()->RemoveDir(tempPath) != ERR_OK) {
58 APP_LOGE("RemovePatchFile failed path: %{private}s", tempPath.c_str());
59 }
60 }
61 });
62 // parse check multi hqf files, update status DEPLOY_START
63 InnerAppQuickFix newInnerAppQuickFix;
64 InnerAppQuickFix oldInnerAppQuickFix;
65 ret = ToDeployStartStatus(realFilePaths, newInnerAppQuickFix, oldInnerAppQuickFix);
66 if (ret != ERR_OK) {
67 return ret;
68 }
69 // extract diff files, apply diff patch and copy hqf, update status DEPLOY_END
70 ret = ToDeployEndStatus(newInnerAppQuickFix, oldInnerAppQuickFix);
71 if (ret != ERR_OK) {
72 bool isExist = !oldInnerAppQuickFix.GetAppQuickFix().bundleName.empty();
73 if (isExist) {
74 quickFixDataMgr_->SaveInnerAppQuickFix(oldInnerAppQuickFix);
75 } else {
76 quickFixDataMgr_->DeleteInnerAppQuickFix(newInnerAppQuickFix.GetAppQuickFix().bundleName);
77 }
78 return ret;
79 }
80 // remove old deploying patch_versionCode
81 const AppQuickFix &appQuick = oldInnerAppQuickFix.GetAppQuickFix();
82 if (!appQuick.bundleName.empty()) {
83 std::string oldPath = Constants::BUNDLE_CODE_DIR + Constants::PATH_SEPARATOR +
84 appQuick.bundleName + Constants::PATH_SEPARATOR;
85 if (appQuick.deployingAppqfInfo.type == QuickFixType::HOT_RELOAD) {
86 oldPath += Constants::HOT_RELOAD_PATH + std::to_string(appQuick.deployingAppqfInfo.versionCode);
87 } else {
88 oldPath += Constants::PATCH_PATH + std::to_string(appQuick.deployingAppqfInfo.versionCode);
89 }
90 if (InstalldClient::GetInstance()->RemoveDir(oldPath)) {
91 APP_LOGE("delete %{private}s failed", oldPath.c_str());
92 }
93 }
94 return ERR_OK;
95 }
96
ToDeployStartStatus(const std::vector<std::string> & bundleFilePaths,InnerAppQuickFix & newInnerAppQuickFix,InnerAppQuickFix & oldInnerAppQuickFix)97 ErrCode QuickFixDeployer::ToDeployStartStatus(const std::vector<std::string> &bundleFilePaths,
98 InnerAppQuickFix &newInnerAppQuickFix, InnerAppQuickFix &oldInnerAppQuickFix)
99 {
100 APP_LOGI("ToDeployStartStatus start.");
101 if (GetQuickFixDataMgr() != ERR_OK) {
102 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
103 }
104 std::unordered_map<std::string, AppQuickFix> infos;
105 // parse and check multi app quick fix info
106 ErrCode ret = ParseAndCheckAppQuickFixInfos(bundleFilePaths, infos);
107 if (ret != ERR_OK) {
108 return ret;
109 }
110 const AppQuickFix &appQuickFix = infos.begin()->second;
111 bool isExist = quickFixDataMgr_->QueryInnerAppQuickFix(appQuickFix.bundleName, oldInnerAppQuickFix);
112 const QuickFixMark &mark = oldInnerAppQuickFix.GetQuickFixMark();
113 if (isExist && (mark.status != QuickFixStatus::DEPLOY_START) && (mark.status != QuickFixStatus::DEPLOY_END)) {
114 APP_LOGE("error: wrong quick fix status, now status : %{public}d", mark.status);
115 return ERR_BUNDLEMANAGER_QUICK_FIX_INVALID_PATCH_STATUS;
116 }
117 const AppQuickFix &oldAppQuickFix = oldInnerAppQuickFix.GetAppQuickFix();
118 // exist and type same need to check version code
119 if (isExist && (appQuickFix.deployingAppqfInfo.type == oldAppQuickFix.deployingAppqfInfo.type)) {
120 // check current app quick fix version code
121 ret = CheckPatchVersionCode(appQuickFix, oldAppQuickFix);
122 if (ret != ERR_OK) {
123 return ret;
124 }
125 }
126 // check bundleName exist
127 BundleInfo bundleInfo;
128 ret = GetBundleInfo(appQuickFix.bundleName, bundleInfo);
129 if (ret != ERR_OK) {
130 APP_LOGE("GetBundleInfo failed, bundleName: %{public}s", appQuickFix.bundleName.c_str());
131 return ret;
132 }
133 // check with installed bundle
134 if (appQuickFix.deployingAppqfInfo.type == QuickFixType::PATCH) {
135 ret = ProcessPatchDeployStart(bundleFilePaths, bundleInfo, infos);
136 } else if (appQuickFix.deployingAppqfInfo.type == QuickFixType::HOT_RELOAD) {
137 ret = ProcessHotReloadDeployStart(bundleInfo, appQuickFix);
138 } else {
139 ret = ERR_BUNDLEMANAGER_QUICK_FIX_UNKNOWN_QUICK_FIX_TYPE;
140 }
141 if (ret != ERR_OK) {
142 return ret;
143 }
144 // convert to InnerAppQuickFix
145 ret = ToInnerAppQuickFix(infos, oldInnerAppQuickFix, newInnerAppQuickFix);
146 if (ret != ERR_OK) {
147 return ret;
148 }
149 // save infos and update status DEPLOY_START
150 ret = SaveAppQuickFix(newInnerAppQuickFix);
151 if (ret != ERR_OK) {
152 APP_LOGE("SaveAppQuickFix failed, errcode: %{public}d", ret);
153 return ret;
154 }
155 APP_LOGI("ToDeployStartStatus end.");
156 return ERR_OK;
157 }
158
ToDeployQuickFixResult(const AppQuickFix & appQuickFix)159 void QuickFixDeployer::ToDeployQuickFixResult(const AppQuickFix &appQuickFix)
160 {
161 APP_LOGD("ToDeployQuickFixResult start.");
162 deployQuickFixResult_.bundleName = appQuickFix.bundleName;
163 deployQuickFixResult_.bundleVersionCode = appQuickFix.versionCode;
164 deployQuickFixResult_.patchVersionCode = appQuickFix.deployingAppqfInfo.versionCode;
165 deployQuickFixResult_.type = appQuickFix.deployingAppqfInfo.type;
166 deployQuickFixResult_.isSoContained = HasNativeSoInBundle(appQuickFix);
167 deployQuickFixResult_.moduleNames.clear();
168 for (const auto &hqf : appQuickFix.deployingAppqfInfo.hqfInfos) {
169 deployQuickFixResult_.moduleNames.emplace_back(hqf.moduleName);
170 }
171 APP_LOGD("ToDeployQuickFixResult end.");
172 }
173
ProcessPatchDeployStart(const std::vector<std::string> bundleFilePaths,const BundleInfo & bundleInfo,std::unordered_map<std::string,AppQuickFix> & infos)174 ErrCode QuickFixDeployer::ProcessPatchDeployStart(
175 const std::vector<std::string> bundleFilePaths,
176 const BundleInfo &bundleInfo,
177 std::unordered_map<std::string, AppQuickFix> &infos)
178 {
179 APP_LOGI("ProcessPatchDeployStart start.");
180 if (infos.empty()) {
181 APP_LOGE("error: appQuickFix infos is empty");
182 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
183 }
184 QuickFixChecker checker;
185 // check multiple cpuAbi and native library path
186 ErrCode ret = checker.CheckMultiNativeSo(infos);
187 if (ret != ERR_OK) {
188 APP_LOGE("ProcessPatchDeployStart check native so failed");
189 return ret;
190 }
191 // parse signature info
192 std::vector<Security::Verify::HapVerifyResult> hapVerifyRes;
193 ret = checker.CheckMultipleHqfsSignInfo(bundleFilePaths, hapVerifyRes);
194 if (ret != ERR_OK) {
195 APP_LOGE("ProcessPatchDeployStart check check multiple hqfs signInfo failed");
196 return ret;
197 }
198 if (hapVerifyRes.empty()) {
199 APP_LOGE("error: appQuickFix hapVerifyRes is empty");
200 return ERR_APPEXECFWK_INSTALL_FAILED_INCOMPATIBLE_SIGNATURE;
201 }
202 const auto &provisionInfo = hapVerifyRes[0].GetProvisionInfo();
203 const AppQuickFix &appQuickFix = infos.begin()->second;
204 // check with installed bundle, signature info, bundleName, versionCode
205 ret = checker.CheckPatchWithInstalledBundle(appQuickFix, bundleInfo, provisionInfo);
206 if (ret != ERR_OK) {
207 APP_LOGE("check AppQuickFixInfos with installed bundle failed, errcode : %{public}d", ret);
208 return ret;
209 }
210 APP_LOGI("ProcessPatchDeployStart end.");
211 return ERR_OK;
212 }
213
ProcessHotReloadDeployStart(const BundleInfo & bundleInfo,const AppQuickFix & appQuickFix)214 ErrCode QuickFixDeployer::ProcessHotReloadDeployStart(
215 const BundleInfo &bundleInfo,
216 const AppQuickFix &appQuickFix)
217 {
218 APP_LOGI("ProcessHotReloadDeployStart start.");
219 QuickFixChecker checker;
220 ErrCode ret = checker.CheckHotReloadWithInstalledBundle(appQuickFix, bundleInfo);
221 if (ret != ERR_OK) {
222 APP_LOGE("check AppQuickFixInfos with installed bundle failed");
223 return ret;
224 }
225 APP_LOGI("ProcessHotReloadDeployStart end.");
226 return ERR_OK;
227 }
228
ToDeployEndStatus(InnerAppQuickFix & newInnerAppQuickFix,const InnerAppQuickFix & oldInnerAppQuickFix)229 ErrCode QuickFixDeployer::ToDeployEndStatus(InnerAppQuickFix &newInnerAppQuickFix,
230 const InnerAppQuickFix &oldInnerAppQuickFix)
231 {
232 APP_LOGI("ToDeployEndStatus start.");
233 if ((GetQuickFixDataMgr() != ERR_OK)) {
234 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
235 }
236 // create patch path
237 AppQuickFix newQuickFix = newInnerAppQuickFix.GetAppQuickFix();
238 std::string newPatchPath;
239 ScopeGuard guardRemovePatchPath([&newPatchPath] {
240 InstalldClient::GetInstance()->RemoveDir(newPatchPath);
241 });
242 ErrCode ret = ERR_OK;
243 if (newQuickFix.deployingAppqfInfo.type == QuickFixType::PATCH) {
244 // extract diff files and apply diff patch
245 ret = ProcessPatchDeployEnd(newQuickFix, newPatchPath);
246 } else if (newQuickFix.deployingAppqfInfo.type == QuickFixType::HOT_RELOAD) {
247 ret = ProcessHotReloadDeployEnd(newQuickFix, newPatchPath);
248 } else {
249 APP_LOGE("error: unknown QuickFixType");
250 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
251 }
252 if (ret != ERR_OK) {
253 APP_LOGE("Process Patch or HotReload DeployEnd failed, bundleName:%{public}s",
254 newQuickFix.bundleName.c_str());
255 return ret;
256 }
257
258 // if so files exist, library path add patch_versionCode;
259 // if so files not exist, modify library path to empty.
260 ProcessNativeLibraryPath(newPatchPath, newInnerAppQuickFix);
261
262 // move hqf files to new patch path
263 ret = MoveHqfFiles(newInnerAppQuickFix, newPatchPath);
264 if (ret != ERR_OK) {
265 APP_LOGE("error MoveHqfFiles failed, bundleName: %{public}s", newQuickFix.bundleName.c_str());
266 return ret;
267 }
268 // save and update status DEPLOY_END
269 ret = SaveAppQuickFix(newInnerAppQuickFix);
270 if (ret != ERR_OK) {
271 return ret;
272 }
273 ToDeployQuickFixResult(newQuickFix);
274 ret = SaveToInnerBundleInfo(newInnerAppQuickFix);
275 if (ret != ERR_OK) {
276 APP_LOGE("error: bundleName %{public}s update deploying quick fix info to innerBundleInfo failed",
277 newQuickFix.bundleName.c_str());
278 return ret;
279 }
280 guardRemovePatchPath.Dismiss();
281 APP_LOGI("ToDeployEndStatus end.");
282 return ERR_OK;
283 }
284
ProcessNativeLibraryPath(const std::string & patchPath,InnerAppQuickFix & innerAppQuickFix)285 void QuickFixDeployer::ProcessNativeLibraryPath(const std::string &patchPath, InnerAppQuickFix &innerAppQuickFix)
286 {
287 AppQuickFix appQuickFix = innerAppQuickFix.GetAppQuickFix();
288 if (!appQuickFix.deployingAppqfInfo.nativeLibraryPath.empty()) {
289 std::string nativeLibraryPath = appQuickFix.deployingAppqfInfo.nativeLibraryPath;
290 ProcessNativeLibraryPath(patchPath, innerAppQuickFix, nativeLibraryPath);
291 appQuickFix.deployingAppqfInfo.nativeLibraryPath = nativeLibraryPath;
292 }
293
294 for (auto &hqfInfo : appQuickFix.deployingAppqfInfo.hqfInfos) {
295 if (!hqfInfo.nativeLibraryPath.empty()) {
296 std::string nativeLibraryPath = hqfInfo.nativeLibraryPath;
297 ProcessNativeLibraryPath(patchPath, innerAppQuickFix, nativeLibraryPath);
298 hqfInfo.nativeLibraryPath = nativeLibraryPath;
299 }
300 }
301
302 innerAppQuickFix.SetAppQuickFix(appQuickFix);
303 }
304
ProcessNativeLibraryPath(const std::string & patchPath,const InnerAppQuickFix & innerAppQuickFix,std::string & nativeLibraryPath)305 void QuickFixDeployer::ProcessNativeLibraryPath(
306 const std::string &patchPath, const InnerAppQuickFix &innerAppQuickFix, std::string &nativeLibraryPath)
307 {
308 bool isSoExist = false;
309 auto libraryPath = nativeLibraryPath;
310 std::string soPath = patchPath + Constants::PATH_SEPARATOR + libraryPath;
311 if (InstalldClient::GetInstance()->IsExistDir(soPath, isSoExist) != ERR_OK) {
312 APP_LOGE("ProcessNativeLibraryPath InstalldClient IsExistDir(%{public}s) failed", soPath.c_str());
313 return;
314 }
315
316 AppQuickFix appQuickFix = innerAppQuickFix.GetAppQuickFix();
317 if (isSoExist) {
318 nativeLibraryPath = Constants::PATCH_PATH +
319 std::to_string(appQuickFix.deployingAppqfInfo.versionCode) + Constants::PATH_SEPARATOR + libraryPath;
320 } else {
321 APP_LOGI("So(%{public}s) is not exist and set nativeLibraryPath(%{public}s) empty",
322 soPath.c_str(), nativeLibraryPath.c_str());
323 nativeLibraryPath.clear();
324 }
325 }
326
ProcessPatchDeployEnd(const AppQuickFix & appQuickFix,std::string & patchPath)327 ErrCode QuickFixDeployer::ProcessPatchDeployEnd(const AppQuickFix &appQuickFix, std::string &patchPath)
328 {
329 patchPath = Constants::BUNDLE_CODE_DIR + Constants::PATH_SEPARATOR + appQuickFix.bundleName +
330 Constants::PATH_SEPARATOR + Constants::PATCH_PATH +
331 std::to_string(appQuickFix.deployingAppqfInfo.versionCode);
332 ErrCode ret = InstalldClient::GetInstance()->CreateBundleDir(patchPath);
333 if (ret != ERR_OK) {
334 APP_LOGE("error: creat patch path failed, errcode %{public}d", ret);
335 return ERR_BUNDLEMANAGER_QUICK_FIX_CREATE_PATCH_PATH_FAILED;
336 }
337
338 auto &appQfInfo = appQuickFix.deployingAppqfInfo;
339 for (const auto &hqf : appQfInfo.hqfInfos) {
340 if (hqf.hqfFilePath.empty()) {
341 APP_LOGE("error: hapFilePath is empty");
342 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
343 }
344
345 std::string libraryPath;
346 std::string cpuAbi;
347 bool isLibIsolated = IsLibIsolated(appQuickFix.bundleName, hqf.moduleName);
348 if (!FetchPatchNativeSoAttrs(
349 appQuickFix.deployingAppqfInfo, hqf, isLibIsolated, libraryPath, cpuAbi)) {
350 continue;
351 }
352
353 std::string oldSoPath = Constants::BUNDLE_CODE_DIR + Constants::PATH_SEPARATOR + appQuickFix.bundleName +
354 Constants::PATH_SEPARATOR + libraryPath;
355 APP_LOGD("ProcessPatchDeployEnd oldPath %{public}s", oldSoPath.c_str());
356 bool pathExist = false;
357 // if old so path does not exist then return ERR_OK
358 ret = InstalldClient::GetInstance()->IsExistDir(oldSoPath, pathExist);
359 if (!pathExist && (ret == ERR_OK)) {
360 APP_LOGD("bundleName: %{public}s no so path", appQuickFix.bundleName.c_str());
361 return ERR_OK;
362 }
363
364 // extract diff so, diff so path
365 std::string diffFilePath = Constants::HAP_COPY_PATH + Constants::PATH_SEPARATOR +
366 appQuickFix.bundleName + Constants::TMP_SUFFIX;
367 ScopeGuard guardRemoveDiffPath([diffFilePath] { InstalldClient::GetInstance()->RemoveDir(diffFilePath); });
368
369 // extract so to targetPath
370 ret = InstalldClient::GetInstance()->ExtractDiffFiles(hqf.hqfFilePath, diffFilePath, cpuAbi);
371 if (ret != ERR_OK) {
372 APP_LOGE("error: ExtractDiffFiles failed errcode :%{public}d", ret);
373 return ERR_BUNDLEMANAGER_QUICK_FIX_EXTRACT_DIFF_FILES_FAILED;
374 }
375
376 // apply diff patch
377 std::string newSoPath = patchPath + Constants::PATH_SEPARATOR + libraryPath;
378 ret = InstalldClient::GetInstance()->ApplyDiffPatch(oldSoPath, diffFilePath, newSoPath);
379 if (ret != ERR_OK) {
380 APP_LOGE("ApplyDiffPatch failed, bundleName:%{public}s, errcode: %{public}d",
381 appQuickFix.bundleName.c_str(), ret);
382 return ERR_BUNDLEMANAGER_QUICK_FIX_APPLY_DIFF_PATCH_FAILED;
383 }
384 }
385
386 return ERR_OK;
387 }
388
ProcessHotReloadDeployEnd(const AppQuickFix & appQuickFix,std::string & patchPath)389 ErrCode QuickFixDeployer::ProcessHotReloadDeployEnd(const AppQuickFix &appQuickFix, std::string &patchPath)
390 {
391 patchPath = Constants::BUNDLE_CODE_DIR + Constants::PATH_SEPARATOR + appQuickFix.bundleName +
392 Constants::PATH_SEPARATOR + Constants::HOT_RELOAD_PATH +
393 std::to_string(appQuickFix.deployingAppqfInfo.versionCode);
394 ErrCode ret = InstalldClient::GetInstance()->CreateBundleDir(patchPath);
395 if (ret != ERR_OK) {
396 APP_LOGE("error: creat hotreload path failed, errcode %{public}d", ret);
397 return ERR_BUNDLEMANAGER_QUICK_FIX_CREATE_PATCH_PATH_FAILED;
398 }
399 return ERR_OK;
400 }
401
ParseAndCheckAppQuickFixInfos(const std::vector<std::string> & bundleFilePaths,std::unordered_map<std::string,AppQuickFix> & infos)402 ErrCode QuickFixDeployer::ParseAndCheckAppQuickFixInfos(
403 const std::vector<std::string> &bundleFilePaths,
404 std::unordered_map<std::string, AppQuickFix> &infos)
405 {
406 // parse hqf file to AppQuickFix
407 PatchParser patchParser;
408 ErrCode ret = patchParser.ParsePatchInfo(bundleFilePaths, infos);
409 if ((ret != ERR_OK) || infos.empty()) {
410 APP_LOGE("parse AppQuickFixFiles failed, errcode %{public}d", ret);
411 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
412 }
413
414 ResetNativeSoAttrs(infos);
415 QuickFixChecker checker;
416 // check multiple AppQuickFix
417 ret = checker.CheckAppQuickFixInfos(infos);
418 if (ret != ERR_OK) {
419 APP_LOGE("check AppQuickFixInfos failed");
420 return ret;
421 }
422 const QuickFixType &quickFixType = infos.begin()->second.deployingAppqfInfo.type;
423 if (quickFixType == QuickFixType::UNKNOWN) {
424 APP_LOGE("error unknown quick fix type");
425 return ERR_BUNDLEMANAGER_QUICK_FIX_UNKNOWN_QUICK_FIX_TYPE;
426 }
427 // hqf file path
428 for (auto iter = infos.begin(); iter != infos.end(); ++iter) {
429 if (!iter->second.deployingAppqfInfo.hqfInfos.empty()) {
430 iter->second.deployingAppqfInfo.hqfInfos[0].hqfFilePath = iter->first;
431 } else {
432 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
433 }
434 }
435 return ERR_OK;
436 }
437
ResetNativeSoAttrs(std::unordered_map<std::string,AppQuickFix> & infos)438 void QuickFixDeployer::ResetNativeSoAttrs(std::unordered_map<std::string, AppQuickFix> &infos)
439 {
440 for (auto &info : infos) {
441 ResetNativeSoAttrs(info.second);
442 }
443 }
444
ResetNativeSoAttrs(AppQuickFix & appQuickFix)445 void QuickFixDeployer::ResetNativeSoAttrs(AppQuickFix &appQuickFix)
446 {
447 auto &appqfInfo = appQuickFix.deployingAppqfInfo;
448 if (appqfInfo.hqfInfos.size() != 1) {
449 APP_LOGW("The number of hqfInfos is not one.");
450 return;
451 }
452
453 bool isLibIsolated = IsLibIsolated(appQuickFix.bundleName, appqfInfo.hqfInfos[0].moduleName);
454 if (!isLibIsolated) {
455 APP_LOGW("Lib is not isolated.");
456 return;
457 }
458
459 appqfInfo.hqfInfos[0].cpuAbi = appqfInfo.cpuAbi;
460 appqfInfo.hqfInfos[0].nativeLibraryPath =
461 appqfInfo.hqfInfos[0].moduleName + Constants::PATH_SEPARATOR + appqfInfo.nativeLibraryPath;
462 appqfInfo.nativeLibraryPath.clear();
463 }
464
IsLibIsolated(const std::string & bundleName,const std::string & moduleName)465 bool QuickFixDeployer::IsLibIsolated(
466 const std::string &bundleName, const std::string &moduleName)
467 {
468 InnerBundleInfo innerBundleInfo;
469 if (!FetchInnerBundleInfo(bundleName, innerBundleInfo)) {
470 APP_LOGE("Fetch bundleInfo(%{public}s) failed.", bundleName.c_str());
471 return false;
472 }
473
474 return innerBundleInfo.IsLibIsolated(moduleName);
475 }
476
FetchInnerBundleInfo(const std::string & bundleName,InnerBundleInfo & innerBundleInfo)477 bool QuickFixDeployer::FetchInnerBundleInfo(
478 const std::string &bundleName, InnerBundleInfo &innerBundleInfo)
479 {
480 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
481 if (dataMgr == nullptr) {
482 APP_LOGE("error dataMgr is nullptr");
483 return false;
484 }
485
486 if (!dataMgr->FetchInnerBundleInfo(bundleName, innerBundleInfo)) {
487 APP_LOGE("Fetch bundleInfo(%{public}s) failed.", bundleName.c_str());
488 return false;
489 }
490
491 return true;
492 }
493
FetchPatchNativeSoAttrs(const AppqfInfo & appqfInfo,const HqfInfo hqfInfo,bool isLibIsolated,std::string & nativeLibraryPath,std::string & cpuAbi)494 bool QuickFixDeployer::FetchPatchNativeSoAttrs(const AppqfInfo &appqfInfo,
495 const HqfInfo hqfInfo, bool isLibIsolated, std::string &nativeLibraryPath, std::string &cpuAbi)
496 {
497 if (isLibIsolated) {
498 nativeLibraryPath = hqfInfo.nativeLibraryPath;
499 cpuAbi = hqfInfo.cpuAbi;
500 } else {
501 nativeLibraryPath = appqfInfo.nativeLibraryPath;
502 cpuAbi = appqfInfo.cpuAbi;
503 }
504
505 return !nativeLibraryPath.empty();
506 }
507
HasNativeSoInBundle(const AppQuickFix & appQuickFix)508 bool QuickFixDeployer::HasNativeSoInBundle(const AppQuickFix &appQuickFix)
509 {
510 if (!appQuickFix.deployingAppqfInfo.nativeLibraryPath.empty()) {
511 return true;
512 }
513
514 for (const auto &hqfInfo : appQuickFix.deployingAppqfInfo.hqfInfos) {
515 if (!hqfInfo.nativeLibraryPath.empty()) {
516 return true;
517 }
518 }
519
520 return false;
521 }
522
GetBundleInfo(const std::string & bundleName,BundleInfo & bundleInfo)523 ErrCode QuickFixDeployer::GetBundleInfo(const std::string &bundleName, BundleInfo &bundleInfo)
524 {
525 std::shared_ptr<BundleMgrService> bms = DelayedSingleton<BundleMgrService>::GetInstance();
526 if (bms == nullptr) {
527 APP_LOGE("error: bms is nullptr");
528 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
529 }
530 std::shared_ptr<BundleDataMgr> dataMgr = bms->GetDataMgr();
531 if (dataMgr == nullptr) {
532 APP_LOGE("error: dataMgr is nullptr");
533 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
534 }
535 // check bundleName is exists
536 if (!dataMgr->GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_DEFAULT,
537 bundleInfo, Constants::ANY_USERID)) {
538 APP_LOGE("error: GetBundleInfo failed, bundleName: %{public}s not exist", bundleName.c_str());
539 return ERR_BUNDLEMANAGER_QUICK_FIX_BUNDLE_NAME_NOT_EXIST;
540 }
541 return ERR_OK;
542 }
543
ToInnerAppQuickFix(const std::unordered_map<std::string,AppQuickFix> infos,const InnerAppQuickFix & oldInnerAppQuickFix,InnerAppQuickFix & newInnerAppQuickFix)544 ErrCode QuickFixDeployer::ToInnerAppQuickFix(const std::unordered_map<std::string, AppQuickFix> infos,
545 const InnerAppQuickFix &oldInnerAppQuickFix, InnerAppQuickFix &newInnerAppQuickFix)
546 {
547 APP_LOGD("ToInnerAppQuickFix start");
548 if (infos.empty()) {
549 APP_LOGE("error: appQuickFix is empty");
550 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
551 }
552 AppQuickFix oldAppQuickFix = oldInnerAppQuickFix.GetAppQuickFix();
553 AppQuickFix appQuickFix = infos.begin()->second;
554 // copy deployed app qf info
555 appQuickFix.deployedAppqfInfo = oldAppQuickFix.deployedAppqfInfo;
556 newInnerAppQuickFix.SetAppQuickFix(appQuickFix);
557 QuickFixMark mark;
558 mark.bundleName = appQuickFix.bundleName;
559 mark.status = QuickFixStatus::DEPLOY_START;
560 for (auto iter = infos.begin(); iter != infos.end(); ++iter) {
561 const auto &quickFix = iter->second;
562 // hqfInfos will not be empty, it has been judged before.
563 const std::string &moduleName = quickFix.deployingAppqfInfo.hqfInfos[0].moduleName;
564 if (!newInnerAppQuickFix.AddHqfInfo(quickFix)) {
565 APP_LOGE("error: appQuickFix add hqf moduleName: %{public}s failed", moduleName.c_str());
566 return ERR_BUNDLEMANAGER_QUICK_FIX_ADD_HQF_FAILED;
567 }
568 }
569 newInnerAppQuickFix.SetQuickFixMark(mark);
570 APP_LOGD("ToInnerAppQuickFix end");
571 return ERR_OK;
572 }
573
CheckPatchVersionCode(const AppQuickFix & newAppQuickFix,const AppQuickFix & oldAppQuickFix)574 ErrCode QuickFixDeployer::CheckPatchVersionCode(
575 const AppQuickFix &newAppQuickFix,
576 const AppQuickFix &oldAppQuickFix)
577 {
578 const AppqfInfo &newInfo = newAppQuickFix.deployingAppqfInfo;
579 const AppqfInfo &oldInfoDeployed = oldAppQuickFix.deployedAppqfInfo;
580 const AppqfInfo &oldInfoDeploying = oldAppQuickFix.deployingAppqfInfo;
581 if ((newInfo.versionCode > oldInfoDeployed.versionCode) &&
582 (newInfo.versionCode > oldInfoDeploying.versionCode)) {
583 return ERR_OK;
584 }
585 APP_LOGE("CheckPatchVersionCode failed, version code should be greater than the original");
586 return ERR_BUNDLEMANAGER_QUICK_FIX_VERSION_CODE_ERROR;
587 }
588
SaveAppQuickFix(const InnerAppQuickFix & innerAppQuickFix)589 ErrCode QuickFixDeployer::SaveAppQuickFix(const InnerAppQuickFix &innerAppQuickFix)
590 {
591 if ((GetQuickFixDataMgr() != ERR_OK)) {
592 APP_LOGE("error: quickFixDataMgr_ is nullptr");
593 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
594 }
595 if (!quickFixDataMgr_->SaveInnerAppQuickFix(innerAppQuickFix)) {
596 APP_LOGE("bundleName: %{public}s, inner app quick fix save failed",
597 innerAppQuickFix.GetAppQuickFix().bundleName.c_str());
598 return ERR_BUNDLEMANAGER_QUICK_FIX_SAVE_APP_QUICK_FIX_FAILED;
599 }
600 return ERR_OK;
601 }
602
MoveHqfFiles(InnerAppQuickFix & innerAppQuickFix,const std::string & targetPath)603 ErrCode QuickFixDeployer::MoveHqfFiles(InnerAppQuickFix &innerAppQuickFix, const std::string &targetPath)
604 {
605 APP_LOGD("MoveHqfFiles start.");
606 if (targetPath.empty() || (GetQuickFixDataMgr() != ERR_OK)) {
607 APP_LOGE("MoveHqfFiles params error");
608 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
609 }
610 QuickFixMark mark = innerAppQuickFix.GetQuickFixMark();
611 AppQuickFix appQuickFix = innerAppQuickFix.GetAppQuickFix();
612 std::string path = targetPath;
613 if (path.back() != Constants::FILE_SEPARATOR_CHAR) {
614 path.push_back(Constants::FILE_SEPARATOR_CHAR);
615 }
616 for (HqfInfo &info : appQuickFix.deployingAppqfInfo.hqfInfos) {
617 if (info.hqfFilePath.empty()) {
618 APP_LOGE("error hapFilePath is empty");
619 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
620 }
621 std::string realPath = path + info.moduleName + Constants::QUICK_FIX_FILE_SUFFIX;
622 ErrCode ret = InstalldClient::GetInstance()->MoveFile(info.hqfFilePath, realPath);
623 if (ret != ERR_OK) {
624 APP_LOGE("error MoveFile failed, errcode: %{public}d", ret);
625 return ERR_BUNDLEMANAGER_QUICK_FIX_MOVE_PATCH_FILE_FAILED;
626 }
627 info.hqfFilePath = realPath;
628 }
629 mark.status = QuickFixStatus::DEPLOY_END;
630 innerAppQuickFix.SetQuickFixMark(mark);
631 innerAppQuickFix.SetAppQuickFix(appQuickFix);
632 APP_LOGD("MoveHqfFiles end.");
633 return ERR_OK;
634 }
635
GetDeployQuickFixResult() const636 DeployQuickFixResult QuickFixDeployer::GetDeployQuickFixResult() const
637 {
638 return deployQuickFixResult_;
639 }
640
GetQuickFixDataMgr()641 ErrCode QuickFixDeployer::GetQuickFixDataMgr()
642 {
643 if (quickFixDataMgr_ == nullptr) {
644 quickFixDataMgr_ = DelayedSingleton<QuickFixDataMgr>::GetInstance();
645 if (quickFixDataMgr_ == nullptr) {
646 APP_LOGE("error: quickFixDataMgr_ is nullptr");
647 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
648 }
649 }
650 return ERR_OK;
651 }
652
SaveToInnerBundleInfo(const InnerAppQuickFix & newInnerAppQuickFix)653 ErrCode QuickFixDeployer::SaveToInnerBundleInfo(const InnerAppQuickFix &newInnerAppQuickFix)
654 {
655 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
656 if (dataMgr == nullptr) {
657 APP_LOGE("error dataMgr is nullptr");
658 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
659 }
660 const std::string &bundleName = newInnerAppQuickFix.GetAppQuickFix().bundleName;
661 InnerBundleInfo innerBundleInfo;
662 // obtain innerBundleInfo and enableGuard used to enable bundle which is under disable status
663 if (!dataMgr->GetInnerBundleInfo(bundleName, innerBundleInfo)) {
664 APP_LOGE("cannot obtain the innerbundleInfo from data mgr");
665 return ERR_BUNDLEMANAGER_QUICK_FIX_NOT_EXISTED_BUNDLE_INFO;
666 }
667 ScopeGuard enableGuard([&bundleName, &dataMgr] { dataMgr->EnableBundle(bundleName); });
668 AppQuickFix appQuickFix = newInnerAppQuickFix.GetAppQuickFix();
669 appQuickFix.deployedAppqfInfo = innerBundleInfo.GetAppQuickFix().deployedAppqfInfo;
670 innerBundleInfo.SetAppQuickFix(appQuickFix);
671 innerBundleInfo.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
672 if (!dataMgr->UpdateQuickFixInnerBundleInfo(bundleName, innerBundleInfo)) {
673 APP_LOGE("update quickfix innerbundleInfo failed");
674 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
675 }
676 return ERR_OK;
677 }
678
ProcessBundleFilePaths(const std::vector<std::string> & bundleFilePaths,std::vector<std::string> & realFilePaths)679 ErrCode QuickFixDeployer::ProcessBundleFilePaths(const std::vector<std::string> &bundleFilePaths,
680 std::vector<std::string> &realFilePaths)
681 {
682 ErrCode ret = BundleUtil::CheckFilePath(bundleFilePaths, realFilePaths);
683 if (ret != ERR_OK) {
684 APP_LOGE("ProcessBundleFilePaths CheckFilePath failed.");
685 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
686 }
687 for (const auto &path : realFilePaths) {
688 if (!BundleUtil::CheckFileType(path, Constants::QUICK_FIX_FILE_SUFFIX)) {
689 APP_LOGE("ProcessBundleFilePaths CheckFileType failed.");
690 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
691 }
692 }
693 return ERR_OK;
694 }
695 } // AppExecFwk
696 } // OHOS