From 16113ef6a43eb6e68215f5016744789bc67b39fa Mon Sep 17 00:00:00 2001 From: zhangzezhong Date: Thu, 19 Jun 2025 20:13:38 +0800 Subject: [PATCH] 0328test Signed-off-by: zhangzezhong --- .../include/sts_ui_extension_context.h | 44 ++- .../src/sts_ui_extension_context.cpp | 359 +++++++++++++++++- frameworks/ets/ets/BUILD.gn | 17 + frameworks/ets/ets/ability/connectOptions.ets | 35 ++ .../ets/application/UIExtensionContext.ets | 31 ++ frameworks/native/ability/native/BUILD.gn | 1 + 6 files changed, 477 insertions(+), 10 deletions(-) create mode 100644 frameworks/ets/ets/ability/connectOptions.ets diff --git a/frameworks/ets/ani/ui_extension_ability/include/sts_ui_extension_context.h b/frameworks/ets/ani/ui_extension_ability/include/sts_ui_extension_context.h index 8195362b8ab..01be5d1f8c1 100644 --- a/frameworks/ets/ani/ui_extension_ability/include/sts_ui_extension_context.h +++ b/frameworks/ets/ani/ui_extension_ability/include/sts_ui_extension_context.h @@ -24,9 +24,9 @@ #include "hitrace_meter.h" #include "ohos_application.h" #include "sts_free_install_observer.h" + namespace OHOS { namespace AbilityRuntime { - [[maybe_unused]] static void TerminateSelfSync([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, [[maybe_unused]] ani_object callback); [[maybe_unused]] static void TerminateSelfWithResultSync([[maybe_unused]] ani_env *env, @@ -35,6 +35,24 @@ ani_object CreateStsUIExtensionContext(ani_env *env, std::shared_ptr &remoteObject, int resultCode) override; + void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override; + void CallEtsFailed(int32_t errorCode); + void SetConnectionId(int64_t id); + int64_t GetConnectionId() { return connectionId_; } + void SetConnectionRef(ani_object connectOptionsObj); + +protected: + ani_vm *etsVm_; + int64_t connectionId_ = -1; + ani_ref stsConnectionRef_; +}; + class StsUIExtensionContext final { public: static StsUIExtensionContext &GetInstance() @@ -47,9 +65,33 @@ public: static UIExtensionContext* GetAbilityContext(ani_env *env, ani_object obj); void AddFreeInstallObserver(ani_env *env, const AAFwk::Want &want, ani_object callback, UIExtensionContext* context); + static ani_double OnConnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object connectOptionsObj); + static void OnDisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_int connectId, + ani_object connectOptionsObj); + private: + static bool CheckConnectionParam(ani_env *env, ani_object connectOptionsObj, + sptr& connection, AAFwk::Want& want); + sptr freeInstallObserver_ = nullptr; }; + +struct EtsUIExtensionConnectionKey { + AAFwk::Want want; + int64_t id; +}; + +struct Etskey_compare { + bool operator()(const EtsUIExtensionConnectionKey &key1, const EtsUIExtensionConnectionKey &key2) const + { + if (key1.id < key2.id) { + return true; + } + return false; + } +}; + } // namespace AbilityRuntime } // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_STS_UI_EXTENSION_CONTEXT_H \ No newline at end of file diff --git a/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension_context.cpp b/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension_context.cpp index a45aa50d413..0b7c88fbc40 100644 --- a/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension_context.cpp +++ b/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension_context.cpp @@ -12,20 +12,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "common_fun_ani.h" #include "sts_ui_extension_context.h" -#include "ui_extension_context.h" -#include "ani_common_want.h" + #include "ability_manager_client.h" +#include "ani_common_start_options.h" +#include "ani_common_want.h" +#include "ani_remote_object.h" +#include "common_fun_ani.h" +#include "ets_extension_context.h" #include "sts_context_utils.h" #include "sts_error_utils.h" -#include "ets_extension_context.h" -#include "ani_common_start_options.h" +#include "ui_extension_context.h" namespace OHOS { namespace AbilityRuntime { namespace { -constexpr const char* UI_CONTEXT_CLASS_NAME = "Lapplication/UIExtensionContext/UIExtensionContext;"; +static std::mutex g_connectsMutex; +int64_t g_serialNumber = 0; +static std::map, Etskey_compare> g_connects; + +constexpr const int FAILED_CODE = -1; +constexpr const char *UI_CONTEXT_CLASS_NAME = "Lapplication/UIExtensionContext/UIExtensionContext;"; +constexpr const char *CONNECT_OPTIONS_CLASS_NAME = "Lability/connectOptions/ConnectOptionsInner;"; +constexpr const char *SIGNATURE_ONCONNECT = "LbundleManager/ElementName/ElementName;L@ohos/rpc/rpc/IRemoteObject;:V"; +constexpr const char *SIGNATURE_ONDISCONNECT = "LbundleManager/ElementName/ElementName;:V"; +constexpr const char *SIGNATURE_CONNECT_SERVICE_EXTENSION = + "L@ohos/app/ability/Want/Want;Lability/connectOptions/ConnectOptions;:D"; +constexpr const char *SIGNATURE_DISCONNECT_SERVICE_EXTENSION = "DLutils/AbilityUtils/AsyncCallbackWrapper;:V"; } static void TerminateSelfSync([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, @@ -108,6 +121,103 @@ static void StartAbilityWithOption([[maybe_unused]] ani_env *env, [[maybe_unused StsUIExtensionContext::GetInstance().StartAbilityInner(env, aniObj, wantObj, opt, call); } +ani_double StsUIExtensionContext::OnConnectServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_object connectOptionsObj) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "OnConnectServiceExtensionAbility"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return FAILED_CODE; + } + ani_status status = ANI_ERROR; + auto context = StsUIExtensionContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + return FAILED_CODE; + } + AAFwk::Want want; + if (!OHOS::AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to UnwrapWant"); + ThrowStsInvalidParamError(env, "Failed to UnwrapWant"); + return FAILED_CODE; + } + ani_vm *etsVm = nullptr; + if ((status = env->GetVM(&etsVm)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to getVM, status: %{public}d", status); + return FAILED_CODE; + } + if (etsVm == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsVm"); + return FAILED_CODE; + } + sptr connection = new (std::nothrow) EtsUiExtensionConnection(etsVm); + if (!CheckConnectionParam(env, connectOptionsObj, connection, want)) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to CheckConnectionParam"); + ThrowStsInvalidParamError(env, "Failed to CheckConnectionParam"); + return FAILED_CODE; + } + auto innerErrCode = context->ConnectAbility(want, connection); + double connectId = connection->GetConnectionId(); + if (innerErrCode != ERR_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Faied to ConnectAbility, innerErrCode is %{public}d", innerErrCode); + connection->CallEtsFailed(connectId); + return FAILED_CODE; + } + return connectId; +} + +void StsUIExtensionContext::OnDisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_int connectId, ani_object callback) +{ + TAG_LOGE(AAFwkTag::UI_EXT, "OnDisconnectServiceExtensionAbility"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + ani_status status = ANI_ERROR; + ani_object aniObject = nullptr; + auto context = StsUIExtensionContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + aniObject = CreateStsErrorByNativeErr(env, static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); + return; + } + AAFwk::Want want; + ani_vm *etsVm = nullptr; + if ((status = env->GetVM(&etsVm)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to getVm, status: %{public}d", status); + return; + } + if (etsVm == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsVm"); + return; + } + sptr connection = new (std::nothrow) EtsUiExtensionConnection(etsVm); + { + std::lock_guard lock(g_connectsMutex); + auto item = std::find_if( + g_connects.begin(), g_connects.end(), [&connectId](const auto &obj) { return connectId == obj.first.id; }); + if (item != g_connects.end()) { + want = item->first.want; + connection = item->second; + g_connects.erase(item); + } else { + TAG_LOGI(AAFwkTag::CONTEXT, "Failed to found connection"); + return; + } + } + if (!connection) { + aniObject = CreateStsErrorByNativeErr(env, static_cast(AbilityErrorCode::ERROR_CODE_INNER)); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); + TAG_LOGE(AAFwkTag::UI_EXT, "null connection"); + return; + } + context->DisconnectAbility(want, connection); + aniObject = CreateStsErrorByNativeErr(env, static_cast(AbilityErrorCode::ERROR_OK)); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); +} + UIExtensionContext* StsUIExtensionContext::GetAbilityContext(ani_env *env, ani_object obj) { TAG_LOGD(AAFwkTag::UI_EXT, "GetAbilityContext start"); @@ -152,7 +262,7 @@ void StsUIExtensionContext::AddFreeInstallObserver(ani_env *env, const AAFwk::Wa ani_vm *etsVm = nullptr; ani_status status = ANI_ERROR; if ((status = env->GetVM(&etsVm)) != ANI_OK) { - TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); } freeInstallObserver_ = new StsFreeInstallObserver(etsVm); ret = context->AddFreeInstallObserver(freeInstallObserver_); @@ -221,6 +331,46 @@ void StsUIExtensionContext::StartAbilityInner([[maybe_unused]] ani_env *env, [[m } } +bool StsUIExtensionContext::CheckConnectionParam(ani_env *env, ani_object connectOptionsObj, + sptr &connection, AAFwk::Want &want) +{ + ani_type type = nullptr; + ani_boolean res = ANI_FALSE; + ani_status status = ANI_ERROR; + if ((status = env->Object_GetType(connectOptionsObj, &type)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to Object_GetType, status: %{public}d", status); + return false; + } + if (type == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null type"); + return false; + } + if ((status = env->Object_InstanceOf(connectOptionsObj, type, &res)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to Object_InstanceOf, status: %{public}d", status); + return false; + } + if (res != ANI_TRUE) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to CheckConnectionParam"); + return false; + } + connection->SetConnectionRef(connectOptionsObj); + EtsUIExtensionConnectionKey key; + { + std::lock_guard guard(g_connectsMutex); + key.id = g_serialNumber; + key.want = want; + connection->SetConnectionId(key.id); + g_connects.emplace(key, connection); + if (g_serialNumber < INT32_MAX) { + g_serialNumber++; + } else { + g_serialNumber = 0; + } + } + TAG_LOGD(AAFwkTag::UI_EXT, "Failed to find connection, make new one"); + return true; +} + bool BindNativeMethods(ani_env *env, ani_class &cls) { ani_status status = ANI_ERROR; @@ -234,10 +384,14 @@ bool BindNativeMethods(ani_env *env, ani_class &cls) ani_native_function { "nativeStartAbilitySync", "L@ohos/app/ability/Want/Want;L@ohos/app/ability/StartOptions/StartOptions;Lutils/AbilityUtils/" "AsyncCallbackWrapper;:V", - reinterpret_cast(StartAbilityWithOption) }, + reinterpret_cast(StartAbilityWithOption) }, + ani_native_function { "nativeConnectServiceExtensionAbility", SIGNATURE_CONNECT_SERVICE_EXTENSION, + reinterpret_cast(StsUIExtensionContext::OnConnectServiceExtensionAbility) }, + ani_native_function { "nativeDisconnectServiceExtensionAbilitySync", SIGNATURE_DISCONNECT_SERVICE_EXTENSION, + reinterpret_cast(StsUIExtensionContext::OnDisconnectServiceExtensionAbility) }, }; if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to bindNativeMethods status: %{public}d", status); return false; } return true; @@ -283,5 +437,192 @@ ani_object CreateStsUIExtensionContext(ani_env *env, std::shared_ptrGetAbilityInfo()); return contextObj; } + +EtsUiExtensionConnection::EtsUiExtensionConnection(ani_vm *etsVm) : etsVm_(etsVm) {} + +EtsUiExtensionConnection::~EtsUiExtensionConnection() +{ + if (etsVm_ != nullptr && stsConnectionRef_ != nullptr) { + ani_env* env = nullptr; + if (etsVm_->GetEnv(ANI_VERSION_1, &env) == ANI_OK) { + env->GlobalReference_Delete(stsConnectionRef_); + stsConnectionRef_ = nullptr; + } + } +} + +void EtsUiExtensionConnection::SetConnectionId(int64_t id) +{ + connectionId_ = id; +} + +void EtsUiExtensionConnection::CallEtsFailed(int32_t errorCode) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "CallEtsFailed"); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "etsVm_ is nullptr"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_OK; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return; + } + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + if (stsConnectionRef_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null stsConnectionRef_"); + return; + } + ani_class cls = nullptr; + if ((status = env->FindClass(CONNECT_OPTIONS_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to find connectOptions calss, status: %{public}d", status); + return; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null class"); + return; + } + ani_method method = nullptr; + if ((status = env->Class_FindMethod(cls, "onFailed", "D:V", &method))) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to find onFailed method, status: %{public}d", status); + return; + } + if (method == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null method"); + return; + } + status = env->Object_CallMethod_Void( + reinterpret_cast(stsConnectionRef_), method, static_cast(errorCode)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Object_CallMethod_Void status: %{public}d", status); + } +} + +void EtsUiExtensionConnection::SetConnectionRef(ani_object connectOptionsObj) +{ + TAG_LOGI(AAFwkTag::UI_EXT, "called"); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsVm"); + return; + } + + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Faied to getEnv, status: %{public}d", status); + return; + } + if ((status = env->GlobalReference_Create(connectOptionsObj, &stsConnectionRef_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Faied to createReference, status: %{public}d", status); + } +} + +void EtsUiExtensionConnection::OnAbilityConnectDone(const AppExecFwk::ElementName &element, + const sptr &remoteObject, int resultCode) +{ + if (etsVm_ == nullptr || stsConnectionRef_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null stsConnectionRef or etsVm"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + ani_option interopEnabled { "--interop=disable", nullptr }; + ani_options aniArgs { 1, &interopEnabled }; + if ((status = (etsVm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env))) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return; + } + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + ani_class cls = nullptr; + if ((status = env->FindClass(CONNECT_OPTIONS_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to find connectOptions calss, status: %{public}d", status); + return; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null cls"); + return; + } + ani_method method = nullptr; + if ((status = env->Class_FindMethod(cls, "onConnect", SIGNATURE_ONCONNECT, &method))) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to find onConnect method, status: %{public}d", status); + return; + } + if (method == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null method"); + return; + } + ani_ref refElement = AppExecFwk::WrapElementName(env, element); + if (refElement == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null refElement"); + return; + } + ani_object refRemoteObject = ANI_ohos_rpc_CreateJsRemoteObject(env, remoteObject); + status = env->Object_CallMethod_Void( + reinterpret_cast(stsConnectionRef_), method, refElement, refRemoteObject); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Object_CallMethod_Void status: %{public}d", status); + } + if ((status = etsVm_->DetachCurrentThread()) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + } +} + +void EtsUiExtensionConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) +{ + if (etsVm_ == nullptr || stsConnectionRef_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null stsConnectionRef or etsVm"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + ani_option interopEnabled { "--interop=disable", nullptr }; + ani_options aniArgs { 1, &interopEnabled }; + if ((status = (etsVm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env))) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return; + } + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + ani_class cls = nullptr; + if ((status = env->FindClass(CONNECT_OPTIONS_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to find connectOptions calss, status: %{public}d", status); + return; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null cls"); + return; + } + ani_method method = nullptr; + if ((status = env->Class_FindMethod(cls, "onDisconnect", SIGNATURE_ONDISCONNECT, &method))) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to find onDisconnect method, status: %{public}d", status); + return; + } + if (method == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null method"); + return; + } + ani_ref refElement = AppExecFwk::WrapElementName(env, element); + if (refElement == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null refElement"); + return; + } + status = env->Object_CallMethod_Void(reinterpret_cast(stsConnectionRef_), method, refElement); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Object_CallMethod_Void status: %{public}d", status); + } + if ((status = etsVm_->DetachCurrentThread()) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + } +} + } // AbilityRuntime } // OHOS diff --git a/frameworks/ets/ets/BUILD.gn b/frameworks/ets/ets/BUILD.gn index cf3a702bf83..2a9df40b4e2 100644 --- a/frameworks/ets/ets/BUILD.gn +++ b/frameworks/ets/ets/BUILD.gn @@ -883,6 +883,22 @@ ohos_prebuilt_etc("ability_runtime_AbilityRunningInfo_abc_etc") { deps = [ ":ability_runtime_AbilityRunningInfo_abc" ] } +generate_static_abc("ability_runtime_connect_options_abc") { + base_url = "./" + files = [ "./ability/connectOptions.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_connect_options_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_connect_options_abc_etc") { + source = "$target_out_dir/ability_runtime_connect_options_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_connect_options_abc" ] +} + group("ets_packages") { deps = [ ":ability_ability_application_abc_etc", @@ -937,5 +953,6 @@ group("ets_packages") { ":ui_extension_ability_ani_etc", ":ability_runtime_OpenLink_Options_abc_etc", ":ability_runtime_AbilityRunningInfo_abc_etc", + ":ability_runtime_connect_options_abc_etc", ] } diff --git a/frameworks/ets/ets/ability/connectOptions.ets b/frameworks/ets/ets/ability/connectOptions.ets new file mode 100644 index 00000000000..c07b6418a95 --- /dev/null +++ b/frameworks/ets/ets/ability/connectOptions.ets @@ -0,0 +1,35 @@ +/* + * Copyright (c) 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ElementName } from 'bundleManager.ElementName' +import rpc from '@ohos.rpc'; + +export interface ConnectOptions { + onConnect(elementName: ElementName, remote: rpc.IRemoteObject): void; + onDisconnect(elementName: ElementName): void; + onFailed(code: number): void; +} + +class ConnectOptionsInner implements ConnectOptions { + onConnect(elementName: ElementName, remote: rpc.IRemoteObject): void { + console.log('onConnect'); + } + onDisconnect(elementName: ElementName): void { + console.log('onDisconnect'); + } + onFailed(code: number): void { + console.log('onFailed'); + } +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/UIExtensionContext.ets b/frameworks/ets/ets/application/UIExtensionContext.ets index 4d4c5c693e3..b2207fba177 100644 --- a/frameworks/ets/ets/application/UIExtensionContext.ets +++ b/frameworks/ets/ets/application/UIExtensionContext.ets @@ -18,6 +18,7 @@ import StartOptions from '@ohos.app.ability.StartOptions'; import { AbilityResult } from 'ability.abilityResult'; import { AsyncCallback } from '@ohos.base'; import { BusinessError } from '@ohos.base'; +import { ConnectOptions } from 'ability.connectOptions'; import AsyncCallbackWrapper from '../utils/AbilityUtils'; import ExtensionContext from 'application.ExtensionContext'; @@ -26,6 +27,9 @@ export default class UIExtensionContext extends ExtensionContext { native terminateSelfWithResultSync(parameter: AbilityResult, callback: AsyncCallbackWrapper): void; private native nativeStartAbilitySync(want: Want, callback: AsyncCallbackWrapper): void; private native nativeStartAbilitySync(want: Want, options: StartOptions, callback:AsyncCallbackWrapper): void; + private native nativeConnectServiceExtensionAbility(want: Want, options: ConnectOptions): double; + private native nativeDisconnectServiceExtensionAbilitySync(connection: double, callback: AsyncCallbackWrapper): void; + private native nativeStartAbilityForResultAsCaller(want: Want, callback: AsyncCallbackWrapper, options?: StartOptions): void; terminateSelf(callback:AsyncCallback): void { let myCall = new AsyncCallbackWrapper(callback); @@ -103,4 +107,31 @@ export default class UIExtensionContext extends ExtensionContext { }); return p; } + + connectServiceExtensionAbility(want: Want, options: ConnectOptions): number { + return this.nativeConnectServiceExtensionAbility(want, options); + } + + disconnectServiceExtensionAbility(connection: number, callback: AsyncCallback): void { + let syncCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeDisconnectServiceExtensionAbilitySync(connection, syncCall); + }); + } + + disconnectServiceExtensionAbility(connection: number): Promise { + return new Promise((resolve: (data: undefined) => void, + reject: (err: BusinessError) => void): void => { + let syncCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeDisconnectServiceExtensionAbilitySync(connection, syncCall); + }) + }); + } } \ No newline at end of file diff --git a/frameworks/native/ability/native/BUILD.gn b/frameworks/native/ability/native/BUILD.gn index dd19d2a9f00..f39e5a0747a 100644 --- a/frameworks/native/ability/native/BUILD.gn +++ b/frameworks/native/ability/native/BUILD.gn @@ -1639,6 +1639,7 @@ ohos_shared_library("ui_extension") { "hitrace:hitrace_meter", "ipc:ipc_core", "ipc:ipc_napi", + "ipc:rpc_ani", "napi:ace_napi", "runtime_core:ani", "window_manager:embeddablewindowstage_kit", -- Gitee