• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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