1 /*
2 * Copyright (c) 2022-2025 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 "ext_backup_js.h"
17
18 #include <cstdio>
19 #include <memory>
20 #include <sstream>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23
24 #include "bundle_mgr_client.h"
25 #include "ext_backup_context_js.h"
26 #include "js_extension_context.h"
27 #include "js_native_api.h"
28 #include "js_native_api_types.h"
29 #include "js_runtime.h"
30 #include "js_runtime_utils.h"
31 #include "napi/native_api.h"
32 #include "napi/native_node_api.h"
33 #include "napi_common_util.h"
34 #include "napi_common_want.h"
35 #include "napi_remote_object.h"
36 #include "unique_fd.h"
37
38 #include "b_anony/b_anony.h"
39 #include "b_error/b_error.h"
40 #include "b_error/b_excep_utils.h"
41 #include "b_json/b_json_cached_entity.h"
42 #include "b_json/b_json_entity_extension_config.h"
43 #include "b_radar/b_radar.h"
44 #include "b_resources/b_constants.h"
45 #include "directory_ex.h"
46 #include "ext_extension.h"
47 #include "filemgmt_libhilog.h"
48
49 namespace OHOS::FileManagement::Backup {
50 using namespace std;
51 constexpr size_t ARGC_ONE = 1;
52 static std::mutex g_extBackupValidLock;
53 static int32_t g_extBackupCount = 0;
54
GetSrcPath(const AppExecFwk::AbilityInfo & info)55 static string GetSrcPath(const AppExecFwk::AbilityInfo &info)
56 {
57 using AbilityRuntime::Extension;
58 stringstream ss;
59
60 // API9(stage model) 中通过 $(module)$(name)/$(srcEntrance/(.*$)/(.abc)) 获取自定义插件路径
61 if (!info.srcEntrance.empty()) {
62 ss << info.moduleName << '/' << string(info.srcEntrance, 0, info.srcEntrance.rfind(".")) << ".abc";
63 return ss.str();
64 }
65 return "";
66 }
67
DealNapiStrValue(napi_env env,const napi_value napi_StrValue,std::string & result)68 static napi_status DealNapiStrValue(napi_env env, const napi_value napi_StrValue, std::string &result)
69 {
70 HILOGI("Start DealNapiStrValue");
71 std::string buffer = "";
72 size_t bufferSize = 0;
73 napi_status status = napi_ok;
74 status = napi_get_value_string_utf8(env, napi_StrValue, nullptr, -1, &bufferSize);
75 if (status != napi_ok) {
76 HILOGE("Can not get buffer size");
77 return status;
78 }
79 buffer.reserve(bufferSize + 1);
80 buffer.resize(bufferSize);
81 if (bufferSize > 0) {
82 status = napi_get_value_string_utf8(env, napi_StrValue, buffer.data(), bufferSize + 1, &bufferSize);
83 if (status != napi_ok) {
84 HILOGE("Can not get buffer value");
85 return status;
86 }
87 }
88 result = buffer;
89 return status;
90 }
91
DealNapiException(napi_env env,napi_value & exception,std::string & exceptionInfo)92 static napi_status DealNapiException(napi_env env, napi_value &exception, std::string &exceptionInfo)
93 {
94 HILOGI("call DealNapiException start.");
95 napi_status status = napi_get_and_clear_last_exception(env, &exception);
96 if (status != napi_ok) {
97 HILOGE("call napi_get_and_clear_last_exception failed.");
98 return status;
99 }
100 status = DealNapiStrValue(env, exception, exceptionInfo);
101 if (status != napi_ok) {
102 HILOGE("call DealNapiStrValue failed.");
103 return status;
104 }
105 HILOGI("call DealNapiException end, exception info = %{public}s.", exceptionInfo.c_str());
106 return status;
107 }
108
PromiseCallback(napi_env env,napi_callback_info info)109 static napi_value PromiseCallback(napi_env env, napi_callback_info info)
110 {
111 std::lock_guard<std::mutex> lock(g_extBackupValidLock);
112 if (g_extBackupCount <= 0) {
113 HILOGE("ExtBackup is invalid, count=%{public}d", g_extBackupCount);
114 return nullptr;
115 }
116 HILOGI("Promise callback.");
117 void *data = nullptr;
118 if (napi_get_cb_info(env, info, nullptr, 0, nullptr, &data) != napi_ok) {
119 HILOGE("Failed to get callback info.");
120 return nullptr;
121 }
122 auto *callbackInfo = static_cast<CallbackInfo *>(data);
123 if (callbackInfo == nullptr) {
124 HILOGE("CallbackInfo is nullptr");
125 return nullptr;
126 }
127 string str;
128 callbackInfo->callback(BError(BError::Codes::OK), str);
129 data = nullptr;
130 return nullptr;
131 }
132
PromiseCatchCallback(napi_env env,napi_callback_info info)133 static napi_value PromiseCatchCallback(napi_env env, napi_callback_info info)
134 {
135 HILOGI("Promise catch callback begin.");
136 size_t argc = 1;
137 napi_value argv = {nullptr};
138 void *data = nullptr;
139 NAPI_CALL_NO_THROW(napi_get_cb_info(env, info, &argc, &argv, nullptr, &data), nullptr);
140 string exceptionInfo;
141 DealNapiStrValue(env, argv, exceptionInfo);
142 HILOGI("Catch exception info is %{public}s.", exceptionInfo.c_str());
143 auto *callbackInfo = static_cast<CallbackInfo *>(data);
144 if (callbackInfo == nullptr) {
145 HILOGE("CallbackInfo is nullptr");
146 return nullptr;
147 }
148 napi_status throwStatus = napi_fatal_exception(env, argv);
149 if (throwStatus != napi_ok) {
150 HILOGE("Failed to throw an exception, %{public}d", throwStatus);
151 return nullptr;
152 }
153 std::lock_guard<std::mutex> lock(g_extBackupValidLock);
154 if (g_extBackupCount <= 0) {
155 HILOGE("ExtBackup is invalid, count=%{public}d", g_extBackupCount);
156 data = nullptr;
157 return nullptr;
158 }
159 callbackInfo->callback(BError(BError::Codes::EXT_THROW_EXCEPTION), exceptionInfo);
160 data = nullptr;
161 HILOGI("Promise catch callback end.");
162 return nullptr;
163 }
164
PromiseCallbackEx(napi_env env,napi_callback_info info)165 static napi_value PromiseCallbackEx(napi_env env, napi_callback_info info)
166 {
167 std::lock_guard<std::mutex> lock(g_extBackupValidLock);
168 if (g_extBackupCount <= 0) {
169 HILOGE("ExtBackup is invalid, count=%{public}d", g_extBackupCount);
170 return nullptr;
171 }
172 HILOGI("PromiseEx callback.");
173 void *data = nullptr;
174 std::string str;
175 size_t argc = 1;
176 napi_value argv = {nullptr};
177 NAPI_CALL_NO_THROW(napi_get_cb_info(env, info, &argc, &argv, nullptr, &data), nullptr);
178 auto *callbackInfoEx = static_cast<CallbackInfoEx *>(data);
179 if (callbackInfoEx == nullptr) {
180 HILOGE("CallbackInfo is nullPtr");
181 return nullptr;
182 }
183 DealNapiStrValue(env, argv, str);
184 callbackInfoEx->callbackParam(BError(BError::Codes::OK), str);
185 data = nullptr;
186 return nullptr;
187 }
188
PromiseCatchCallbackEx(napi_env env,napi_callback_info info)189 static napi_value PromiseCatchCallbackEx(napi_env env, napi_callback_info info)
190 {
191 HILOGI("PromiseEx catch callback begin.");
192 void *data = nullptr;
193 size_t argc = 1;
194 napi_value argv = {nullptr};
195 NAPI_CALL_NO_THROW(napi_get_cb_info(env, info, &argc, &argv, nullptr, &data), nullptr);
196 string exceptionInfo;
197 DealNapiStrValue(env, argv, exceptionInfo);
198 HILOGI("Catch exception info is %{public}s.", exceptionInfo.c_str());
199 auto *callbackInfoEx = static_cast<CallbackInfoEx *>(data);
200 if (callbackInfoEx == nullptr) {
201 HILOGE("CallbackInfo is nullPtr");
202 return nullptr;
203 }
204 napi_status throwStatus = napi_fatal_exception(env, argv);
205 if (throwStatus != napi_ok) {
206 HILOGE("Failed to throw an exception, %{public}d", throwStatus);
207 return nullptr;
208 }
209 std::lock_guard<std::mutex> lock(g_extBackupValidLock);
210 if (g_extBackupCount <= 0) {
211 HILOGE("ExtBackup is invalid, count=%{public}d", g_extBackupCount);
212 data = nullptr;
213 return nullptr;
214 }
215 callbackInfoEx->callbackParam(BError(BError::Codes::EXT_THROW_EXCEPTION), exceptionInfo);
216 data = nullptr;
217 HILOGI("PromiseEx catch callback end.");
218 return nullptr;
219 }
220
CheckPromise(napi_env env,napi_value value)221 static bool CheckPromise(napi_env env, napi_value value)
222 {
223 if (value == nullptr) {
224 HILOGE("CheckPromise, result is null, no need to call promise.");
225 return false;
226 }
227 bool isPromise = false;
228 if (napi_is_promise(env, value, &isPromise) != napi_ok) {
229 HILOGE("CheckPromise, result is not promise, no need to call promise.");
230 return false;
231 }
232 return isPromise;
233 }
234
CallCatchPromise(AbilityRuntime::JsRuntime & jsRuntime,napi_value result,CallbackInfo * callbackInfo)235 static bool CallCatchPromise(AbilityRuntime::JsRuntime &jsRuntime, napi_value result, CallbackInfo *callbackInfo)
236 {
237 HILOGI("CallCatchPromise Begin.");
238 AbilityRuntime::HandleScope handleScope(jsRuntime);
239 auto env = jsRuntime.GetNapiEnv();
240 napi_value method = nullptr;
241 if (napi_get_named_property(env, result, "catch", &method) != napi_ok) {
242 HILOGE("CallCatchPromise, Failed to get method catch");
243 return false;
244 }
245 bool isCallable = false;
246 if (napi_is_callable(env, method, &isCallable) != napi_ok) {
247 HILOGE("CallCatchPromise, Failed to check method then is callable");
248 return false;
249 }
250 if (!isCallable) {
251 HILOGE("CallCatchPromise, property then is not callable.");
252 return false;
253 }
254 napi_value ret;
255 if (napi_create_function(env, "promiseCatchCallback", strlen("promiseCatchCallback"), PromiseCatchCallback,
256 callbackInfo, &ret) != napi_ok) {
257 HILOGE("napi create function failed");
258 return false;
259 }
260 napi_value argv[1] = {ret};
261 if (napi_call_function(env, result, method, 1, argv, nullptr) != napi_ok) {
262 HILOGE("napi call function failed");
263 return false;
264 }
265 return true;
266 }
267
CallPromise(AbilityRuntime::JsRuntime & jsRuntime,napi_value result,CallbackInfo * callbackInfo)268 static bool CallPromise(AbilityRuntime::JsRuntime &jsRuntime, napi_value result, CallbackInfo *callbackInfo)
269 {
270 AbilityRuntime::HandleScope handleScope(jsRuntime);
271 auto env = jsRuntime.GetNapiEnv();
272 napi_value method = nullptr;
273 if (napi_get_named_property(env, result, "then", &method) != napi_ok) {
274 HILOGE("CallPromise, Failed to get method then");
275 return false;
276 }
277 bool isCallable = false;
278 if (napi_is_callable(env, method, &isCallable) != napi_ok) {
279 HILOGE("CallPromise, Failed to check method then is callable");
280 return false;
281 }
282 if (!isCallable) {
283 HILOGE("CallPromise, property then is not callable.");
284 return false;
285 }
286 napi_value ret;
287 if (napi_create_function(env, "promiseCallback", strlen("promiseCallback"), PromiseCallback, callbackInfo, &ret) !=
288 napi_ok) {
289 HILOGE("napi create function failed");
290 return false;
291 }
292 napi_value argv[1] = {ret};
293 if (napi_call_function(env, result, method, 1, argv, nullptr) != napi_ok) {
294 HILOGE("napi call function failed");
295 return false;
296 }
297 if (!CallCatchPromise(jsRuntime, result, callbackInfo)) {
298 HILOGE("CallCatchPromise failed.");
299 return false;
300 }
301 return true;
302 }
303
CallCatchPromiseEx(AbilityRuntime::JsRuntime & jsRuntime,napi_value result,CallbackInfoEx * callbackInfoEx)304 static bool CallCatchPromiseEx(AbilityRuntime::JsRuntime &jsRuntime, napi_value result, CallbackInfoEx *callbackInfoEx)
305 {
306 HILOGI("CallCatchPromiseEx Begin.");
307 AbilityRuntime::HandleScope handleScope(jsRuntime);
308 auto env = jsRuntime.GetNapiEnv();
309 napi_value method = nullptr;
310 if (napi_get_named_property(env, result, "catch", &method) != napi_ok) {
311 HILOGE("CallCatchPromiseEx, Failed to get method catch");
312 return false;
313 }
314 bool isCallable = false;
315 if (napi_is_callable(env, method, &isCallable) != napi_ok) {
316 HILOGE("CallCatchPromiseEx, Failed to check method then is callable");
317 return false;
318 }
319 if (!isCallable) {
320 HILOGE("CallCatchPromiseEx, property then is not callable.");
321 return false;
322 }
323 napi_value ret;
324 if (napi_create_function(env, "promiseCatchCallbackEx", strlen("promiseCatchCallbackEx"), PromiseCatchCallbackEx,
325 callbackInfoEx, &ret) != napi_ok) {
326 HILOGE("napi create function failed");
327 return false;
328 }
329 napi_value argv[1] = {ret};
330 if (napi_call_function(env, result, method, 1, argv, nullptr) != napi_ok) {
331 HILOGE("napi call function failed");
332 return false;
333 }
334 return true;
335 }
336
CallPromiseEx(AbilityRuntime::JsRuntime & jsRuntime,napi_value result,CallbackInfoEx * callbackInfoEx)337 static bool CallPromiseEx(AbilityRuntime::JsRuntime &jsRuntime, napi_value result, CallbackInfoEx *callbackInfoEx)
338 {
339 AbilityRuntime::HandleScope handleScope(jsRuntime);
340 auto env = jsRuntime.GetNapiEnv();
341 napi_value method = nullptr;
342 if (napi_get_named_property(env, result, "then", &method) != napi_ok) {
343 HILOGE("CallPromise, Failed to get method then");
344 return false;
345 }
346 bool isCallable = false;
347 if (napi_is_callable(env, method, &isCallable) != napi_ok) {
348 HILOGE("CallPromise, Failed to check method then is callable");
349 return false;
350 }
351 if (!isCallable) {
352 HILOGE("CallPromise, property then is not callable.");
353 return false;
354 }
355 napi_value ret;
356 if (napi_create_function(env, "promiseCallbackEx", strlen("promiseCallbackEx"), PromiseCallbackEx, callbackInfoEx,
357 &ret) != napi_ok) {
358 HILOGE("napi create function failed");
359 return false;
360 }
361 napi_value argv[1] = {ret};
362 if (napi_call_function(env, result, method, 1, argv, nullptr) != napi_ok) {
363 HILOGE("napi call function failed");
364 return false;
365 }
366 if (!CallCatchPromiseEx(jsRuntime, result, callbackInfoEx)) {
367 HILOGE("CallCatchPromiseEx failed.");
368 return false;
369 }
370 return true;
371 }
372
CallPromiseEx(AbilityRuntime::JsRuntime & jsRuntime,napi_value result,CallbackInfoBackup * callbackInfoBackup)373 static bool CallPromiseEx(AbilityRuntime::JsRuntime &jsRuntime, napi_value result,
374 CallbackInfoBackup *callbackInfoBackup)
375 {
376 AbilityRuntime::HandleScope handleScope(jsRuntime);
377 auto env = jsRuntime.GetNapiEnv();
378 napi_value method = nullptr;
379 if (napi_get_named_property(env, result, "then", &method) != napi_ok) {
380 HILOGE("CallPromise, Failed to get method then");
381 return false;
382 }
383 bool isCallable = false;
384 if (napi_is_callable(env, method, &isCallable) != napi_ok) {
385 HILOGE("CallPromise, Failed to check method then is callable");
386 return false;
387 }
388 if (!isCallable) {
389 HILOGE("CallPromise, property then is not callable.");
390 return false;
391 }
392 napi_value ret;
393 if (napi_create_function(env, "promiseCallbackEx", strlen("promiseCallbackEx"), PromiseCallbackEx,
394 callbackInfoBackup, &ret) != napi_ok) {
395 HILOGE("napi create function failed");
396 return false;
397 }
398 napi_value argv[1] = {ret};
399 if (napi_call_function(env, result, method, 1, argv, nullptr) != napi_ok) {
400 HILOGE("napi call function failed");
401 return false;
402 }
403 return true;
404 }
405
Init(const shared_ptr<AppExecFwk::AbilityLocalRecord> & record,const shared_ptr<AppExecFwk::OHOSApplication> & application,shared_ptr<AppExecFwk::AbilityHandler> & handler,const sptr<IRemoteObject> & token)406 void ExtBackupJs::Init(const shared_ptr<AppExecFwk::AbilityLocalRecord> &record,
407 const shared_ptr<AppExecFwk::OHOSApplication> &application,
408 shared_ptr<AppExecFwk::AbilityHandler> &handler,
409 const sptr<IRemoteObject> &token)
410 {
411 HILOGI("Init the BackupExtensionAbility(JS)");
412 try {
413 ExtBackup::Init(record, application, handler, token);
414 BExcepUltils::BAssert(abilityInfo_, BError::Codes::EXT_BROKEN_FRAMEWORK, "Invalid abilityInfo_");
415 // 获取应用扩展的 BackupExtensionAbility 的路径
416 const AppExecFwk::AbilityInfo &info = *abilityInfo_;
417 string bundleName = info.bundleName;
418 InitTempPath(bundleName);
419 string moduleName(info.moduleName + "::" + info.name);
420 string modulePath = GetSrcPath(info);
421 int moduleType = static_cast<int>(info.type);
422 HILOGI("Try to load %{public}s's %{public}s(type %{public}d) from %{public}s", bundleName.c_str(),
423 moduleName.c_str(), moduleType, modulePath.c_str());
424
425 // 加载用户扩展 BackupExtensionAbility 到 JS 引擎,并将之暂存在 jsObj_ 中。注意,允许加载失败,往后执行默认逻辑
426 AbilityRuntime::HandleScope handleScope(jsRuntime_);
427 jsObj_ = jsRuntime_.LoadModule(moduleName, modulePath, info.hapPath,
428 abilityInfo_->compileMode == AbilityRuntime::CompileMode::ES_MODULE);
429 if (jsObj_ == nullptr) {
430 HILOGW("Oops! There's no custom BackupExtensionAbility");
431 return;
432 }
433 HILOGI("Wow! Here's a custsom BackupExtensionAbility");
434 ExportJsContext();
435 } catch (const BError &e) {
436 HILOGE("%{public}s", e.what());
437 } catch (const exception &e) {
438 HILOGE("%{public}s", e.what());
439 }
440 }
441
AttachBackupExtensionContext(napi_env env,void * value,void *)442 napi_value AttachBackupExtensionContext(napi_env env, void *value, void *)
443 {
444 HILOGI("AttachBackupExtensionContext");
445 if (value == nullptr || env == nullptr) {
446 HILOG_WARN("invalid parameter.");
447 return nullptr;
448 }
449 auto ptr = reinterpret_cast<std::weak_ptr<ExtBackupContext> *>(value)->lock();
450 if (ptr == nullptr) {
451 HILOGE("invalid context.");
452 return nullptr;
453 }
454 auto object = CreateExtBackupJsContext(env, ptr);
455 if (object == nullptr) {
456 HILOGE("Failed to get js backup extension context");
457 return nullptr;
458 }
459 auto contextRef =
460 AbilityRuntime::JsRuntime::LoadSystemModuleByEngine(env, "application.BackupExtensionContext", &object, 1);
461 if (contextRef == nullptr) {
462 HILOGE("Failed to load BackupExtensionContext.");
463 return nullptr;
464 }
465 napi_value contextObj = contextRef->GetNapiValue();
466 napi_coerce_to_native_binding_object(env, contextObj, AbilityRuntime::DetachCallbackFunc,
467 AttachBackupExtensionContext, value, nullptr);
468
469 auto workContext = new (std::nothrow) std::weak_ptr<ExtBackupContext>(ptr);
470 if (workContext == nullptr) {
471 HILOGE("Failed to get backup extension context");
472 return nullptr;
473 }
474 napi_status status = napi_wrap(
475 env, contextObj, workContext,
476 [](napi_env, void *data, void *) {
477 HILOG_DEBUG("Finalizer for weak_ptr base context is called");
478 delete static_cast<std::weak_ptr<ExtBackupContext> *>(data);
479 },
480 nullptr, nullptr);
481 if (status != napi_ok) {
482 HILOG_DEBUG("Failed to wrap js instance");
483 delete workContext;
484 workContext = nullptr;
485 }
486 return contextObj;
487 }
488
ExtBackupJs(AbilityRuntime::JsRuntime & jsRuntime)489 ExtBackupJs::ExtBackupJs(AbilityRuntime::JsRuntime &jsRuntime) : jsRuntime_(jsRuntime)
490 {
491 std::lock_guard<std::mutex> lock(g_extBackupValidLock);
492 g_extBackupCount += 1;
493 HILOGI("ExtBackupJs::ExtBackupJs, count=%{public}d.", g_extBackupCount);
494 }
495
~ExtBackupJs()496 ExtBackupJs::~ExtBackupJs()
497 {
498 jsRuntime_.FreeNativeReference(std::move(jsObj_));
499 std::lock_guard<std::mutex> lock(g_extBackupValidLock);
500 g_extBackupCount -= 1;
501 HILOGI("ExtBackupJs::~ExtBackupJs, count=%{public}d.", g_extBackupCount);
502 }
503
ExportJsContext(void)504 void ExtBackupJs::ExportJsContext(void)
505 {
506 auto env = jsRuntime_.GetNapiEnv();
507 if (jsObj_ == nullptr) {
508 HILOGE("Failed to get js object.");
509 return;
510 }
511 napi_value obj = jsObj_->GetNapiValue();
512 if (obj == nullptr) {
513 HILOGE("Failed to get BackupExtAbility object");
514 return;
515 }
516
517 auto context = GetContext();
518 if (context == nullptr) {
519 HILOGE("Failed to get context");
520 return;
521 }
522
523 HILOGI("CreateBackupExtAbilityContext");
524 napi_value contextObj = CreateExtBackupJsContext(env, context);
525 auto contextRef = jsRuntime_.LoadSystemModule("application.BackupExtensionContext", &contextObj, ARGC_ONE);
526 if (!contextRef) {
527 HILOGE("context is nullptr");
528 return;
529 }
530 contextObj = contextRef->GetNapiValue();
531 HILOGI("Bind context");
532 context->Bind(jsRuntime_, contextRef.release());
533 napi_set_named_property(env, obj, "context", contextObj);
534
535 auto workContext = new (std::nothrow) std::weak_ptr<ExtBackupContext>(context);
536 if (workContext == nullptr) {
537 HILOGE("Failed to create ExtBackupContext.");
538 return;
539 }
540 napi_coerce_to_native_binding_object(env, contextObj, AbilityRuntime::DetachCallbackFunc,
541 AttachBackupExtensionContext, workContext, nullptr);
542 HILOGI("Set backup extension ability context pointer is nullptr: %{public}d", context.get() == nullptr);
543 napi_status status = napi_wrap(
544 env, contextObj, workContext,
545 [](napi_env, void *data, void *) {
546 HILOG_DEBUG("Finalizer for weak_ptr base context is called");
547 delete static_cast<std::weak_ptr<ExtBackupContext> *>(data);
548 },
549 nullptr, nullptr);
550 if (status != napi_ok) {
551 HILOG_DEBUG("Failed to wrap js instance");
552 delete workContext;
553 workContext = nullptr;
554 }
555 }
556
CallObjectMethod(string_view name,const vector<napi_value> & argv)557 [[maybe_unused]] tuple<ErrCode, napi_value> ExtBackupJs::CallObjectMethod(string_view name,
558 const vector<napi_value> &argv)
559 {
560 HILOGI("Call %{public}s", name.data());
561 return {BError(BError::Codes::OK).GetCode(), nullptr};
562 }
563
Create(const unique_ptr<AbilityRuntime::Runtime> & runtime)564 ExtBackupJs *ExtBackupJs::Create(const unique_ptr<AbilityRuntime::Runtime> &runtime)
565 {
566 HILOGI("Create as an BackupExtensionAbility(JS)");
567 return new ExtBackupJs(static_cast<AbilityRuntime::JsRuntime &>(*runtime));
568 }
569
OnBackup(function<void (ErrCode,std::string)> callback,std::function<void (ErrCode,const std::string)> callbackEx)570 ErrCode ExtBackupJs::OnBackup(function<void(ErrCode, std::string)> callback,
571 std::function<void(ErrCode, const std::string)> callbackEx)
572 {
573 HILOGI("BackupExtensionAbility(JS) OnBackup ex");
574 BExcepUltils::BAssert(jsObj_, BError::Codes::EXT_BROKEN_FRAMEWORK,
575 "The app does not provide the onBackup interface.");
576 BExcepUltils::BAssert(callback, BError::Codes::EXT_BROKEN_FRAMEWORK, "OnBackup callback is nullptr.");
577 BExcepUltils::BAssert(callbackEx, BError::Codes::EXT_BROKEN_FRAMEWORK, "OnBackup callbackEx is nullptr.");
578 callExtDefaultFunc_.store(false);
579 callJsExMethodDone_.store(false);
580 callbackInfo_ = std::make_shared<CallbackInfo>(callback);
581 callbackInfoEx_ = std::make_shared<CallbackInfoEx>(callbackEx);
582 return CallJsOnBackupEx();
583 }
584
CallJsOnBackupEx()585 ErrCode ExtBackupJs::CallJsOnBackupEx()
586 {
587 HILOGI("Start call app js method onBackupEx");
588 auto retParser = [jsRuntime{ &jsRuntime_ }, callbackInfoEx { callbackInfoEx_ }](napi_env envir,
589 napi_value result) -> bool {
590 if (!CheckPromise(envir, result)) {
591 string str;
592 bool isExceptionPending;
593 napi_is_exception_pending(envir, &isExceptionPending);
594 HILOGI("napi exception pending = %{public}d.", isExceptionPending);
595 if (!callbackInfoEx) {
596 HILOGE("callbackInfoEx is nullptr");
597 return false;
598 }
599 if (isExceptionPending) {
600 napi_value exception;
601 DealNapiException(envir, exception, str);
602 napi_fatal_exception(envir, exception);
603 callbackInfoEx->callbackParam(BError(BError::Codes::EXT_THROW_EXCEPTION), str);
604 } else {
605 DealNapiStrValue(envir, result, str);
606 callbackInfoEx->callbackParam(BError(BError::Codes::OK), str);
607 }
608 return true;
609 }
610 HILOGI("CheckPromise onBackupEx ok");
611 return CallPromiseEx(*jsRuntime, result, callbackInfoEx.get());
612 };
613 auto errCode = CallJsMethod("onBackupEx", jsRuntime_, jsObj_.get(), ParseBackupExInfo(), retParser);
614 if (errCode != ERR_OK) {
615 HILOGE("Call onBackupEx error");
616 return errCode;
617 }
618 HILOGI("Check call onBackupEx load");
619 std::unique_lock<std::mutex> lock(callJsMutex_);
620 callJsCon_.wait(lock, [this] { return callJsExMethodDone_.load(); });
621
622 if (!callExtDefaultFunc_.load()) {
623 HILOGI("Call Js method onBackupEx done");
624 return ERR_OK;
625 }
626 return CallJsOnBackup();
627 }
628
CallJsOnBackup()629 ErrCode ExtBackupJs::CallJsOnBackup()
630 {
631 HILOGI("Start call app js method onBackup");
632 auto retParser = [jsRuntime {&jsRuntime_}, callbackInfo {callbackInfo_}](napi_env env,
633 napi_value result) -> bool {
634 if (!CheckPromise(env, result)) {
635 string str;
636 bool isExceptionPending;
637 napi_is_exception_pending(env, &isExceptionPending);
638 HILOGI("napi exception pending = %{public}d.", isExceptionPending);
639 if (!callbackInfo) {
640 HILOGE("callbackInfo is nullptr");
641 return false;
642 }
643 if (isExceptionPending) {
644 napi_value exception;
645 DealNapiException(env, exception, str);
646 napi_fatal_exception(env, exception);
647 callbackInfo->callback(BError(BError::Codes::EXT_THROW_EXCEPTION), str);
648 } else {
649 callbackInfo->callback(BError(BError::Codes::OK), str);
650 }
651 return true;
652 }
653 HILOGI("CheckPromise Js Method onBackup ok.");
654 return CallPromise(*jsRuntime, result, callbackInfo.get());
655 };
656 auto errCode = CallJsMethod("onBackup", jsRuntime_, jsObj_.get(), {}, retParser);
657 if (errCode != ERR_OK) {
658 HILOGE("CallJsMethod error, code:%{public}d.", errCode);
659 }
660 return errCode;
661 }
662
OnRestore(function<void (ErrCode,std::string)> callback,std::function<void (ErrCode,const std::string)> callbackEx)663 ErrCode ExtBackupJs::OnRestore(function<void(ErrCode, std::string)> callback,
664 std::function<void(ErrCode, const std::string)> callbackEx)
665 {
666 HILOGI("BackupExtensionAbility(JS) OnRestore.");
667 BExcepUltils::BAssert(jsObj_, BError::Codes::EXT_BROKEN_FRAMEWORK,
668 "The app does not provide the onRestore interface.");
669 BExcepUltils::BAssert(callback, BError::Codes::EXT_BROKEN_FRAMEWORK, "OnRestore callback is nullptr.");
670 BExcepUltils::BAssert(callbackEx, BError::Codes::EXT_BROKEN_FRAMEWORK, "OnRestore callbackEx is nullptr.");
671 callExtDefaultFunc_.store(false);
672 callJsExMethodDone_.store(false);
673 callbackInfo_ = std::make_shared<CallbackInfo>(callback);
674 callbackInfoEx_ = std::make_shared<CallbackInfoEx>(callbackEx);
675 return CallJSRestoreEx();
676 }
677
CallJSRestoreEx()678 ErrCode ExtBackupJs::CallJSRestoreEx()
679 {
680 HILOGI("Start call app js method onRestoreEx");
681 auto retParser = [jsRuntime {&jsRuntime_}, callbackInfoEx {callbackInfoEx_}](napi_env envir, napi_value result) ->
682 bool {
683 if (!CheckPromise(envir, result)) {
684 string str;
685 bool isExceptionPending;
686 napi_is_exception_pending(envir, &isExceptionPending);
687 HILOGI("napi exception pending = %{public}d.", isExceptionPending);
688 if (!callbackInfoEx) {
689 HILOGE("callbackInfoEx is nullptr");
690 return false;
691 }
692 if (isExceptionPending) {
693 napi_value exception;
694 DealNapiException(envir, exception, str);
695 napi_fatal_exception(envir, exception);
696 callbackInfoEx->callbackParam(BError(BError::Codes::EXT_THROW_EXCEPTION), str);
697 } else {
698 DealNapiStrValue(envir, result, str);
699 callbackInfoEx->callbackParam(BError(BError::Codes::OK), str);
700 }
701 return true;
702 }
703 HILOGI("CheckPromise onRestoreEx ok");
704 return CallPromiseEx(*jsRuntime, result, callbackInfoEx.get());
705 };
706 auto errCode = CallJsMethod("onRestoreEx", jsRuntime_, jsObj_.get(), ParseRestoreExInfo(), retParser);
707 if (errCode != ERR_OK) {
708 HILOGE("Call onRestoreEx error");
709 return errCode;
710 }
711 HILOGI("Check callRestoreExDone load");
712 std::unique_lock<std::mutex> lock(callJsMutex_);
713 callJsCon_.wait(lock, [this] { return callJsExMethodDone_.load(); });
714 HILOGI("Check needCallOnRestore load");
715 if (!callExtDefaultFunc_.load()) {
716 HILOGI("Call Js method onRestoreEx done");
717 return ERR_OK;
718 }
719 return CallJSRestore();
720 }
721
CallJSRestore()722 ErrCode ExtBackupJs::CallJSRestore()
723 {
724 HILOGI("Start call app js method onRestore");
725 auto retParser = [jsRuntime {&jsRuntime_}, callbackInfo {callbackInfo_}](napi_env env, napi_value result) -> bool {
726 if (!CheckPromise(env, result)) {
727 string str;
728 bool isExceptionPending;
729 napi_is_exception_pending(env, &isExceptionPending);
730 HILOGI("napi exception pending = %{public}d.", isExceptionPending);
731 if (!callbackInfo) {
732 HILOGE("callbackInfo is nullptr");
733 return false;
734 }
735 if (isExceptionPending) {
736 napi_value exception;
737 DealNapiException(env, exception, str);
738 napi_fatal_exception(env, exception);
739 callbackInfo->callback(BError(BError::Codes::EXT_THROW_EXCEPTION), str);
740 } else {
741 callbackInfo->callback(BError(BError::Codes::OK), str);
742 }
743 return true;
744 }
745 HILOGI("CheckPromise Js Method onRestore ok.");
746 return CallPromise(*jsRuntime, result, callbackInfo.get());
747 };
748 auto errCode = CallJsMethod("onRestore", jsRuntime_, jsObj_.get(), ParseRestoreInfo(), retParser);
749 if (errCode != ERR_OK) {
750 HILOGE("CallJsMethod error, code:%{public}d.", errCode);
751 return errCode;
752 }
753 return ERR_OK;
754 }
755
GetBackupInfo(std::function<void (ErrCode,const std::string)> callback)756 ErrCode ExtBackupJs::GetBackupInfo(std::function<void(ErrCode, const std::string)> callback)
757 {
758 HILOGI("BackupExtensionAbility(JS) GetBackupInfo begin.");
759 BExcepUltils::BAssert(jsObj_, BError::Codes::EXT_BROKEN_FRAMEWORK,
760 "The app does not provide the GetBackupInfo interface.");
761 callbackInfoBackup_ = std::make_shared<CallbackInfoBackup>(callback);
762 auto retParser = [jsRuntime {&jsRuntime_}, callBackInfo {callbackInfoBackup_}](napi_env env,
763 napi_value result) -> bool {
764 if (!CheckPromise(env, result)) {
765 bool isExceptionPending;
766 napi_is_exception_pending(env, &isExceptionPending);
767 HILOGI("napi exception pending = %{public}d.", isExceptionPending);
768 if (!callBackInfo) {
769 HILOGE("callBackInfo is nullptr");
770 return false;
771 }
772 if (isExceptionPending) {
773 string str;
774 napi_value exception;
775 DealNapiException(env, exception, str);
776 callBackInfo->callbackParam(BError(BError::Codes::EXT_THROW_EXCEPTION), str);
777 return false;
778 }
779 size_t strLen = 0;
780 napi_status status = napi_get_value_string_utf8(env, result, nullptr, -1, &strLen);
781 if (status != napi_ok) {
782 return false;
783 }
784 size_t bufLen = strLen + 1;
785 unique_ptr<char[]> str = make_unique<char[]>(bufLen);
786 status = napi_get_value_string_utf8(env, result, str.get(), bufLen, &strLen);
787 callBackInfo->callbackParam(BError(BError::Codes::OK), str.get());
788 return true;
789 }
790 HILOGI("BackupExtensionAbulity(JS) GetBackupInfo ok.");
791 return CallPromiseEx(*jsRuntime, result, callBackInfo.get());
792 };
793
794 auto errCode = CallJsMethod("getBackupInfo", jsRuntime_, jsObj_.get(), {}, retParser);
795 if (errCode != ERR_OK) {
796 HILOGE("CallJsMethod error, code:%{public}d.", errCode);
797 }
798 HILOGI("BackupExtensionAbulity(JS) GetBackupInfo end.");
799 return errCode;
800 }
801
InvokeJsMethod(CallJsParam * param,AbilityRuntime::HandleEscape & handleEscape,napi_env env,napi_handle_scope & scope,vector<napi_value> & argv)802 static int InvokeJsMethod(CallJsParam *param, AbilityRuntime::HandleEscape& handleEscape, napi_env env,
803 napi_handle_scope& scope, vector<napi_value>& argv)
804 {
805 if (param == nullptr || param->jsObj == nullptr) {
806 HILOGE("param or jsObj is nullptr");
807 return EINVAL;
808 }
809 napi_value value = param->jsObj->GetNapiValue();
810 if (value == nullptr) {
811 HILOGE("failed to get napi value object.");
812 return EINVAL;
813 }
814 napi_status status;
815 napi_value method;
816 status = napi_get_named_property(env, value, param->funcName.c_str(), &method);
817 if (status != napi_ok || param->retParser == nullptr) {
818 HILOGE("ResultValueParser must not null.");
819 return EINVAL;
820 }
821 napi_value result;
822 HILOGI("Extension start do call current js method, methodName:%{public}s", param->funcName.c_str());
823 if (napi_call_function(env, value, method, argv.size(), argv.data(), &result) != napi_ok) {
824 HILOGE("napi call function failed");
825 }
826 if (!param->retParser(env, handleEscape.Escape(result))) {
827 HILOGE("Parser js result fail.");
828 return EINVAL;
829 }
830 return ERR_OK;
831 }
832
DoCallJsMethod(CallJsParam * param)833 static int DoCallJsMethod(CallJsParam *param)
834 {
835 if (param == nullptr) {
836 HILOGE("param is nullptr");
837 return EINVAL;
838 }
839 AbilityRuntime::JsRuntime *jsRuntime = param->jsRuntime;
840 HILOGI("Start execute DoCallJsMethod");
841 if (jsRuntime == nullptr) {
842 HILOGE("failed to get jsRuntime");
843 return EINVAL;
844 }
845 AbilityRuntime::HandleEscape handleEscape(*jsRuntime);
846 auto env = jsRuntime->GetNapiEnv();
847 napi_handle_scope scope = nullptr;
848 napi_open_handle_scope(env, &scope);
849 if (scope == nullptr) {
850 HILOGE("scope is nullptr");
851 return EINVAL;
852 }
853 vector<napi_value> argv = {};
854 if (param->argParser != nullptr) {
855 if (!param->argParser(env, argv)) {
856 HILOGE("failed to get params.");
857 napi_close_handle_scope(env, scope);
858 return EINVAL;
859 }
860 }
861 auto ret = InvokeJsMethod(param, handleEscape, env, scope, argv);
862 napi_close_handle_scope(env, scope);
863 HILOGI("End execute DoCallJsMethod");
864 return ret;
865 }
866
CallJsMethod(const std::string & funcName,AbilityRuntime::JsRuntime & jsRuntime,NativeReference * jsObj,InputArgsParser argParser,ResultValueParser retParser)867 int ExtBackupJs::CallJsMethod(const std::string &funcName,
868 AbilityRuntime::JsRuntime &jsRuntime,
869 NativeReference *jsObj,
870 InputArgsParser argParser,
871 ResultValueParser retParser)
872 {
873 uv_loop_s *loop = nullptr;
874 napi_status status = napi_get_uv_event_loop(jsRuntime.GetNapiEnv(), &loop);
875 if (status != napi_ok) {
876 HILOGE("failed to get uv event loop.");
877 return EINVAL;
878 }
879 auto param = std::make_shared<CallJsParam>(funcName, &jsRuntime, jsObj, argParser, retParser);
880 BExcepUltils::BAssert(param, BError::Codes::EXT_BROKEN_FRAMEWORK, "failed to new param.");
881
882 auto work = std::make_shared<uv_work_t>();
883 BExcepUltils::BAssert(work, BError::Codes::EXT_BROKEN_FRAMEWORK, "failed to new uv_work_t.");
884
885 work->data = reinterpret_cast<void *>(param.get());
886 HILOGI("Will execute current js method");
887 auto task = [work {work.get()}]() {
888 if (work == nullptr) {
889 HILOGE("failed to get work.");
890 return;
891 }
892 HILOGI("AsyncWork Enter, %{public}zu", (size_t)work);
893 CallJsParam *param = reinterpret_cast<CallJsParam *>(work->data);
894 do {
895 if (param == nullptr) {
896 HILOGE("failed to get CallJsParam.");
897 break;
898 }
899 HILOGI("Start call current js method");
900 if (DoCallJsMethod(param) != ERR_OK) {
901 HILOGE("failed to call DoCallJsMethod.");
902 }
903 } while (false);
904 HILOGI("will notify current thread info");
905 std::unique_lock<std::mutex> lock(param->backupOperateMutex);
906 param->isReady.store(true);
907 param->backupOperateCondition.notify_all();
908 };
909 auto ret = napi_send_event(jsRuntime.GetNapiEnv(), task, napi_eprio_high);
910 if (ret != napi_status::napi_ok) {
911 HILOGE("failed to napi_send_event, ret:%{public}d.", ret);
912 return EINVAL;
913 }
914 HILOGI("Wait execute current js method");
915 std::unique_lock<std::mutex> lock(param->backupOperateMutex);
916 param->backupOperateCondition.wait(lock, [param]() { return param->isReady.load(); });
917 HILOGI("End do call current js method");
918 return ERR_OK;
919 }
920
ParseBackupExInfo()921 std::function<bool(napi_env env, std::vector<napi_value> &argv)> ExtBackupJs::ParseBackupExInfo()
922 {
923 auto onBackupExFun = [backupExtInfo(backupExtInfo_)](napi_env env, vector<napi_value> &argv) -> bool {
924 napi_value backupExtInfoVal = nullptr;
925 napi_create_object(env, &backupExtInfoVal);
926 HILOGI("backupExtInfo is:%{public}s", GetAnonyString(backupExtInfo).c_str());
927 if (napi_create_string_utf8(env, backupExtInfo.c_str(), backupExtInfo.size(), &backupExtInfoVal) != napi_ok) {
928 HILOGE("create napi string failed");
929 return false;
930 }
931 argv.emplace_back(backupExtInfoVal);
932 return true;
933 };
934 return onBackupExFun;
935 }
936
ParseRestoreExInfo()937 std::function<bool(napi_env env, std::vector<napi_value> &argv)> ExtBackupJs::ParseRestoreExInfo()
938 {
939 auto onRestoreExFun = [appVersionCode(appVersionCode_), appVersionStr(appVersionStr_),
940 restoreExtInfo(restoreExtInfo_)](napi_env env, vector<napi_value> &argv) -> bool {
941 HILOGI("restoreExtInfo is:%{public}s", GetAnonyString(restoreExtInfo).c_str());
942 napi_value objValue = nullptr;
943 napi_value restoreRetValue = nullptr;
944 napi_create_object(env, &objValue);
945 napi_create_object(env, &restoreRetValue);
946 napi_set_named_property(env, objValue, "code", AbilityRuntime::CreateJsValue(env, appVersionCode));
947 napi_set_named_property(env, objValue, "name", AbilityRuntime::CreateJsValue(env, appVersionStr.c_str()));
948 if (napi_create_string_utf8(env, restoreExtInfo.c_str(), restoreExtInfo.size(), &restoreRetValue) != napi_ok) {
949 HILOGE("create napi string failed");
950 return false;
951 }
952 argv.emplace_back(objValue);
953 argv.emplace_back(restoreRetValue);
954 return true;
955 };
956 return onRestoreExFun;
957 }
958
ParseRestoreInfo()959 std::function<bool(napi_env env, std::vector<napi_value> &argv)> ExtBackupJs::ParseRestoreInfo()
960 {
961 auto onRestoreFun = [appVersionCode(appVersionCode_), appVersionStr(appVersionStr_)](napi_env env,
962 vector<napi_value> &argv) -> bool {
963 std::string appVersionStrFlag = appVersionStr;
964 int64_t appVersionCodeFlag = appVersionCode;
965 napi_value objValue = nullptr;
966 napi_create_object(env, &objValue);
967 auto pos = appVersionStrFlag.find_first_of(BConstants::VERSION_NAME_SEPARATOR_CHAR);
968 std::string appVersionFlag = "";
969 if (pos != string::npos) {
970 appVersionFlag = appVersionStrFlag.substr(0, pos);
971 if (appVersionFlag == BConstants::DEFAULT_VERSION_NAME) {
972 appVersionStrFlag = appVersionFlag;
973 appVersionCodeFlag = 0;
974 }
975 }
976 napi_set_named_property(env, objValue, "code", AbilityRuntime::CreateJsValue(env, appVersionCodeFlag));
977 napi_set_named_property(env, objValue, "name", AbilityRuntime::CreateJsValue(env, appVersionStrFlag.c_str()));
978 argv.emplace_back(objValue);
979 return true;
980 };
981 return onRestoreFun;
982 }
983
InvokeAppExtMethod(ErrCode errCode,const std::string result)984 ErrCode ExtBackupJs::InvokeAppExtMethod(ErrCode errCode, const std::string result)
985 {
986 HILOGI("Start Get onBackupEx/onRestoreEx method result, errCode: %{public}d, result: %{public}s",
987 errCode, result.c_str());
988 if ((result.size() == 0) && (errCode == BError(BError::Codes::OK))) {
989 callExtDefaultFunc_.store(true);
990 } else {
991 callExtDefaultFunc_.store(false);
992 }
993 callJsExMethodDone_.store(true);
994 callJsCon_.notify_one();
995 HILOGI("End Get App onBackupEx/onRestoreEx method result");
996 return ERR_OK;
997 }
998
OnProcess(std::function<void (ErrCode,const std::string)> callback)999 ErrCode ExtBackupJs::OnProcess(std::function<void(ErrCode, const std::string)> callback)
1000 {
1001 HILOGI("BackupExtensionAbility(JS) OnProcess begin.");
1002 BExcepUltils::BAssert(jsObj_, BError::Codes::EXT_BROKEN_FRAMEWORK,
1003 "The app does not provide the OnProcess interface.");
1004 onProcessCallback_ = std::make_shared<OnProcessCallBackInfo>(callback);
1005 auto retParser = [jsRuntime {&jsRuntime_}, callBackInfo {onProcessCallback_}](napi_env env,
1006 napi_value result) -> bool {
1007 string processStr;
1008 bool isExceptionPending;
1009 napi_is_exception_pending(env, &isExceptionPending);
1010 HILOGI("napi exception pending = %{public}d.", isExceptionPending);
1011 if (!callBackInfo) {
1012 HILOGE("callbackInfo is nullptr");
1013 return false;
1014 }
1015 if (isExceptionPending) {
1016 napi_value exception;
1017 napi_get_and_clear_last_exception(env, &exception);
1018 callBackInfo->onProcessCallback(BError(BError::Codes::EXT_THROW_EXCEPTION), processStr);
1019 } else {
1020 DealNapiStrValue(env, result, processStr);
1021 callBackInfo->onProcessCallback(BError(BError::Codes::OK), processStr);
1022 }
1023 return true;
1024 };
1025 auto errCode = CallJsMethod("onProcess", jsRuntime_, jsObj_.get(), {}, retParser);
1026 if (errCode != ERR_OK) {
1027 HILOGE("CallJsMethod error, code:%{public}d.", errCode);
1028 }
1029 HILOGI("BackupExtensionAbulity(JS) OnProcess end.");
1030 return errCode;
1031 }
1032
InitTempPath(const std::string & bundleName)1033 void ExtBackupJs::InitTempPath(const std::string &bundleName)
1034 {
1035 std::string el2BackupDir(BConstants::PATH_BUNDLE_BACKUP_HOME);
1036 if (access(el2BackupDir.c_str(), F_OK) != 0) {
1037 HILOGW("backup home el2 dir not exits, try to create");
1038 if (!ForceCreateDirectory(el2BackupDir.data())) {
1039 HILOGE("Failed to create directory, err = %{public}d", errno);
1040 AppRadar::Info info(bundleName, "", "Create backup home el2 dir failed");
1041 AppRadar::GetInstance().RecordDefaultFuncRes(info, "ExtBackupJs::InitTempPath",
1042 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_DEFAULT,
1043 static_cast<int32_t>(BError::Codes::EXT_CREATE_DIR_ERROR));
1044 }
1045 }
1046 std::string el1BackupDir(BConstants::PATH_BUNDLE_BACKUP_HOME_EL1);
1047 if (access(el1BackupDir.c_str(), F_OK) != 0) {
1048 HILOGW("backup home el1 dir not exits, try to create");
1049 if (!ForceCreateDirectory(el1BackupDir.data())) {
1050 HILOGE("Failed to create home el1 dir, err = %{public}d", errno);
1051 AppRadar::Info info(bundleName, "", "Create backup home el1 dir failed");
1052 AppRadar::GetInstance().RecordDefaultFuncRes(info, "ExtBackupJs::InitTempPath",
1053 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_DEFAULT,
1054 static_cast<int32_t>(BError::Codes::EXT_CREATE_DIR_ERROR));
1055 }
1056 }
1057 }
1058 } // namespace OHOS::FileManagement::Backup
1059