diff --git a/frameworks/native/ability/ability_runtime/ability_context_impl.cpp b/frameworks/native/ability/ability_runtime/ability_context_impl.cpp index 07ee28e0361c6547bcea207f90cfa0b3cc1f8163..67f00f1379ad10f7dc1307c9318f765ccb601c66 100644 --- a/frameworks/native/ability/ability_runtime/ability_context_impl.cpp +++ b/frameworks/native/ability/ability_runtime/ability_context_impl.cpp @@ -1205,6 +1205,12 @@ ErrCode AbilityContextImpl::OpenAtomicService(AAFwk::Want& want, const AAFwk::St if (err != ERR_OK && err != AAFwk::START_ABILITY_WAITING) { TAG_LOGE(AAFwkTag::CONTEXT, "failed, ret=%{public}d", err); OnAbilityResultInner(requestCode, err, want); + if (!options.requestId_.empty()) { + nlohmann::json jsonObject = nlohmann::json { + { JSON_KEY_ERR_MSG, "failed to call openAtomicService" }, + }; + OnRequestFailure(options.requestId_, want.GetElement(), jsonObject.dump()); + } } return err; } diff --git a/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp b/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp index 1ee51b9bb9e166fa1be793af61bd3cdac36bdbb6..45b72b10af2b1a84d91149d653881a2eaba68962 100644 --- a/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp +++ b/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -2942,6 +2942,7 @@ napi_value JsAbilityContext::OnOpenAtomicService(napi_env env, NapiCallbackInfo& ThrowInvalidParamError(env, "Parse param startOptions failed, startOptions must be StartOption."); return CreateJsUndefined(env); } + UnwrapCompletionHandlerInStartOptions(env, info.argv[INDEX_ONE], startOptions); } std::string bundleName = ATOMIC_SERVICE_PREFIX + appId; diff --git a/frameworks/native/ability/native/extension.cpp b/frameworks/native/ability/native/extension.cpp index 259c13cfeaa580ae1c1600f11a22328d8d0559f1..0fb8e87300acfccc54398d118901b9afe494cb62 100644 --- a/frameworks/native/ability/native/extension.cpp +++ b/frameworks/native/ability/native/extension.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -201,8 +201,17 @@ bool Extension::HandleInsightIntent(const AAFwk::Want &want) bool Extension::OnInsightIntentExecuteDone(uint64_t intentId, const AppExecFwk::InsightIntentExecuteResult &result) { - TAG_LOGD(AAFwkTag::EXT, "call"); return true; } + +void Extension::OnExtensionAbilityRequestFailure(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) +{ +} + +void Extension::OnExtensionAbilityRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) +{ +} } } diff --git a/frameworks/native/ability/native/extension_ability_thread.cpp b/frameworks/native/ability/native/extension_ability_thread.cpp index 5ecc8cf6f2175692165a4461f6a8b880080171c1..d44ae3c67615c78da09d48d845b56d48fc559aad 100644 --- a/frameworks/native/ability/native/extension_ability_thread.cpp +++ b/frameworks/native/ability/native/extension_ability_thread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -614,6 +614,60 @@ void ExtensionAbilityThread::DumpAbilityInfo(const std::vector &par TAG_LOGD(AAFwkTag::EXT, "End"); } +void ExtensionAbilityThread::ScheduleAbilityRequestFailure(const std::string &requestId, + const AppExecFwk::ElementName &element, const std::string &message) +{ + TAG_LOGD(AAFwkTag::EXT, "ExtensionAbilityThread::ScheduleAbilityRequestFailure called"); + if (extensionImpl_ == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "null extensionImpl_"); + return; + } + wptr weak = this; + auto task = [weak, requestId, element, message]() { + auto extensionAbilityThread = weak.promote(); + if (extensionAbilityThread == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "null extensionAbilityThread"); + return; + } + if (extensionAbilityThread->extensionImpl_ != nullptr) { + extensionAbilityThread->extensionImpl_->ScheduleAbilityRequestFailure(requestId, element, message); + return; + } + }; + bool ret = abilityHandler_->PostTask(task, "ExtensionAbilityThread:ScheduleAbilityRequestFailure"); + if (!ret) { + TAG_LOGE(AAFwkTag::EXT, "postTask error"); + return; + } +} + +void ExtensionAbilityThread::ScheduleAbilityRequestSuccess(const std::string &requestId, + const AppExecFwk::ElementName &element) +{ + TAG_LOGD(AAFwkTag::EXT, "ExtensionAbilityThread::ScheduleAbilityRequestSuccess called"); + if (extensionImpl_ == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "null extensionImpl_"); + return; + } + wptr weak = this; + auto task = [weak, requestId, element]() { + auto extensionAbilityThread = weak.promote(); + if (extensionAbilityThread == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "null extensionAbilityThread"); + return; + } + if (extensionAbilityThread->extensionImpl_ != nullptr) { + extensionAbilityThread->extensionImpl_->ScheduleAbilityRequestSuccess(requestId, element); + return; + } + }; + bool ret = abilityHandler_->PostTask(task, "ExtensionAbilityThread:ScheduleAbilityRequestSuccess"); + if (!ret) { + TAG_LOGE(AAFwkTag::EXT, "postTask error"); + return; + } +} + void ExtensionAbilityThread::DumpAbilityInfoInner( const std::vector ¶ms, std::vector &info) { diff --git a/frameworks/native/ability/native/extension_impl.cpp b/frameworks/native/ability/native/extension_impl.cpp index ea559e946cdf73b21f258f608469de932edbc04b..1733397a6a66df3e2cb98c6376d347f582f3ebcf 100644 --- a/frameworks/native/ability/native/extension_impl.cpp +++ b/frameworks/native/ability/native/extension_impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -28,6 +28,7 @@ namespace OHOS { namespace AbilityRuntime { +const std::string JSON_KEY_ERR_MSG = "errMsg"; ExtensionImpl::~ExtensionImpl() { TAG_LOGI(AAFwkTag::EXT, "~ExtensionImpl"); @@ -469,6 +470,30 @@ void ExtensionImpl::SetLaunchParam(const AAFwk::LaunchParam &launchParam) extension_->SetLaunchParam(launchParam); } +void ExtensionImpl::ScheduleAbilityRequestFailure(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) +{ + TAG_LOGD(AAFwkTag::EXT, "ScheduleAbilityRequestFailure called"); + if (extension_ == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "null extension_"); + return; + } + extension_->OnExtensionAbilityRequestFailure(requestId, element, message); +} + +void ExtensionImpl::ScheduleAbilityRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element) +{ + TAG_LOGD(AAFwkTag::EXT, "ScheduleAbilityRequestSuccess called"); + if (extension_ == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "null ability_"); + return; + } + nlohmann::json jsonObject = nlohmann::json { + { JSON_KEY_ERR_MSG, "Succeeded" }, + }; + extension_->OnExtensionAbilityRequestSuccess(requestId, element, jsonObject.dump()); +} + void ExtensionImpl::Foreground(const Want &want, sptr sessionInfo) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); diff --git a/frameworks/native/ability/native/js_service_extension_context.cpp b/frameworks/native/ability/native/js_service_extension_context.cpp index 0458470579360be8230b8e69d5a519ffa40e517d..7cb500eb22bf374db8ef6da3d41b1203e49fee58 100644 --- a/frameworks/native/ability/native/js_service_extension_context.cpp +++ b/frameworks/native/ability/native/js_service_extension_context.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2024 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -53,6 +53,7 @@ constexpr size_t ARGC_TWO = 2; constexpr size_t ARGC_THREE = 3; constexpr size_t ARGC_FOUR = 4; constexpr const char* ATOMIC_SERVICE_PREFIX = "com.atomicservice."; +const std::string JSON_KEY_ERR_MSG = "errMsg"; class StartAbilityByCallParameters { public: @@ -388,6 +389,58 @@ private: return result; } + + void UnwrapCompletionHandlerInStartOptions(napi_env env, napi_value param, + AAFwk::StartOptions &options) + { + napi_value completionHandler = AppExecFwk::GetPropertyValueByPropertyName(env, param, + "completionHandler", napi_object); + if (completionHandler == nullptr) { + TAG_LOGD(AAFwkTag::SERVICE_EXT, "null completionHandler"); + return; + } + TAG_LOGI(AAFwkTag::SERVICE_EXT, "completionHandler exists"); + napi_value onRequestSuccObj = AppExecFwk::GetPropertyValueByPropertyName(env, completionHandler, + "onRequestSuccess", napi_function); + napi_value onRequestFailObj = AppExecFwk::GetPropertyValueByPropertyName(env, completionHandler, + "onRequestFailure", napi_function); + if (onRequestSuccObj == nullptr || onRequestFailObj == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null onRequestSuccObj or onRequestFailObj"); + return; + } + OnRequestResult onRequestSucc = [env, completionHandler, onRequestSuccObj]( + const AppExecFwk::ElementName &element, const std::string &message) { + size_t argc = ARGC_TWO; + napi_value argv[ARGC_TWO] = { AppExecFwk::WrapElementName(env, element), CreateJsValue(env, message) }; + napi_status status = napi_call_function(env, completionHandler, onRequestSuccObj, argc, argv, nullptr); + if (status != napi_ok) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "call onRequestSuccess, failed: %{public}d", status); + } + }; + OnRequestResult onRequestFail = [env, completionHandler, onRequestFailObj]( + const AppExecFwk::ElementName &element, const std::string &message) { + size_t argc = ARGC_TWO; + napi_value argv[ARGC_TWO] = { AppExecFwk::WrapElementName(env, element), CreateJsValue(env, message) }; + napi_status status = napi_call_function(env, completionHandler, onRequestFailObj, argc, argv, nullptr); + if (status != napi_ok) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "call onRequestFailure, failed: %{public}d", status); + } + }; + auto context = context_.lock(); + if (!context) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); + return; + } + auto time = static_cast(std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()).count()); + std::string requestId = std::to_string(time); + if (context->AddCompletionHandler(requestId, onRequestSucc, onRequestFail) != ERR_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "add completionHandler failed"); + return; + } + options.requestId_ = requestId; + } + napi_value OnOpenAtomicService(napi_env env, NapiCallbackInfo &info) { TAG_LOGD(AAFwkTag::SERVICE_EXT, "OpenAtomicService"); @@ -412,6 +465,7 @@ private: ThrowInvalidParamError(env, "Parse param startOptions failed, startOptions must be StartOption."); return CreateJsUndefined(env); } + UnwrapCompletionHandlerInStartOptions(env, info.argv[INDEX_ONE], startOptions); } std::string bundleName = ATOMIC_SERVICE_PREFIX + appId; @@ -437,7 +491,8 @@ private: } *innerErrorCode = context->OpenAtomicService(want, options); }; - NapiAsyncTask::CompleteCallback complete = [innerErrorCode, startTime, want, observer = freeInstallObserver_]( + NapiAsyncTask::CompleteCallback complete = [innerErrorCode, startTime, want, observer = freeInstallObserver_, + weak = context_, options]( napi_env env, NapiAsyncTask &task, int32_t status) { if (*innerErrorCode == 0) { TAG_LOGI(AAFwkTag::SERVICE_EXT, "OpenAtomicService success"); @@ -449,6 +504,17 @@ private: std::string abilityName = want.GetElement().GetAbilityName(); observer->OnInstallFinished(bundleName, abilityName, startTime, *innerErrorCode); } + auto context = weak.lock(); + if (context == nullptr) { + TAG_LOGW(AAFwkTag::SERVICE_EXT, "null context"); + return; + } + if (!options.requestId_.empty()) { + nlohmann::json jsonObject = nlohmann::json { + { JSON_KEY_ERR_MSG, "failed to call openAtomicService" } + }; + context->OnRequestFailure(options.requestId_, want.GetElement(), jsonObject.dump()); + } }; napi_value result = nullptr; AddFreeInstallObserver(env, want, nullptr, &result); diff --git a/frameworks/native/ability/native/ui_extension_base/js_ui_extension_context.cpp b/frameworks/native/ability/native/ui_extension_base/js_ui_extension_context.cpp index 5a2e7fcbdb0cb28029e92e40fbda72143baa3b26..14efb57ff196a5128047203897132e392380d99d 100755 --- a/frameworks/native/ability/native/ui_extension_base/js_ui_extension_context.cpp +++ b/frameworks/native/ability/native/ui_extension_base/js_ui_extension_context.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -55,6 +55,7 @@ constexpr size_t ARGC_ZERO = 0; constexpr size_t ARGC_ONE = 1; constexpr size_t ARGC_TWO = 2; constexpr size_t ARGC_THREE = 3; +const std::string JSON_KEY_ERR_MSG = "errMsg"; const std::string ATOMIC_SERVICE_PREFIX = "com.atomicservice."; } // namespace @@ -383,7 +384,7 @@ napi_value JsUIExtensionContext::OnOpenLinkInner(napi_env env, const AAFwk::Want } auto context = weak.lock(); if (context == nullptr) { - TAG_LOGW(AAFwkTag::CONTEXT, "null context"); + TAG_LOGW(AAFwkTag::UI_EXT, "null context"); return; } if (observer != nullptr) { @@ -945,6 +946,7 @@ napi_value JsUIExtensionContext::OnOpenAtomicService(napi_env env, NapiCallbackI "Parse param startOptions failed, startOptions must be StartOption."); return CreateJsUndefined(env); } + UnwrapCompletionHandlerInStartOptions(env, info.argv[INDEX_ONE], startOptions); unwrapArgc++; } std::string bundleName = ATOMIC_SERVICE_PREFIX + appId; @@ -1013,7 +1015,8 @@ napi_value JsUIExtensionContext::OpenAtomicServiceInner(napi_env env, NapiCallba return CreateJsUndefined(env); } AddFreeInstallObserver(env, want, nullptr, &result, true); - RuntimeTask task = [env, element = want.GetElement(), startTime, &observer = freeInstallObserver_]( + RuntimeTask task = [env, element = want.GetElement(), startTime, &observer = freeInstallObserver_, + weak = context_, options]( int resultCode, const AAFwk::Want& want, bool isInner) { TAG_LOGD(AAFwkTag::UI_EXT, "start async callback"); if (observer == nullptr) { @@ -1034,6 +1037,17 @@ napi_value JsUIExtensionContext::OpenAtomicServiceInner(napi_env env, NapiCallba } else { observer->OnInstallFinished(bundleName, abilityName, startTime, abilityResult); } + auto context = weak.lock(); + if (context == nullptr) { + TAG_LOGW(AAFwkTag::UI_EXT, "null context"); + return; + } + if (!options.requestId_.empty()) { + nlohmann::json jsonObject = nlohmann::json { + { JSON_KEY_ERR_MSG, "failed to call openAtomicService" } + }; + context->OnRequestFailure(options.requestId_, element, jsonObject.dump()); + } }; want.SetParam(Want::PARAM_RESV_FOR_RESULT, true); auto curRequestCode = context->GenerateCurRequestCode(); @@ -1623,5 +1637,55 @@ napi_value JSUIExtensionConnection::CallObjectMethod(const char* name, napi_valu return result; } +void JsUIExtensionContext::UnwrapCompletionHandlerInStartOptions(napi_env env, napi_value param, + AAFwk::StartOptions &options) +{ + napi_value completionHandler = AppExecFwk::GetPropertyValueByPropertyName(env, param, + "completionHandler", napi_object); + if (completionHandler == nullptr) { + TAG_LOGD(AAFwkTag::UI_EXT, "null completionHandler"); + return; + } + TAG_LOGI(AAFwkTag::UI_EXT, "completionHandler exists"); + napi_value onRequestSuccObj = AppExecFwk::GetPropertyValueByPropertyName(env, completionHandler, + "onRequestSuccess", napi_function); + napi_value onRequestFailObj = AppExecFwk::GetPropertyValueByPropertyName(env, completionHandler, + "onRequestFailure", napi_function); + if (onRequestSuccObj == nullptr || onRequestFailObj == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null onRequestSuccObj or onRequestFailObj"); + return; + } + OnRequestResult onRequestSucc = [env, completionHandler, onRequestSuccObj](const AppExecFwk::ElementName &element, + const std::string &message) { + size_t argc = ARGC_TWO; + napi_value argv[ARGC_TWO] = { AppExecFwk::WrapElementName(env, element), CreateJsValue(env, message) }; + napi_status status = napi_call_function(env, completionHandler, onRequestSuccObj, argc, argv, nullptr); + if (status != napi_ok) { + TAG_LOGE(AAFwkTag::UI_EXT, "call onRequestSuccess, failed: %{public}d", status); + } + }; + OnRequestResult onRequestFail = [env, completionHandler, onRequestFailObj](const AppExecFwk::ElementName &element, + const std::string &message) { + size_t argc = ARGC_TWO; + napi_value argv[ARGC_TWO] = { AppExecFwk::WrapElementName(env, element), CreateJsValue(env, message) }; + napi_status status = napi_call_function(env, completionHandler, onRequestFailObj, argc, argv, nullptr); + if (status != napi_ok) { + TAG_LOGE(AAFwkTag::UI_EXT, "call onRequestFailure, failed: %{public}d", status); + } + }; + auto context = context_.lock(); + if (!context) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + return; + } + std::string requestId = std::to_string(static_cast(std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()).count())); + if (context->AddCompletionHandler(requestId, onRequestSucc, onRequestFail) != ERR_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "add completionHandler failed"); + return; + } + options.requestId_ = requestId; +} + } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/native/ability/native/ui_extension_base/ui_extension_context.cpp b/frameworks/native/ability/native/ui_extension_base/ui_extension_context.cpp index 57510b29014124d65b2a53091682a51dc8488ed1..27cfbbf3ed85c2d2b660a432c22a7f2a05e15e9e 100755 --- a/frameworks/native/ability/native/ui_extension_base/ui_extension_context.cpp +++ b/frameworks/native/ability/native/ui_extension_base/ui_extension_context.cpp @@ -460,6 +460,56 @@ void UIExtensionContext::RequestComponentTerminate() } } +ErrCode UIExtensionContext::AddCompletionHandler(const std::string &requestId, OnRequestResult onRequestSucc, + OnRequestResult onRequestFail) +{ + if (onRequestSucc == nullptr || onRequestFail == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "either func is null"); + return ERR_INVALID_VALUE; + } + std::lock_guard lock(onRequestResultMutex_); + for (auto iter = onRequestResults_.begin(); iter != onRequestResults_.end(); iter++) { + if (iter->requestId_ == requestId) { + TAG_LOGI(AAFwkTag::UI_EXT, "requestId=%{public}s already exists", requestId.c_str()); + return ERR_OK; + } + } + onRequestResults_.emplace_back(requestId, onRequestSucc, onRequestFail); + return ERR_OK; +} + +void UIExtensionContext::OnRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) +{ + std::lock_guard lock(onRequestResultMutex_); + for (auto iter = onRequestResults_.begin(); iter != onRequestResults_.end(); iter++) { + if (iter->requestId_ == requestId) { + TAG_LOGI(AAFwkTag::UI_EXT, "requestId=%{public}s, call onRequestSuccess", requestId.c_str()); + iter->onRequestSuccess_(element, message); + onRequestResults_.erase(iter); + return; + } + } + + TAG_LOGE(AAFwkTag::UI_EXT, "requestId=%{public}s not exist", requestId.c_str()); +} + +void UIExtensionContext::OnRequestFailure(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) +{ + std::lock_guard lock(onRequestResultMutex_); + for (auto iter = onRequestResults_.begin(); iter != onRequestResults_.end(); iter++) { + if (iter->requestId_ == requestId) { + TAG_LOGI(AAFwkTag::UI_EXT, "requestId=%{public}s, call onRequestFailure", requestId.c_str()); + iter->onRequestFailure_(element, message); + onRequestResults_.erase(iter); + return; + } + } + + TAG_LOGE(AAFwkTag::UI_EXT, "requestId=%{public}s not exist", requestId.c_str()); +} + int32_t UIExtensionContext::curRequestCode_ = 0; std::mutex UIExtensionContext::requestCodeMutex_; } // namespace AbilityRuntime diff --git a/frameworks/native/appkit/ability_runtime/extension_context.cpp b/frameworks/native/appkit/ability_runtime/extension_context.cpp index febfd2e312e95a6905a85e589103c16d7beafbb1..87004822e3417ad5c53f2087be387622bdbeed15 100644 --- a/frameworks/native/appkit/ability_runtime/extension_context.cpp +++ b/frameworks/native/appkit/ability_runtime/extension_context.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -34,5 +34,21 @@ std::shared_ptr ExtensionContext::GetAbilityInfo() cons { return abilityInfo_; } + +ErrCode ExtensionContext::AddCompletionHandler(const std::string &requestId, OnRequestResult onRequestSucc, + OnRequestResult onRequestFail) +{ + return ERR_OK; +} + +void ExtensionContext::OnRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) +{ +} + +void ExtensionContext::OnRequestFailure(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) +{ +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/native/appkit/ability_runtime/service_extension_context.cpp b/frameworks/native/appkit/ability_runtime/service_extension_context.cpp index fd9a99c56169f0d959fc9405577559fdbba19e0c..d391de66e5b399fce0d142fa2ad66d4035e6d7de 100644 --- a/frameworks/native/appkit/ability_runtime/service_extension_context.cpp +++ b/frameworks/native/appkit/ability_runtime/service_extension_context.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2024 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -277,5 +277,70 @@ ErrCode ServiceExtensionContext::OpenAtomicService(const AAFwk::Want &want, cons } return err; } + +ErrCode ServiceExtensionContext::AddCompletionHandler(const std::string &requestId, OnRequestResult onRequestSucc, + OnRequestResult onRequestFail) +{ + if (onRequestSucc == nullptr || onRequestFail == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "either func is null"); + return ERR_INVALID_VALUE; + } + std::lock_guard lock(onRequestResultMutex_); + for (auto iter = onRequestResults_.begin(); iter != onRequestResults_.end(); iter++) { + if ((*iter)->requestId_ == requestId) { + TAG_LOGI(AAFwkTag::APPKIT, "requestId=%{public}s already exists", requestId.c_str()); + return ERR_OK; + } + } + onRequestResults_.emplace_back(std::make_shared(requestId, onRequestSucc, onRequestFail)); + return ERR_OK; +} + +void ServiceExtensionContext::OnRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) +{ + std::shared_ptr result = nullptr; + { + std::lock_guard lock(onRequestResultMutex_); + for (auto iter = onRequestResults_.begin(); iter != onRequestResults_.end(); iter++) { + if ((*iter)->requestId_ == requestId) { + result = *iter; + onRequestResults_.erase(iter); + break; + } + } + } + + if (result != nullptr) { + TAG_LOGI(AAFwkTag::APPKIT, "requestId=%{public}s, call onRequestSuccess", requestId.c_str()); + result->onRequestSuccess_(element, message); + return; + } + TAG_LOGE(AAFwkTag::APPKIT, "requestId=%{public}s not exist", requestId.c_str()); +} + +void ServiceExtensionContext::OnRequestFailure(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) +{ + std::shared_ptr result = nullptr; + { + std::lock_guard lock(onRequestResultMutex_); + for (auto iter = onRequestResults_.begin(); iter != onRequestResults_.end(); iter++) { + if ((*iter)->requestId_ == requestId) { + result = *iter; + onRequestResults_.erase(iter); + break; + } + } + } + + if (result != nullptr) { + TAG_LOGI(AAFwkTag::APPKIT, "requestId=%{public}s, call onRequestFailure", requestId.c_str()); + result->onRequestFailure_(element, message); + return; + } + + TAG_LOGE(AAFwkTag::APPKIT, "requestId=%{public}s not exist", requestId.c_str()); +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/inner_api/ability_manager/include/start_options.h b/interfaces/inner_api/ability_manager/include/start_options.h index 78235c65b42d31b3de17cd7f13436b5dd03ea7ea..3c7667760639de2988ef2d85755cd9bc3b1238b1 100644 --- a/interfaces/inner_api/ability_manager/include/start_options.h +++ b/interfaces/inner_api/ability_manager/include/start_options.h @@ -23,6 +23,20 @@ #include "parcel.h" namespace OHOS { +namespace AbilityRuntime { +using OnRequestResult = std::function; +struct OnRequestResultElement { + std::string requestId_; + OnRequestResult onRequestSuccess_; + OnRequestResult onRequestFailure_; + + OnRequestResultElement(const std::string &requestId, OnRequestResult onRequestSucc, + OnRequestResult onRequestFail) : requestId_(requestId), onRequestSuccess_(onRequestSucc), + onRequestFailure_(onRequestFail) + {} +}; +} + namespace AAFwk { class ProcessOptions; class StartWindowOption; diff --git a/interfaces/kits/native/ability/ability_runtime/ability_context.h b/interfaces/kits/native/ability/ability_runtime/ability_context.h index 37be28a188de8479d2d4c48d2991e1cde8865e22..2bf0c66ae9e5d0d34d2b7ec01eaf02e6e6537593 100644 --- a/interfaces/kits/native/ability/ability_runtime/ability_context.h +++ b/interfaces/kits/native/ability/ability_runtime/ability_context.h @@ -50,7 +50,6 @@ using RuntimeTask = std::function; using PermissionRequestTask = std::function&, const std::vector&)>; using RequestDialogResultTask = std::function; using AbilityConfigUpdateCallback = std::function; -using OnRequestResult = std::function; class LocalCallContainer; constexpr int32_t DEFAULT_INVAL_VALUE = -1; class AbilityContext : public Context { diff --git a/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h b/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h index 98bc1bf90066b123ca525b3f35259b76a3c15b37..d9bc3f2314b21a74b0df1d38cd6fed6f0ec7f947 100644 --- a/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h +++ b/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h @@ -397,16 +397,6 @@ private: sptr GetSessionToken(); void SetWindowRectangleParams(AAFwk::Want &want); - struct OnRequestResultElement { - std::string requestId_; - OnRequestResult onRequestSuccess_; - OnRequestResult onRequestFailure_; - - OnRequestResultElement(const std::string &requestId, OnRequestResult onRequestSucc, - OnRequestResult onRequestFail) : requestId_(requestId), onRequestSuccess_(onRequestSucc), - onRequestFailure_(onRequestFail) - {} - }; std::mutex onRequestResultMutex_; std::vector> onRequestResults_; }; diff --git a/interfaces/kits/native/ability/native/extension.h b/interfaces/kits/native/ability/native/extension.h index f1236563e4e0fe4c136cc24f89e7f227cea6a337..6b52f6e6a48885d37667ab4ea6102e6f80afa31c 100644 --- a/interfaces/kits/native/ability/native/extension.h +++ b/interfaces/kits/native/ability/native/extension.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -261,6 +261,12 @@ public: virtual bool OnInsightIntentExecuteDone(uint64_t intentId, const AppExecFwk::InsightIntentExecuteResult &result); + virtual void OnExtensionAbilityRequestFailure(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message); + + virtual void OnExtensionAbilityRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message); + std::shared_ptr abilityInfo_ = nullptr; protected: std::shared_ptr handler_ = nullptr; diff --git a/interfaces/kits/native/ability/native/extension_ability_thread.h b/interfaces/kits/native/ability/native/extension_ability_thread.h index b5eca2c8602f43572dc6d09b618d5ec172f31a69..7df082e08354220d300023b0a3ff3b860bbf2a93 100644 --- a/interfaces/kits/native/ability/native/extension_ability_thread.h +++ b/interfaces/kits/native/ability/native/extension_ability_thread.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -130,6 +130,11 @@ public: */ void DumpAbilityInfo(const std::vector ¶ms, std::vector &info) override; + void ScheduleAbilityRequestFailure(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) override; + + void ScheduleAbilityRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element) override; + private: /** * @brief Dump Ability Info Inner diff --git a/interfaces/kits/native/ability/native/extension_base.h b/interfaces/kits/native/ability/native/extension_base.h index d9d11d29d371dc0d97df93f1af6b032a78781ec3..d6ce31c399980076ea8138f2b43f78fda7a24dd5 100644 --- a/interfaces/kits/native/ability/native/extension_base.h +++ b/interfaces/kits/native/ability/native/extension_base.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -89,6 +89,12 @@ public: virtual void OnMemoryLevel(int level) override; void SetExtensionCommon(const std::shared_ptr &common); + + void OnExtensionAbilityRequestFailure(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) override; + + void OnExtensionAbilityRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) override; private: std::shared_ptr context_ = nullptr; std::shared_ptr extensionCommon_ = nullptr; diff --git a/interfaces/kits/native/ability/native/extension_base.inl b/interfaces/kits/native/ability/native/extension_base.inl index 2881db9f26e7b1ab4630a93c27e7d725cfa0523c..37459b9a60c863a8a3514603b355b90b8ada22c6 100644 --- a/interfaces/kits/native/ability/native/extension_base.inl +++ b/interfaces/kits/native/ability/native/extension_base.inl @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -120,5 +120,29 @@ void ExtensionBase::SetExtensionCommon(const std::shared_ptr { extensionCommon_ = common; } + +template +void ExtensionBase::OnExtensionAbilityRequestFailure( + const std::string &requestId, const AppExecFwk::ElementName &element, const std::string &message) +{ + TAG_LOGD(AAFwkTag::EXT, "OnAbilityRequestFailure called"); + if (context_ == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "null context_"); + return; + } + context_->OnRequestFailure(requestId, element, message); +} + +template +void ExtensionBase::OnExtensionAbilityRequestSuccess( + const std::string &requestId, const AppExecFwk::ElementName &element, const std::string &message) +{ + TAG_LOGD(AAFwkTag::EXT, "OnAbilityRequestSuccess called"); + if (context_ == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "null context_"); + return; + } + context_->OnRequestSuccess(requestId, element, message); +} } } diff --git a/interfaces/kits/native/ability/native/extension_impl.h b/interfaces/kits/native/ability/native/extension_impl.h index 28e0473a52526f2eee1d49ae618c9b2102d0352b..a33d18fc221a47b9bba7ee130f81eee10ee0708f 100644 --- a/interfaces/kits/native/ability/native/extension_impl.h +++ b/interfaces/kits/native/ability/native/extension_impl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -160,6 +160,11 @@ public: */ void SetLaunchParam(const AAFwk::LaunchParam &launchParam); + void ScheduleAbilityRequestFailure(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message); + + void ScheduleAbilityRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element); + protected: /** * @brief Toggles the lifecycle status of Extension to AAFwk::ABILITY_STATE_INACTIVE. And notifies the application diff --git a/interfaces/kits/native/ability/native/ui_extension_base/js_ui_extension_context.h b/interfaces/kits/native/ability/native/ui_extension_base/js_ui_extension_context.h index 8e74c60d1df35ee4bb2c747d8ec940acdd867da0..041003c4cb1c2ca6698ec7f35fd292b4ce4a0437 100755 --- a/interfaces/kits/native/ability/native/ui_extension_base/js_ui_extension_context.h +++ b/interfaces/kits/native/ability/native/ui_extension_base/js_ui_extension_context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -98,6 +98,7 @@ private: napi_value OnOpenLink(napi_env env, NapiCallbackInfo& info); napi_value OnOpenLinkInner(napi_env env, const AAFwk::Want& want, int requestCode, const std::string& startTime, const std::string& url); + void UnwrapCompletionHandlerInStartOptions(napi_env env, napi_value param, AAFwk::StartOptions &options); #ifdef SUPPORT_SCREEN void InitDisplayId(AAFwk::Want &want); void InitDisplayId(AAFwk::Want &want, AAFwk::StartOptions &startOptions, napi_env &env, NapiCallbackInfo& info); diff --git a/interfaces/kits/native/ability/native/ui_extension_base/ui_extension_context.h b/interfaces/kits/native/ability/native/ui_extension_base/ui_extension_context.h index 8f82651f6d66b2c1ba68208ab437963125b6940d..e1d2c24f7e9db98fdd20cd626983676fdb024ea4 100755 --- a/interfaces/kits/native/ability/native/ui_extension_base/ui_extension_context.h +++ b/interfaces/kits/native/ability/native/ui_extension_base/ui_extension_context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -185,6 +185,15 @@ public: void RemoveResultCallbackTask(int requestCode); + ErrCode AddCompletionHandler(const std::string &requestId, OnRequestResult onRequestSucc, + OnRequestResult onRequestFail) override; + + void OnRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) override; + + void OnRequestFailure(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) override; + /** * @brief Start a new ability using type; * @return errCode ERR_OK on success, others on failure. @@ -227,6 +236,9 @@ private: OHOS::AppExecFwk::AbilityType GetAbilityInfoType() const; void OnAbilityResultInner(int requestCode, int resultCode, const AAFwk::Want &resultData); + + std::mutex onRequestResultMutex_; + std::vector onRequestResults_; }; } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/kits/native/appkit/ability_runtime/extension_context.h b/interfaces/kits/native/appkit/ability_runtime/extension_context.h index 158c107f069a485d338f60fe363739c25438a391..7775daaed83e5fe6da0468cd7e0ba94685f3c73d 100644 --- a/interfaces/kits/native/appkit/ability_runtime/extension_context.h +++ b/interfaces/kits/native/appkit/ability_runtime/extension_context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -18,6 +18,7 @@ #include "ability_info.h" #include "context_impl.h" +#include "start_options.h" namespace OHOS { namespace AbilityRuntime { @@ -44,6 +45,37 @@ public: */ void SetAbilityInfo(const std::shared_ptr &abilityInfo); + /** + * @brief Add CompletioHandler. + * + * @param requestId, the requestId. + * @param onRequestSucc, the callback ot be called upon request success. + * @param onRequestFail, the callback ot be called upon request failure. + * @return ERR_OK on success, otherwise failure. + */ + virtual ErrCode AddCompletionHandler(const std::string &requestId, OnRequestResult onRequestSucc, + OnRequestResult onRequestFail); + + /** + * @brief Callback on request success. + * + * @param requestId, the requestId. + * @param element, the want element of startAbility. + * @param message, the message returned to the callback. + */ + virtual void OnRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message); + + /** + * @brief Callback on request failure. + * + * @param requestId, the requestId. + * @param element, the want element of startAbility. + * @param message, the message returned to the callback. + */ + virtual void OnRequestFailure(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message); + using SelfType = ExtensionContext; static const size_t CONTEXT_TYPE_ID; diff --git a/interfaces/kits/native/appkit/ability_runtime/service_extension_context.h b/interfaces/kits/native/appkit/ability_runtime/service_extension_context.h index 3baf1b6f15cf19243e2db83e82b1db9f5c972b04..bd66558ba3e9985498146aea93fbe8d8260125a6 100644 --- a/interfaces/kits/native/appkit/ability_runtime/service_extension_context.h +++ b/interfaces/kits/native/appkit/ability_runtime/service_extension_context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -172,6 +172,15 @@ public: ErrCode OpenLink(const AAFwk::Want& want, int reuqestCode); ErrCode OpenAtomicService(const AAFwk::Want &want, const AAFwk::StartOptions &options); + ErrCode AddCompletionHandler(const std::string &requestId, OnRequestResult onRequestSucc, + OnRequestResult onRequestFail) override; + + void OnRequestSuccess(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) override; + + void OnRequestFailure(const std::string &requestId, const AppExecFwk::ElementName &element, + const std::string &message) override; + protected: bool IsContext(size_t contextTypeId) override { @@ -188,6 +197,9 @@ private: * @return Current Ability Type */ OHOS::AppExecFwk::AbilityType GetAbilityInfoType() const; + + std::mutex onRequestResultMutex_; + std::vector> onRequestResults_; }; } // namespace AbilityRuntime } // namespace OHOS diff --git a/services/abilitymgr/src/free_install_manager.cpp b/services/abilitymgr/src/free_install_manager.cpp index 540ba2b18cd9b3c33f84cd4cdf9df5e4aa091d57..977415ffedff585e20db1e9dd9c95e783f04ff29 100644 --- a/services/abilitymgr/src/free_install_manager.cpp +++ b/services/abilitymgr/src/free_install_manager.cpp @@ -182,6 +182,10 @@ FreeInstallInfo FreeInstallManager::BuildFreeInstallInfo(const Want &want, int32 .startOptions = param->startOptions, .want = want }; + if (param->startOptions != nullptr && !param->startOptions->requestId_.empty()) { + TAG_LOGD(AAFwkTag::FREE_INSTALL, "set requestId:%{public}s", param->startOptions->requestId_.c_str()); + info.want.SetParam(KEY_REQUEST_ID, param->startOptions->requestId_); + } if (!param->isAsync) { auto promise = std::make_shared>(); info.promise = promise; diff --git a/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp b/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp index 1682b45bcf159a6897a9df797ec5859c72e336d2..5e0ba544eff182bce0cd9646b6c0465829ee94ce 100644 --- a/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp +++ b/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp @@ -1393,6 +1393,15 @@ int UIAbilityLifecycleManager::NotifySCBPendingActivation(sptr &ses TAG_LOGE(AAFwkTag::ABILITYMGR, "%{public}s", errMsg.c_str()); return ERR_INVALID_VALUE; } + abilityRecord = Token::GetAbilityRecordByToken(abilityRequest.callerToken); + if (abilityRecord != nullptr) { + auto requestId = abilityRequest.want.GetStringParam(KEY_REQUEST_ID); + if (!requestId.empty()) { + TAG_LOGI(AAFwkTag::ABILITYMGR, "notify request success, requestId:%{public}s", requestId.c_str()); + abilityRecord->NotifyAbilityRequestSuccess(requestId, abilityRequest.want.GetElement()); + } + const_cast(abilityRequest).want.RemoveParam(KEY_REQUEST_ID); + } sessionInfo->canStartAbilityFromBackground = true; TAG_LOGI(AAFwkTag::ABILITYMGR, "scb call, NotifySCBPendingActivation for rootSceneSession, target: %{public}s", sessionInfo->want.GetElement().GetAbilityName().c_str()); diff --git a/test/unittest/frameworks_kits_ability_native_test/extension_ability_thread_test.cpp b/test/unittest/frameworks_kits_ability_native_test/extension_ability_thread_test.cpp index 5ece1a597b78b935a95c704480aa46c2d481288c..9f031eca83dc963a9494c2c614f1265030922edb 100644 --- a/test/unittest/frameworks_kits_ability_native_test/extension_ability_thread_test.cpp +++ b/test/unittest/frameworks_kits_ability_native_test/extension_ability_thread_test.cpp @@ -1025,5 +1025,91 @@ HWTEST_F(ExtensionAbilityThreadTest, ExtensionAbilityThread_HandleDisconnectExte extensionabilitythread->HandleDisconnectExtension(want); GTEST_LOG_(INFO) << "ExtensionAbilityThread_HandleDisconnectExtension_0100 end"; } + +/** + * @tc.number: ExtensionAbilityThread_ScheduleAbilityRequestFailure_0100 + * @tc.name: ScheduleAbilityRequestFailure + * @tc.desc: Test ScheduleAbilityRequestFailure function + */ +HWTEST_F(ExtensionAbilityThreadTest, ExtensionAbilityThread_ScheduleAbilityRequestFailure_0100, + Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "ExtensionAbilityThread_ScheduleAbilityRequestFailure_0100 start"; + AbilityRuntime::ExtensionAbilityThread *extensionabilitythread = + new (std::nothrow) AbilityRuntime::ExtensionAbilityThread(); + EXPECT_NE(extensionabilitythread, nullptr); + extensionabilitythread->extensionImpl_ = std::make_shared(); + EXPECT_NE(extensionabilitythread->extensionImpl_, nullptr); + extensionabilitythread->abilityHandler_ = std::make_shared(nullptr); + EXPECT_NE(extensionabilitythread->abilityHandler_, nullptr); + std::string requestId = "1234567890"; + AppExecFwk::ElementName element("", "com.example.com", "MainAbility"); + std::string message = "failure"; + extensionabilitythread->ScheduleAbilityRequestFailure(requestId, element, message); + GTEST_LOG_(INFO) << "ExtensionAbilityThread_ScheduleAbilityRequestFailure_0100 end"; +} + +/** + * @tc.number: ExtensionAbilityThread_ScheduleAbilityRequestFailure_0200 + * @tc.name: ScheduleAbilityRequestFailure + * @tc.desc: Test ScheduleAbilityRequestFailure function + */ +HWTEST_F(ExtensionAbilityThreadTest, ExtensionAbilityThread_ScheduleAbilityRequestFailure_0200, + Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "ExtensionAbilityThread_ScheduleAbilityRequestFailure_0200 start"; + AbilityRuntime::ExtensionAbilityThread *extensionabilitythread = + new (std::nothrow) AbilityRuntime::ExtensionAbilityThread(); + EXPECT_NE(extensionabilitythread, nullptr); + EXPECT_EQ(extensionabilitythread->extensionImpl_, nullptr); + std::string requestId = "1234567890"; + AppExecFwk::ElementName element("", "com.example.com", "MainAbility"); + std::string message = "failure"; + extensionabilitythread->ScheduleAbilityRequestFailure(requestId, element, message); + GTEST_LOG_(INFO) << "ExtensionAbilityThread_ScheduleAbilityRequestFailure_0200 end"; +} + +/** + * @tc.number: ExtensionAbilityThread_ScheduleAbilityRequestSuccess_0100 + * @tc.name: ScheduleAbilityRequestSuccess + * @tc.desc: Test ScheduleAbilityRequestSuccess function + */ +HWTEST_F(ExtensionAbilityThreadTest, ExtensionAbilityThread_ScheduleAbilityRequestSuccess_0100, + Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AbilityRuntime_ScheduleAbilityRequestSuccess_0100 start"; + AbilityRuntime::ExtensionAbilityThread *extensionabilitythread = + new (std::nothrow) AbilityRuntime::ExtensionAbilityThread(); + EXPECT_NE(extensionabilitythread, nullptr); + extensionabilitythread->extensionImpl_ = std::make_shared(); + EXPECT_NE(extensionabilitythread->extensionImpl_, nullptr); + extensionabilitythread->abilityHandler_ = std::make_shared(nullptr); + EXPECT_NE(extensionabilitythread->abilityHandler_, nullptr); + std::string requestId = "1234567890"; + AppExecFwk::ElementName element("", "com.example.com", "MainAbility"); + std::string message = "success"; + extensionabilitythread->ScheduleAbilityRequestSuccess(requestId, element); + GTEST_LOG_(INFO) << "AbilityRuntime_ScheduleAbilityRequestSuccess_0100 end"; +} + +/** + * @tc.number: ExtensionAbilityThread_ScheduleAbilityRequestSuccess_0200 + * @tc.name: ScheduleAbilityRequestSuccess + * @tc.desc: Test ScheduleAbilityRequestSuccess function + */ +HWTEST_F(ExtensionAbilityThreadTest, ExtensionAbilityThread_ScheduleAbilityRequestSuccess_0200, + Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AbilityRuntime_ScheduleAbilityRequestSuccess_0200 start"; + AbilityRuntime::ExtensionAbilityThread *extensionabilitythread = + new (std::nothrow) AbilityRuntime::ExtensionAbilityThread(); + EXPECT_NE(extensionabilitythread, nullptr); + EXPECT_EQ(extensionabilitythread->extensionImpl_, nullptr); + std::string requestId = "1234567890"; + AppExecFwk::ElementName element("", "com.example.com", "MainAbility"); + std::string message = "success"; + extensionabilitythread->ScheduleAbilityRequestSuccess(requestId, element); + GTEST_LOG_(INFO) << "AbilityRuntime_ScheduleAbilityRequestSuccess_0200 end"; +} } // namespace AbilityRuntime } // namespace OHOS \ No newline at end of file diff --git a/test/unittest/free_install_manager_test/free_install_manager_test.cpp b/test/unittest/free_install_manager_test/free_install_manager_test.cpp index 7c1d5997ffbb3fd274db625f30a3058f74a06fce..7956a73bd15c4dafd3a014df1914912304bfd202 100644 --- a/test/unittest/free_install_manager_test/free_install_manager_test.cpp +++ b/test/unittest/free_install_manager_test/free_install_manager_test.cpp @@ -32,6 +32,7 @@ namespace { const int BUNDLE_MGR_SERVICE_SYS_ABILITY_ID = 401; const int VALID_RECORD_ID = 1; const int INVALID_RECORD_ID = -1; +constexpr const char* KEY_REQUEST_ID = "com.ohos.param.requestId"; } class FreeInstallTest : public testing::Test { public: @@ -603,5 +604,29 @@ HWTEST_F(FreeInstallTest, FreeInstall_GetRecordIdByToken_002, TestSize.Level1) int32_t result = freeInstallManager_->GetRecordIdByToken(callerToken); EXPECT_EQ(result, INVALID_RECORD_ID); } + +/** + * @tc.number: FreeInstall_BuildFreeInstallInfo_002 + * @tc.name: BuildFreeInstallInfo + * @tc.desc: Test BuildFreeInstallInfo. + */ +HWTEST_F(FreeInstallTest, FreeInstall_BuildFreeInstallInfo_002, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + freeInstallManager_ = std::make_shared(abilityMs_); + Want want; + ElementName element("", "com.test.demo", "MainAbility"); + want.SetElement(element); + const int32_t userId = 1; + const int requestCode = 0; + want.SetParam(Want::PARAM_RESV_START_TIME, std::string("0")); + auto param = std::make_shared(); + AAFwk::StartOptions startOptions; + startOptions.requestId_ = "test"; + param->startOptions = std::make_shared(startOptions); + + FreeInstallInfo info = freeInstallManager_->BuildFreeInstallInfo(want, userId, requestCode, nullptr, param); + EXPECT_EQ(info.want.GetStringParam(KEY_REQUEST_ID), "test"); +} } // namespace AppExecFwk } // namespace OHOS \ No newline at end of file diff --git a/test/unittest/service_extension_context_test/service_extension_context_test.cpp b/test/unittest/service_extension_context_test/service_extension_context_test.cpp index a9c548e2626fc11abe560aff5f97319fb658153d..d72eee7f1f640b8f8fe5f00d882ae65df6708b27 100644 --- a/test/unittest/service_extension_context_test/service_extension_context_test.cpp +++ b/test/unittest/service_extension_context_test/service_extension_context_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -552,5 +552,123 @@ HWTEST_F(ServiceExtensionContextTest, service_extension_context_OpenAtomicServic auto result = serviceExtensionContextTest.OpenAtomicService(want, options); EXPECT_NE(result, ERR_OK); } + +/** + * @tc.number: AddCompletionHandler_0100 + * @tc.name: AddCompletionHandler + * @tc.desc: Verify that function AddCompletionHandler. + */ +HWTEST_F(ServiceExtensionContextTest, AddCompletionHandler_100, Function | MediumTest | Level1) +{ + std::string requestId = "1234567890"; + OnRequestResult onRequestSucc = nullptr; + OnRequestResult onRequestFail = nullptr; + ServiceExtensionContext serviceExtensionContextTest; + auto result = serviceExtensionContextTest.AddCompletionHandler(requestId, onRequestSucc, onRequestFail); + EXPECT_EQ(result, ERR_INVALID_VALUE); + EXPECT_EQ(serviceExtensionContextTest.onRequestResults_.empty(), true); +} + +/** + * @tc.number: AddCompletionHandler_0200 + * @tc.name: AddCompletionHandler + * @tc.desc: Verify that function AddCompletionHandler. + */ +HWTEST_F(ServiceExtensionContextTest, AddCompletionHandler_0200, Function | MediumTest | Level1) +{ + std::string requestId = "1234567890"; + OnRequestResult onRequestSucc = [](const AppExecFwk::ElementName&, const std::string&) {}; + OnRequestResult onRequestFail = nullptr; + ServiceExtensionContext serviceExtensionContextTest; + auto result = serviceExtensionContextTest.AddCompletionHandler(requestId, onRequestSucc, onRequestFail); + EXPECT_EQ(result, ERR_INVALID_VALUE); + EXPECT_EQ(serviceExtensionContextTest.onRequestResults_.empty(), true); +} + +/** + * @tc.number: AddCompletionHandler_0300 + * @tc.name: AddCompletionHandler + * @tc.desc: Verify that function AddCompletionHandler. + */ +HWTEST_F(ServiceExtensionContextTest, AddCompletionHandler_0300, Function | MediumTest | Level1) +{ + std::string requestId = "1234567890"; + OnRequestResult onRequestSucc = [](const AppExecFwk::ElementName&, const std::string&) {}; + OnRequestResult onRequestFail = [](const AppExecFwk::ElementName&, const std::string&) {}; + ServiceExtensionContext serviceExtensionContextTest; + auto result = serviceExtensionContextTest.AddCompletionHandler(requestId, onRequestSucc, onRequestFail); + EXPECT_EQ(result, ERR_OK); + EXPECT_EQ(serviceExtensionContextTest.onRequestResults_.empty(), false); + serviceExtensionContextTest.onRequestResults_.clear(); +} + +/** + * @tc.number: OnRequestSuccess_0100 + * @tc.name: OnRequestSuccess + * @tc.desc: Verify that function OnRequestSuccess. + */ +HWTEST_F(ServiceExtensionContextTest, OnRequestSuccess_0100, Function | MediumTest | Level1) +{ + std::string requestId = "1234567890"; + OnRequestResult onRequestSucc = [](const AppExecFwk::ElementName&, const std::string&) {}; + OnRequestResult onRequestFail = [](const AppExecFwk::ElementName&, const std::string&) {}; + ServiceExtensionContext serviceExtensionContextTest; + auto result = serviceExtensionContextTest.AddCompletionHandler(requestId, onRequestSucc, onRequestFail); + EXPECT_EQ(result, ERR_OK); + EXPECT_EQ(serviceExtensionContextTest.onRequestResults_.empty(), false); + AppExecFwk::ElementName element("", "com.example.com", "MainAbility"); + serviceExtensionContextTest.OnRequestSuccess(requestId, element, "success"); + EXPECT_EQ(serviceExtensionContextTest.onRequestResults_.empty(), true); +} + +/** + * @tc.number: OnRequestSuccess_0200 + * @tc.name: OnRequestSuccess + * @tc.desc: Verify that function OnRequestSuccess. + */ +HWTEST_F(ServiceExtensionContextTest, OnRequestSuccess_0200, Function | MediumTest | Level1) +{ + std::string requestId = "1234567890"; + ServiceExtensionContext serviceExtensionContextTest; + EXPECT_EQ(serviceExtensionContextTest.onRequestResults_.empty(), true); + AppExecFwk::ElementName element("", "com.example.com", "MainAbility"); + serviceExtensionContextTest.OnRequestSuccess(requestId, element, "success"); + EXPECT_EQ(serviceExtensionContextTest.onRequestResults_.empty(), true); +} + +/** + * @tc.number: OnRequestFailure_0100 + * @tc.name: OnRequestFailure + * @tc.desc: Verify that function OnRequestFailure. + */ +HWTEST_F(ServiceExtensionContextTest, OnRequestFailure_0100, Function | MediumTest | Level1) +{ + std::string requestId = "1234567890"; + OnRequestResult onRequestSucc = [](const AppExecFwk::ElementName&, const std::string&) {}; + OnRequestResult onRequestFail = [](const AppExecFwk::ElementName&, const std::string&) {}; + ServiceExtensionContext serviceExtensionContextTest; + auto result = serviceExtensionContextTest.AddCompletionHandler(requestId, onRequestSucc, onRequestFail); + EXPECT_EQ(result, ERR_OK); + EXPECT_EQ(serviceExtensionContextTest.onRequestResults_.empty(), false); + AppExecFwk::ElementName element("", "com.example.com", "MainAbility"); + serviceExtensionContextTest.OnRequestFailure(requestId, element, "failure"); + EXPECT_EQ(serviceExtensionContextTest.onRequestResults_.empty(), true); + serviceExtensionContextTest.onRequestResults_.clear(); +} + +/** + * @tc.number: OnRequestFailure_0200 + * @tc.name: OnRequestFailure + * @tc.desc: Verify that function OnRequestFailure. + */ +HWTEST_F(ServiceExtensionContextTest, OnRequestFailure_0200, Function | MediumTest | Level1) +{ + std::string requestId = "1234567890"; + ServiceExtensionContext serviceExtensionContextTest; + EXPECT_EQ(serviceExtensionContextTest.onRequestResults_.empty(), true); + AppExecFwk::ElementName element("", "com.example.com", "MainAbility"); + serviceExtensionContextTest.OnRequestFailure(requestId, element, "failure"); + EXPECT_EQ(serviceExtensionContextTest.onRequestResults_.empty(), true); +} } } diff --git a/test/unittest/ui_extension_context_test/ui_extension_context_test.cpp b/test/unittest/ui_extension_context_test/ui_extension_context_test.cpp index 9fe7f53bbd24a5f0fbcaa59413182889d43df2cc..fc00798aa117ed05129cfb123d3d0b2a36f3bf65 100644 --- a/test/unittest/ui_extension_context_test/ui_extension_context_test.cpp +++ b/test/unittest/ui_extension_context_test/ui_extension_context_test.cpp @@ -790,5 +790,142 @@ HWTEST_F(UIExtensionContextTest, StartAbilityByType_0400, TestSize.Level1) TAG_LOGI(AAFwkTag::TEST, "StartAbilityByType_0400 end"); } + + /** + * @tc.number: IsTerminating_0100 + * @tc.name: UIExtensionContext IsTerminating + * @tc.desc: UIExtensionContext IsTerminating. + */ +HWTEST_F(UIExtensionContextTest, IsTerminating_0100, TestSize.Level1) +{ + auto context = std::make_shared(); + context->SetTerminating(true); + EXPECT_TRUE(context->IsTerminating()); +} + +/** + * @tc.number: AddCompletionHandler_0100 + * @tc.name: AddCompletionHandler + * @tc.desc: Verify that function AddCompletionHandler. + */ +HWTEST_F(UIExtensionContextTest, AddCompletionHandler_100, Function | MediumTest | Level1) +{ + std::string requestId = "1234567890"; + OnRequestResult onRequestSucc = nullptr; + OnRequestResult onRequestFail = nullptr; + auto context = std::make_shared(); + ASSERT_NE(context, nullptr); + auto result = context->AddCompletionHandler(requestId, onRequestSucc, onRequestFail); + EXPECT_EQ(result, ERR_INVALID_VALUE); + EXPECT_EQ(context->onRequestResults_.empty(), true); +} + +/** + * @tc.number: AddCompletionHandler_0200 + * @tc.name: AddCompletionHandler + * @tc.desc: Verify that function AddCompletionHandler. + */ +HWTEST_F(UIExtensionContextTest, AddCompletionHandler_0200, Function | MediumTest | Level1) +{ + std::string requestId = "1234567890"; + OnRequestResult onRequestSucc = [](const AppExecFwk::ElementName&, const std::string&) {}; + OnRequestResult onRequestFail = nullptr; + auto context = std::make_shared(); + ASSERT_NE(context, nullptr); + auto result = context->AddCompletionHandler(requestId, onRequestSucc, onRequestFail); + EXPECT_EQ(result, ERR_INVALID_VALUE); + EXPECT_EQ(context->onRequestResults_.empty(), true); +} + +/** + * @tc.number: AddCompletionHandler_0300 + * @tc.name: AddCompletionHandler + * @tc.desc: Verify that function AddCompletionHandler. + */ +HWTEST_F(UIExtensionContextTest, AddCompletionHandler_0300, Function | MediumTest | Level1) +{ + std::string requestId = "1234567890"; + OnRequestResult onRequestSucc = [](const AppExecFwk::ElementName&, const std::string&) {}; + OnRequestResult onRequestFail = [](const AppExecFwk::ElementName&, const std::string&) {}; + auto context = std::make_shared(); + ASSERT_NE(context, nullptr); + auto result = context->AddCompletionHandler(requestId, onRequestSucc, onRequestFail); + EXPECT_EQ(result, ERR_OK); + EXPECT_EQ(context->onRequestResults_.empty(), false); + context->onRequestResults_.clear(); +} + +/** + * @tc.number: OnRequestSuccess_0100 + * @tc.name: OnRequestSuccess + * @tc.desc: Verify that function OnRequestSuccess. + */ +HWTEST_F(UIExtensionContextTest, OnRequestSuccess_0100, Function | MediumTest | Level1) +{ + std::string requestId = "1234567890"; + OnRequestResult onRequestSucc = [](const AppExecFwk::ElementName&, const std::string&) {}; + OnRequestResult onRequestFail = [](const AppExecFwk::ElementName&, const std::string&) {}; + auto context = std::make_shared(); + ASSERT_NE(context, nullptr); + auto result = context->AddCompletionHandler(requestId, onRequestSucc, onRequestFail); + EXPECT_EQ(result, ERR_OK); + EXPECT_EQ(context->onRequestResults_.empty(), false); + AppExecFwk::ElementName element("", "com.example.com", "MainAbility"); + context->OnRequestSuccess(requestId, element, "success"); + EXPECT_EQ(context->onRequestResults_.empty(), true); +} + +/** + * @tc.number: OnRequestSuccess_0200 + * @tc.name: OnRequestSuccess + * @tc.desc: Verify that function OnRequestSuccess. + */ +HWTEST_F(UIExtensionContextTest, OnRequestSuccess_0200, Function | MediumTest | Level1) +{ + std::string requestId = "1234567890"; + auto context = std::make_shared(); + ASSERT_NE(context, nullptr); + EXPECT_EQ(context->onRequestResults_.empty(), true); + AppExecFwk::ElementName element("", "com.example.com", "MainAbility"); + context->OnRequestSuccess(requestId, element, "success"); + EXPECT_EQ(context->onRequestResults_.empty(), true); +} + +/** + * @tc.number: OnRequestFailure_0100 + * @tc.name: OnRequestFailure + * @tc.desc: Verify that function OnRequestFailure. + */ +HWTEST_F(UIExtensionContextTest, OnRequestFailure_0100, Function | MediumTest | Level1) +{ + std::string requestId = "1234567890"; + OnRequestResult onRequestSucc = [](const AppExecFwk::ElementName&, const std::string&) {}; + OnRequestResult onRequestFail = [](const AppExecFwk::ElementName&, const std::string&) {}; + auto context = std::make_shared(); + ASSERT_NE(context, nullptr); + auto result = context->AddCompletionHandler(requestId, onRequestSucc, onRequestFail); + EXPECT_EQ(result, ERR_OK); + EXPECT_EQ(context->onRequestResults_.empty(), false); + AppExecFwk::ElementName element("", "com.example.com", "MainAbility"); + context->OnRequestFailure(requestId, element, "failure"); + EXPECT_EQ(context->onRequestResults_.empty(), true); + context->onRequestResults_.clear(); +} + +/** + * @tc.number: OnRequestFailure_0200 + * @tc.name: OnRequestFailure + * @tc.desc: Verify that function OnRequestFailure. + */ +HWTEST_F(UIExtensionContextTest, OnRequestFailure_0200, Function | MediumTest | Level1) +{ + std::string requestId = "1234567890"; + auto context = std::make_shared(); + ASSERT_NE(context, nullptr); + EXPECT_EQ(context->onRequestResults_.empty(), true); + AppExecFwk::ElementName element("", "com.example.com", "MainAbility"); + context->OnRequestFailure(requestId, element, "failure"); + EXPECT_EQ(context->onRequestResults_.empty(), true); +} } // namespace AbilityRuntime } // namespace OHOS