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 "event_report.h"
25 #include "patch_extractor.h"
26 #include "patch_parser.h"
27 #include "scope_guard.h"
28
29 namespace OHOS {
30 namespace AppExecFwk {
QuickFixDeployer(const std::vector<std::string> & bundleFilePaths,bool isDebug)31 QuickFixDeployer::QuickFixDeployer(const std::vector<std::string> &bundleFilePaths,
32 bool isDebug) : patchPaths_(bundleFilePaths), isDebug_(isDebug)
33 {}
34
Execute()35 ErrCode QuickFixDeployer::Execute()
36 {
37 ErrCode ret = DeployQuickFix();
38 if (ret != ERR_OK) {
39 APP_LOGE("QuickFixDeployer errcode %{public}d", ret);
40 }
41 return ret;
42 }
43
DeployQuickFix()44 ErrCode QuickFixDeployer::DeployQuickFix()
45 {
46 if (patchPaths_.empty() || (GetQuickFixDataMgr() != ERR_OK)) {
47 APP_LOGE("DeployQuickFix wrong parms");
48 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
49 }
50
51 std::vector<std::string> realFilePaths;
52 ErrCode ret = ProcessBundleFilePaths(patchPaths_, realFilePaths);
53 if (ret != ERR_OK) {
54 return ret;
55 }
56 ScopeGuard guardRemovePath([realFilePaths] {
57 for (const auto &path: realFilePaths) {
58 std::string tempPath = path.substr(0, path.rfind(Constants::PATH_SEPARATOR));
59 if (InstalldClient::GetInstance()->RemoveDir(tempPath) != ERR_OK) {
60 APP_LOGE("RemovePatchFile failed path: %{private}s", tempPath.c_str());
61 }
62 }
63 });
64 // parse check multi hqf files, update status DEPLOY_START
65 InnerAppQuickFix newInnerAppQuickFix;
66 InnerAppQuickFix oldInnerAppQuickFix;
67 ret = ToDeployStartStatus(realFilePaths, newInnerAppQuickFix, oldInnerAppQuickFix);
68 if (ret != ERR_OK) {
69 return ret;
70 }
71 // extract diff files, apply diff patch and copy hqf, update status DEPLOY_END
72 ret = ToDeployEndStatus(newInnerAppQuickFix, oldInnerAppQuickFix);
73 if (ret != ERR_OK) {
74 bool isExist = !oldInnerAppQuickFix.GetAppQuickFix().bundleName.empty();
75 if (isExist) {
76 quickFixDataMgr_->SaveInnerAppQuickFix(oldInnerAppQuickFix);
77 } else {
78 quickFixDataMgr_->DeleteInnerAppQuickFix(newInnerAppQuickFix.GetAppQuickFix().bundleName);
79 }
80 return ret;
81 }
82 // remove old deploying patch_versionCode
83 const AppQuickFix &appQuick = oldInnerAppQuickFix.GetAppQuickFix();
84 if (!appQuick.bundleName.empty()) {
85 std::string oldPath = Constants::BUNDLE_CODE_DIR + Constants::PATH_SEPARATOR +
86 appQuick.bundleName + Constants::PATH_SEPARATOR;
87 if (appQuick.deployingAppqfInfo.type == QuickFixType::HOT_RELOAD) {
88 oldPath += Constants::HOT_RELOAD_PATH + std::to_string(appQuick.deployingAppqfInfo.versionCode);
89 } else {
90 oldPath += Constants::PATCH_PATH + std::to_string(appQuick.deployingAppqfInfo.versionCode);
91 }
92 if (InstalldClient::GetInstance()->RemoveDir(oldPath)) {
93 APP_LOGE("delete %{private}s failed", oldPath.c_str());
94 }
95 }
96 return ERR_OK;
97 }
98
ToDeployStartStatus(const std::vector<std::string> & bundleFilePaths,InnerAppQuickFix & newInnerAppQuickFix,InnerAppQuickFix & oldInnerAppQuickFix)99 ErrCode QuickFixDeployer::ToDeployStartStatus(const std::vector<std::string> &bundleFilePaths,
100 InnerAppQuickFix &newInnerAppQuickFix, InnerAppQuickFix &oldInnerAppQuickFix)
101 {
102 APP_LOGI("ToDeployStartStatus start.");
103 if (GetQuickFixDataMgr() != ERR_OK) {
104 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
105 }
106 std::unordered_map<std::string, AppQuickFix> infos;
107 // parse and check multi app quick fix info
108 ErrCode ret = ParseAndCheckAppQuickFixInfos(bundleFilePaths, infos);
109 if (ret != ERR_OK) {
110 return ret;
111 }
112 const AppQuickFix &appQuickFix = infos.begin()->second;
113 bool isExist = quickFixDataMgr_->QueryInnerAppQuickFix(appQuickFix.bundleName, oldInnerAppQuickFix);
114 const QuickFixMark &mark = oldInnerAppQuickFix.GetQuickFixMark();
115 if (isExist && (mark.status != QuickFixStatus::DEPLOY_START) && (mark.status != QuickFixStatus::DEPLOY_END)) {
116 APP_LOGE("error: wrong quick fix status, now status : %{public}d", mark.status);
117 return ERR_BUNDLEMANAGER_QUICK_FIX_INVALID_PATCH_STATUS;
118 }
119 const AppQuickFix &oldAppQuickFix = oldInnerAppQuickFix.GetAppQuickFix();
120 // exist and type same need to check version code
121 if (isExist && (appQuickFix.deployingAppqfInfo.type == oldAppQuickFix.deployingAppqfInfo.type)) {
122 // check current app quick fix version code
123 ret = CheckPatchVersionCode(appQuickFix, oldAppQuickFix);
124 if (ret != ERR_OK) {
125 return ret;
126 }
127 }
128 // check bundleName exist
129 BundleInfo bundleInfo;
130 ret = GetBundleInfo(appQuickFix.bundleName, bundleInfo);
131 if (ret != ERR_OK) {
132 APP_LOGE("GetBundleInfo failed, bundleName: %{public}s", appQuickFix.bundleName.c_str());
133 return ret;
134 }
135 // check with installed bundle
136 if (appQuickFix.deployingAppqfInfo.type == QuickFixType::PATCH) {
137 ret = ProcessPatchDeployStart(bundleFilePaths, bundleInfo, infos);
138 } else if (appQuickFix.deployingAppqfInfo.type == QuickFixType::HOT_RELOAD) {
139 ret = ProcessHotReloadDeployStart(bundleInfo, appQuickFix);
140 } else {
141 ret = ERR_BUNDLEMANAGER_QUICK_FIX_UNKNOWN_QUICK_FIX_TYPE;
142 }
143 if (ret != ERR_OK) {
144 return ret;
145 }
146 // convert to InnerAppQuickFix
147 ret = ToInnerAppQuickFix(infos, oldInnerAppQuickFix, newInnerAppQuickFix);
148 if (ret != ERR_OK) {
149 return ret;
150 }
151 // save infos and update status DEPLOY_START
152 ret = SaveAppQuickFix(newInnerAppQuickFix);
153 if (ret != ERR_OK) {
154 APP_LOGE("SaveAppQuickFix failed, errcode: %{public}d", ret);
155 return ret;
156 }
157 APP_LOGI("ToDeployStartStatus end.");
158 return ERR_OK;
159 }
160
ToDeployQuickFixResult(const AppQuickFix & appQuickFix)161 void QuickFixDeployer::ToDeployQuickFixResult(const AppQuickFix &appQuickFix)
162 {
163 APP_LOGD("ToDeployQuickFixResult start.");
164 deployQuickFixResult_.bundleName = appQuickFix.bundleName;
165 deployQuickFixResult_.bundleVersionCode = appQuickFix.versionCode;
166 deployQuickFixResult_.patchVersionCode = appQuickFix.deployingAppqfInfo.versionCode;
167 deployQuickFixResult_.type = appQuickFix.deployingAppqfInfo.type;
168 deployQuickFixResult_.isSoContained = HasNativeSoInBundle(appQuickFix);
169 deployQuickFixResult_.moduleNames.clear();
170 for (const auto &hqf : appQuickFix.deployingAppqfInfo.hqfInfos) {
171 deployQuickFixResult_.moduleNames.emplace_back(hqf.moduleName);
172 }
173 APP_LOGD("ToDeployQuickFixResult end.");
174 }
175
ProcessPatchDeployStart(const std::vector<std::string> bundleFilePaths,const BundleInfo & bundleInfo,std::unordered_map<std::string,AppQuickFix> & infos)176 ErrCode QuickFixDeployer::ProcessPatchDeployStart(
177 const std::vector<std::string> bundleFilePaths,
178 const BundleInfo &bundleInfo,
179 std::unordered_map<std::string, AppQuickFix> &infos)
180 {
181 APP_LOGI("ProcessPatchDeployStart start.");
182 if (infos.empty()) {
183 APP_LOGE("error: appQuickFix infos is empty");
184 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
185 }
186 QuickFixChecker checker;
187 // check multiple cpuAbi and native library path
188 ErrCode ret = checker.CheckMultiNativeSo(infos);
189 if (ret != ERR_OK) {
190 APP_LOGE("ProcessPatchDeployStart check native so failed");
191 return ret;
192 }
193 // parse signature info
194 std::vector<Security::Verify::HapVerifyResult> hapVerifyRes;
195 ret = checker.CheckMultipleHqfsSignInfo(bundleFilePaths, hapVerifyRes);
196 if (ret != ERR_OK) {
197 APP_LOGE("ProcessPatchDeployStart check check multiple hqfs signInfo failed");
198 return ret;
199 }
200 if (hapVerifyRes.empty()) {
201 APP_LOGE("error: appQuickFix hapVerifyRes is empty");
202 return ERR_APPEXECFWK_INSTALL_FAILED_INCOMPATIBLE_SIGNATURE;
203 }
204 const auto &provisionInfo = hapVerifyRes[0].GetProvisionInfo();
205 const AppQuickFix &appQuickFix = infos.begin()->second;
206 // check with installed bundle, signature info, bundleName, versionCode
207 ret = checker.CheckPatchWithInstalledBundle(appQuickFix, bundleInfo, provisionInfo);
208 if (ret != ERR_OK) {
209 APP_LOGE("check AppQuickFixInfos with installed bundle failed, errcode : %{public}d", ret);
210 return ret;
211 }
212 appDistributionType_ = checker.GetAppDistributionType(provisionInfo.distributionType);
213 APP_LOGI("ProcessPatchDeployStart end.");
214 return ERR_OK;
215 }
216
ProcessHotReloadDeployStart(const BundleInfo & bundleInfo,const AppQuickFix & appQuickFix)217 ErrCode QuickFixDeployer::ProcessHotReloadDeployStart(
218 const BundleInfo &bundleInfo,
219 const AppQuickFix &appQuickFix)
220 {
221 APP_LOGI("ProcessHotReloadDeployStart start.");
222 QuickFixChecker checker;
223 ErrCode ret = checker.CheckHotReloadWithInstalledBundle(appQuickFix, bundleInfo);
224 if (ret != ERR_OK) {
225 APP_LOGE("check AppQuickFixInfos with installed bundle failed");
226 return ret;
227 }
228 APP_LOGI("ProcessHotReloadDeployStart end.");
229 return ERR_OK;
230 }
231
ToDeployEndStatus(InnerAppQuickFix & newInnerAppQuickFix,const InnerAppQuickFix & oldInnerAppQuickFix)232 ErrCode QuickFixDeployer::ToDeployEndStatus(InnerAppQuickFix &newInnerAppQuickFix,
233 const InnerAppQuickFix &oldInnerAppQuickFix)
234 {
235 APP_LOGI("ToDeployEndStatus start.");
236 if ((GetQuickFixDataMgr() != ERR_OK)) {
237 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
238 }
239 // create patch path
240 AppQuickFix newQuickFix = newInnerAppQuickFix.GetAppQuickFix();
241 std::string newPatchPath;
242 ScopeGuard guardRemovePatchPath([&newPatchPath] {
243 InstalldClient::GetInstance()->RemoveDir(newPatchPath);
244 });
245 ErrCode ret = ERR_OK;
246 if (newQuickFix.deployingAppqfInfo.type == QuickFixType::PATCH) {
247 // extract diff files and apply diff patch
248 ret = ProcessPatchDeployEnd(newQuickFix, newPatchPath);
249 } else if (newQuickFix.deployingAppqfInfo.type == QuickFixType::HOT_RELOAD) {
250 ret = ProcessHotReloadDeployEnd(newQuickFix, newPatchPath);
251 } else {
252 APP_LOGE("error: unknown QuickFixType");
253 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
254 }
255 if (ret != ERR_OK) {
256 APP_LOGE("Process Patch or HotReload DeployEnd failed, bundleName:%{public}s",
257 newQuickFix.bundleName.c_str());
258 return ret;
259 }
260
261 // if so files exist, library path add patch_versionCode;
262 // if so files not exist, modify library path to empty.
263 ProcessNativeLibraryPath(newPatchPath, newInnerAppQuickFix);
264
265 // move hqf files to new patch path
266 ret = MoveHqfFiles(newInnerAppQuickFix, newPatchPath);
267 if (ret != ERR_OK) {
268 APP_LOGE("error MoveHqfFiles failed, bundleName: %{public}s", newQuickFix.bundleName.c_str());
269 return ret;
270 }
271 // save and update status DEPLOY_END
272 ret = SaveAppQuickFix(newInnerAppQuickFix);
273 if (ret != ERR_OK) {
274 return ret;
275 }
276 ToDeployQuickFixResult(newQuickFix);
277 ret = SaveToInnerBundleInfo(newInnerAppQuickFix);
278 if (ret != ERR_OK) {
279 APP_LOGE("error: bundleName %{public}s update deploying quick fix info to innerBundleInfo failed",
280 newQuickFix.bundleName.c_str());
281 return ret;
282 }
283 guardRemovePatchPath.Dismiss();
284 APP_LOGI("ToDeployEndStatus end.");
285 return ERR_OK;
286 }
287
ProcessNativeLibraryPath(const std::string & patchPath,InnerAppQuickFix & innerAppQuickFix)288 void QuickFixDeployer::ProcessNativeLibraryPath(const std::string &patchPath, InnerAppQuickFix &innerAppQuickFix)
289 {
290 AppQuickFix appQuickFix = innerAppQuickFix.GetAppQuickFix();
291 if (!appQuickFix.deployingAppqfInfo.nativeLibraryPath.empty()) {
292 std::string nativeLibraryPath = appQuickFix.deployingAppqfInfo.nativeLibraryPath;
293 ProcessNativeLibraryPath(patchPath, innerAppQuickFix, nativeLibraryPath);
294 appQuickFix.deployingAppqfInfo.nativeLibraryPath = nativeLibraryPath;
295 }
296
297 for (auto &hqfInfo : appQuickFix.deployingAppqfInfo.hqfInfos) {
298 if (!hqfInfo.nativeLibraryPath.empty()) {
299 std::string nativeLibraryPath = hqfInfo.nativeLibraryPath;
300 ProcessNativeLibraryPath(patchPath, innerAppQuickFix, nativeLibraryPath);
301 hqfInfo.nativeLibraryPath = nativeLibraryPath;
302 }
303 }
304
305 innerAppQuickFix.SetAppQuickFix(appQuickFix);
306 }
307
ProcessNativeLibraryPath(const std::string & patchPath,const InnerAppQuickFix & innerAppQuickFix,std::string & nativeLibraryPath)308 void QuickFixDeployer::ProcessNativeLibraryPath(
309 const std::string &patchPath, const InnerAppQuickFix &innerAppQuickFix, std::string &nativeLibraryPath)
310 {
311 bool isSoExist = false;
312 auto libraryPath = nativeLibraryPath;
313 std::string soPath = patchPath + Constants::PATH_SEPARATOR + libraryPath;
314 if (InstalldClient::GetInstance()->IsExistDir(soPath, isSoExist) != ERR_OK) {
315 APP_LOGE("ProcessNativeLibraryPath InstalldClient IsExistDir(%{public}s) failed", soPath.c_str());
316 return;
317 }
318
319 AppQuickFix appQuickFix = innerAppQuickFix.GetAppQuickFix();
320 if (isSoExist) {
321 nativeLibraryPath = Constants::PATCH_PATH +
322 std::to_string(appQuickFix.deployingAppqfInfo.versionCode) + Constants::PATH_SEPARATOR + libraryPath;
323 } else {
324 APP_LOGI("So(%{public}s) is not exist and set nativeLibraryPath(%{public}s) empty",
325 soPath.c_str(), nativeLibraryPath.c_str());
326 nativeLibraryPath.clear();
327 }
328 }
329
ProcessPatchDeployEnd(const AppQuickFix & appQuickFix,std::string & patchPath)330 ErrCode QuickFixDeployer::ProcessPatchDeployEnd(const AppQuickFix &appQuickFix, std::string &patchPath)
331 {
332 patchPath = Constants::BUNDLE_CODE_DIR + Constants::PATH_SEPARATOR + appQuickFix.bundleName +
333 Constants::PATH_SEPARATOR + Constants::PATCH_PATH + std::to_string(appQuickFix.deployingAppqfInfo.versionCode);
334 if (InstalldClient::GetInstance()->CreateBundleDir(patchPath) != ERR_OK) {
335 APP_LOGE("error: creat patch path failed");
336 return ERR_BUNDLEMANAGER_QUICK_FIX_CREATE_PATCH_PATH_FAILED;
337 }
338 BundleInfo bundleInfo;
339 ErrCode ret = GetBundleInfo(appQuickFix.bundleName, bundleInfo);
340 if (ret != ERR_OK) {
341 return ret;
342 }
343 if (isDebug_ && (bundleInfo.applicationInfo.appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG)) {
344 return ExtractQuickFixSoFile(appQuickFix, patchPath, bundleInfo);
345 }
346 std::string oldSoPath = Constants::HAP_COPY_PATH + Constants::PATH_SEPARATOR +
347 appQuickFix.bundleName + Constants::TMP_SUFFIX + Constants::LIBS;
348 ScopeGuard guardRemoveOldSoPath([oldSoPath] {InstalldClient::GetInstance()->RemoveDir(oldSoPath);});
349
350 auto &appQfInfo = appQuickFix.deployingAppqfInfo;
351 for (const auto &hqf : appQfInfo.hqfInfos) {
352 // if hap has no so file then continue
353 std::string tmpSoPath = oldSoPath;
354
355 InnerBundleInfo innerBundleInfo;
356 if (!FetchInnerBundleInfo(appQuickFix.bundleName, innerBundleInfo)) {
357 APP_LOGE("Fetch bundleInfo(%{public}s) failed.", appQuickFix.bundleName.c_str());
358 return false;
359 }
360 int32_t bundleUid = Constants::INVALID_UID;
361 if (innerBundleInfo.IsEncryptedMoudle(hqf.moduleName)) {
362 InnerBundleUserInfo innerBundleUserInfo;
363 if (!innerBundleInfo.GetInnerBundleUserInfo(Constants::ALL_USERID, innerBundleUserInfo)) {
364 APP_LOGE("no user info of bundle %{public}s", appQuickFix.bundleName.c_str());
365 return ERR_BUNDLEMANAGER_QUICK_FIX_BUNDLE_NAME_NOT_EXIST;
366 }
367 bundleUid = innerBundleUserInfo.uid;
368 if (!ExtractEncryptedSoFiles(bundleInfo, hqf.moduleName, bundleUid, tmpSoPath)) {
369 APP_LOGW("module:%{public}s has no so file", hqf.moduleName.c_str());
370 continue;
371 }
372 } else {
373 if (!ExtractSoFiles(bundleInfo, hqf.moduleName, tmpSoPath)) {
374 APP_LOGW("module:%{public}s has no so file", hqf.moduleName.c_str());
375 continue;
376 }
377 }
378
379 auto result = ProcessApplyDiffPatch(appQuickFix, hqf, tmpSoPath, patchPath, bundleUid);
380 if (result != ERR_OK) {
381 APP_LOGE("bundleName: %{public}s ProcessApplyDiffPatch failed.", appQuickFix.bundleName.c_str());
382 return result;
383 }
384 }
385 return ERR_OK;
386 }
387
ProcessHotReloadDeployEnd(const AppQuickFix & appQuickFix,std::string & patchPath)388 ErrCode QuickFixDeployer::ProcessHotReloadDeployEnd(const AppQuickFix &appQuickFix, std::string &patchPath)
389 {
390 patchPath = Constants::BUNDLE_CODE_DIR + Constants::PATH_SEPARATOR + appQuickFix.bundleName +
391 Constants::PATH_SEPARATOR + Constants::HOT_RELOAD_PATH +
392 std::to_string(appQuickFix.deployingAppqfInfo.versionCode);
393 ErrCode ret = InstalldClient::GetInstance()->CreateBundleDir(patchPath);
394 if (ret != ERR_OK) {
395 APP_LOGE("error: creat hotreload path failed, errcode %{public}d", ret);
396 return ERR_BUNDLEMANAGER_QUICK_FIX_CREATE_PATCH_PATH_FAILED;
397 }
398 return ERR_OK;
399 }
400
ParseAndCheckAppQuickFixInfos(const std::vector<std::string> & bundleFilePaths,std::unordered_map<std::string,AppQuickFix> & infos)401 ErrCode QuickFixDeployer::ParseAndCheckAppQuickFixInfos(
402 const std::vector<std::string> &bundleFilePaths,
403 std::unordered_map<std::string, AppQuickFix> &infos)
404 {
405 // parse hqf file to AppQuickFix
406 PatchParser patchParser;
407 ErrCode ret = patchParser.ParsePatchInfo(bundleFilePaths, infos);
408 if ((ret != ERR_OK) || infos.empty()) {
409 APP_LOGE("parse AppQuickFixFiles failed, errcode %{public}d", ret);
410 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
411 }
412
413 ResetNativeSoAttrs(infos);
414 QuickFixChecker checker;
415 // check multiple AppQuickFix
416 ret = checker.CheckAppQuickFixInfos(infos);
417 if (ret != ERR_OK) {
418 APP_LOGE("check AppQuickFixInfos failed");
419 return ret;
420 }
421 const QuickFixType &quickFixType = infos.begin()->second.deployingAppqfInfo.type;
422 if (quickFixType == QuickFixType::UNKNOWN) {
423 APP_LOGE("error unknown quick fix type");
424 return ERR_BUNDLEMANAGER_QUICK_FIX_UNKNOWN_QUICK_FIX_TYPE;
425 }
426 // hqf file path
427 for (auto iter = infos.begin(); iter != infos.end(); ++iter) {
428 if (!iter->second.deployingAppqfInfo.hqfInfos.empty()) {
429 iter->second.deployingAppqfInfo.hqfInfos[0].hqfFilePath = iter->first;
430 } else {
431 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
432 }
433 }
434 return ERR_OK;
435 }
436
ResetNativeSoAttrs(std::unordered_map<std::string,AppQuickFix> & infos)437 void QuickFixDeployer::ResetNativeSoAttrs(std::unordered_map<std::string, AppQuickFix> &infos)
438 {
439 for (auto &info : infos) {
440 ResetNativeSoAttrs(info.second);
441 }
442 }
443
ResetNativeSoAttrs(AppQuickFix & appQuickFix)444 void QuickFixDeployer::ResetNativeSoAttrs(AppQuickFix &appQuickFix)
445 {
446 auto &appqfInfo = appQuickFix.deployingAppqfInfo;
447 if (appqfInfo.hqfInfos.size() != 1) {
448 APP_LOGW("The number of hqfInfos is not one.");
449 return;
450 }
451
452 bool isLibIsolated = IsLibIsolated(appQuickFix.bundleName, appqfInfo.hqfInfos[0].moduleName);
453 if (!isLibIsolated) {
454 APP_LOGW("Lib is not isolated.");
455 return;
456 }
457
458 appqfInfo.hqfInfos[0].cpuAbi = appqfInfo.cpuAbi;
459 appqfInfo.hqfInfos[0].nativeLibraryPath =
460 appqfInfo.hqfInfos[0].moduleName + Constants::PATH_SEPARATOR + appqfInfo.nativeLibraryPath;
461 appqfInfo.nativeLibraryPath.clear();
462 }
463
IsLibIsolated(const std::string & bundleName,const std::string & moduleName)464 bool QuickFixDeployer::IsLibIsolated(
465 const std::string &bundleName, const std::string &moduleName)
466 {
467 InnerBundleInfo innerBundleInfo;
468 if (!FetchInnerBundleInfo(bundleName, innerBundleInfo)) {
469 APP_LOGE("Fetch bundleInfo(%{public}s) failed.", bundleName.c_str());
470 return false;
471 }
472
473 return innerBundleInfo.IsLibIsolated(moduleName);
474 }
475
FetchInnerBundleInfo(const std::string & bundleName,InnerBundleInfo & innerBundleInfo)476 bool QuickFixDeployer::FetchInnerBundleInfo(
477 const std::string &bundleName, InnerBundleInfo &innerBundleInfo)
478 {
479 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
480 if (dataMgr == nullptr) {
481 APP_LOGE("error dataMgr is nullptr");
482 return false;
483 }
484
485 if (!dataMgr->FetchInnerBundleInfo(bundleName, innerBundleInfo)) {
486 APP_LOGE("Fetch bundleInfo(%{public}s) failed.", bundleName.c_str());
487 return false;
488 }
489
490 return true;
491 }
492
FetchPatchNativeSoAttrs(const AppqfInfo & appqfInfo,const HqfInfo hqfInfo,bool isLibIsolated,std::string & nativeLibraryPath,std::string & cpuAbi)493 bool QuickFixDeployer::FetchPatchNativeSoAttrs(const AppqfInfo &appqfInfo,
494 const HqfInfo hqfInfo, bool isLibIsolated, std::string &nativeLibraryPath, std::string &cpuAbi)
495 {
496 if (isLibIsolated) {
497 nativeLibraryPath = hqfInfo.nativeLibraryPath;
498 cpuAbi = hqfInfo.cpuAbi;
499 } else {
500 nativeLibraryPath = appqfInfo.nativeLibraryPath;
501 cpuAbi = appqfInfo.cpuAbi;
502 }
503
504 return !nativeLibraryPath.empty();
505 }
506
HasNativeSoInBundle(const AppQuickFix & appQuickFix)507 bool QuickFixDeployer::HasNativeSoInBundle(const AppQuickFix &appQuickFix)
508 {
509 if (!appQuickFix.deployingAppqfInfo.nativeLibraryPath.empty()) {
510 return true;
511 }
512
513 for (const auto &hqfInfo : appQuickFix.deployingAppqfInfo.hqfInfos) {
514 if (!hqfInfo.nativeLibraryPath.empty()) {
515 return true;
516 }
517 }
518
519 return false;
520 }
521
GetBundleInfo(const std::string & bundleName,BundleInfo & bundleInfo)522 ErrCode QuickFixDeployer::GetBundleInfo(const std::string &bundleName, BundleInfo &bundleInfo)
523 {
524 std::shared_ptr<BundleMgrService> bms = DelayedSingleton<BundleMgrService>::GetInstance();
525 if (bms == nullptr) {
526 APP_LOGE("error: bms is nullptr");
527 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
528 }
529 std::shared_ptr<BundleDataMgr> dataMgr = bms->GetDataMgr();
530 if (dataMgr == nullptr) {
531 APP_LOGE("error: dataMgr is nullptr");
532 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
533 }
534 // check bundleName is exists
535 if (!dataMgr->GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_DEFAULT,
536 bundleInfo, Constants::ANY_USERID)) {
537 APP_LOGE("error: GetBundleInfo failed, bundleName: %{public}s not exist", bundleName.c_str());
538 return ERR_BUNDLEMANAGER_QUICK_FIX_BUNDLE_NAME_NOT_EXIST;
539 }
540 return ERR_OK;
541 }
542
ToInnerAppQuickFix(const std::unordered_map<std::string,AppQuickFix> infos,const InnerAppQuickFix & oldInnerAppQuickFix,InnerAppQuickFix & newInnerAppQuickFix)543 ErrCode QuickFixDeployer::ToInnerAppQuickFix(const std::unordered_map<std::string, AppQuickFix> infos,
544 const InnerAppQuickFix &oldInnerAppQuickFix, InnerAppQuickFix &newInnerAppQuickFix)
545 {
546 APP_LOGD("ToInnerAppQuickFix start");
547 if (infos.empty()) {
548 APP_LOGE("error: appQuickFix is empty");
549 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
550 }
551 AppQuickFix oldAppQuickFix = oldInnerAppQuickFix.GetAppQuickFix();
552 AppQuickFix appQuickFix = infos.begin()->second;
553 // copy deployed app qf info
554 appQuickFix.deployedAppqfInfo = oldAppQuickFix.deployedAppqfInfo;
555 newInnerAppQuickFix.SetAppQuickFix(appQuickFix);
556 QuickFixMark mark;
557 mark.bundleName = appQuickFix.bundleName;
558 mark.status = QuickFixStatus::DEPLOY_START;
559 for (auto iter = infos.begin(); iter != infos.end(); ++iter) {
560 const auto &quickFix = iter->second;
561 // hqfInfos will not be empty, it has been judged before.
562 const std::string &moduleName = quickFix.deployingAppqfInfo.hqfInfos[0].moduleName;
563 if (!newInnerAppQuickFix.AddHqfInfo(quickFix)) {
564 APP_LOGE("error: appQuickFix add hqf moduleName: %{public}s failed", moduleName.c_str());
565 return ERR_BUNDLEMANAGER_QUICK_FIX_ADD_HQF_FAILED;
566 }
567 }
568 newInnerAppQuickFix.SetQuickFixMark(mark);
569 APP_LOGD("ToInnerAppQuickFix end");
570 return ERR_OK;
571 }
572
CheckPatchVersionCode(const AppQuickFix & newAppQuickFix,const AppQuickFix & oldAppQuickFix)573 ErrCode QuickFixDeployer::CheckPatchVersionCode(
574 const AppQuickFix &newAppQuickFix,
575 const AppQuickFix &oldAppQuickFix)
576 {
577 const AppqfInfo &newInfo = newAppQuickFix.deployingAppqfInfo;
578 const AppqfInfo &oldInfoDeployed = oldAppQuickFix.deployedAppqfInfo;
579 const AppqfInfo &oldInfoDeploying = oldAppQuickFix.deployingAppqfInfo;
580 if ((newInfo.versionCode > oldInfoDeployed.versionCode) &&
581 (newInfo.versionCode > oldInfoDeploying.versionCode)) {
582 return ERR_OK;
583 }
584 APP_LOGE("CheckPatchVersionCode failed, version code should be greater than the original");
585 return ERR_BUNDLEMANAGER_QUICK_FIX_VERSION_CODE_ERROR;
586 }
587
SaveAppQuickFix(const InnerAppQuickFix & innerAppQuickFix)588 ErrCode QuickFixDeployer::SaveAppQuickFix(const InnerAppQuickFix &innerAppQuickFix)
589 {
590 if ((GetQuickFixDataMgr() != ERR_OK)) {
591 APP_LOGE("error: quickFixDataMgr_ is nullptr");
592 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
593 }
594 if (!quickFixDataMgr_->SaveInnerAppQuickFix(innerAppQuickFix)) {
595 APP_LOGE("bundleName: %{public}s, inner app quick fix save failed",
596 innerAppQuickFix.GetAppQuickFix().bundleName.c_str());
597 return ERR_BUNDLEMANAGER_QUICK_FIX_SAVE_APP_QUICK_FIX_FAILED;
598 }
599 return ERR_OK;
600 }
601
MoveHqfFiles(InnerAppQuickFix & innerAppQuickFix,const std::string & targetPath)602 ErrCode QuickFixDeployer::MoveHqfFiles(InnerAppQuickFix &innerAppQuickFix, const std::string &targetPath)
603 {
604 APP_LOGD("MoveHqfFiles start.");
605 if (targetPath.empty() || (GetQuickFixDataMgr() != ERR_OK)) {
606 APP_LOGE("MoveHqfFiles params error");
607 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
608 }
609 QuickFixMark mark = innerAppQuickFix.GetQuickFixMark();
610 AppQuickFix appQuickFix = innerAppQuickFix.GetAppQuickFix();
611 std::string path = targetPath;
612 if (path.back() != Constants::FILE_SEPARATOR_CHAR) {
613 path.push_back(Constants::FILE_SEPARATOR_CHAR);
614 }
615 for (HqfInfo &info : appQuickFix.deployingAppqfInfo.hqfInfos) {
616 if (info.hqfFilePath.empty()) {
617 APP_LOGE("error hapFilePath is empty");
618 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
619 }
620 std::string realPath = path + info.moduleName + Constants::QUICK_FIX_FILE_SUFFIX;
621 ErrCode ret = InstalldClient::GetInstance()->CopyFile(info.hqfFilePath, realPath);
622 if (ret != ERR_OK) {
623 APP_LOGE("error CopyFile failed, errcode: %{public}d", ret);
624 return ERR_BUNDLEMANAGER_QUICK_FIX_MOVE_PATCH_FILE_FAILED;
625 }
626 info.hqfFilePath = realPath;
627 }
628 mark.status = QuickFixStatus::DEPLOY_END;
629 innerAppQuickFix.SetQuickFixMark(mark);
630 innerAppQuickFix.SetAppQuickFix(appQuickFix);
631 APP_LOGD("MoveHqfFiles end.");
632 return ERR_OK;
633 }
634
GetDeployQuickFixResult() const635 DeployQuickFixResult QuickFixDeployer::GetDeployQuickFixResult() const
636 {
637 return deployQuickFixResult_;
638 }
639
GetQuickFixDataMgr()640 ErrCode QuickFixDeployer::GetQuickFixDataMgr()
641 {
642 if (quickFixDataMgr_ == nullptr) {
643 quickFixDataMgr_ = DelayedSingleton<QuickFixDataMgr>::GetInstance();
644 if (quickFixDataMgr_ == nullptr) {
645 APP_LOGE("error: quickFixDataMgr_ is nullptr");
646 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
647 }
648 }
649 return ERR_OK;
650 }
651
SaveToInnerBundleInfo(const InnerAppQuickFix & newInnerAppQuickFix)652 ErrCode QuickFixDeployer::SaveToInnerBundleInfo(const InnerAppQuickFix &newInnerAppQuickFix)
653 {
654 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
655 if (dataMgr == nullptr) {
656 APP_LOGE("error dataMgr is nullptr");
657 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
658 }
659 const std::string &bundleName = newInnerAppQuickFix.GetAppQuickFix().bundleName;
660 InnerBundleInfo innerBundleInfo;
661 // obtain innerBundleInfo and enableGuard used to enable bundle which is under disable status
662 if (!dataMgr->GetInnerBundleInfo(bundleName, innerBundleInfo)) {
663 APP_LOGE("cannot obtain the innerbundleInfo from data mgr");
664 return ERR_BUNDLEMANAGER_QUICK_FIX_NOT_EXISTED_BUNDLE_INFO;
665 }
666 ScopeGuard enableGuard([&bundleName, &dataMgr] { dataMgr->EnableBundle(bundleName); });
667 AppQuickFix appQuickFix = newInnerAppQuickFix.GetAppQuickFix();
668 appQuickFix.deployedAppqfInfo = innerBundleInfo.GetAppQuickFix().deployedAppqfInfo;
669 // add apply quick fix frequency
670 innerBundleInfo.AddApplyQuickFixFrequency();
671 innerBundleInfo.SetAppQuickFix(appQuickFix);
672 innerBundleInfo.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
673 if (!dataMgr->UpdateQuickFixInnerBundleInfo(bundleName, innerBundleInfo)) {
674 APP_LOGE("update quickfix innerbundleInfo failed");
675 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
676 }
677 // send quick fix data
678 SendQuickFixSystemEvent(innerBundleInfo);
679 return ERR_OK;
680 }
681
ProcessBundleFilePaths(const std::vector<std::string> & bundleFilePaths,std::vector<std::string> & realFilePaths)682 ErrCode QuickFixDeployer::ProcessBundleFilePaths(const std::vector<std::string> &bundleFilePaths,
683 std::vector<std::string> &realFilePaths)
684 {
685 for (const auto &path : bundleFilePaths) {
686 if (path.find(Constants::RELATIVE_PATH) != std::string::npos) {
687 APP_LOGE("ProcessBundleFilePaths path is illegal.");
688 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
689 }
690 if (path.find(Constants::HAP_COPY_PATH + Constants::PATH_SEPARATOR +
691 Constants::SECURITY_QUICK_FIX_PATH + Constants::PATH_SEPARATOR) != 0) {
692 APP_LOGE("ProcessBundleFilePaths path is illegal.");
693 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
694 }
695 }
696 ErrCode ret = BundleUtil::CheckFilePath(bundleFilePaths, realFilePaths);
697 if (ret != ERR_OK) {
698 APP_LOGE("ProcessBundleFilePaths CheckFilePath failed.");
699 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
700 }
701 for (const auto &path : realFilePaths) {
702 if (!BundleUtil::CheckFileType(path, Constants::QUICK_FIX_FILE_SUFFIX)) {
703 APP_LOGE("ProcessBundleFilePaths CheckFileType failed.");
704 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
705 }
706 }
707 return ERR_OK;
708 }
709
SendQuickFixSystemEvent(const InnerBundleInfo & innerBundleInfo)710 void QuickFixDeployer::SendQuickFixSystemEvent(const InnerBundleInfo &innerBundleInfo)
711 {
712 EventInfo sysEventInfo;
713 sysEventInfo.errCode = ERR_OK;
714 sysEventInfo.bundleName = innerBundleInfo.GetBundleName();
715 sysEventInfo.appDistributionType = appDistributionType_;
716 for (const auto &hqfInfo : innerBundleInfo.GetAppQuickFix().deployingAppqfInfo.hqfInfos) {
717 sysEventInfo.filePath.push_back(hqfInfo.hqfFilePath);
718 sysEventInfo.hashValue.push_back(hqfInfo.hapSha256);
719 }
720 sysEventInfo.applyQuickFixFrequency = innerBundleInfo.GetApplyQuickFixFrequency();
721 EventReport::SendBundleSystemEvent(BundleEventType::QUICK_FIX, sysEventInfo);
722 }
723
ExtractQuickFixSoFile(const AppQuickFix & appQuickFix,const std::string & hqfSoPath,const BundleInfo & bundleInfo)724 ErrCode QuickFixDeployer::ExtractQuickFixSoFile(
725 const AppQuickFix &appQuickFix, const std::string &hqfSoPath, const BundleInfo &bundleInfo)
726 {
727 APP_LOGD("start, bundleName:%{public}s", appQuickFix.bundleName.c_str());
728 auto &appQfInfo = appQuickFix.deployingAppqfInfo;
729 if (appQfInfo.hqfInfos.empty()) {
730 APP_LOGE("hqfInfos is empty");
731 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
732 }
733 for (const auto &hqf : appQfInfo.hqfInfos) {
734 auto iter = std::find_if(std::begin(bundleInfo.hapModuleInfos), std::end(bundleInfo.hapModuleInfos),
735 [hqf](const HapModuleInfo &info) {
736 return info.moduleName == hqf.moduleName;
737 });
738 if (iter == bundleInfo.hapModuleInfos.end()) {
739 APP_LOGW("moduleName:%{public}s not exist", hqf.moduleName.c_str());
740 continue;
741 }
742
743 std::string libraryPath;
744 std::string cpuAbi;
745 bool isLibIsolated = IsLibIsolated(appQuickFix.bundleName, hqf.moduleName);
746 if (!FetchPatchNativeSoAttrs(appQuickFix.deployingAppqfInfo, hqf, isLibIsolated, libraryPath, cpuAbi)) {
747 APP_LOGD("no so file");
748 continue;
749 }
750 std::string soPath = hqfSoPath + Constants::PATH_SEPARATOR + libraryPath;
751 ExtractParam extractParam;
752 extractParam.extractFileType = ExtractFileType::SO;
753 extractParam.srcPath = hqf.hqfFilePath;
754 extractParam.targetPath = soPath;
755 extractParam.cpuAbi = cpuAbi;
756 if (InstalldClient::GetInstance()->ExtractFiles(extractParam) != ERR_OK) {
757 APP_LOGW("moduleName: %{public}s extract so failed", hqf.moduleName.c_str());
758 continue;
759 }
760 }
761 return ERR_OK;
762 APP_LOGD("end");
763 }
764
ExtractSoFiles(const BundleInfo & bundleInfo,const std::string & moduleName,std::string & tmpSoPath)765 bool QuickFixDeployer::ExtractSoFiles(
766 const BundleInfo &bundleInfo,
767 const std::string &moduleName,
768 std::string &tmpSoPath)
769 {
770 auto iter = std::find_if(std::begin(bundleInfo.hapModuleInfos), std::end(bundleInfo.hapModuleInfos),
771 [&moduleName](const HapModuleInfo &info) {
772 return info.moduleName == moduleName;
773 });
774 if (iter == bundleInfo.hapModuleInfos.end()) {
775 return false;
776 }
777 std::string cpuAbi = bundleInfo.applicationInfo.cpuAbi;
778 std::string nativeLibraryPath = bundleInfo.applicationInfo.nativeLibraryPath;
779 if (!iter->nativeLibraryPath.empty()) {
780 cpuAbi = iter->cpuAbi;
781 nativeLibraryPath = iter->nativeLibraryPath;
782 }
783 if (nativeLibraryPath.empty()) {
784 return false;
785 }
786
787 tmpSoPath = (tmpSoPath.back() == Constants::PATH_SEPARATOR[0]) ? (tmpSoPath + moduleName) :
788 (tmpSoPath + Constants::PATH_SEPARATOR + moduleName);
789 ExtractParam extractParam;
790 extractParam.extractFileType = ExtractFileType::SO;
791 extractParam.srcPath = iter->hapPath;
792 extractParam.targetPath = tmpSoPath;
793 extractParam.cpuAbi = cpuAbi;
794 if (InstalldClient::GetInstance()->ExtractFiles(extractParam) != ERR_OK) {
795 APP_LOGW("bundleName: %{public}s moduleName: %{public}s extract so failed, ",
796 bundleInfo.name.c_str(), moduleName.c_str());
797 return false;
798 }
799 return true;
800 }
801
ProcessApplyDiffPatch(const AppQuickFix & appQuickFix,const HqfInfo & hqf,const std::string & oldSoPath,const std::string & patchPath,int32_t uid)802 ErrCode QuickFixDeployer::ProcessApplyDiffPatch(const AppQuickFix &appQuickFix, const HqfInfo &hqf,
803 const std::string &oldSoPath, const std::string &patchPath, int32_t uid)
804 {
805 std::string libraryPath;
806 std::string cpuAbi;
807 bool isLibIsolated = IsLibIsolated(appQuickFix.bundleName, hqf.moduleName);
808 if (!FetchPatchNativeSoAttrs(appQuickFix.deployingAppqfInfo, hqf, isLibIsolated, libraryPath, cpuAbi)) {
809 return ERR_OK;
810 }
811 // extract diff so, diff so path
812 std::string diffFilePath = Constants::HAP_COPY_PATH + Constants::PATH_SEPARATOR +
813 appQuickFix.bundleName + Constants::TMP_SUFFIX;
814 ScopeGuard guardRemoveDiffPath([diffFilePath] { InstalldClient::GetInstance()->RemoveDir(diffFilePath); });
815 // extract diff so to targetPath
816 auto ret = InstalldClient::GetInstance()->ExtractDiffFiles(hqf.hqfFilePath, diffFilePath, cpuAbi);
817 if (ret != ERR_OK) {
818 APP_LOGE("error: ExtractDiffFiles failed errcode :%{public}d", ret);
819 return ERR_BUNDLEMANAGER_QUICK_FIX_EXTRACT_DIFF_FILES_FAILED;
820 }
821 // apply diff patch
822 std::string newSoPath = patchPath + Constants::PATH_SEPARATOR + libraryPath;
823 ret = InstalldClient::GetInstance()->ApplyDiffPatch(oldSoPath, diffFilePath, newSoPath, uid);
824 if (ret != ERR_OK) {
825 APP_LOGE("ApplyDiffPatch failed, bundleName:%{public}s, errcode: %{public}d",
826 appQuickFix.bundleName.c_str(), ret);
827 return ERR_BUNDLEMANAGER_QUICK_FIX_APPLY_DIFF_PATCH_FAILED;
828 }
829 return ERR_OK;
830 }
831
ExtractEncryptedSoFiles(const BundleInfo & bundleInfo,const std::string & moduleName,int32_t uid,std::string & tmpSoPath)832 bool QuickFixDeployer::ExtractEncryptedSoFiles(const BundleInfo &bundleInfo, const std::string &moduleName,
833 int32_t uid, std::string &tmpSoPath)
834 {
835 APP_LOGD("start to extract decoded so files to tmp path");
836 auto iter = std::find_if(std::begin(bundleInfo.hapModuleInfos), std::end(bundleInfo.hapModuleInfos),
837 [&moduleName](const HapModuleInfo &info) {
838 return info.moduleName == moduleName;
839 });
840 if (iter == bundleInfo.hapModuleInfos.end()) {
841 return false;
842 }
843 std::string cpuAbi = bundleInfo.applicationInfo.cpuAbi;
844 std::string nativeLibraryPath = bundleInfo.applicationInfo.nativeLibraryPath;
845 if (!iter->nativeLibraryPath.empty()) {
846 cpuAbi = iter->cpuAbi;
847 nativeLibraryPath = iter->nativeLibraryPath;
848 }
849 if (nativeLibraryPath.empty()) {
850 return false;
851 }
852 std::string hapPath = iter->hapPath;
853 std::string realSoFilesPath;
854 if (iter->compressNativeLibs) {
855 realSoFilesPath.append(Constants::BUNDLE_CODE_DIR).append(Constants::PATH_SEPARATOR)
856 .append(bundleInfo.name).append(Constants::PATH_SEPARATOR).append(nativeLibraryPath)
857 .append(Constants::PATH_SEPARATOR);
858 }
859 tmpSoPath = (tmpSoPath.back() == Constants::PATH_SEPARATOR[0]) ? (tmpSoPath + moduleName) :
860 (tmpSoPath + Constants::PATH_SEPARATOR + moduleName + Constants::PATH_SEPARATOR);
861 APP_LOGD("real so files path is %{public}s, tmpSoPath is %{public}s", realSoFilesPath.c_str(), tmpSoPath.c_str());
862 return InstalldClient::GetInstance()->ExtractEncryptedSoFiles(hapPath, realSoFilesPath, cpuAbi, tmpSoPath, uid) ==
863 ERR_OK;
864 }
865 } // AppExecFwk
866 } // OHOS