diff --git a/frameworks/native/backup_ext/include/ext_backup.h b/frameworks/native/backup_ext/include/ext_backup.h index 6977778af9ca72a50b7bcc21ff3013491ce7150b..f96fa6b92d6050ddd5353dbe8e26a828662284b9 100644 --- a/frameworks/native/backup_ext/include/ext_backup.h +++ b/frameworks/native/backup_ext/include/ext_backup.h @@ -16,13 +16,29 @@ #ifndef OHOS_FILEMGMT_BACKUP_EXT_BACKUP_H #define OHOS_FILEMGMT_BACKUP_EXT_BACKUP_H +#include "b_resources/b_constants.h" #include "ext_backup_context.h" #include "extension_base.h" #include "runtime.h" +#include "want.h" namespace OHOS::FileManagement::Backup { + +class ExtBackup; +using CreatorFunc = std::function& runtime)>; + class ExtBackup : public AbilityRuntime::ExtensionBase { public: + + /** + * @brief Called when this extension is started. You must override this function if you want to perform some + * initialization operations during extension startup. + * + * This function can be called only once in the entire lifecycle of an extension. + * @param Want Indicates the {@link Want} structure containing startup information about the extension. + */ + void OnStart(const AAFwk::Want &want) override; + /** * @brief Init the extension. * @@ -36,6 +52,43 @@ public: std::shared_ptr &handler, const sptr &token) override; + /** + * @brief Called back when Service is started. + * This method can be called only by Service. You can use the StartAbility(ohos.aafwk.content.Want) method to start + * Service. Then the system calls back the current method to use the transferred want parameter to execute its own + * logic. + * + * @param want Indicates the want of Service to start. + * @param restart Indicates the startup mode. The value true indicates that Service is restarted after being + * destroyed, and the value false indicates a normal startup. + * @param startId Indicates the number of times the Service extension has been started. The startId is + * incremented by 1 every time the extension is started. For example, if the extension has been started + * for six times, the value of startId is 6. + */ + void OnCommand(const AAFwk::Want &want, bool restart, int startId) override; + + /** + * @brief Called when this backup extension ability is connected for the first time. + * + * You can override this function to implement your own processing logic. + * + * @param want Indicates the {@link Want} structure containing connection information about the backup + * extension. + * @return Returns a pointer to the sid of the connected backup extension ability. + */ + sptr OnConnect(const AAFwk::Want &want) override; + + + /** + * @brief Called when all abilities connected to this Wallpaper extension are disconnected. + * + * You can override this function to implement your own processing logic. + * + */ + void OnDisconnect(const AAFwk::Want &want) override; + +public: + /** * @brief Create Extension. * @@ -44,11 +97,59 @@ public: */ static ExtBackup *Create(const std::unique_ptr &runtime); + /** + * @brief Get the Extension Action object + * + * @return BConstants::ExtensionAction + */ + virtual BConstants::ExtensionAction GetExtensionAction() const; + + /** + * @brief Get the User Config, then check if + * + * @return allowed ro not + */ + virtual bool AllowToBackupRestore() const; + + /** + * @brief Get the user configure + * + * @return user configure + */ + virtual std::string GetUsrConfig() const; + + /** + * @brief do backup. Subclasses can inherit to implement their own custom functionality. + */ + virtual ErrCode OnBackup(void); + + /** + * @brief Called do restore. + */ + virtual ErrCode OnRestore(void); + public: ExtBackup() = default; ~ExtBackup() override = default; + static void SetCreator(const CreatorFunc& creator); + +protected: + + std::string appVersionStr_; + int appVersionCode_; + int restoreType_; + private: + + BConstants::ExtensionAction VerifyAndGetAction(const AAFwk::Want &want, + std::shared_ptr abilityInfo); + + ErrCode GetParament(const AAFwk::Want &want); + + BConstants::ExtensionAction extAction_ {BConstants::ExtensionAction::INVALID}; + + static CreatorFunc creator_; }; } // namespace OHOS::FileManagement::Backup diff --git a/frameworks/native/backup_ext/include/ext_backup_js.h b/frameworks/native/backup_ext/include/ext_backup_js.h index ae0797887757c671e41fccd4c5a424879b13174f..78b17af5873d10e15939071ba8e4c376944951b5 100644 --- a/frameworks/native/backup_ext/include/ext_backup_js.h +++ b/frameworks/native/backup_ext/include/ext_backup_js.h @@ -29,17 +29,26 @@ #include "want.h" namespace OHOS::FileManagement::Backup { +using ResultValueParser = std::function; + +struct CallJsParam { + std::mutex backupOperateMutex; + std::condition_variable backupOperateCondition; + bool isReady = false; + std::string funcName; + AbilityRuntime::JsRuntime *jsRuntime; + NativeReference *jsObj; + const std::vector &argv; + ResultValueParser retParser; + + CallJsParam(const std::string &funcNameIn, AbilityRuntime::JsRuntime *jsRuntimeIn, NativeReference *jsObjIn, + const std::vector &argvIn, ResultValueParser &retParserIn) + : funcName(funcNameIn), jsRuntime(jsRuntimeIn), jsObj(jsObjIn), argv(argvIn), retParser(retParserIn) + {} +}; + class ExtBackupJs : public ExtBackup { public: - /** - * @brief Called when this extension is started. You must override this function if you want to perform some - * initialization operations during extension startup. - * - * This function can be called only once in the entire lifecycle of an extension. - * @param Want Indicates the {@link Want} structure containing startup information about the extension. - */ - void OnStart(const AAFwk::Want &want) override; - /** * @brief Init the extension. * @@ -53,40 +62,6 @@ public: std::shared_ptr &handler, const sptr &token) override; - /** - * @brief Called back when Service is started. - * This method can be called only by Service. You can use the StartAbility(ohos.aafwk.content.Want) method to start - * Service. Then the system calls back the current method to use the transferred want parameter to execute its own - * logic. - * - * @param want Indicates the want of Service to start. - * @param restart Indicates the startup mode. The value true indicates that Service is restarted after being - * destroyed, and the value false indicates a normal startup. - * @param startId Indicates the number of times the Service extension has been started. The startId is - * incremented by 1 every time the extension is started. For example, if the extension has been started - * for six times, the value of startId is 6. - */ - void OnCommand(const AAFwk::Want &want, bool restart, int startId) override; - - /** - * @brief Called when this backup extension ability is connected for the first time. - * - * You can override this function to implement your own processing logic. - * - * @param want Indicates the {@link Want} structure containing connection information about the backup - * extension. - * @return Returns a pointer to the sid of the connected backup extension ability. - */ - sptr OnConnect(const AAFwk::Want &want) override; - - /** - * @brief Called when all abilities connected to this Wallpaper extension are disconnected. - * - * You can override this function to implement your own processing logic. - * - */ - void OnDisconnect(const AAFwk::Want &want) override; - public: /** * @brief Create ExtBackupJs. @@ -97,33 +72,14 @@ public: static ExtBackupJs *Create(const std::unique_ptr &runtime); /** - * @brief Get the File Handle object - * - * @param fileName - * @return UniqueFd + * @brief Call the app's OnBackup. */ - UniqueFd GetFileHandle(std::string &fileName); + ErrCode OnBackup(void) override; /** - * @brief Get the Extension Action object - * - * @return BConstants::ExtensionAction - */ - BConstants::ExtensionAction GetExtensionAction() const; - - /** - * @brief Get the User Config, then check if - * - * @return allowed ro not - */ - bool AllowToBackupRestore() const; - - /** - * @brief Get the user configure - * - * @return user configure + * @brief Call the app's OnRestore. */ - std::string GetUsrConfig() const; + ErrCode OnRestore(void) override; public: explicit ExtBackupJs(AbilityRuntime::JsRuntime &jsRuntime) : jsRuntime_(jsRuntime) {} @@ -133,12 +89,16 @@ public: } private: + int CallJsMethod(const std::string &funcName, + AbilityRuntime::JsRuntime &jsRuntime, + NativeReference *jsObj, + const std::vector &argv, + ResultValueParser retParser); std::tuple CallObjectMethod(std::string_view name, const std::vector &argv = {}); AbilityRuntime::JsRuntime &jsRuntime_; std::unique_ptr jsObj_; - BConstants::ExtensionAction extAction_ {BConstants::ExtensionAction::INVALID}; }; } // namespace OHOS::FileManagement::Backup diff --git a/frameworks/native/backup_ext/include/ext_extension.h b/frameworks/native/backup_ext/include/ext_extension.h index d0cbc4b7422738cb288852d26cae3fafedebb012..4532da4a507f841dd0dc291d2a7e9eee0e6a969e 100644 --- a/frameworks/native/backup_ext/include/ext_extension.h +++ b/frameworks/native/backup_ext/include/ext_extension.h @@ -34,8 +34,10 @@ public: ErrCode PublishFile(const std::string &fileName) override; ErrCode HandleBackup() override; + void AsyncTaskRestoreForUpgrade(void); + public: - explicit BackupExtExtension(const std::shared_ptr &extension) : extension_(extension) + explicit BackupExtExtension(const std::shared_ptr &extension) : extension_(extension) { threadPool_.Start(BConstants::EXTENSION_THREAD_POOL_COUNT); } @@ -82,7 +84,7 @@ private: private: std::shared_mutex lock_; - std::shared_ptr extension_; + std::shared_ptr extension_; std::vector tars_; OHOS::ThreadPool threadPool_; }; diff --git a/frameworks/native/backup_ext/src/ext_backup.cpp b/frameworks/native/backup_ext/src/ext_backup.cpp index a38123042deead2f602b77261ffd51d0f63bb9f9..0bd7341a4c1d44875b8268cd999530e9618f7e74 100644 --- a/frameworks/native/backup_ext/src/ext_backup.cpp +++ b/frameworks/native/backup_ext/src/ext_backup.cpp @@ -15,11 +15,34 @@ #include "ext_backup.h" +#include +#include + +#include +#include + +#include "bundle_mgr_client.h" +#include "unique_fd.h" + +#include "b_error/b_error.h" +#include "b_error/b_excep_utils.h" +#include "b_json/b_json_cached_entity.h" +#include "b_json/b_json_entity_extension_config.h" +#include "b_resources/b_constants.h" #include "ext_backup_js.h" +#include "ext_extension.h" #include "filemgmt_libhilog.h" +#include "i_service.h" namespace OHOS::FileManagement::Backup { using namespace std; + +CreatorFunc ExtBackup::creator_ = nullptr; +void ExtBackup::SetCreator(const CreatorFunc &creator) +{ + creator_ = creator; +} + void ExtBackup::Init(const shared_ptr &record, const shared_ptr &application, shared_ptr &handler, @@ -31,17 +54,172 @@ void ExtBackup::Init(const shared_ptr &recor ExtBackup *ExtBackup::Create(const unique_ptr &runtime) { - HILOGI("Create as an BackupExtensionAbility(Base)"); if (!runtime) { + HILOGD("Create as BackupExtensionAbility(base)"); return new ExtBackup(); } + if (creator_) { + HILOGD("Create as BackupExtensionAbility(creater)"); + return creator_(runtime); + } + switch (runtime->GetLanguage()) { case AbilityRuntime::Runtime::Language::JS: + HILOGD("Create as BackupExtensionAbility(JS)"); return ExtBackupJs::Create(runtime); default: + HILOGD("Create as BackupExtensionAbility(base)"); return new ExtBackup(); } } -} // namespace OHOS::FileManagement::Backup \ No newline at end of file + +void ExtBackup::OnStart(const AAFwk::Want &want) +{ + HILOGI("BackupExtensionAbility was started"); + Extension::OnStart(want); +} + +void ExtBackup::OnCommand(const AAFwk::Want &want, bool restart, int startId) +{ + HILOGI("BackupExtensionAbility was invoked. restart=%{public}d, startId=%{public}d", restart, startId); + + // REM: 处理返回结果 ret + // REM: 通过杀死进程实现 Stop +} + +string ExtBackup::GetUsrConfig() const +{ + vector config; + AppExecFwk::BundleMgrClient client; + BExcepUltils::BAssert(abilityInfo_, BError::Codes::EXT_BROKEN_FRAMEWORK, "Invalid abilityInfo_"); + const AppExecFwk::AbilityInfo &info = *abilityInfo_; + if (!client.GetProfileFromAbility(info, "ohos.extension.backup", config)) { + throw BError(BError::Codes::EXT_INVAL_ARG, "Failed to invoke the GetProfileFromAbility method."); + } + + return config.empty() ? "" : config[0]; +} + +bool ExtBackup::AllowToBackupRestore() const +{ + string usrConfig = GetUsrConfig(); + BJsonCachedEntity cachedEntity(usrConfig); + auto cache = cachedEntity.Structuralize(); + if (cache.GetAllowToBackupRestore()) { + return true; + } + return false; +} + +BConstants::ExtensionAction ExtBackup::GetExtensionAction() const +{ + return extAction_; +} + +BConstants::ExtensionAction ExtBackup::VerifyAndGetAction(const AAFwk::Want &want, + std::shared_ptr abilityInfo) +{ + string pendingMsg = "Received an empty ability. You must missed the init proc"; + BExcepUltils::BAssert(abilityInfo, BError::Codes::EXT_INVAL_ARG, pendingMsg); + using namespace BConstants; + ExtensionAction extAction {want.GetIntParam(EXTENSION_ACTION_PARA, static_cast(ExtensionAction::INVALID))}; + if (extAction == ExtensionAction::INVALID) { + int extActionInt = static_cast(extAction); + pendingMsg = string("Want must specify a valid action instead of ").append(to_string(extActionInt)); + throw BError(BError::Codes::EXT_INVAL_ARG, pendingMsg); + } + return extAction; +} + +ErrCode ExtBackup::GetParament(const AAFwk::Want &want) +{ + if (extAction_ == BConstants::ExtensionAction::RESTORE) { + appVersionStr_ = want.GetStringParam(BConstants::EXTENSION_VERSION_NAME_PARA); + appVersionCode_ = want.GetIntParam(BConstants::EXTENSION_VERSION_CODE_PARA, 0); + restoreType_ = want.GetIntParam(BConstants::EXTENSION_RESTORE_TYPE_PARA, 0); + + HILOGI("Get version %{public}s type %{public}d from want when restore.", appVersionStr_.c_str(), restoreType_); + } + /* backup don't need parament. */ + return ERR_OK; +} + +sptr ExtBackup::OnConnect(const AAFwk::Want &want) +{ + try { + HILOGI("begin connect"); + BExcepUltils::BAssert(abilityInfo_, BError::Codes::EXT_BROKEN_FRAMEWORK, "Invalid abilityInfo_"); + // 发起者必须是备份服务 + auto extAction = VerifyAndGetAction(want, abilityInfo_); + if (extAction_ != BConstants::ExtensionAction::INVALID && extAction == BConstants::ExtensionAction::INVALID && + extAction_ != extAction) { + HILOGE("Verification action failed."); + return nullptr; + } + // 应用必须配置支持备份恢复 + if (!AllowToBackupRestore()) { + HILOGE("The application does not allow to backup and restore."); + return nullptr; + } + extAction_ = extAction; + GetParament(want); + + Extension::OnConnect(want); + + auto remoteObject = + sptr(new BackupExtExtension(std::static_pointer_cast(shared_from_this()))); + + // async do restore. + if (extAction_ == BConstants::ExtensionAction::RESTORE && + restoreType_ == RestoreTypeEnum::RESTORE_DATA_READDY && appVersionCode_ == 0 && + appVersionStr_ == "0.0.0.0") { + HILOGI("Restore directly when upgrading."); + remoteObject->AsyncTaskRestoreForUpgrade(); + } + + return remoteObject->AsObject(); + + } catch (const BError &e) { + return nullptr; + } catch (const exception &e) { + HILOGE("%{public}s", e.what()); + return nullptr; + } catch (...) { + HILOGE(""); + return nullptr; + } +} + +void ExtBackup::OnDisconnect(const AAFwk::Want &want) +{ + try { + HILOGI("begin disconnect"); + Extension::OnDisconnect(want); + extAction_ = BConstants::ExtensionAction::INVALID; + HILOGI("end"); + } catch (const BError &e) { + return; + } catch (const exception &e) { + HILOGE("%{public}s", e.what()); + return; + } catch (...) { + HILOGE(""); + return; + } +} + +ErrCode ExtBackup::OnBackup(void) +{ + HILOGI("BackupExtensionAbility(base) OnBackup."); + return ERR_OK; +} + +ErrCode ExtBackup::OnRestore(void) +{ + HILOGI("BackupExtensionAbility(base) OnRestore."); + return ERR_OK; +} + +} // namespace OHOS::FileManagement::Backup diff --git a/frameworks/native/backup_ext/src/ext_backup_js.cpp b/frameworks/native/backup_ext/src/ext_backup_js.cpp index 3a69b02bc3f1420f9b21873358daf496d5a57d8d..c82e9d3112e548ffac99a723c23e6fc2e0710e7b 100644 --- a/frameworks/native/backup_ext/src/ext_backup_js.cpp +++ b/frameworks/native/backup_ext/src/ext_backup_js.cpp @@ -16,30 +16,32 @@ #include "ext_backup_js.h" #include +#include #include #include #include +#include "bundle_mgr_client.h" +#include "js_runtime.h" +#include "js_runtime_utils.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "napi_common_util.h" +#include "napi_common_want.h" +#include "napi_remote_object.h" +#include "unique_fd.h" + #include "b_error/b_error.h" #include "b_error/b_excep_utils.h" #include "b_json/b_json_cached_entity.h" #include "b_json/b_json_entity_extension_config.h" #include "b_resources/b_constants.h" -#include "bundle_mgr_client.h" #include "ext_extension.h" #include "filemgmt_libhilog.h" -#include "js_runtime_utils.h" -#include "unique_fd.h" namespace OHOS::FileManagement::Backup { using namespace std; -void ExtBackupJs::OnStart(const AAFwk::Want &want) -{ - HILOGI("BackupExtensionAbility(JS) was started"); - Extension::OnStart(want); -} - static string GetSrcPath(const AppExecFwk::AbilityInfo &info) { using AbilityRuntime::Extension; @@ -74,7 +76,7 @@ void ExtBackupJs::Init(const shared_ptr &record, // 加载用户扩展 BackupExtensionAbility 到 JS 引擎,并将之暂存在 jsObj_ 中。注意,允许加载失败,往后执行默认逻辑 AbilityRuntime::HandleScope handleScope(jsRuntime_); jsObj_ = jsRuntime_.LoadModule(moduleName, modulePath, info.hapPath, - abilityInfo_->compileMode == AbilityRuntime::CompileMode::ES_MODULE); + abilityInfo_->compileMode == AbilityRuntime::CompileMode::ES_MODULE); if (jsObj_) { HILOGI("Wow! Here's a custsom BackupExtensionAbility"); } else { @@ -119,116 +121,168 @@ void ExtBackupJs::Init(const shared_ptr &record, return {BError(BError::Codes::OK).GetCode(), ret}; } -void ExtBackupJs::OnCommand(const AAFwk::Want &want, bool restart, int startId) -{ - HILOGI("BackupExtensionAbility(JS) was invoked. restart=%{public}d, startId=%{public}d", restart, startId); - - // REM: 处理返回结果 ret - // REM: 通过杀死进程实现 Stop -} - ExtBackupJs *ExtBackupJs::Create(const unique_ptr &runtime) { HILOGI("Create as an BackupExtensionAbility(JS)"); return new ExtBackupJs(static_cast(*runtime)); } -string ExtBackupJs::GetUsrConfig() const +ErrCode ExtBackupJs::OnBackup(void) { - vector config; - AppExecFwk::BundleMgrClient client; - BExcepUltils::BAssert(abilityInfo_, BError::Codes::EXT_BROKEN_FRAMEWORK, "Invalid abilityInfo_"); - const AppExecFwk::AbilityInfo &info = *abilityInfo_; - if (!client.GetProfileFromAbility(info, "ohos.extension.backup", config)) { - throw BError(BError::Codes::EXT_INVAL_ARG, "Failed to invoke the GetProfileFromAbility method."); + HILOGI("BackupExtensionAbility(JS) OnBackup."); + if (!jsObj_) { + HILOGI("The app does not provide the onBackup interface."); + return ERR_OK; } + auto ret = std::make_shared(); + auto retParser = [ret](NativeEngine &engine, NativeValue *result) -> bool { + bool res = AbilityRuntime::ConvertFromJsValue(engine, result, *ret); + if (!res) { + HILOG_ERROR("Convert js value fail."); + } + return res; + }; - return config.empty() ? "" : config[0]; -} + auto errCode = CallJsMethod("onBackup", jsRuntime_, jsObj_.get(), {}, retParser); + if (errCode != ERR_OK) { + HILOGE("CallJsMethod error, code:%{public}d.", errCode); + return errCode; + } -bool ExtBackupJs::AllowToBackupRestore() const -{ - string usrConfig = GetUsrConfig(); - BJsonCachedEntity cachedEntity(usrConfig); - auto cache = cachedEntity.Structuralize(); - if (cache.GetAllowToBackupRestore()) { - return true; + if (*ret != ERR_OK) { + HILOGE("backup fail."); + return *ret; } - return false; + return ERR_OK; } -BConstants::ExtensionAction ExtBackupJs::GetExtensionAction() const +ErrCode ExtBackupJs::OnRestore(void) { - return extAction_; + HILOGI("BackupExtensionAbility(JS) OnRestore."); + if (!jsObj_) { + HILOGI("The app does not provide the onRestore interface."); + return ERR_OK; + } + auto ret = std::make_shared(); + vector argv; + NativeValue *verCode = jsRuntime_.GetNativeEngine().CreateNumber(appVersionCode_); + NativeValue *verStr = jsRuntime_.GetNativeEngine().CreateString(appVersionStr_.c_str(), appVersionStr_.length()); + + NativeValue *param = jsRuntime_.GetNativeEngine().CreateObject(); + auto paramObj = reinterpret_cast(param->GetInterface(NativeObject::INTERFACE_ID)); + paramObj->SetProperty("code", verCode); + paramObj->SetProperty("name", verStr); + argv.push_back(param); + + auto retParser = [ret](NativeEngine &engine, NativeValue *result) -> bool { + bool res = AbilityRuntime::ConvertFromJsValue(engine, result, *ret); + if (!res) { + HILOG_ERROR("Convert js value fail."); + } + return res; + }; + + auto errCode = CallJsMethod("onRestore", jsRuntime_, jsObj_.get(), argv, retParser); + if (errCode != ERR_OK) { + HILOGE("CallJsMethod error, code:%{public}d.", errCode); + return errCode; + } + + if (*ret != ERR_OK) { + HILOGE("backup fail."); + return *ret; + } + return ERR_OK; } -static BConstants::ExtensionAction VerifyAndGetAction(const AAFwk::Want &want, - std::shared_ptr abilityInfo) +static int DoCallJsMethod(CallJsParam *param) { - string pendingMsg = "Received an empty ability. You must missed the init proc"; - BExcepUltils::BAssert(abilityInfo, BError::Codes::EXT_INVAL_ARG, pendingMsg); - using namespace BConstants; - ExtensionAction extAction {want.GetIntParam(EXTENSION_ACTION_PARA, static_cast(ExtensionAction::INVALID))}; - if (extAction == ExtensionAction::INVALID) { - int extActionInt = static_cast(extAction); - pendingMsg = string("Want must specify a valid action instead of ").append(to_string(extActionInt)); - throw BError(BError::Codes::EXT_INVAL_ARG, pendingMsg); + AbilityRuntime::JsRuntime *jsRuntime = param->jsRuntime; + if (jsRuntime == nullptr) { + HILOGE("failed to get jsRuntime."); + return EINVAL; } - - return extAction; + AbilityRuntime::HandleEscape handleEscape(*jsRuntime); + auto &nativeEngine = jsRuntime->GetNativeEngine(); + NativeValue *value = param->jsObj->Get(); + if (value == nullptr) { + HILOGE("failed to get native value object."); + return EINVAL; + } + NativeObject *obj = AbilityRuntime::ConvertNativeValueTo(value); + if (obj == nullptr) { + HILOGE("failed to get BackupExtAbility object."); + return EINVAL; + } + NativeValue *method = obj->GetProperty(param->funcName.c_str()); + if (method == nullptr) { + HILOGE("failed to get %{public}s from BackupExtAbility object.", param->funcName.c_str()); + return EINVAL; + } + if (param->retParser == nullptr) { + HILOGE("ResultValueParser must not null."); + return EINVAL; + } + if (!param->retParser(nativeEngine, handleEscape.Escape(nativeEngine.CallFunction(value, method, param->argv.data(), + param->argv.size())))) { + HILOGI("Parser js result fail."); + return EINVAL; + } + return ERR_OK; } -sptr ExtBackupJs::OnConnect(const AAFwk::Want &want) +int ExtBackupJs::CallJsMethod(const std::string &funcName, + AbilityRuntime::JsRuntime &jsRuntime, + NativeReference *jsObj, + const std::vector &argv, + ResultValueParser retParser) { - try { - HILOGI("begin"); - BExcepUltils::BAssert(abilityInfo_, BError::Codes::EXT_BROKEN_FRAMEWORK, "Invalid abilityInfo_"); - // 发起者必须是备份服务 - auto extAction = VerifyAndGetAction(want, abilityInfo_); - if (extAction_ != BConstants::ExtensionAction::INVALID && extAction == BConstants::ExtensionAction::INVALID && - extAction_ != extAction) { - HILOGI("Verification failed."); - return nullptr; - } - // 应用必须配置支持备份恢复 - if (!AllowToBackupRestore()) { - HILOGI("The application does not allow to backup and restore."); - return nullptr; - } - extAction_ = extAction; - Extension::OnConnect(want); + uv_loop_s *loop = nullptr; + napi_status status = napi_get_uv_event_loop(reinterpret_cast(&jsRuntime.GetNativeEngine()), &loop); + if (status != napi_ok) { - auto remoteObject = - sptr(new BackupExtExtension(std::static_pointer_cast(shared_from_this()))); - HILOGI("end"); - return remoteObject->AsObject(); - } catch (const BError &e) { - return nullptr; - } catch (const exception &e) { - HILOGE("%{public}s", e.what()); - return nullptr; - } catch (...) { - HILOGE(""); - return nullptr; + HILOGE("failed to get uv event loop."); + return EINVAL; } -} + auto param = std::make_shared(funcName, &jsRuntime, jsObj, argv, retParser); + if (param == nullptr) { -void ExtBackupJs::OnDisconnect(const AAFwk::Want &want) -{ - try { - HILOGI("begin"); - Extension::OnDisconnect(want); - extAction_ = BConstants::ExtensionAction::INVALID; - HILOGI("end"); - } catch (const BError &e) { - return; - } catch (const exception &e) { - HILOGE("%{public}s", e.what()); - return; - } catch (...) { - HILOGE(""); - return; + HILOGE("failed to new param."); + return EINVAL; + } + auto work = std::make_shared(); + if (work == nullptr) { + + HILOGE("failed to new uv_work_t."); + return EINVAL; } + work->data = reinterpret_cast(param.get()); + int ret = uv_queue_work( + loop, work.get(), [](uv_work_t *work) {}, + [](uv_work_t *work, int status) { + CallJsParam *param = reinterpret_cast(work->data); + do { + if (param == nullptr) { + HILOGE("failed to get CallJsParam."); + break; + } + if (DoCallJsMethod(param) != ERR_OK) { + HILOGE("failed to call DoCallJsMethod."); + } + } while (false); + std::unique_lock lock(param->backupOperateMutex); + param->isReady = true; + param->backupOperateCondition.notify_one(); + }); + if (ret != 0) { + + HILOGE("failed to exec uv_queue_work."); + return EINVAL; + } + std::unique_lock lock(param->backupOperateMutex); + param->backupOperateCondition.wait(lock, [param]() { return param->isReady; }); + + return ERR_OK; } } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index 5d8ef02d8d9dc1e4cfaa339c777a4fdac583c550..4a3bcd1229b481a47bdce80d13ff26c5ae29b6d0 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -364,17 +364,23 @@ void BackupExtExtension::AsyncTaskBackup(const string config) return; } - int ret = ptr->HandleBackup(cache); + int ret = ptr->extension_->OnBackup(); + HILOGI("backup ret %{public}d", ret); + + if (ret == ERR_OK) { + ret = ptr->HandleBackup(cache); + } // REM: 处理返回结果 ret auto proxy = ServiceProxy::GetInstance(); if (proxy == nullptr) { HILOGE("Failed to obtain the ServiceProxy handle"); return; - } else { - proxy->AppDone(ret); } + proxy->AppDone(ret); + HILOGI("backup app done %{public}d", ret); + // 清空备份目录 ptr->HandleClear(); }; @@ -495,15 +501,59 @@ void BackupExtExtension::AsyncTaskRestore() // 恢复大文件 RestoreBigFiles(); + if (ret == ERR_OK) { + HILOGI("after extra, do restore."); + ret = ptr->extension_->OnRestore(); + } + // 处理返回结果 auto proxy = ServiceProxy::GetInstance(); if (proxy == nullptr) { HILOGE("Failed to obtain the ServiceProxy handle"); return; - } else { - proxy->AppDone(ret); } + proxy->AppDone(ret); + + // 清空恢复目录 + ptr->HandleClear(); + }; + + // REM: 这里异步化了,需要做并发控制 + // 在往线程池中投入任务之前将需要的数据拷贝副本到参数中,保证不发生读写竞争, + // 由于拷贝参数时尚运行在主线程中,故在参数拷贝过程中是线程安全的。 + threadPool_.AddTask([task]() { + try { + task(); + } catch (const BError &e) { + HILOGE("%{public}s", e.what()); + } catch (const exception &e) { + HILOGE("%{public}s", e.what()); + } catch (...) { + HILOGE(""); + } + }); +} + +void BackupExtExtension::AsyncTaskRestoreForUpgrade() +{ + auto task = [obj {wptr(this)}]() { + auto ptr = obj.promote(); + if (!ptr) { + HILOGI("ext_extension handle have been already released"); + return; + } + auto ret = ptr->extension_->OnRestore(); + + // 处理返回结果 + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + HILOGE("Failed to obtain the ServiceProxy handle"); + return; + } + + proxy->AppDone(ret); + // 清空恢复目录 ptr->HandleClear(); };