From b2f2adc91838a9514d8c2dcffffbc2de40ece3fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=95=E6=8C=AF=E6=9D=B0?= Date: Sat, 28 Jun 2025 17:47:07 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=94=AF=E6=8C=81getCompatibilityInfo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 吕振杰 --- .../native/backup_ext/include/ext_backup.h | 12 ++ .../native/backup_ext/include/ext_backup_js.h | 22 +++ .../native/backup_ext/include/ext_extension.h | 7 + .../native/backup_ext/src/ext_backup.cpp | 13 ++ .../native/backup_ext/src/ext_backup_js.cpp | 98 +++++++++++ .../backup_ext/src/sub_ext_extension.cpp | 63 +++++++ .../backup_ext/backup_extension_ability.js | 8 + services/backup_sa/IExtension.idl | 2 + .../backup_ext/include/ext_backup_js_mock.h | 3 + .../mock/backup_ext/include/ext_backup_mock.h | 4 + .../backup_ext/include/ext_extension_mock.h | 2 + .../backup_ext/src/ext_backup_js_mock.cpp | 17 ++ tests/mock/backup_ext/src/ext_backup_mock.cpp | 12 ++ .../backup_ext/src/ext_extension_mock.cpp | 6 + .../include/svc_extension_proxy_mock.h | 1 + .../module_ipc/svc_extension_proxy_mock.cpp | 6 + .../backup_impl/include/ext_extension_mock.h | 6 + .../backup_ext/ext_backup_js_test.cpp | 161 ++++++++++++++++++ utils/include/b_resources/b_constants.h | 2 + 19 files changed, 445 insertions(+) diff --git a/frameworks/native/backup_ext/include/ext_backup.h b/frameworks/native/backup_ext/include/ext_backup.h index c0599ba3e..b5fcd4665 100644 --- a/frameworks/native/backup_ext/include/ext_backup.h +++ b/frameworks/native/backup_ext/include/ext_backup.h @@ -185,6 +185,18 @@ public: * @brief Invoke the extended function of the APP */ virtual ErrCode InvokeAppExtMethod(ErrCode, const std::string); + + /** + * @brief Called do getBackupCompatibilityInfo. + */ + virtual ErrCode GetBackupCompatibilityInfo(std::function callbackEx, + std::string extInfo); + + /** + * @brief Called do getRestoreCompatibilityInfo. + */ + virtual ErrCode GetRestoreCompatibilityInfo(std::function callbackEx, + std::string extInfo); public: ExtBackup() = default; diff --git a/frameworks/native/backup_ext/include/ext_backup_js.h b/frameworks/native/backup_ext/include/ext_backup_js.h index f7f0c14f1..c80ad2f8f 100644 --- a/frameworks/native/backup_ext/include/ext_backup_js.h +++ b/frameworks/native/backup_ext/include/ext_backup_js.h @@ -145,6 +145,24 @@ public: */ ErrCode OnRelease(std::function callback, int32_t scenario) override; + /** + * @brief Call the app's GetBackupCompatibilityInfo + * + * @param callbackEx The callBackEx. + * @param extInfo The extInfo: json string. + */ + ErrCode GetBackupCompatibilityInfo(std::function callbackEx, + std::string extInfo) override; + + /** + * @brief Call the app's GetRestoreCompatibilityInfo + * + * @param callbackEx The callBackEx. + * @param extInfo The extInfo: json string. + */ + ErrCode GetRestoreCompatibilityInfo(std::function callbackEx, + std::string extInfo) override; + public: explicit ExtBackupJs(AbilityRuntime::JsRuntime &jsRuntime); ~ExtBackupJs(); @@ -161,6 +179,7 @@ private: std::function &argv)> ParseBackupExInfo(); std::function &argv)> ParseReleaseInfo(); + std::function &argv)> ParseCompatibilityInfo(); ErrCode CallJSRestoreEx(); ErrCode CallJSRestore(); @@ -182,6 +201,9 @@ private: std::atomic callExtDefaultFunc_ {false}; // extension default method, onBackup or onRestore std::atomic callJsExMethodDone_ {false}; int32_t scenario_ { 0 }; + + std::shared_ptr getComInfoCallbackEx_; + std::string extInfo_; }; } // 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 6d545f815..4a2abed45 100644 --- a/frameworks/native/backup_ext/include/ext_extension.h +++ b/frameworks/native/backup_ext/include/ext_extension.h @@ -65,6 +65,7 @@ public: ErrCode UpdateDfxInfo(int64_t uniqId, uint32_t extConnectSpend, const std::string &bundleName) override; ErrCode CleanBundleTempDir() override; ErrCode HandleOnRelease(int32_t scenario) override; + ErrCode HandleGetCompatibilityInfo(const string &extInfo, int32_t scenario, string &compatibilityInfo) override; public: explicit BackupExtExtension(const std::shared_ptr &extension, @@ -400,6 +401,7 @@ private: void SetAppResultReport(const std::string resultInfo, ErrCode errCode); void HandleExtOnRelease(); std::function OnReleaseCallback(wptr obj); + std::function GetComInfoCallback(wptr obj); private: pair> GetFileInfos(const vector &includes, const vector &excludes); TarMap GetIncrmentBigInfos(const vector &files); @@ -457,6 +459,11 @@ private: std::string appResultReportInfo_; ErrCode appResultReportErrCode_ { 0 }; std::mutex serviceCallReleaseLock_; + + std::mutex getCompatibilityInfoLock_; + std::condition_variable getCompatibilityInfoCon_; + std::atomic stopGetComInfo_ {false}; + std::string compatibilityInfo_; }; } // namespace OHOS::FileManagement::Backup diff --git a/frameworks/native/backup_ext/src/ext_backup.cpp b/frameworks/native/backup_ext/src/ext_backup.cpp index 75a48cdcd..304936753 100644 --- a/frameworks/native/backup_ext/src/ext_backup.cpp +++ b/frameworks/native/backup_ext/src/ext_backup.cpp @@ -326,4 +326,17 @@ ErrCode ExtBackup::OnRelease(std::function callback, return ERR_OK; } +ErrCode ExtBackup::GetBackupCompatibilityInfo(std::function callbackEx, + std::string extInfo) +{ + HILOGI("BackupExtensionAbility(base) GetBackupCompatibilityInfo."); + return ERR_OK; +} + +ErrCode ExtBackup::GetRestoreCompatibilityInfo(std::function callbackEx, + std::string extInfo) +{ + HILOGI("BackupExtensionAbility(base) GetRestoreCompatibilityInfo."); + 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 f8b190796..34d25631d 100644 --- a/frameworks/native/backup_ext/src/ext_backup_js.cpp +++ b/frameworks/native/backup_ext/src/ext_backup_js.cpp @@ -1095,4 +1095,102 @@ void ExtBackupJs::InitTempPath(const std::string &bundleName) } } } + +ErrCode ExtBackupJs::GetBackupCompatibilityInfo(std::function callbackEx, + std::string extInfo) +{ + HILOGI("BackupExtensionAbility(JS) GetBackupCompatibilityInfo begin."); + BExcepUltils::BAssert(jsObj_, BError::Codes::EXT_BROKEN_FRAMEWORK, + "The app does not provide the GetBackupCompatibilityInfo interface."); + extInfo_ = extInfo; + getComInfoCallbackEx_ = std::make_shared(callbackEx); + auto retParser = [jsRuntime {&jsRuntime_}, callbackInfoEx {getComInfoCallbackEx_}](napi_env env, + napi_value result) -> bool { + if (!CheckPromise(env, result)) { + string str; + bool isExceptionPending; + napi_is_exception_pending(env, &isExceptionPending); + HILOGI("napi exception pending = %{public}d.", isExceptionPending); + if (!callbackInfoEx) { + HILOGE("callbackInfoEx is nullptr"); + return false; + } + if (isExceptionPending) { + napi_value exception; + DealNapiException(env, exception, str); + napi_fatal_exception(env, exception); + callbackInfoEx->callbackParam(BError(BError::Codes::EXT_THROW_EXCEPTION), str); + } else { + callbackInfoEx->callbackParam(BError(BError::Codes::OK), str); + } + return true; + } + HILOGI("CheckPromise Js Method GetBackupCompatibilityInfo ok."); + return CallPromiseEx(*jsRuntime, result, callbackInfoEx.get()); + }; + auto errCode = CallJsMethod("getBackupCompatibilityInfo", jsRuntime_, jsObj_.get(), + ParseCompatibilityInfo(), retParser); + if (errCode != ERR_OK) { + HILOGE("CallJsMethod error, code:%{public}d.", errCode); + } + HILOGI("BackupExtensionAbility(JS) GetBackupCompatibilityInfo end."); + return errCode; +} + +ErrCode ExtBackupJs::GetRestoreCompatibilityInfo(std::function callbackEx, + std::string extInfo) +{ + HILOGI("BackupExtensionAbility(JS) GetRestoreCompatibilityInfo begin."); + BExcepUltils::BAssert(jsObj_, BError::Codes::EXT_BROKEN_FRAMEWORK, + "The app does not provide the GetRestoreCompatibilityInfo interface."); + extInfo_ = extInfo; + getComInfoCallbackEx_ = std::make_shared(callbackEx); + auto retParser = [jsRuntime {&jsRuntime_}, callbackInfoEx {getComInfoCallbackEx_}](napi_env env, + napi_value result) -> bool { + if (!CheckPromise(env, result)) { + string str; + bool isExceptionPending; + napi_is_exception_pending(env, &isExceptionPending); + HILOGI("napi exception pending = %{public}d.", isExceptionPending); + if (!callbackInfoEx) { + HILOGE("callbackInfoEx is nullptr"); + return false; + } + if (isExceptionPending) { + napi_value exception; + DealNapiException(env, exception, str); + napi_fatal_exception(env, exception); + callbackInfoEx->callbackParam(BError(BError::Codes::EXT_THROW_EXCEPTION), str); + } else { + callbackInfoEx->callbackParam(BError(BError::Codes::OK), str); + } + return true; + } + HILOGI("CheckPromise Js Method GetRestoreCompatibilityInfo ok."); + return CallPromiseEx(*jsRuntime, result, callbackInfoEx.get()); + }; + auto errCode = CallJsMethod("getRestoreCompatibilityInfo", jsRuntime_, jsObj_.get(), + ParseCompatibilityInfo(), retParser); + if (errCode != ERR_OK) { + HILOGE("CallJsMethod error, code:%{public}d.", errCode); + } + HILOGI("BackupExtensionAbility(JS) GetRestoreCompatibilityInfo end."); + return errCode; +} + +std::function &argv)> ExtBackupJs::ParseCompatibilityInfo() +{ + auto getCompatibilityInfoFun = [extInfo(extInfo_)](napi_env env, vector &argv) -> bool { + napi_value extInfoValue = nullptr; + napi_create_object(env, &extInfoValue); + HILOGI("ParseCompatibilityInfo, extInfo is:%{public}s", GetAnonyString(extInfo).c_str()); + if (napi_create_string_utf8(env, extInfo.c_str(), extInfo.size(), &extInfoValue) != napi_ok) { + HILOGE("create napi string failed"); + return false; + } + argv.emplace_back(extInfoValue); + return true; + }; + return getCompatibilityInfoFun; +} } // namespace OHOS::FileManagement::Backup diff --git a/frameworks/native/backup_ext/src/sub_ext_extension.cpp b/frameworks/native/backup_ext/src/sub_ext_extension.cpp index 4cd89419b..621ec50b7 100644 --- a/frameworks/native/backup_ext/src/sub_ext_extension.cpp +++ b/frameworks/native/backup_ext/src/sub_ext_extension.cpp @@ -1884,4 +1884,67 @@ void BackupExtExtension::HandleExtOnRelease() StartOnReleaseTimeOutTimer(ptr); CallJsOnReleaseTask(ptr, scenario, true); } + +std::function BackupExtExtension::GetComInfoCallback(wptr obj) +{ + HILOGI("Begin get GetComInfoCallback"); + return [obj](ErrCode errCode, std::string compatibilityInfo) { + HILOGI("GetComInfoCallback: App getCompatibilityInfo end"); + auto extPtr = obj.promote(); + if (extPtr == nullptr) { + HILOGE("Ext extension handle have been released"); + return; + } + if (extPtr->extension_ == nullptr) { + HILOGE("Extension handle have been released"); + return; + } + if (extPtr->stopGetComInfo_.load()) { + HILOGE("App getCompatibilityInfo timeout"); + return; + } + HILOGI("GetCompatibilityInfo end, errCode: %{public}d, compatibilityInfo size is %{public}zu", + errCode, compatibilityInfo.size()); + std::unique_lock lock(extPtr->getCompatibilityInfoLock_); + extPtr->compatibilityInfo_ = compatibilityInfo; + extPtr->stopGetComInfo_.store(true); + extPtr->getCompatibilityInfoCon_.notify_all(); + }; +} + +ErrCode BackupExtExtension::HandleGetCompatibilityInfo(const string &extInfo, int32_t scenario, + string &compatibilityInfo) +{ + try { + HILOGI("Begin, scenario: %{public}d, extInfo size: %{public}zu", scenario, extInfo.size()); + VerifyCaller(); + auto ptr = wptr(this); + auto callback = GetComInfoCallback(ptr); + ErrCode ret = ERR_OK; + if (scenario == BConstants::ExtensionScenario::BACKUP) { + ret = extension_->GetBackupCompatibilityInfo(callback, extInfo); + } else if (scenario == BConstants::ExtensionScenario::RESTORE) { + ret = extension_->GetRestoreCompatibilityInfo(callback, extInfo); + } else { + return BError(BError::Codes::EXT_INVAL_ARG).GetCode(); + } + if (ret != ERR_OK) { + HILOGE("Call GetCompatibilityInfo failed, ret = %{public}d", ret); + return ret; + } + HILOGI("wait GetCompatibilityInfo"); + compatibilityInfo = ""; + std::unique_lock lock(getCompatibilityInfoLock_); + auto isTimeout = getCompatibilityInfoCon_.wait_for(lock, + std::chrono::milliseconds(BConstants::APP_GETCOMINFO_MAX_TIMEOUT)); + if (isTimeout == std::cv_status::no_timeout) { + compatibilityInfo = compatibilityInfo_; + } + HILOGI("getCompatibilityInfo size: %{public}zu", compatibilityInfo.size()); + return ret; + } catch (...) { + HILOGE("Failed to HandleGetCompatibilityInfo"); + return BError(BError::Codes::EXT_BROKEN_IPC).GetCode(); + } +} } // namespace OHOS::FileManagement::Backup diff --git a/interfaces/api/js/napi/backup_ext/backup_extension_ability.js b/interfaces/api/js/napi/backup_ext/backup_extension_ability.js index a6d51a71b..92f4078e6 100644 --- a/interfaces/api/js/napi/backup_ext/backup_extension_ability.js +++ b/interfaces/api/js/napi/backup_ext/backup_extension_ability.js @@ -37,6 +37,14 @@ class BackupExtensionAbility { onRelease(scenario) { console.log(); } + + getBackupCompatibilityInfo(extInfo) { + console.log(); + } + + getRestoreCompatibilityInfo(extInfo) { + console.log(); + } } export default BackupExtensionAbility; \ No newline at end of file diff --git a/services/backup_sa/IExtension.idl b/services/backup_sa/IExtension.idl index eb1b0f34a..77725ada6 100644 --- a/services/backup_sa/IExtension.idl +++ b/services/backup_sa/IExtension.idl @@ -31,4 +31,6 @@ interface OHOS.FileManagement.Backup.IExtension{ [ipccode 14] void UpdateDfxInfo([in] long uniqId, [in] unsigned int extConnectSpend, [in] String bundleName); [ipccode 15] void CleanBundleTempDir(); [ipccode 16] void HandleOnRelease([in] int scenario); + [ipccode 17] void HandleGetCompatibilityInfo([in] String extInfo, [in] int scenario, + [out] String compatibilityInfo); } \ No newline at end of file diff --git a/tests/mock/backup_ext/include/ext_backup_js_mock.h b/tests/mock/backup_ext/include/ext_backup_js_mock.h index 5838cdaf7..fb59bfaa7 100644 --- a/tests/mock/backup_ext/include/ext_backup_js_mock.h +++ b/tests/mock/backup_ext/include/ext_backup_js_mock.h @@ -52,6 +52,9 @@ public: virtual void ExportJsContext() = 0; virtual ErrCode OnRelease(std::function, int32_t scenario) = 0; virtual std::function &argv) ParseReleaseInfo() = 0; + virtual ErrCode GetBackupCompatibilityInfo(std::function , std::string) = 0; + virtual ErrCode GetRestoreCompatibilityInfo(std::function , std::string) = 0; + virtual std::function &argv) ParseCompatibilityInfo() = 0; public: virtual bool GetProfileFromAbility(const OHOS::AppExecFwk::AbilityInfo &, const std::string &, std::vector &) const = 0; diff --git a/tests/mock/backup_ext/include/ext_backup_mock.h b/tests/mock/backup_ext/include/ext_backup_mock.h index bee304753..9687dcef1 100644 --- a/tests/mock/backup_ext/include/ext_backup_mock.h +++ b/tests/mock/backup_ext/include/ext_backup_mock.h @@ -53,6 +53,8 @@ public: virtual ErrCode GetParament(const AAFwk::Want &) = 0; virtual ErrCode OnProcess(std::function callback) = 0; virtual ErrCode OnRelease(std::function callback, int32_t scenario) = 0; + virtual ErrCode GetBackupCompatibilityInfo(std::function , std::string) = 0; + virtual ErrCode GetRestoreCompatibilityInfo(std::function , std::string) = 0; public: virtual std::unique_ptr LoadSystemModuleByEngine(napi_env, const std::string&, const napi_value*, size_t) = 0; @@ -99,6 +101,8 @@ public: MOCK_METHOD(ErrCode, GetParament, (const AAFwk::Want &)); MOCK_METHOD(napi_value, CreateExtBackupJsContext, (napi_env, std::shared_ptr)); MOCK_METHOD(ErrCode, OnRelease, (std::function, int32_t)); + MOCK_METHOD(ErrCode, GetBackupCompatibilityInfo, (std::function, std::string)); + MOCK_METHOD(ErrCode, GetRestoreCompatibilityInfo, (std::function, std::string)); public: MOCK_METHOD((std::unique_ptr), LoadSystemModuleByEngine, (napi_env, const std::string&, const napi_value*, size_t)); diff --git a/tests/mock/backup_ext/include/ext_extension_mock.h b/tests/mock/backup_ext/include/ext_extension_mock.h index a92a98bb1..a5817f2e0 100644 --- a/tests/mock/backup_ext/include/ext_extension_mock.h +++ b/tests/mock/backup_ext/include/ext_extension_mock.h @@ -68,6 +68,7 @@ public: virtual void WaitToSendFd(std::chrono::system_clock::time_point&, int&) = 0; virtual void RefreshTimeInfo(std::chrono::system_clock::time_point&, int&) = 0; virtual ErrCode HandleOnRelease(int32_t) = 0; + virtual ErrCode HandleGetCompatibilityInfo(const std::string &, int32_t, std::string &) = 0; public: BExtExtension() = default; virtual ~BExtExtension() = default; @@ -123,6 +124,7 @@ public: MOCK_METHOD(void, RefreshTimeInfo, ((std::chrono::system_clock::time_point&), int&)); MOCK_METHOD(ErrCode, CleanBundleTempDir, ()); MOCK_METHOD(ErrCode, HandleOnRelease, (int32_t)); + MOCK_METHOD(ErrCode, HandleGetCompatibilityInfo, (const std::string &, int32_t, std::string &)); }; } // namespace OHOS::FileManagement::Backup #endif // OHOS_FILEMGMT_BACKUP_EXT_EXTENSION_MOCK_H \ No newline at end of file diff --git a/tests/mock/backup_ext/src/ext_backup_js_mock.cpp b/tests/mock/backup_ext/src/ext_backup_js_mock.cpp index 3d64f12e9..ea41e0363 100644 --- a/tests/mock/backup_ext/src/ext_backup_js_mock.cpp +++ b/tests/mock/backup_ext/src/ext_backup_js_mock.cpp @@ -108,4 +108,21 @@ ErrCode ExtBackupJs::OnRelease(function callback, int32_t { return BExtBackupJs::extBackupJs->OnRelease(callback, scenario); } + +ErrCode ExtBackupJs::GetBackupCompatibilityInfo(std::function callbackEx, + std::string extInfo) +{ + return BExtBackupJs::extBackupJs->GetBackupCompatibilityInfo(callbackEx, extInfo); +} + +ErrCode ExtBackupJs::GetRestoreCompatibilityInfo(std::function callbackEx, + std::string extInfo) +{ + return BExtBackupJs::extBackupJs->GetRestoreCompatibilityInfo(callbackEx, extInfo); +} + +std::function &argv)> ExtBackupJs::ParseCompatibilityInfo() +{ + return BExtBackupJs::extBackupJs->ParseCompatibilityInfo(); +} } // namespace OHOS::FileManagement::Backup diff --git a/tests/mock/backup_ext/src/ext_backup_mock.cpp b/tests/mock/backup_ext/src/ext_backup_mock.cpp index 43f091594..16ab1e438 100644 --- a/tests/mock/backup_ext/src/ext_backup_mock.cpp +++ b/tests/mock/backup_ext/src/ext_backup_mock.cpp @@ -143,4 +143,16 @@ ErrCode ExtBackup::OnRelease(function callback, int3 { return BExtBackup::extBackup->OnRelease(callback, scenario); } + +ErrCode ExtBackup::GetBackupCompatibilityInfo(std::function callbackEx, + std::string extInfo) +{ + return BExtBackup::extBackup->GetBackupCompatibilityInfo(callbackEx, extInfo); +} + +ErrCode ExtBackup::GetRestoreCompatibilityInfo(std::function callbackEx, + std::string extInfo) +{ + return BExtBackup::extBackup->GetRestoreCompatibilityInfo(callbackEx, extInfo); +} } // namespace OHOS::FileManagement::Backup diff --git a/tests/mock/backup_ext/src/ext_extension_mock.cpp b/tests/mock/backup_ext/src/ext_extension_mock.cpp index b38cd0573..9765ccc0d 100644 --- a/tests/mock/backup_ext/src/ext_extension_mock.cpp +++ b/tests/mock/backup_ext/src/ext_extension_mock.cpp @@ -227,4 +227,10 @@ ErrCode BackupExtExtension::HandleOnRelease(int32_t scenario) { return BExtExtension::extExtension->HandleOnRelease(scenario); } + +ErrCode BackupExtExtension::HandleGetCompatibilityInfo(const std::string &extInfo, int32_t scenario, + std::string &compatibilityInfo) +{ + return BExtExtension::extExtension->HandleGetCompatibilityInfo(extInfo, scenario, compatibilityInfo); +} } // namespace OHOS::FileManagement::Backup diff --git a/tests/mock/module_ipc/include/svc_extension_proxy_mock.h b/tests/mock/module_ipc/include/svc_extension_proxy_mock.h index eb5600d4f..ed98bfdd3 100644 --- a/tests/mock/module_ipc/include/svc_extension_proxy_mock.h +++ b/tests/mock/module_ipc/include/svc_extension_proxy_mock.h @@ -41,6 +41,7 @@ MOCK_METHOD(ErrCode, User0OnBackup, ()); MOCK_METHOD(ErrCode, UpdateDfxInfo, (int64_t, uint32_t, const std::string &)); MOCK_METHOD(ErrCode, CleanBundleTempDir, ()); MOCK_METHOD(ErrCode, HandleOnRelease, (int32_t)); +MOCK_METHOD(ErrCode, HandleGetCompatibilityInfo, (const std::string &, int32_t, std::string &)); }; } // namespace OHOS::FileManagement::Backup #endif // OHOS_FILEMGMT_BACKUP_SVC_BACKUP_CONNECTION_MOCK_H \ No newline at end of file diff --git a/tests/mock/module_ipc/svc_extension_proxy_mock.cpp b/tests/mock/module_ipc/svc_extension_proxy_mock.cpp index 00a120b78..75891ebe2 100644 --- a/tests/mock/module_ipc/svc_extension_proxy_mock.cpp +++ b/tests/mock/module_ipc/svc_extension_proxy_mock.cpp @@ -98,4 +98,10 @@ ErrCode ExtensionProxy::HandleOnRelease(int32_t scenario) { return 0; } + +ErrCode ExtensionProxy::HandleGetCompatibilityInfo(const std::string &extInfo, int32_t scenario, + std::string &compatibilityInfo) +{ + return 0; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/unittests/backup_api/backup_impl/include/ext_extension_mock.h b/tests/unittests/backup_api/backup_impl/include/ext_extension_mock.h index 79604825a..38411a68e 100644 --- a/tests/unittests/backup_api/backup_impl/include/ext_extension_mock.h +++ b/tests/unittests/backup_api/backup_impl/include/ext_extension_mock.h @@ -179,6 +179,12 @@ public: { return BError(BError::Codes::OK); }; + + ErrCode HandleGetCompatibilityInfo(const std::string &extInfo, int32_t scenario, + std::string &compatibilityInfo) override + { + return BError(BError::Codes::OK); + } private: int32_t nHandleBackupNum_ = 0; }; diff --git a/tests/unittests/backup_ext/ext_backup_js_test.cpp b/tests/unittests/backup_ext/ext_backup_js_test.cpp index df44d0ac8..0605fb56f 100644 --- a/tests/unittests/backup_ext/ext_backup_js_test.cpp +++ b/tests/unittests/backup_ext/ext_backup_js_test.cpp @@ -1666,4 +1666,165 @@ HWTEST_F(ExtBackupJsTest, SUB_backup_ext_js_OnRelease_0200, testing::ext::TestSi } GTEST_LOG_(INFO) << "ExtBackupJsTest-end SUB_backup_ext_js_OnRelease_0200"; } + +/** + * @tc.number: SUB_backup_ext_js_GetBackupCompatibilityInfo_0100 + * @tc.name: SUB_backup_ext_js_GetBackupCompatibilityInfo_0100 + * @tc.desc: 测试 GetBackupCompatibilityInfo 各个分支成功与失败 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: issuesIAFBOS + */ +HWTEST_F(ExtBackupJsTest, SUB_backup_ext_js_GetBackupCompatibilityInfo_0100, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ExtBackupJsTest-begin SUB_backup_ext_js_GetBackupCompatibilityInfo_0100"; + try { + std::string extInfo = ""; + EXPECT_CALL(*extBackupMock, GetNapiEnv()).WillOnce(Return(nullptr)).WillOnce(Return(nullptr)); + EXPECT_CALL(*napiMock, napi_is_exception_pending(_, _)).WillOnce(Return(napi_ok)); + EXPECT_CALL(*napiMock, napi_get_value_string_utf8(_, _, _, _, _)).WillOnce(Return(napi_invalid_arg)); + EXPECT_CALL(*napiMock, napi_send_cancelable_event(_, _, _, _, _, _)).WillOnce(Return(napi_invalid_arg)); + auto ret = extBackupJs->GetBackupCompatibilityInfo([](ErrCode, std::string){}, extInfo); + EXPECT_EQ(ret, EINVAL); + + EXPECT_CALL(*extBackupMock, GetNapiEnv()).WillOnce(Return(nullptr)).WillOnce(Return(nullptr)); + EXPECT_CALL(*napiMock, napi_is_exception_pending(_, _)) + .WillOnce(DoAll(SetArgPointee(true), Return(napi_ok))); + EXPECT_CALL(*napiMock, napi_get_and_clear_last_exception(_, _)).WillOnce(Return(napi_invalid_arg)); + EXPECT_CALL(*napiMock, napi_send_cancelable_event(_, _, _, _, _, _)).WillOnce(Return(napi_invalid_arg)); + ret = extBackupJs->GetBackupCompatibilityInfo([](ErrCode, std::string){}, extInfo); + EXPECT_EQ(ret, EINVAL); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "ExtBackupJsTest-an exception occurred by GetBackupCompatibilityInfo."; + } + GTEST_LOG_(INFO) << "ExtBackupJsTest-end SUB_backup_ext_js_GetBackupCompatibilityInfo_0100"; +} + +/** + * @tc.number: SUB_backup_ext_js_GetBackupCompatibilityInfo_0200 + * @tc.name: SUB_backup_ext_js_GetBackupCompatibilityInfo_0200 + * @tc.desc: 测试 GetBackupCompatibilityInfo 各个分支成功与失败 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: issuesIAFBOS + */ +HWTEST_F(ExtBackupJsTest, SUB_backup_ext_js_GetBackupCompatibilityInfo_0200, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ExtBackupJsTest-begin SUB_backup_ext_js_GetBackupCompatibilityInfo_0200"; + try { + std::string extInfo = ""; + EXPECT_CALL(*extBackupMock, GetNapiEnv()).WillOnce(Return(nullptr)).WillOnce(Return(nullptr)); + EXPECT_CALL(*napiMock, napi_is_promise(_, _, _)) + .WillOnce(DoAll(SetArgPointee(true), Return(napi_ok))); + EXPECT_CALL(*napiMock, napi_open_handle_scope(_, _)).WillOnce(Return(napi_ok)); + EXPECT_CALL(*napiMock, napi_close_handle_scope(_, _)).WillOnce(Return(napi_ok)); + EXPECT_CALL(*napiMock, napi_get_named_property(_, _, _, _)).WillOnce(Return(napi_invalid_arg)); + EXPECT_CALL(*napiMock, napi_send_cancelable_event(_, _, _, _, _, _)).WillOnce(Return(napi_invalid_arg)); + auto ret = extBackupJs->GetBackupCompatibilityInfo([](ErrCode, std::string){}, extInfo); + EXPECT_EQ(ret, EINVAL); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "ExtBackupJsTest-an exception occurred by GetBackupCompatibilityInfo."; + } + GTEST_LOG_(INFO) << "ExtBackupJsTest-end SUB_backup_ext_js_GetBackupCompatibilityInfo_0200"; +} + +/** + * @tc.number: SUB_backup_ext_js_GetRestoreCompatibilityInfo_0100 + * @tc.name: SUB_backup_ext_js_GetRestoreCompatibilityInfo_0100 + * @tc.desc: 测试 GetRestoreCompatibilityInfo 各个分支成功与失败 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: issuesIAFBOS + */ +HWTEST_F(ExtBackupJsTest, SUB_backup_ext_js_GetRestoreCompatibilityInfo_0100, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ExtBackupJsTest-begin SUB_backup_ext_js_GetRestoreCompatibilityInfo_0100"; + try { + std::string extInfo = ""; + EXPECT_CALL(*extBackupMock, GetNapiEnv()).WillOnce(Return(nullptr)).WillOnce(Return(nullptr)); + EXPECT_CALL(*napiMock, napi_is_exception_pending(_, _)).WillOnce(Return(napi_ok)); + EXPECT_CALL(*napiMock, napi_get_value_string_utf8(_, _, _, _, _)).WillOnce(Return(napi_invalid_arg)); + EXPECT_CALL(*napiMock, napi_send_cancelable_event(_, _, _, _, _, _)).WillOnce(Return(napi_invalid_arg)); + auto ret = extBackupJs->GetRestoreCompatibilityInfo([](ErrCode, std::string){}, extInfo); + EXPECT_EQ(ret, EINVAL); + + EXPECT_CALL(*extBackupMock, GetNapiEnv()).WillOnce(Return(nullptr)).WillOnce(Return(nullptr)); + EXPECT_CALL(*napiMock, napi_is_exception_pending(_, _)) + .WillOnce(DoAll(SetArgPointee(true), Return(napi_ok))); + EXPECT_CALL(*napiMock, napi_get_and_clear_last_exception(_, _)).WillOnce(Return(napi_invalid_arg)); + EXPECT_CALL(*napiMock, napi_send_cancelable_event(_, _, _, _, _, _)).WillOnce(Return(napi_invalid_arg)); + ret = extBackupJs->GetRestoreCompatibilityInfo([](ErrCode, std::string){}, extInfo); + EXPECT_EQ(ret, EINVAL); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "ExtBackupJsTest-an exception occurred by GetRestoreCompatibilityInfo."; + } + GTEST_LOG_(INFO) << "ExtBackupJsTest-end SUB_backup_ext_js_GetRestoreCompatibilityInfo_0100"; +} + +/** + * @tc.number: SUB_backup_ext_js_GetRestoreCompatibilityInfo_0200 + * @tc.name: SUB_backup_ext_js_GetRestoreCompatibilityInfo_0200 + * @tc.desc: 测试 GetRestoreCompatibilityInfo 各个分支成功与失败 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: issuesIAFBOS + */ +HWTEST_F(ExtBackupJsTest, SUB_backup_ext_js_GetRestoreCompatibilityInfo_0200, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ExtBackupJsTest-begin SUB_backup_ext_js_GetRestoreCompatibilityInfo_0200"; + try { + std::string extInfo = ""; + EXPECT_CALL(*extBackupMock, GetNapiEnv()).WillOnce(Return(nullptr)).WillOnce(Return(nullptr)); + EXPECT_CALL(*napiMock, napi_is_promise(_, _, _)) + .WillOnce(DoAll(SetArgPointee(true), Return(napi_ok))); + EXPECT_CALL(*napiMock, napi_open_handle_scope(_, _)).WillOnce(Return(napi_ok)); + EXPECT_CALL(*napiMock, napi_close_handle_scope(_, _)).WillOnce(Return(napi_ok)); + EXPECT_CALL(*napiMock, napi_get_named_property(_, _, _, _)).WillOnce(Return(napi_invalid_arg)); + EXPECT_CALL(*napiMock, napi_send_cancelable_event(_, _, _, _, _, _)).WillOnce(Return(napi_invalid_arg)); + auto ret = extBackupJs->GetRestoreCompatibilityInfo([](ErrCode, std::string){}, extInfo); + EXPECT_EQ(ret, EINVAL); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "ExtBackupJsTest-an exception occurred by GetRestoreCompatibilityInfo."; + } + GTEST_LOG_(INFO) << "ExtBackupJsTest-end SUB_backup_ext_js_GetRestoreCompatibilityInfo_0200"; +} + +/** + * @tc.number: SUB_backup_ext_js_ParseCompatibilityInfo_0100 + * @tc.name: SUB_backup_ext_js_ParseCompatibilityInfo_0100 + * @tc.desc: 测试 ParseCompatibilityInfo 各个分支成功与失败 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: issuesIAFBOS + */ +HWTEST_F(ExtBackupJsTest, SUB_backup_ext_js_ParseCompatibilityInfo_0100, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ExtBackupJsTest-begin SUB_backup_ext_js_ParseCompatibilityInfo_0100"; + try { + std::vector argv; + auto ext = extBackupJs->extInfo_; + extBackupJs->extInfo_ = "ext_info"; + EXPECT_CALL(*napiMock, napi_create_string_utf8(_, _, _, _)).WillOnce(Return(napi_ok)); + auto ret = extBackupJs->ParseCompatibilityInfo()(nullptr, argv); + EXPECT_TRUE(ret); + + EXPECT_CALL(*napiMock, napi_create_string_utf8(_, _, _, _)).WillOnce(Return(napi_invalid_arg)); + ret = extBackupJs->ParseCompatibilityInfo()(nullptr, argv); + extBackupJs->extInfo_ = ext; + EXPECT_FALSE(ret); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "ExtBackupJsTest-an exception occurred by ParseCompatibilityInfo."; + } + GTEST_LOG_(INFO) << "ExtBackupJsTest-end SUB_backup_ext_js_ParseCompatibilityInfo_0100"; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/utils/include/b_resources/b_constants.h b/utils/include/b_resources/b_constants.h index 2687c38e0..6075332a4 100644 --- a/utils/include/b_resources/b_constants.h +++ b/utils/include/b_resources/b_constants.h @@ -103,6 +103,8 @@ constexpr int FIRST_CALL_APP_ON_PROCESS_MAX_TIMEOUT = 15000; // 首次调用应 constexpr int APP_ON_PROCESS_TIMEOUT_MAX_COUNT = 3; // 应用的onProcess接口超时的上限次数 constexpr int APP_ON_RELEASE_MAX_TIMEOUT = 5000; // 应用的onRelease接口最大超时时间为5秒 +// 应用的getBackupCompatibilityInfo/getRestoreCompatibilityInfo接口最大超时时间为1秒 +constexpr int APP_GETCOMINFO_MAX_TIMEOUT = 1000; // backup.para内配置项的名称,该配置项值为true时可在不更新hap包的情况下,可以读取包管理元数据配置文件的内容 static inline std::string BACKUP_DEBUG_OVERRIDE_EXTENSION_CONFIG_KEY = "backup.debug.overrideExtensionConfig"; -- Gitee From 49085bbb06b84b06870d84826f8aab0a759ff31f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=95=E6=8C=AF=E6=9D=B0?= Date: Thu, 3 Jul 2025 21:45:31 +0800 Subject: [PATCH 2/3] add GetCompatibilityInfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 吕振杰 --- .../backup_ext/src/sub_ext_extension.cpp | 9 +- .../src/b_incremental_backup_session.cpp | 11 ++ .../src/b_incremental_restore_session.cpp | 11 ++ .../backup_kit_inner/src/b_session_backup.cpp | 11 ++ .../src/b_session_restore.cpp | 11 ++ .../impl/b_incremental_backup_session.h | 10 ++ .../impl/b_incremental_restore_session.h | 10 ++ .../backup_kit_inner/impl/b_session_backup.h | 10 ++ .../backup_kit_inner/impl/b_session_restore.h | 10 ++ .../js/backup/session_backup_n_exporter.cpp | 76 ++++++++++ .../js/backup/session_backup_n_exporter.h | 1 + .../session_incremental_backup_n_exporter.cpp | 77 ++++++++++ .../session_incremental_backup_n_exporter.h | 1 + .../js/backup/session_restore_n_exporter.cpp | 79 ++++++++++ .../js/backup/session_restore_n_exporter.h | 1 + services/backup_sa/IService.idl | 1 + .../backup_sa/include/module_ipc/service.h | 2 + .../src/module_external/bms_adapter.cpp | 40 ++--- .../backup_sa/src/module_ipc/sub_service.cpp | 47 ++++++ .../backup_ext/include/ext_backup_js_mock.h | 4 +- .../mock/backup_ext/include/ext_backup_mock.h | 4 +- .../backup_kit_inner/service_proxy_mock.cpp | 6 + .../mock/module_external/bms_adapter_mock.cpp | 16 +- tests/mock/module_ipc/service_mock.cpp | 6 + .../b_session_backup_test.cpp | 31 ++++ .../b_session_restore_test.cpp | 31 ++++ .../backup_impl/include/i_service_mock.h | 5 + .../module_ipc/service_incremental_test.cpp | 8 + .../module_ipc/service_other_test.cpp | 2 +- .../backup_sa/module_ipc/sub_service_test.cpp | 141 ++++++++++++++++++ .../session/b_incremental_session_test.cpp | 76 ++++++++++ .../backup_sa/session/service_proxy_mock.cpp | 6 + .../backup_sa/session/service_proxy_mock.h | 1 + .../b_json_entity_extension_config_test.cpp | 43 ++++++ utils/include/b_json/b_json_entity_caps.h | 9 +- .../b_json/b_json_entity_extension_config.h | 7 + .../b_json/b_json_entity_extension_config.cpp | 11 ++ 37 files changed, 789 insertions(+), 36 deletions(-) diff --git a/frameworks/native/backup_ext/src/sub_ext_extension.cpp b/frameworks/native/backup_ext/src/sub_ext_extension.cpp index 621ec50b7..1da153964 100644 --- a/frameworks/native/backup_ext/src/sub_ext_extension.cpp +++ b/frameworks/native/backup_ext/src/sub_ext_extension.cpp @@ -1921,6 +1921,7 @@ ErrCode BackupExtExtension::HandleGetCompatibilityInfo(const string &extInfo, in auto ptr = wptr(this); auto callback = GetComInfoCallback(ptr); ErrCode ret = ERR_OK; + compatibilityInfo = ""; if (scenario == BConstants::ExtensionScenario::BACKUP) { ret = extension_->GetBackupCompatibilityInfo(callback, extInfo); } else if (scenario == BConstants::ExtensionScenario::RESTORE) { @@ -1933,11 +1934,11 @@ ErrCode BackupExtExtension::HandleGetCompatibilityInfo(const string &extInfo, in return ret; } HILOGI("wait GetCompatibilityInfo"); - compatibilityInfo = ""; std::unique_lock lock(getCompatibilityInfoLock_); - auto isTimeout = getCompatibilityInfoCon_.wait_for(lock, - std::chrono::milliseconds(BConstants::APP_GETCOMINFO_MAX_TIMEOUT)); - if (isTimeout == std::cv_status::no_timeout) { + auto noTimeout = getCompatibilityInfoCon_.wait_for(lock, + std::chrono::milliseconds(BConstants::APP_GETCOMINFO_MAX_TIMEOUT), + [this] { return this->stopGetComInfo_.load(); }); + if (noTimeout) { compatibilityInfo = compatibilityInfo_; } HILOGI("getCompatibilityInfo size: %{public}zu", compatibilityInfo.size()); diff --git a/frameworks/native/backup_kit_inner/src/b_incremental_backup_session.cpp b/frameworks/native/backup_kit_inner/src/b_incremental_backup_session.cpp index be5413d5d..9f6ef2247 100644 --- a/frameworks/native/backup_kit_inner/src/b_incremental_backup_session.cpp +++ b/frameworks/native/backup_kit_inner/src/b_incremental_backup_session.cpp @@ -215,4 +215,15 @@ ErrCode BIncrementalBackupSession::CleanBundleTempDir(const std::string &bundleN } return proxy->CleanBundleTempDir(bundleName); } + +ErrCode BIncrementalBackupSession::GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, + std::string &compatInfo) +{ + HILOGI("BIncrementalBackupSession::GetCompatibilityInfo"); + auto proxy = ServiceClient::GetInstance(); + if (proxy == nullptr) { + return BError(BError::Codes::SDK_BROKEN_IPC, "Failed to get backup service").GetCode(); + } + return proxy->GetCompatibilityInfo(bundleName, extInfo, compatInfo); +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/frameworks/native/backup_kit_inner/src/b_incremental_restore_session.cpp b/frameworks/native/backup_kit_inner/src/b_incremental_restore_session.cpp index 78b92c231..23fc5385e 100644 --- a/frameworks/native/backup_kit_inner/src/b_incremental_restore_session.cpp +++ b/frameworks/native/backup_kit_inner/src/b_incremental_restore_session.cpp @@ -237,4 +237,15 @@ ErrCode BIncrementalRestoreSession::CleanBundleTempDir(const std::string &bundle } return proxy->CleanBundleTempDir(bundleName); } + +ErrCode BIncrementalRestoreSession::GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, + std::string &compatInfo) +{ + HILOGI("BIncrementalRestoreSession::GetCompatibilityInfo"); + auto proxy = ServiceClient::GetInstance(); + if (proxy == nullptr) { + return BError(BError::Codes::SDK_BROKEN_IPC, "Failed to get backup service").GetCode(); + } + return proxy->GetCompatibilityInfo(bundleName, extInfo, compatInfo); +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/frameworks/native/backup_kit_inner/src/b_session_backup.cpp b/frameworks/native/backup_kit_inner/src/b_session_backup.cpp index 992125a31..ec93502a9 100644 --- a/frameworks/native/backup_kit_inner/src/b_session_backup.cpp +++ b/frameworks/native/backup_kit_inner/src/b_session_backup.cpp @@ -234,4 +234,15 @@ ErrCode BSessionBackup::CleanBundleTempDir(const std::string &bundleName) } return proxy->CleanBundleTempDir(bundleName); } + +ErrCode BSessionBackup::GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, + std::string &compatInfo) +{ + HILOGI("BSessionBackup::GetCompatibilityInfo"); + auto proxy = ServiceClient::GetInstance(); + if (proxy == nullptr) { + return BError(BError::Codes::SDK_BROKEN_IPC, "Failed to get backup service").GetCode(); + } + return proxy->GetCompatibilityInfo(bundleName, extInfo, compatInfo); +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/frameworks/native/backup_kit_inner/src/b_session_restore.cpp b/frameworks/native/backup_kit_inner/src/b_session_restore.cpp index 34dfc57c3..e2215940c 100644 --- a/frameworks/native/backup_kit_inner/src/b_session_restore.cpp +++ b/frameworks/native/backup_kit_inner/src/b_session_restore.cpp @@ -215,4 +215,15 @@ ErrCode BSessionRestore::CleanBundleTempDir(const std::string &bundleName) } return proxy->CleanBundleTempDir(bundleName); } + +ErrCode BSessionRestore::GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, + std::string &compatInfo) +{ + HILOGI("BSessionRestore::GetCompatibilityInfo"); + auto proxy = ServiceClient::GetInstance(); + if (proxy == nullptr) { + return BError(BError::Codes::SDK_BROKEN_IPC, "Failed to get backup service").GetCode(); + } + return proxy->GetCompatibilityInfo(bundleName, extInfo, compatInfo); +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_backup_session.h b/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_backup_session.h index b32113789..d1bbec06e 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_backup_session.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_backup_session.h @@ -123,6 +123,16 @@ public: */ ErrCode CleanBundleTempDir(const std::string &bundleName); + /** + * @brief 获取备份或恢复的应用的兼容性信息 + * + * @param bundleName 应用名称 + * @param extInfo 导入给应用的信息 + * @param compatInfo 应用返回的兼容信息 + * @return ErrCode 规范错误码 + */ + ErrCode GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, std::string &compatInfo); + public: ~BIncrementalBackupSession(); diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_restore_session.h b/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_restore_session.h index feaadb654..64855efab 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_restore_session.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/b_incremental_restore_session.h @@ -145,6 +145,16 @@ public: */ ErrCode CleanBundleTempDir(const std::string &bundleName); + /** + * @brief 获取备份或恢复的应用的兼容性信息 + * + * @param bundleName 应用名称 + * @param extInfo 导入给应用的信息 + * @param compatInfo 应用返回的兼容信息 + * @return ErrCode 规范错误码 + */ + ErrCode GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, std::string &compatInfo); + public: ~BIncrementalRestoreSession(); diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/b_session_backup.h b/interfaces/inner_api/native/backup_kit_inner/impl/b_session_backup.h index 7f5cd583d..4382c0d08 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/b_session_backup.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/b_session_backup.h @@ -138,6 +138,16 @@ public: */ ErrCode CleanBundleTempDir(const std::string &bundleName); + /** + * @brief 获取备份或恢复的应用的兼容性信息 + * + * @param bundleName 应用名称 + * @param extInfo 导入给应用的信息 + * @param compatInfo 应用返回的兼容信息 + * @return ErrCode 规范错误码 + */ + ErrCode GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, std::string &compatInfo); + public: ~BSessionBackup(); diff --git a/interfaces/inner_api/native/backup_kit_inner/impl/b_session_restore.h b/interfaces/inner_api/native/backup_kit_inner/impl/b_session_restore.h index 4dd41dc36..e637a1354 100644 --- a/interfaces/inner_api/native/backup_kit_inner/impl/b_session_restore.h +++ b/interfaces/inner_api/native/backup_kit_inner/impl/b_session_restore.h @@ -145,6 +145,16 @@ public: */ ErrCode CleanBundleTempDir(const std::string &bundleName); + /** + * @brief 获取备份或恢复的应用的兼容性信息 + * + * @param bundleName 应用名称 + * @param extInfo 导入给应用的信息 + * @param compatInfo 应用返回的兼容信息 + * @return ErrCode 规范错误码 + */ + ErrCode GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, std::string &compatInfo); + public: ~BSessionRestore(); diff --git a/interfaces/kits/js/backup/session_backup_n_exporter.cpp b/interfaces/kits/js/backup/session_backup_n_exporter.cpp index bcd5846fc..e1d5f6328 100644 --- a/interfaces/kits/js/backup/session_backup_n_exporter.cpp +++ b/interfaces/kits/js/backup/session_backup_n_exporter.cpp @@ -712,6 +712,81 @@ napi_value SessionBackupNExporter::CleanBundleTempDir(napi_env env, napi_callbac return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_; } +static NContextCBExec GetCompatibilityInfoCBExec(napi_env env, const NFuncArg &funcArg, string bundleName, + string extInfo, shared_ptr compatInfo) +{ + auto backupEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!(backupEntity && (backupEntity->session))) { + HILOGE("Failed to get BackupSession entity."); + return nullptr; + } + return [entity {backupEntity}, bundleName, extInfo, compatInfo]() -> NError { + if (!(entity && (entity->session))) { + return NError(BError(BError::Codes::SDK_INVAL_ARG, "Backup session is nullptr").GetCode()); + } + return NError(entity->session->GetCompatibilityInfo(bundleName, extInfo, *compatInfo)); + }; +} + +static bool ParseCompatInfoParam(napi_env env, NFuncArg &funcArg, string &bundleName, string &extInfo) +{ + if (!funcArg.InitArgs(NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + return false; + } + NVal jsBundleName(env, funcArg[NARG_POS::FIRST]); + auto [succ, bundleNamePtr, sizeStr] = jsBundleName.ToUTF8String(); + if (!succ) { + HILOGE("First arguments is not string."); + return false; + } + NVal jsExtInfo(env, funcArg[NARG_POS::SECOND]); + auto [succ1, extInfoPtr, sizeStr1] = jsExtInfo.ToUTF8String(); + if (!succ1) { + HILOGE("Second arguments is not string."); + return false; + } + bundleName = string(bundleNamePtr.get()); + extInfo = string(extInfoPtr.get()); + return true; +} + +napi_value SessionBackupNExporter::GetCompatibilityInfo(napi_env env, napi_callback_info cbinfo) +{ + HILOGI("Called SessionBackupNExporter::GetCompatibilityInfo begin."); + if (!SAUtils::CheckBackupPermission()) { + HILOGE("Has not permission!"); + NError(E_PERMISSION).ThrowErr(env); + return nullptr; + } + if (!SAUtils::IsSystemApp()) { + HILOGE("System App check fail!"); + NError(E_PERMISSION_SYS).ThrowErr(env); + return nullptr; + } + + NFuncArg funcArg(env, cbinfo); + string bundleName; + string extInfo; + if (!ParseCompatInfoParam(env, funcArg, bundleName, extInfo)) { + NError(E_PARAMS).ThrowErr(env); + return nullptr; + } + + auto compatInfo = std::make_shared(); + auto cbExec = GetCompatibilityInfoCBExec(env, funcArg, bundleName, extInfo, compatInfo); + if (cbExec == nullptr) { + NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get BackupSession entity.").GetCode()).ThrowErr(env); + return nullptr; + } + auto cbCompl = [compatInfo](napi_env env, NError err) -> NVal { + return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUTF8String(env, *compatInfo); + }; + + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_; +} + bool SessionBackupNExporter::Export() { HILOGD("called SessionBackupNExporter::Export begin"); @@ -722,6 +797,7 @@ bool SessionBackupNExporter::Export() NVal::DeclareNapiFunction("release", Release), NVal::DeclareNapiFunction("cancel", Cancel), NVal::DeclareNapiFunction("cleanBundleTempDir", CleanBundleTempDir), + NVal::DeclareNapiFunction("getCompatibilityInfo", GetCompatibilityInfo), }; auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props)); diff --git a/interfaces/kits/js/backup/session_backup_n_exporter.h b/interfaces/kits/js/backup/session_backup_n_exporter.h index 708f3b9b7..92b0c8291 100644 --- a/interfaces/kits/js/backup/session_backup_n_exporter.h +++ b/interfaces/kits/js/backup/session_backup_n_exporter.h @@ -32,6 +32,7 @@ public: static napi_value Release(napi_env env, napi_callback_info cbinfo); static napi_value Cancel(napi_env env, napi_callback_info cbinfo); static napi_value CleanBundleTempDir(napi_env env, napi_callback_info cbinfo); + static napi_value GetCompatibilityInfo(napi_env env, napi_callback_info cbinfo); SessionBackupNExporter(napi_env env, napi_value exports); ~SessionBackupNExporter() override; diff --git a/interfaces/kits/js/backup/session_incremental_backup_n_exporter.cpp b/interfaces/kits/js/backup/session_incremental_backup_n_exporter.cpp index 6c7c377fd..1cef934ed 100644 --- a/interfaces/kits/js/backup/session_incremental_backup_n_exporter.cpp +++ b/interfaces/kits/js/backup/session_incremental_backup_n_exporter.cpp @@ -711,6 +711,82 @@ napi_value SessionIncrementalBackupNExporter::CleanBundleTempDir(napi_env env, n return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_; } + +static NContextCBExec GetCompatibilityInfoCBExec(napi_env env, const NFuncArg &funcArg, string bundleName, + string extInfo, shared_ptr compatInfo) +{ + auto backupEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!(backupEntity && (backupEntity->session))) { + HILOGE("Failed to get BackupSession entity."); + return nullptr; + } + return [entity {backupEntity}, bundleName, extInfo, compatInfo]() -> NError { + if (!(entity && (entity->session))) { + return NError(BError(BError::Codes::SDK_INVAL_ARG, "Backup session is nullptr").GetCode()); + } + return NError(entity->session->GetCompatibilityInfo(bundleName, extInfo, *compatInfo)); + }; +} + +static bool ParseCompatInfoParam(napi_env env, NFuncArg &funcArg, string &bundleName, string &extInfo) +{ + if (!funcArg.InitArgs(NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + return false; + } + NVal jsBundleName(env, funcArg[NARG_POS::FIRST]); + auto [succ, bundleNamePtr, sizeStr] = jsBundleName.ToUTF8String(); + if (!succ) { + HILOGE("First arguments is not string."); + return false; + } + NVal jsExtInfo(env, funcArg[NARG_POS::SECOND]); + auto [succ1, extInfoPtr, sizeStr1] = jsExtInfo.ToUTF8String(); + if (!succ1) { + HILOGE("Second arguments is not string."); + return false; + } + bundleName = string(bundleNamePtr.get()); + extInfo = string(extInfoPtr.get()); + return true; +} + +napi_value SessionIncrementalBackupNExporter::GetCompatibilityInfo(napi_env env, napi_callback_info cbinfo) +{ + HILOGI("Called SessionIncrementalBackupNExporter::GetCompatibilityInfo begin."); + if (!SAUtils::CheckBackupPermission()) { + HILOGE("Has not permission!"); + NError(E_PERMISSION).ThrowErr(env); + return nullptr; + } + if (!SAUtils::IsSystemApp()) { + HILOGE("System App check fail!"); + NError(E_PERMISSION_SYS).ThrowErr(env); + return nullptr; + } + + NFuncArg funcArg(env, cbinfo); + string bundleName; + string extInfo; + if (!ParseCompatInfoParam(env, funcArg, bundleName, extInfo)) { + NError(E_PARAMS).ThrowErr(env); + return nullptr; + } + + auto compatInfo = std::make_shared(); + auto cbExec = GetCompatibilityInfoCBExec(env, funcArg, bundleName, extInfo, compatInfo); + if (cbExec == nullptr) { + NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get BackupSession entity.").GetCode()).ThrowErr(env); + return nullptr; + } + auto cbCompl = [compatInfo](napi_env env, NError err) -> NVal { + return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUTF8String(env, *compatInfo); + }; + + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_; +} + bool SessionIncrementalBackupNExporter::Export() { HILOGD("called SessionIncrementalBackupNExporter::Export begin"); @@ -721,6 +797,7 @@ bool SessionIncrementalBackupNExporter::Export() NVal::DeclareNapiFunction("release", Release), NVal::DeclareNapiFunction("cancel", Cancel), NVal::DeclareNapiFunction("cleanBundleTempDir", CleanBundleTempDir), + NVal::DeclareNapiFunction("getCompatibilityInfo", GetCompatibilityInfo), }; auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props)); diff --git a/interfaces/kits/js/backup/session_incremental_backup_n_exporter.h b/interfaces/kits/js/backup/session_incremental_backup_n_exporter.h index 7f9547232..6ebba0c6f 100644 --- a/interfaces/kits/js/backup/session_incremental_backup_n_exporter.h +++ b/interfaces/kits/js/backup/session_incremental_backup_n_exporter.h @@ -32,6 +32,7 @@ public: static napi_value Release(napi_env env, napi_callback_info cbinfo); static napi_value Cancel(napi_env env, napi_callback_info cbinfo); static napi_value CleanBundleTempDir(napi_env env, napi_callback_info cbinfo); + static napi_value GetCompatibilityInfo(napi_env env, napi_callback_info cbinfo); SessionIncrementalBackupNExporter(napi_env env, napi_value exports); ~SessionIncrementalBackupNExporter() override; diff --git a/interfaces/kits/js/backup/session_restore_n_exporter.cpp b/interfaces/kits/js/backup/session_restore_n_exporter.cpp index b57a9b271..154012230 100644 --- a/interfaces/kits/js/backup/session_restore_n_exporter.cpp +++ b/interfaces/kits/js/backup/session_restore_n_exporter.cpp @@ -905,6 +905,84 @@ napi_value SessionRestoreNExporter::CleanBundleTempDir(napi_env env, napi_callba return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_; } +static NContextCBExec GetCompatibilityInfoCBExec(napi_env env, const NFuncArg &funcArg, string bundleName, + string extInfo, shared_ptr compatInfo) +{ + auto restoreEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!(restoreEntity && (restoreEntity->sessionWhole || restoreEntity->sessionSheet))) { + HILOGE("Failed to get RestoreSession entity."); + return nullptr; + } + return [entity {restoreEntity}, bundleName, extInfo, compatInfo]() -> NError { + if (!(entity && (entity->sessionWhole || entity->sessionSheet))) { + return NError(BError(BError::Codes::SDK_INVAL_ARG, "restore session is nullptr").GetCode()); + } + if (entity->sessionWhole) { + return NError(entity->sessionWhole->GetCompatibilityInfo(bundleName, extInfo, *compatInfo)); + } + return NError(entity->sessionSheet->GetCompatibilityInfo(bundleName, extInfo, *compatInfo)); + }; +} + +static bool ParseCompatInfoParam(napi_env env, NFuncArg &funcArg, string &bundleName, string &extInfo) +{ + if (!funcArg.InitArgs(NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + return false; + } + NVal jsBundleName(env, funcArg[NARG_POS::FIRST]); + auto [succ, bundleNamePtr, sizeStr] = jsBundleName.ToUTF8String(); + if (!succ) { + HILOGE("First arguments is not string."); + return false; + } + NVal jsExtInfo(env, funcArg[NARG_POS::SECOND]); + auto [succ1, extInfoPtr, sizeStr1] = jsExtInfo.ToUTF8String(); + if (!succ1) { + HILOGE("Second arguments is not string."); + return false; + } + bundleName = string(bundleNamePtr.get()); + extInfo = string(extInfoPtr.get()); + return true; +} + +napi_value SessionRestoreNExporter::GetCompatibilityInfo(napi_env env, napi_callback_info cbinfo) +{ + HILOGI("Called SessionRestore::GetCompatibilityInfo begin."); + if (!SAUtils::CheckBackupPermission()) { + HILOGE("Has not permission!"); + NError(E_PERMISSION).ThrowErr(env); + return nullptr; + } + if (!SAUtils::IsSystemApp()) { + HILOGE("System App check fail!"); + NError(E_PERMISSION_SYS).ThrowErr(env); + return nullptr; + } + + NFuncArg funcArg(env, cbinfo); + string bundleName; + string extInfo; + if (!ParseCompatInfoParam(env, funcArg, bundleName, extInfo)) { + NError(E_PARAMS).ThrowErr(env); + return nullptr; + } + + auto compatInfo = std::make_shared(); + auto cbExec = GetCompatibilityInfoCBExec(env, funcArg, bundleName, extInfo, compatInfo); + if (cbExec == nullptr) { + NError(BError(BError::Codes::SDK_INVAL_ARG, "Failed to get RestoreSession entity.").GetCode()).ThrowErr(env); + return nullptr; + } + auto cbCompl = [compatInfo](napi_env env, NError err) -> NVal { + return err ? NVal {env, err.GetNapiErr(env)} : NVal::CreateUTF8String(env, *compatInfo); + }; + + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(className, cbExec, cbCompl).val_; +} + bool SessionRestoreNExporter::Export() { HILOGD("called SessionRestoreNExporter::Export begin"); @@ -916,6 +994,7 @@ bool SessionRestoreNExporter::Export() NVal::DeclareNapiFunction("release", Release), NVal::DeclareNapiFunction("cancel", Cancel), NVal::DeclareNapiFunction("cleanBundleTempDir", CleanBundleTempDir), + NVal::DeclareNapiFunction("getCompatibilityInfo", GetCompatibilityInfo), }; auto [succ, classValue] = NClass::DefineClass(exports_.env_, className, Constructor, std::move(props)); diff --git a/interfaces/kits/js/backup/session_restore_n_exporter.h b/interfaces/kits/js/backup/session_restore_n_exporter.h index 12a40fca8..8924a4dfc 100644 --- a/interfaces/kits/js/backup/session_restore_n_exporter.h +++ b/interfaces/kits/js/backup/session_restore_n_exporter.h @@ -36,6 +36,7 @@ public: static napi_value Release(napi_env env, napi_callback_info cbinfo); static napi_value Cancel(napi_env env, napi_callback_info cbinfo); static napi_value CleanBundleTempDir(napi_env env, napi_callback_info cbinfo); + static napi_value GetCompatibilityInfo(napi_env env, napi_callback_info cbinfo); SessionRestoreNExporter(napi_env env, napi_value exports); ~SessionRestoreNExporter() override; diff --git a/services/backup_sa/IService.idl b/services/backup_sa/IService.idl index 1fdf7524e..dda0fe4a0 100644 --- a/services/backup_sa/IService.idl +++ b/services/backup_sa/IService.idl @@ -76,4 +76,5 @@ interface OHOS.FileManagement.Backup.IService{ [ipccode 42] void GetExtOnRelease([out] boolean isExtOnRelease); [ipccode 43] void AppFileReadyWithoutFd([in]String fileName, [in] int appFileReadyErrCode); [ipccode 44] void AppIncrementalFileReadyWithoutFd([in] String fileName, [in] int appIncrementalFileReadyErrCode); + [ipccode 45] void GetCompatibilityInfo([in] String bundleName, [in] String extInfo, [out] String compatInfo); } \ No newline at end of file diff --git a/services/backup_sa/include/module_ipc/service.h b/services/backup_sa/include/module_ipc/service.h index 4a56703c7..3e5052d5b 100644 --- a/services/backup_sa/include/module_ipc/service.h +++ b/services/backup_sa/include/module_ipc/service.h @@ -120,6 +120,8 @@ public: ErrCode CleanBundleTempDir(const std::string &bundleName) override; ErrCode HandleExtDisconnect(bool isIncBackup) override; ErrCode GetExtOnRelease(bool &isExtOnRelease) override; + ErrCode GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, + std::string &compatInfo) override; // 以下都是非IPC接口 public: diff --git a/services/backup_sa/src/module_external/bms_adapter.cpp b/services/backup_sa/src/module_external/bms_adapter.cpp index b5b2c0204..67eb26936 100644 --- a/services/backup_sa/src/module_external/bms_adapter.cpp +++ b/services/backup_sa/src/module_external/bms_adapter.cpp @@ -68,7 +68,7 @@ static sptr GetBundleManager() return iface_cast(bundleObj); } -static tuple GetAllowAndExtName( +static tuple GetAllowAndExtName( const vector &extensionInfos) { for (auto &&ext : extensionInfos) { @@ -84,9 +84,9 @@ static tuple GetAllowAndExtName BJsonCachedEntity cachedEntity(out[0], ext.bundleName); auto cache = cachedEntity.Structuralize(); return {cache.GetAllowToBackupRestore(), cache.GetFullBackupOnly(), ext.name, cache.GetRestoreDeps(), - cache.GetSupportScene(), cache.GetExtraInfo()}; + cache.GetSupportScene(), cache.GetExtraInfo(), cache.GetRequireCompatibility()}; } - return {false, false, "", "", "", Json::Value()}; + return {false, false, "", "", "", Json::Value(), false}; } static int64_t GetBundleStats(const string &bundleName, int32_t userId) @@ -135,7 +135,7 @@ vector BundleMgrAdapter::GetBundleInfos(const vecto HILOGE("Get current extension failed, bundleName:%{public}s", bundleName.c_str()); continue; } - auto [allToBackup, fullBackupOnly, extName, restoreDeps, supportScene, extraInfo] = + auto [allToBackup, fullBackupOnly, extName, restoreDeps, supportScene, extraInfo, requireCompatibility] = GetAllowAndExtName(bundleExtInfo.extensionInfos_); int64_t dataSize = 0; if (allToBackup) { @@ -143,7 +143,7 @@ vector BundleMgrAdapter::GetBundleInfos(const vecto } bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {bundleExtInfo.bundleInfo_.name, bundleExtInfo.bundleInfo_.appIndex, bundleExtInfo.bundleInfo_.versionCode, - bundleExtInfo.bundleInfo_.versionName, dataSize, 0, allToBackup, fullBackupOnly, + bundleExtInfo.bundleInfo_.versionName, dataSize, 0, allToBackup, fullBackupOnly, requireCompatibility, extName, restoreDeps, supportScene, extraInfo}); } HILOGI("End, bundleInfos size:%{public}zu", bundleInfos.size()); @@ -184,6 +184,7 @@ static bool GetBackupExtConfig(const vector &e backupPara.extraInfo = cache.GetExtraInfo(); backupPara.includes = cache.GetIncludes(); backupPara.excludes = cache.GetExcludes(); + backupPara.requireCompatibility = cache.GetRequireCompatibility(); return true; } return false; @@ -310,7 +311,8 @@ vector BundleMgrAdapter::GetBundleInfosForIncrement bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {bundleExtInfo.bundleInfo_.name, bundleExtInfo.bundleInfo_.appIndex, bundleExtInfo.bundleInfo_.versionCode, bundleExtInfo.bundleInfo_.versionName, 0, 0, backupPara.allToBackup, backupPara.fullBackupOnly, - backupPara.extensionName, backupPara.restoreDeps, backupPara.supportScene, backupPara.extraInfo}); + backupPara.requireCompatibility, backupPara.extensionName, backupPara.restoreDeps, backupPara.supportScene, + backupPara.extraInfo}); if (bundleExtInfo.bundleInfo_.appIndex > 0) { std::string bundleNameIndex = "+clone-" + std::to_string(bundleExtInfo.bundleInfo_.appIndex) + "+" + bundleExtInfo.bundleInfo_.name; @@ -349,12 +351,12 @@ vector BundleMgrAdapter::GetBundleInfosForIncrement HILOGI("Unsupported applications, name : %{public}s", installedBundle.name.data()); continue; } - auto [allToBackup, fullBackupOnly, extName, restoreDeps, supportScene, extraInfo] = + auto [allToBackup, fullBackupOnly, extName, restoreDeps, supportScene, extraInfo, requireCompatibility] = GetAllowAndExtName(installedBundle.extensionInfos); if (!allToBackup) { bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {installedBundle.name, installedBundle.appIndex, installedBundle.versionCode, installedBundle.versionName, 0, 0, allToBackup, fullBackupOnly, - extName, restoreDeps, supportScene, extraInfo}); + requireCompatibility, extName, restoreDeps, supportScene, extraInfo}); continue; } auto it = std::find_if(extraIncreData.begin(), extraIncreData.end(), @@ -404,13 +406,13 @@ vector BundleMgrAdapter::GetFullBundleInfos(int32_t bundleNames.emplace_back(bundleNameIndexInfo); continue; } - auto [allToBackup, fullBackupOnly, extName, restoreDeps, supportScene, extraInfo] = + auto [allToBackup, fullBackupOnly, extName, restoreDeps, supportScene, extraInfo, requireCompatibility] = GetAllowAndExtName(installedBundle.extensionInfos); if (!allToBackup) { HILOGI("Not allToBackup, bundleName = %{public}s", installedBundle.name.data()); bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {installedBundle.name, installedBundle.appIndex, - installedBundle.versionCode, installedBundle.versionName, 0, 0, allToBackup, fullBackupOnly, extName, - restoreDeps, supportScene, extraInfo}); + installedBundle.versionCode, installedBundle.versionName, 0, 0, allToBackup, fullBackupOnly, + requireCompatibility, extName, restoreDeps, supportScene, extraInfo}); continue; } bundleNames.emplace_back(installedBundle.name); @@ -464,7 +466,7 @@ std::vector BundleMgrAdapter::GetBundleInfosForSA() HILOGI("GetExtensionSaIds ret: %{public}d", ret); for (const auto &saId : saIds) { saBundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {std::to_string(saId), 0, 0, "", 0, 0, true, false, - "", "", "", ""}); + false, "", "", "", ""}); } return saBundleInfos; } @@ -493,7 +495,8 @@ void BundleMgrAdapter::GetBundleInfoForSA(std::string bundleName, std::vector BundleMgrAdapter::GetBundleInfosForLoca bundleNames.emplace_back(bundleNameIndexInfo); continue; } - auto [allToBackup, fullBackupOnly, extName, restoreDeps, supportScene, extraInfo] = + auto [allToBackup, fullBackupOnly, extName, restoreDeps, supportScene, extraInfo, requireCompatibility] = GetAllowAndExtName(installedBundle.extensionInfos); if (!allToBackup) { HILOGI("Not allToBackup, bundleName = %{public}s, appIndex = %{public}d", @@ -601,7 +604,7 @@ std::vector BundleMgrAdapter::GetBundleInfosForLoca bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo { installedBundle.name, installedBundle.appIndex, installedBundle.versionCode, installedBundle.versionName, - 0, 0, allToBackup, fullBackupOnly, + 0, 0, allToBackup, fullBackupOnly, requireCompatibility, extName, restoreDeps, supportScene, extraInfo}); } auto bundleInfosIndex = GetBundleInfosForIndex(bundleNames, userId); @@ -625,7 +628,7 @@ std::vector BundleMgrAdapter::GetBundleInfosForInde HILOGE("Get current extension failed, bundleName:%{public}s", bundleName.c_str()); continue; } - auto [allToBackup, fullBackupOnly, extName, restoreDeps, supportScene, extraInfo] = + auto [allToBackup, fullBackupOnly, extName, restoreDeps, supportScene, extraInfo, requireCompatibility] = GetAllowAndExtName(bundleExtInfo.extensionInfos_); if (!allToBackup) { HILOGI("Not allToBackup, bundleName = %{public}s, appIndex = %{public}d", @@ -635,7 +638,7 @@ std::vector BundleMgrAdapter::GetBundleInfosForInde bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo { bundleExtInfo.bundleInfo_.name, bundleExtInfo.bundleInfo_.appIndex, bundleExtInfo.bundleInfo_.versionCode, bundleExtInfo.bundleInfo_.versionName, - 0, 0, allToBackup, fullBackupOnly, + 0, 0, allToBackup, fullBackupOnly, requireCompatibility, extName, restoreDeps, supportScene, extraInfo}); } HILOGI("End, bundleInfos size:%{public}zu", bundleInfos.size()); @@ -699,7 +702,8 @@ std::vector BundleMgrAdapter::GetBundleInfosForAppe bundleInfos.emplace_back(BJsonEntityCaps::BundleInfo {bundleExtInfo.bundleInfo_.name, bundleExtInfo.bundleInfo_.appIndex, bundleExtInfo.bundleInfo_.versionCode, bundleExtInfo.bundleInfo_.versionName, 0, 0, backupPara.allToBackup, backupPara.fullBackupOnly, - backupPara.extensionName, backupPara.restoreDeps, backupPara.supportScene, backupPara.extraInfo}); + backupPara.requireCompatibility, backupPara.extensionName, backupPara.restoreDeps, backupPara.supportScene, + backupPara.extraInfo}); } for (const auto &info : incrementalDataList) { if (SAUtils::IsSABundleName(info.bundleName)) { diff --git a/services/backup_sa/src/module_ipc/sub_service.cpp b/services/backup_sa/src/module_ipc/sub_service.cpp index 897c9bf15..d26e879c5 100644 --- a/services/backup_sa/src/module_ipc/sub_service.cpp +++ b/services/backup_sa/src/module_ipc/sub_service.cpp @@ -1532,4 +1532,51 @@ void Service::HandleOnReleaseAndDisconnect(sptr sessionPtr, c proxy->HandleOnRelease(static_cast(sessionPtr->GetScenario())); sessionConnection->DisconnectBackupExtAbility(); } + +ErrCode Service::GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, + std::string &compatInfo) +{ + HILOGI("Service::GetCompatibilityInfo begin bundleName: %{public}s", bundleName.c_str()); + HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); + ErrCode err = VerifyCaller(); + if (err != ERR_OK) { + HILOGE("VerifyCaller failed"); + return err; + } + if (SAUtils::IsSABundleName(bundleName)) { + HILOGE("SA not support"); + return BError(BError::Codes::SA_INVAL_ARG); + } + if (session_ == nullptr) { + HILOGE("session is empty or busy"); + return BError(BError::Codes::SA_INVAL_ARG); + } + sptr backupConnection; + err = TryToConnectExt(bundleName, backupConnection); + if (err != BError(BError::Codes::OK)) { + return err; + } + std::unique_lock lock(getBackupInfoSyncLock_); + getBackupInfoCondition_.wait_for(lock, std::chrono::seconds(CONNECT_WAIT_TIME_S)); + if (isConnectDied_.load()) { + HILOGE("backupConnection connect timeout"); + isConnectDied_.store(false); + return BError(BError::Codes::EXT_ABILITY_DIED); + } + session_->IncreaseSessionCnt(__PRETTY_FUNCTION__); + auto proxy = backupConnection->GetBackupExtProxy(); + if (!proxy) { + HILOGE("Extension backup Proxy is empty."); + backupConnection->DisconnectBackupExtAbility(); + session_->DecreaseSessionCnt(__PRETTY_FUNCTION__); + return BError(BError::Codes::SA_INVAL_ARG); + } + err = proxy->HandleGetCompatibilityInfo(extInfo, static_cast(session_->GetScenario()), compatInfo); + if (err != BError(BError::Codes::OK)) { + HILOGE("HandleGetCompatibilityInfo failed"); + } + backupConnection->DisconnectBackupExtAbility(); + session_->DecreaseSessionCnt(__PRETTY_FUNCTION__); + return err; +} } \ No newline at end of file diff --git a/tests/mock/backup_ext/include/ext_backup_js_mock.h b/tests/mock/backup_ext/include/ext_backup_js_mock.h index fb59bfaa7..e8cf5e60c 100644 --- a/tests/mock/backup_ext/include/ext_backup_js_mock.h +++ b/tests/mock/backup_ext/include/ext_backup_js_mock.h @@ -52,8 +52,8 @@ public: virtual void ExportJsContext() = 0; virtual ErrCode OnRelease(std::function, int32_t scenario) = 0; virtual std::function &argv) ParseReleaseInfo() = 0; - virtual ErrCode GetBackupCompatibilityInfo(std::function , std::string) = 0; - virtual ErrCode GetRestoreCompatibilityInfo(std::function , std::string) = 0; + virtual ErrCode GetBackupCompatibilityInfo(std::function, std::string) = 0; + virtual ErrCode GetRestoreCompatibilityInfo(std::function, std::string) = 0; virtual std::function &argv) ParseCompatibilityInfo() = 0; public: virtual bool GetProfileFromAbility(const OHOS::AppExecFwk::AbilityInfo &, const std::string &, diff --git a/tests/mock/backup_ext/include/ext_backup_mock.h b/tests/mock/backup_ext/include/ext_backup_mock.h index 9687dcef1..909d706b2 100644 --- a/tests/mock/backup_ext/include/ext_backup_mock.h +++ b/tests/mock/backup_ext/include/ext_backup_mock.h @@ -53,8 +53,8 @@ public: virtual ErrCode GetParament(const AAFwk::Want &) = 0; virtual ErrCode OnProcess(std::function callback) = 0; virtual ErrCode OnRelease(std::function callback, int32_t scenario) = 0; - virtual ErrCode GetBackupCompatibilityInfo(std::function , std::string) = 0; - virtual ErrCode GetRestoreCompatibilityInfo(std::function , std::string) = 0; + virtual ErrCode GetBackupCompatibilityInfo(std::function, std::string) = 0; + virtual ErrCode GetRestoreCompatibilityInfo(std::function, std::string) = 0; public: virtual std::unique_ptr LoadSystemModuleByEngine(napi_env, const std::string&, const napi_value*, size_t) = 0; diff --git a/tests/mock/backup_kit_inner/service_proxy_mock.cpp b/tests/mock/backup_kit_inner/service_proxy_mock.cpp index fe62af42e..e605bfbf5 100644 --- a/tests/mock/backup_kit_inner/service_proxy_mock.cpp +++ b/tests/mock/backup_kit_inner/service_proxy_mock.cpp @@ -286,4 +286,10 @@ ErrCode ServiceProxy::GetExtOnRelease(bool &isExtOnRelease) { return BError(BError::Codes::OK); } + +ErrCode ServiceProxy::GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, + std::string &compatInfo) +{ + return BError(BError::Codes::OK); +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/mock/module_external/bms_adapter_mock.cpp b/tests/mock/module_external/bms_adapter_mock.cpp index 83f98eace..9694e08bc 100644 --- a/tests/mock/module_external/bms_adapter_mock.cpp +++ b/tests/mock/module_external/bms_adapter_mock.cpp @@ -32,7 +32,7 @@ vector BundleMgrAdapter::GetBundleInfos(const vecto { vector bundleInfos; bundleInfos.emplace_back( - BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, + BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, false, "com.example.app2backup"}); return bundleInfos; } @@ -47,7 +47,7 @@ vector BundleMgrAdapter::GetBundleInfosForIncrement { vector bundleInfos; bundleInfos.emplace_back( - BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, + BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, false, "com.example.app2backup"}); return bundleInfos; } @@ -57,7 +57,7 @@ vector BundleMgrAdapter::GetBundleInfosForIncrement { vector bundleInfos; bundleInfos.emplace_back( - BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, + BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, false, "com.example.app2backup"}); return bundleInfos; } @@ -67,7 +67,7 @@ vector BundleMgrAdapter::GetFullBundleInfos(int32_t { vector bundleInfos; bundleInfos.emplace_back( - BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, + BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, false, "com.example.app2backup"}); return bundleInfos; } @@ -87,7 +87,7 @@ vector BundleMgrAdapter::GetBundleInfosForAppend( { vector bundleInfos; bundleInfos.emplace_back( - BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, + BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, false, "com.example.app2backup"}); return bundleInfos; } @@ -96,7 +96,7 @@ std::vector BundleMgrAdapter::GetBundleInfosForLoca { vector bundleInfos; bundleInfos.emplace_back( - BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, + BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, false, "com.example.app2backup"}); return bundleInfos; } @@ -106,7 +106,7 @@ std::vector BundleMgrAdapter::GetBundleInfosForInde { vector bundleInfos; bundleInfos.emplace_back( - BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, + BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, false, "com.example.app2backup"}); return bundleInfos; } @@ -123,7 +123,7 @@ vector BundleMgrAdapter::GetBundleInfosForAppendBun { vector bundleInfos; bundleInfos.emplace_back( - BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, + BJsonEntityCaps::BundleInfo {"com.example.app2backup", 0, {}, {}, 0, 0, true, false, false, "com.example.app2backup"}); return bundleInfos; } diff --git a/tests/mock/module_ipc/service_mock.cpp b/tests/mock/module_ipc/service_mock.cpp index ed5c558fe..ff713dbb0 100644 --- a/tests/mock/module_ipc/service_mock.cpp +++ b/tests/mock/module_ipc/service_mock.cpp @@ -450,4 +450,10 @@ ErrCode Service::GetExtOnRelease(bool &isExtOnRelease) { return BError(BError::Codes::OK); } + +ErrCode Service::GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, + std::string &compatInfo) +{ + return BError(BError::Codes::OK); +} } // namespace OHOS::FileManagement::Backup diff --git a/tests/moduletests/backup_kit_inner/b_session_backup_test.cpp b/tests/moduletests/backup_kit_inner/b_session_backup_test.cpp index 727593169..5c616fb12 100644 --- a/tests/moduletests/backup_kit_inner/b_session_backup_test.cpp +++ b/tests/moduletests/backup_kit_inner/b_session_backup_test.cpp @@ -509,4 +509,35 @@ HWTEST_F(BSessionBackupTest, SUB_backup_b_session_backup_1300, testing::ext::Tes } GTEST_LOG_(INFO) << "BSessionBackupTest-end SUB_backup_b_session_backup_1300"; } + +/** + * @tc.number: SUB_BSessionBackup_GetCompatibilityInfo_0000 + * @tc.name: SUB_BSessionBackup_GetCompatibilityInfo_0000 + * @tc.desc: 测试 GetCompatibilityInfo 接口 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: NA + */ +HWTEST_F(BSessionBackupTest, SUB_BSessionBackup_GetCompatibilityInfo_0000, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BSessionBackupTest-begin SUB_BSessionBackup_GetCompatibilityInfo_0000"; + try { + ASSERT_TRUE(backupPtr_ != nullptr); + std::string bundleName = "com.example.app"; + std::string extInfo = ""; + std::string compatInfo = ""; + SetMockGetInstance(false); + auto err = backupPtr_->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(err, BError(BError::Codes::SDK_BROKEN_IPC).GetCode()); + + SetMockGetInstance(true); + err = backupPtr_->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(err, ERR_OK); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "BSessionBackupTest-an exception occurred by GetCompatibilityInfo."; + } + GTEST_LOG_(INFO) << "BSessionBackupTest-end SUB_BSessionBackup_GetCompatibilityInfo_0000"; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/moduletests/backup_kit_inner/b_session_restore_test.cpp b/tests/moduletests/backup_kit_inner/b_session_restore_test.cpp index cfac6d5a4..526da2354 100644 --- a/tests/moduletests/backup_kit_inner/b_session_restore_test.cpp +++ b/tests/moduletests/backup_kit_inner/b_session_restore_test.cpp @@ -545,4 +545,35 @@ HWTEST_F(BSessionRestoreTest, SUB_backup_b_session_restore_1200, testing::ext::T } GTEST_LOG_(INFO) << "BSessionRestoreTest-end SUB_backup_b_session_restore_1200"; } + +/** + * @tc.number: SUB_BSessionRestore_GetCompatibilityInfo_0000 + * @tc.name: SUB_BSessionRestore_GetCompatibilityInfo_0000 + * @tc.desc: 测试 GetCompatibilityInfo 接口 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: NA + */ +HWTEST_F(BSessionRestoreTest, SUB_BSessionRestore_GetCompatibilityInfo_0000, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "BSessionRestoreTest-begin SUB_BSessionRestore_GetCompatibilityInfo_0000"; + try { + ASSERT_TRUE(restorePtr_ != nullptr); + std::string bundleName = "com.example.app"; + std::string extInfo = ""; + std::string compatInfo = ""; + SetMockGetInstance(false); + auto err = restorePtr_->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(err, BError(BError::Codes::SDK_BROKEN_IPC).GetCode()); + + SetMockGetInstance(true); + err = restorePtr_->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(err, ERR_OK); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "BSessionRestoreTest-an exception occurred by GetCompatibilityInfo."; + } + GTEST_LOG_(INFO) << "BSessionRestoreTest-end SUB_BSessionRestore_GetCompatibilityInfo_0000"; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/unittests/backup_api/backup_impl/include/i_service_mock.h b/tests/unittests/backup_api/backup_impl/include/i_service_mock.h index 7f2c4e24a..6745527d4 100644 --- a/tests/unittests/backup_api/backup_impl/include/i_service_mock.h +++ b/tests/unittests/backup_api/backup_impl/include/i_service_mock.h @@ -282,6 +282,11 @@ public: { return BError(BError::Codes::OK); }; + + ErrCode GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, std::string &compatInfo) + { + return BError(BError::Codes::OK); + } }; } // namespace OHOS::FileManagement::Backup #endif // MOCK_I_SERVICE_MOCK_H \ No newline at end of file diff --git a/tests/unittests/backup_sa/module_ipc/service_incremental_test.cpp b/tests/unittests/backup_sa/module_ipc/service_incremental_test.cpp index 314bcd047..918949c97 100644 --- a/tests/unittests/backup_sa/module_ipc/service_incremental_test.cpp +++ b/tests/unittests/backup_sa/module_ipc/service_incremental_test.cpp @@ -81,6 +81,7 @@ public: virtual ErrCode GetExtOnRelease(bool&) = 0; virtual void SetExtOnRelease(const BundleName&, bool) = 0; virtual void RemoveExtOnRelease(const BundleName&) = 0; + virtual ErrCode GetCompatibilityInfo(const std::string&, const std::string&, std::string&) = 0; public: virtual bool UpdateToRestoreBundleMap(const string&, const string&) = 0; public: @@ -141,6 +142,7 @@ public: MOCK_METHOD(ErrCode, GetExtOnRelease, (bool&)); MOCK_METHOD(void, SetExtOnRelease, (const BundleName&, bool)); MOCK_METHOD(void, RemoveExtOnRelease, (const BundleName&)); + MOCK_METHOD(ErrCode, GetCompatibilityInfo, (const std::string&, const std::string&, std::string&)); public: MOCK_METHOD(bool, UpdateToRestoreBundleMap, (const string&, const string&)); }; @@ -478,6 +480,12 @@ void Service::RemoveExtOnRelease(const BundleName &bundleName) { return BService::serviceMock->RemoveExtOnRelease(bundleName); } + +ErrCode Service::GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, + std::string &compatInfo) +{ + return BService::serviceMock->GetCompatibilityInfo(bundleName, extInfo, compatInfo); +} } // namespace OHOS::FileManagement::Backup namespace OHOS::FileManagement::Backup { diff --git a/tests/unittests/backup_sa/module_ipc/service_other_test.cpp b/tests/unittests/backup_sa/module_ipc/service_other_test.cpp index 8dd2ecd81..57a64d87f 100644 --- a/tests/unittests/backup_sa/module_ipc/service_other_test.cpp +++ b/tests/unittests/backup_sa/module_ipc/service_other_test.cpp @@ -947,7 +947,7 @@ HWTEST_F(ServiceTest, SUB_Service_SetCurrentSessProperties_0100, TestSize.Level1 service->session_ = sptr(new SvcSessionManager(wptr(service))); service->SetCurrentSessProperties(info, isClearDataFlags, bundleNameIndexInfo); - info = BJsonEntityCaps::BundleInfo{BUNDLE_NAME, 0, {}, {}, 0, 0, true, false, BUNDLE_NAME}; + info = BJsonEntityCaps::BundleInfo {BUNDLE_NAME, 0, {}, {}, 0, 0, true, false, false, BUNDLE_NAME}; isClearDataFlags = {{BUNDLE_NAME, true}}; service->SetCurrentSessProperties(info, isClearDataFlags, bundleNameIndexInfo); } catch (...) { diff --git a/tests/unittests/backup_sa/module_ipc/sub_service_test.cpp b/tests/unittests/backup_sa/module_ipc/sub_service_test.cpp index 9c4d3fb16..161dfe7c5 100644 --- a/tests/unittests/backup_sa/module_ipc/sub_service_test.cpp +++ b/tests/unittests/backup_sa/module_ipc/sub_service_test.cpp @@ -2177,4 +2177,145 @@ HWTEST_F(ServiceTest, SUB_Service_GetExtOnRelease_0200, testing::ext::TestSize.L GTEST_LOG_(INFO) << "ServiceTest-an exception occurred by GetExtOnRelease."; } GTEST_LOG_(INFO) << "ServiceTest-end SUB_Service_GetExtOnRelease_0200"; +} + +/** + * @tc.number: SUB_Service_GetCompatibilityInfo_0000 + * @tc.name: SUB_Service_GetCompatibilityInfo_0000 + * @tc.desc: 测试 GetCompatibilityInfo 的正常/异常分支 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: NA + */ +HWTEST_F(ServiceTest, SUB_Service_GetCompatibilityInfo_0000, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ServiceTest-begin SUB_Service_GetCompatibilityInfo_0000"; + try { + std::string bundleName = "com.ohos.test"; + std::string extInfo = ""; + std::string compatInfo = ""; + + EXPECT_CALL(*skeleton, GetCallingTokenID()).WillRepeatedly(Return(0)); + EXPECT_CALL(*token, GetTokenType(_)) + .WillRepeatedly(Return(Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE)); + EXPECT_CALL(*token, VerifyAccessToken(_, _)) + .WillOnce(Return(Security::AccessToken::PermissionState::PERMISSION_DENIED)) + .WillRepeatedly(Return(Security::AccessToken::PermissionState::PERMISSION_GRANTED)); + EXPECT_CALL(*param, GetBackupDebugOverrideAccount()) + .WillRepeatedly(Return(make_pair(true, DEBUG_ID + 1))); + EXPECT_CALL(*saUtils, IsSABundleName(_)).WillOnce(Return(true)); + + int res = service->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(res, BError(BError::Codes::SA_REFUSED_ACT).GetCode()); + + res = service->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(res, BError(BError::Codes::SA_INVAL_ARG).GetCode()); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "ServiceTest-an exception occurred by GetCompatibilityInfo."; + } + GTEST_LOG_(INFO) << "ServiceTest-end SUB_Service_GetCompatibilityInfo_0000"; +} + +/** + * @tc.number: SUB_Service_GetCompatibilityInfo_0100 + * @tc.name: SUB_Service_GetCompatibilityInfo_0100 + * @tc.desc: 测试 GetCompatibilityInfo 的正常/异常分支 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: NA + */ +HWTEST_F(ServiceTest, SUB_Service_GetCompatibilityInfo_0100, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ServiceTest-begin SUB_Service_GetCompatibilityInfo_0100"; + try { + std::string bundleName = "com.ohos.test"; + std::string extInfo = ""; + std::string compatInfo = ""; + + EXPECT_CALL(*skeleton, GetCallingTokenID()).WillRepeatedly(Return(0)); + EXPECT_CALL(*token, GetTokenType(_)) + .WillRepeatedly(Return(Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE)); + EXPECT_CALL(*token, VerifyAccessToken(_, _)) + .WillRepeatedly(Return(Security::AccessToken::PermissionState::PERMISSION_GRANTED)); + EXPECT_CALL(*param, GetBackupDebugOverrideAccount()) + .WillRepeatedly(Return(make_pair(true, DEBUG_ID + 1))); + EXPECT_CALL(*saUtils, IsSABundleName(_)).WillRepeatedly(Return(false)); + + auto session_ = service->session_; + service->session_ = nullptr; + int res = service->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(res, BError(BError::Codes::SA_INVAL_ARG).GetCode()); + service->session_ = session_; + + EXPECT_CALL(*session, GetExtConnection(_)).WillOnce(Return(nullptr)); + EXPECT_CALL(*session, CreateBackupConnection(_)).WillOnce(Return(nullptr)); + res = service->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(res, BError(BError::Codes::SA_INVAL_ARG).GetCode()); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "ServiceTest-an exception occurred by GetCompatibilityInfo."; + } + GTEST_LOG_(INFO) << "ServiceTest-end SUB_Service_GetCompatibilityInfo_0100"; +} + +/** + * @tc.number: SUB_Service_GetCompatibilityInfo_0200 + * @tc.name: SUB_Service_GetCompatibilityInfo_0200 + * @tc.desc: 测试 GetCompatibilityInfo 的正常/异常分支 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: NA + */ +HWTEST_F(ServiceTest, SUB_Service_GetCompatibilityInfo_0200, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ServiceTest-begin SUB_Service_GetCompatibilityInfo_0200"; + try { + std::string bundleName = "com.ohos.test"; + std::string extInfo = ""; + std::string compatInfo = ""; + + EXPECT_CALL(*skeleton, GetCallingTokenID()).WillRepeatedly(Return(0)); + EXPECT_CALL(*token, GetTokenType(_)) + .WillRepeatedly(Return(Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE)); + EXPECT_CALL(*token, VerifyAccessToken(_, _)) + .WillRepeatedly(Return(Security::AccessToken::PermissionState::PERMISSION_GRANTED)); + EXPECT_CALL(*param, GetBackupDebugOverrideAccount()) + .WillRepeatedly(Return(make_pair(true, DEBUG_ID + 1))); + EXPECT_CALL(*saUtils, IsSABundleName(_)).WillRepeatedly(Return(false)); + + auto callDied = [](const string &&bundleName, bool isCleanCalled) {}; + auto callConnected = [](const string &&bundleName) {}; + auto connectPtr = sptr(new SvcBackupConnection(callDied, callConnected, bundleName)); + EXPECT_CALL(*session, GetExtConnection(_)).WillRepeatedly(Return(wptr(connectPtr))); + EXPECT_CALL(*connect, IsExtAbilityConnected()).WillRepeatedly(Return(true)); + service->isConnectDied_ = true; + int res = service->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(res, BError(BError::Codes::EXT_ABILITY_DIED).GetCode()); + + service->isConnectDied_ = false; + EXPECT_CALL(*connect, GetBackupExtProxy()) + .WillOnce(Return(nullptr)) + .WillRepeatedly(Return(svcProxy)); + EXPECT_CALL(*connect, DisconnectBackupExtAbility()).WillRepeatedly(Return(BError(BError::Codes::OK).GetCode())); + res = service->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(res, BError(BError::Codes::SA_INVAL_ARG).GetCode()); + + EXPECT_CALL(*svcProxy, HandleGetCompatibilityInfo(_, _, _)) + .WillOnce(Return(BError(BError::Codes::SA_INVAL_ARG).GetCode())); + res = service->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(res, BError(BError::Codes::SA_INVAL_ARG).GetCode()); + + EXPECT_CALL(*svcProxy, HandleGetCompatibilityInfo(_, _, _)) + .WillOnce(Return(BError(BError::Codes::OK).GetCode())); + res = service->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(res, BError(BError::Codes::OK).GetCode()); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "ServiceTest-an exception occurred by GetCompatibilityInfo."; + } + GTEST_LOG_(INFO) << "ServiceTest-end SUB_Service_GetCompatibilityInfo_0200"; } \ No newline at end of file diff --git a/tests/unittests/backup_sa/session/b_incremental_session_test.cpp b/tests/unittests/backup_sa/session/b_incremental_session_test.cpp index 6cfb25ca4..817879ecb 100644 --- a/tests/unittests/backup_sa/session/b_incremental_session_test.cpp +++ b/tests/unittests/backup_sa/session/b_incremental_session_test.cpp @@ -973,4 +973,80 @@ HWTEST_F(IncrementalSessionTest, SUB_b_incremental_session_test_2900, testing::e } GTEST_LOG_(INFO) << "IncrementalSessionTest-end SUB_b_incremental_session_test_2900"; } + +/** + * @tc.number: SUB_BIncrementalBackupSession_GetCompatibilityInfo_0000 + * @tc.name: SUB_BIncrementalBackupSession_GetCompatibilityInfo_0000 + * @tc.desc: 测试 GetCompatibilityInfo 接口 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: NA + */ +HWTEST_F(IncrementalSessionTest, SUB_BIncrementalBackupSession_GetCompatibilityInfo_0000, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IncrementalSessionTest-begin SUB_BIncrementalBackupSession_GetCompatibilityInfo_0000"; + try { + std::string bundleName = "com.example.app"; + std::string extInfo = ""; + std::string compatInfo = ""; + + ServiceClient::serviceProxy_ = nullptr; + ASSERT_TRUE(backupSession != nullptr); + auto err = backupSession->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(err, BError(BError::Codes::SDK_BROKEN_IPC).GetCode()); + + ServiceClient::serviceProxy_ = proxy; + EXPECT_CALL(*proxy, GetCompatibilityInfo(_, _, _)) + .WillOnce(Return(BError(BError::Codes::SDK_INVAL_ARG).GetCode())); + err = backupSession->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(err, BError(BError::Codes::SDK_INVAL_ARG).GetCode()); + + EXPECT_CALL(*proxy, GetCompatibilityInfo(_, _, _)).WillOnce(Return(BError(BError::Codes::OK).GetCode())); + err = backupSession->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(err, ERROR_OK); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "IncrementalSessionTest-an exception occurred by GetCompatibilityInfo."; + } + GTEST_LOG_(INFO) << "IncrementalSessionTest-end SUB_BIncrementalBackupSession_GetCompatibilityInfo_0000"; +} + +/** + * @tc.number: SUB_BIncrementalStoreSession_GetCompatibilityInfo_0000 + * @tc.name: SUB_BIncrementalStoreSession_GetCompatibilityInfo_0000 + * @tc.desc: 测试 GetCompatibilityInfo 接口 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: NA + */ +HWTEST_F(IncrementalSessionTest, SUB_BIncrementalStoreSession_GetCompatibilityInfo_0000, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IncrementalSessionTest-begin SUB_BIncrementalStoreSession_GetCompatibilityInfo_0000"; + try { + std::string bundleName = "com.example.app"; + std::string extInfo = ""; + std::string compatInfo = ""; + + ServiceClient::serviceProxy_ = nullptr; + ASSERT_TRUE(restoreSession != nullptr); + auto err = restoreSession->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(err, BError(BError::Codes::SDK_BROKEN_IPC).GetCode()); + + ServiceClient::serviceProxy_ = proxy; + EXPECT_CALL(*proxy, GetCompatibilityInfo(_, _, _)) + .WillOnce(Return(BError(BError::Codes::SDK_INVAL_ARG).GetCode())); + err = restoreSession->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(err, BError(BError::Codes::SDK_INVAL_ARG).GetCode()); + + EXPECT_CALL(*proxy, GetCompatibilityInfo(_, _, _)).WillOnce(Return(BError(BError::Codes::OK).GetCode())); + err = restoreSession->GetCompatibilityInfo(bundleName, extInfo, compatInfo); + EXPECT_EQ(err, ERROR_OK); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "IncrementalSessionTest-an exception occurred by GetCompatibilityInfo."; + } + GTEST_LOG_(INFO) << "IncrementalSessionTest-end SUB_BIncrementalStoreSession_GetCompatibilityInfo_0000"; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/unittests/backup_sa/session/service_proxy_mock.cpp b/tests/unittests/backup_sa/session/service_proxy_mock.cpp index 19d658f02..f07378af4 100644 --- a/tests/unittests/backup_sa/session/service_proxy_mock.cpp +++ b/tests/unittests/backup_sa/session/service_proxy_mock.cpp @@ -260,4 +260,10 @@ ErrCode ServiceProxy::GetExtOnRelease(bool &isExtOnRelease) { return BError(BError::Codes::OK); } + +ErrCode ServiceProxy::GetCompatibilityInfo(const std::string &bundleName, const std::string &extInfo, + std::string &compatInfo) +{ + return BError(BError::Codes::OK); +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/unittests/backup_sa/session/service_proxy_mock.h b/tests/unittests/backup_sa/session/service_proxy_mock.h index b5675cf8e..40271c70d 100644 --- a/tests/unittests/backup_sa/session/service_proxy_mock.h +++ b/tests/unittests/backup_sa/session/service_proxy_mock.h @@ -77,6 +77,7 @@ public: MOCK_METHOD1(CleanBundleTempDir, ErrCode(const std::string &bundleName)); MOCK_METHOD1(HandleExtDisconnect, ErrCode(bool isIncBackup)); MOCK_METHOD1(GetExtOnRelease, ErrCode(bool &isExtOnRelease)); + MOCK_METHOD3(GetCompatibilityInfo, ErrCode(const std::string&, const std::string&, std::string&)); }; } // End of namespace OHOS::FileManagement::Backup #endif // TEST_UNITTEST_SERVICE_PROXY_MOCK_H diff --git a/tests/unittests/backup_utils/b_json/b_json_entity_extension_config_test.cpp b/tests/unittests/backup_utils/b_json/b_json_entity_extension_config_test.cpp index 3da3ab4c1..e91e5663f 100644 --- a/tests/unittests/backup_utils/b_json/b_json_entity_extension_config_test.cpp +++ b/tests/unittests/backup_utils/b_json/b_json_entity_extension_config_test.cpp @@ -1037,4 +1037,47 @@ HWTEST_F(BJsonEntityExtensionConfigTest, b_json_entity_extension_config_3700, te } GTEST_LOG_(INFO) << "BJsonEntityExtensionConfigTest-end b_json_entity_extension_config_3700"; } + +/** + * @tc.number: SUB_backup_b_json_entity_extension_config_3800 + * @tc.name: backup_b_json_entity_extension_config_3800 + * @tc.desc: 测试GetRequireCompatibility接口能否成功返回 + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 2 + * @tc.require: NA + */ +HWTEST_F(BJsonEntityExtensionConfigTest, backup_b_json_entity_extension_config_3800, testing::ext::TestSize.Level2) +{ + GTEST_LOG_(INFO) << "BJsonEntityExtensionConfigTest-begin backup_b_json_entity_extension_config_3800"; + try { + string_view sv1 = R"({"":true})"; + BJsonCachedEntity cachedEntity1(sv1); + auto cache1 = cachedEntity1.Structuralize(); + bool ret = cache1.GetRequireCompatibility(); + EXPECT_FALSE(ret); + + string_view sv2 = R"({"requireCompatibility1":true})"; + BJsonCachedEntity cachedEntity2(sv2); + auto cache2 = cachedEntity2.Structuralize(); + ret = cache2.GetRequireCompatibility(); + EXPECT_FALSE(ret); + + string_view sv3 = R"({"requireCompatibility":123})"; + BJsonCachedEntity cachedEntity3(sv3); + auto cache3 = cachedEntity3.Structuralize(); + ret = cache3.GetRequireCompatibility(); + EXPECT_FALSE(ret); + + string_view sv4 = R"({"requireCompatibility":true})"; + BJsonCachedEntity cachedEntity4(sv4); + auto cache4 = cachedEntity4.Structuralize(); + ret = cache4.GetRequireCompatibility(); + EXPECT_TRUE(ret); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "BJsonEntityExtensionConfigTest-an exception occurred by GetRequireCompatibility."; + } + GTEST_LOG_(INFO) << "BJsonEntityExtensionConfigTest-end backup_b_json_entity_extension_config_3800"; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/utils/include/b_json/b_json_entity_caps.h b/utils/include/b_json/b_json_entity_caps.h index 1321ecde5..eabbf02ad 100644 --- a/utils/include/b_json/b_json_entity_caps.h +++ b/utils/include/b_json/b_json_entity_caps.h @@ -31,6 +31,7 @@ public: int64_t increSpaceOccupied; bool allToBackup; bool fullBackupOnly; + bool requireCompatibility; std::string extensionName; std::string restoreDeps; std::string supportScene; @@ -39,6 +40,7 @@ public: struct BundleBackupConfigPara { bool allToBackup; bool fullBackupOnly; + bool requireCompatibility; std::string extensionName; std::string restoreDeps; std::string supportScene; @@ -84,6 +86,7 @@ public: } arrObj["allToBackup"] = item.allToBackup; arrObj["fullBackupOnly"] = item.fullBackupOnly; + arrObj["requireCompatibility"] = item.requireCompatibility; arrObj["extensionName"] = item.extensionName; arrObj["restoreDeps"] = item.restoreDeps; arrObj["supportScene"] = item.supportScene; @@ -233,6 +236,10 @@ public: if (item.isMember("fullBackupOnly") && item["fullBackupOnly"].isBool()) { fullBackupOnly = item["fullBackupOnly"].asBool(); } + bool requireCompatibility = false; + if (item.isMember("requireCompatibility") && item["requireCompatibility"].isBool()) { + requireCompatibility = item["requireCompatibility"].asBool(); + } int appIndex = 0; if (item.isMember("appIndex") && item["appIndex"].isInt()) { appIndex = item["appIndex"].asInt(); @@ -244,7 +251,7 @@ public: bundleInfos.emplace_back(BundleInfo {item["name"].asString(), appIndex, item["versionCode"].asInt64(), item["versionName"].asString(), item["spaceOccupied"].asInt64(), increSpaceOccupied, item["allToBackup"].asBool(), fullBackupOnly, - item["extensionName"].asString(), + requireCompatibility, item["extensionName"].asString(), restoreDeps, supportScene, extraInfo}); } return bundleInfos; diff --git a/utils/include/b_json/b_json_entity_extension_config.h b/utils/include/b_json/b_json_entity_extension_config.h index 80177038e..8523f2e93 100644 --- a/utils/include/b_json/b_json_entity_extension_config.h +++ b/utils/include/b_json/b_json_entity_extension_config.h @@ -76,6 +76,13 @@ public: */ Json::Value GetExtraInfo() const; + /** + * @brief 从JSon对象中获取兼容能力标志 + * + * @return 兼容标志: 应用是否要做兼容处理 + */ + bool GetRequireCompatibility() const; + public: std::string GetJSonSource(std::string_view jsonFromRealWorld, std::any option); diff --git a/utils/src/b_json/b_json_entity_extension_config.cpp b/utils/src/b_json/b_json_entity_extension_config.cpp index a6e639d51..6f17cf0da 100644 --- a/utils/src/b_json/b_json_entity_extension_config.cpp +++ b/utils/src/b_json/b_json_entity_extension_config.cpp @@ -179,4 +179,15 @@ string BJsonEntityExtensionConfig::GetRestoreDeps() const return obj_["restoreDeps"].asString(); } +bool BJsonEntityExtensionConfig::GetRequireCompatibility() const +{ + if (!obj_ || !obj_.isMember("requireCompatibility") || !obj_["requireCompatibility"].isBool()) { + HILOGD("Failed to get field requireCompatibility"); + return false; + } + + return obj_["requireCompatibility"].asBool(); +} + + } // namespace OHOS::FileManagement::Backup -- Gitee From 9261024110886a5247d3f9216e6792050176569a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=95=E6=8C=AF=E6=9D=B0?= Date: Fri, 4 Jul 2025 16:50:27 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=8F=98=E9=87=8F=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 吕振杰 --- frameworks/native/backup_ext/include/ext_backup_js.h | 2 +- frameworks/native/backup_ext/include/ext_extension.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frameworks/native/backup_ext/include/ext_backup_js.h b/frameworks/native/backup_ext/include/ext_backup_js.h index c80ad2f8f..6f87145cc 100644 --- a/frameworks/native/backup_ext/include/ext_backup_js.h +++ b/frameworks/native/backup_ext/include/ext_backup_js.h @@ -203,7 +203,7 @@ private: int32_t scenario_ { 0 }; std::shared_ptr getComInfoCallbackEx_; - std::string extInfo_; + std::string extInfo_ {}; }; } // 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 4a2abed45..cbc5b9c49 100644 --- a/frameworks/native/backup_ext/include/ext_extension.h +++ b/frameworks/native/backup_ext/include/ext_extension.h @@ -460,10 +460,10 @@ private: ErrCode appResultReportErrCode_ { 0 }; std::mutex serviceCallReleaseLock_; - std::mutex getCompatibilityInfoLock_; - std::condition_variable getCompatibilityInfoCon_; + std::mutex getCompatibilityInfoLock_ {}; + std::condition_variable getCompatibilityInfoCon_ {}; std::atomic stopGetComInfo_ {false}; - std::string compatibilityInfo_; + std::string compatibilityInfo_ {}; }; } // namespace OHOS::FileManagement::Backup -- Gitee