diff --git a/frameworks/ets/ani/ani_common/BUILD.gn b/frameworks/ets/ani/ani_common/BUILD.gn index 9f75ba5d0a737612855432a94bb172950178a1fc..ca089329b52dfa225fb1e557a08bd43cf5808c29 100644 --- a/frameworks/ets/ani/ani_common/BUILD.gn +++ b/frameworks/ets/ani/ani_common/BUILD.gn @@ -32,9 +32,11 @@ ohos_shared_library("ani_common") { "./include", "${ability_runtime_innerkits_path}/app_manager/include/appmgr", "${ability_runtime_path}/frameworks/ets/ani/enum_convert", + "${ability_runtime_path}/frameworks/ets/ani/service_extension_ability/include", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", "${ability_runtime_path}/interfaces/kits/native/ability/native", + "${ability_runtime_path}/utils/global/freeze/include", "${ability_runtime_services_path}/common/include", ] @@ -52,6 +54,7 @@ ohos_shared_library("ani_common") { "src/ani_task.cpp", "src/context_transfer.cpp", "src/ets_application_context_utils.cpp", + "src/ets_app_service_extension_context.cpp", "src/ets_application_state_change_callback.cpp", "src/ets_context_utils.cpp", "src/ets_data_struct_converter.cpp", diff --git a/frameworks/ets/ani/ani_common/include/ets_app_service_extension_context.h b/frameworks/ets/ani/ani_common/include/ets_app_service_extension_context.h new file mode 100644 index 0000000000000000000000000000000000000000..558eb78925b7fb32ef37a71566b66ed5aca333ba --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ets_app_service_extension_context.h @@ -0,0 +1,74 @@ +/* + * 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. + */ +#ifndef OHOS_ABILITY_RUNTIME_ETS_APP_SERVICE_EXTENSION_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_ETS_APP_SERVICE_EXTENSION_CONTEXT_H + +#include + +#include "ability_connect_callback.h" +#include "app_service_extension_context.h" +#include "event_handler.h" +#include "ets_free_install_observer.h" +#include "native_engine/native_engine.h" + +namespace OHOS { +namespace AbilityRuntime { + +struct EtsConnectionKey { + AAFwk::Want want; + int32_t id = 0; + int32_t accountId = 0; +}; +struct EtsKeyCompare { + bool operator()(const EtsConnectionKey &key1, const EtsConnectionKey &key2) const + { + return key1.id < key2.id; + } +}; + +class EtsAppServiceExtensionContext final { +public: + explicit EtsAppServiceExtensionContext(const std::shared_ptr &context) + : context_(context) {} + ~EtsAppServiceExtensionContext() = default; + + static int32_t InsertConnection(std::shared_ptrconnection, + const AAFwk::Want &want, int32_t accountId = -1); + static void RemoveConnection(int32_t connectId); + static void Finalizer(ani_env *env, void *data, void *hint); + void SetConnectionId(int32_t id); + void RemoveConnectionObject(); + void CallEtsFailed(int32_t errorCode); + void SetConnectionRef(ani_object connectOptionsObj); + static void OnTerminateSelf(ani_env *env, ani_object obj, ani_object callback); + static ani_int OnConnectAbility(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object connectOptionsObj); + static void OnDisconnectAbility(ani_env *env, ani_object aniObj, ani_int connectId, ani_object callback); + static ani_object OnStartAbility(ani_env* env, ani_object aniObj, ani_object wantObj, ani_object optionsObj); + static AppServiceExtensionContext *GetContext(ani_env *env, ani_object aniObj); + static ani_object StartAbilityInner(ani_env* env, AAFwk::Want& want, AAFwk::StartOptions& startOptions, + ani_object optionsObj); + +private: + std::weak_ptr context_; + ani_vm *etsVm_ = nullptr; + int32_t connectionId_ = -1; + ani_ref etsConnectionRef_ = nullptr; +}; + +ani_object CreateEtsAppServiceExtensionContext(ani_env *env, + const std::shared_ptr &context); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_SERVICE_EXTENSION_CONTEXT_H \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/src/ets_app_service_extension_context.cpp b/frameworks/ets/ani/ani_common/src/ets_app_service_extension_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a4d0b5571fb5aede054ab99eb7f87d7f0fcab70e --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ets_app_service_extension_context.cpp @@ -0,0 +1,367 @@ +/* + * 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. + */ + +#include "ets_app_service_extension_context.h" + +#include +#include +#include +#include "ability_manager_client.h" +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "ets_context_utils.h" +#include "ets_data_struct_converter.h" +#include "ets_error_utils.h" +#include "ets_extension_context.h" +#include "ets_runtime.h" +#include "hilog_tag_wrapper.h" +#include "hitrace_meter.h" +#include "js_runtime_utils.h" +#include "napi_common_ability.h" +#include "napi_common_start_options.h" +#include "napi_common_util.h" +#include "napi_common_want.h" +#include "napi_remote_object.h" +#include "open_link_options.h" +#include "start_options.h" +#include "uri.h" +#include "ability_runtime/js_caller_complex.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { + constexpr const char *CONTEXT_CLASS_NAME = "Lapplication/AppServiceExtensionContext/AppServiceExtensionContext;"; + static std::mutex g_connectsMutex; + static std::recursive_mutex g_connectsLock; + static std::map, EtsKeyCompare> g_connects; + static int64_t g_serialNumber = 0; + constexpr const int FAILED_CODE = -1; +} + +void EtsAppServiceExtensionContext::Finalizer(ani_env *env, void *data, void *hint) +{ + TAG_LOGI(AAFwkTag::SERVICE_EXT, "EtsAppServiceExtensionContext::Finalizer called"); + std::unique_ptr(static_cast(data)); +} + +void EtsAppServiceExtensionContext::SetConnectionId(int32_t id) +{ + connectionId_ = id; +} + +int32_t EtsAppServiceExtensionContext::InsertConnection(std::shared_ptr connection, + const AAFwk::Want &want, int32_t accountId) +{ + std::lock_guard lock(g_connectsLock); + if (connection == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null connection"); + return FAILED_CODE; + } + int32_t connectId = static_cast(g_serialNumber); + EtsConnectionKey key; + key.id = g_serialNumber; + key.want = want; + key.accountId = accountId; + connection->SetConnectionId(key.id); + g_connects.emplace(key, connection); + g_serialNumber++; + return connectId; +} + +void EtsAppServiceExtensionContext::RemoveConnection(int32_t connectId) +{ + std::lock_guard lock(g_connectsLock); + 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()) { + TAG_LOGD(AAFwkTag::SERVICE_EXT, "remove connection ability exist"); + if (item->second) { + item->second->RemoveConnectionObject(); + } + g_connects.erase(item); + } else { + TAG_LOGD(AAFwkTag::SERVICE_EXT, "remove connection ability not exist"); + } +} + +void EtsAppServiceExtensionContext::RemoveConnectionObject() +{ + if (etsVm_ != nullptr && etsConnectionRef_ != nullptr) { + ani_env *env = nullptr; + if (etsVm_->GetEnv(ANI_VERSION_1, &env) == ANI_OK && env != nullptr) { + env->GlobalReference_Delete(etsConnectionRef_); + etsConnectionRef_ = nullptr; + } + } +} + +void EtsAppServiceExtensionContext::CallEtsFailed(int32_t errorCode) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "CallEtsFailed"); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null etsVm"); + return; + } + if (etsConnectionRef_ == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null etsConnectionRef_"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_OK; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to get env, status: %{public}d", status); + return; + } + status = env->Object_CallMethodByName_Void(reinterpret_cast(etsConnectionRef_), "onFailed", "D:V", + static_cast(errorCode)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to call onFailed, status: %{public}d", status); + } +} + +void EtsAppServiceExtensionContext::OnTerminateSelf(ani_env *env, ani_object obj, ani_object callback) +{ + TAG_LOGI(AAFwkTag::SERVICE_EXT, "called"); + if (env == nullptr || callback == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Invalid environment or callback"); + return; + } + auto context = GetContext(env, obj); + if (!context) { + TAG_LOGW(AAFwkTag::SERVICE_EXT, "context released"); + ani_object error = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(AAFwk::ERR_INVALID_CONTEXT)); + AppExecFwk::AsyncCallback(env, callback, error, nullptr); + return; + } + std::thread([env, callback, context]() { + int32_t errCode = 0; + ani_object result = EtsErrorUtil::CreateErrorByNativeErr(env, errCode); + AppExecFwk::AsyncCallback(env, callback, result, nullptr); + }).detach(); +} + +void EtsAppServiceExtensionContext::SetConnectionRef(ani_object connectOptionsObj) +{ + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "etsVm_ is nullptr"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return; + } + if ((status = env->GlobalReference_Create(connectOptionsObj, &etsConnectionRef_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + } +} + +ani_int EtsAppServiceExtensionContext::OnConnectAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object connectOptionsObj) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "OnConnectAbility call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return FAILED_CODE; + } + AAFwk::Want want; + if (!OHOS::AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to UnwrapWant"); + EtsErrorUtil::ThrowInvalidParamError(env, "Failed to UnwrapWant"); + return FAILED_CODE; + } + std::shared_ptr sharedContext(GetContext(env, aniObj)); + auto connection = std::make_shared(sharedContext); + if (!connection) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to create EtsAppServiceExtensionContext instance"); + return -1; + } + connection->SetConnectionRef(connectOptionsObj); + int32_t connectId = InsertConnection(connection, want); + if (connectId < 0) { + RemoveConnection(connectId); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return -1; + } + return connectId; +} + +void EtsAppServiceExtensionContext::OnDisconnectAbility(ani_env *env, ani_object aniObj, ani_int connectId, + ani_object callback) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "OnDisconnectAbility call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return; + } + auto context = GetContext(env, aniObj); + ani_object errorObject = nullptr; + ErrCode errCode = ERR_OK; + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); + errCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + errorObject = EtsErrorUtil::CreateError(env, static_cast(errCode)); + AppExecFwk::AsyncCallback(env, callback, errorObject, nullptr); + return; + } + std::shared_ptr connection = nullptr; + AAFwk::Want want; + int32_t accountId = -1; + { + std::lock_guard lock(g_connectsMutex); + auto iter = std::find_if( + g_connects.begin(), g_connects.end(), [&connectId](const auto &obj) { return connectId == obj.first.id; }); + if (iter != g_connects.end()) { + want = iter->first.want; + connection = iter->second; + accountId = iter->first.accountId; + g_connects.erase(iter); + } else { + TAG_LOGI(AAFwkTag::SERVICE_EXT, "Failed to found connection"); + } + } + if (!connection) { + errCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + errorObject = EtsErrorUtil::CreateError(env, static_cast(errCode)); + AppExecFwk::AsyncCallback(env, callback, errorObject, nullptr); + return; + } + errCode = static_cast(AbilityErrorCode::ERROR_OK); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, + static_cast(errCode)), nullptr); +} + +ani_object EtsAppServiceExtensionContext::OnStartAbility(ani_env* env, ani_object aniObj, ani_object wantObj, + ani_object optionsObj) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::SERVICE_EXT, "StartAbility"); + auto context = GetContext(env, aniObj); + ErrCode errCode = ERR_OK; + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); + errCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return EtsErrorUtil::CreateError(env, static_cast(errCode)); + } + AAFwk::Want want; + if (!OHOS::AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "parse want failed"); + return EtsErrorUtil::CreateInvalidParamError(env, "Parse param want failed, want must be Want."); + } + AAFwk::StartOptions startOptions; + if (optionsObj != nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "parse startOptions failed"); + return EtsErrorUtil::CreateInvalidParamError(env, "Parse param startOptions failed."); + } + return StartAbilityInner(env, want, startOptions, optionsObj); +} + +AppServiceExtensionContext *EtsAppServiceExtensionContext::GetContext(ani_env *env, ani_object aniObj) +{ + ani_long nativeContextLong; + ani_class cls {}; + ani_field contextField = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return nullptr; + } + if ((status = env->FindClass(CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeContext", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_GetField_Long(aniObj, contextField, &nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status: %{public}d", status); + return nullptr; + } + return reinterpret_cast(nativeContextLong); +} + +ani_object EtsAppServiceExtensionContext::StartAbilityInner(ani_env* env, AAFwk::Want& want, + AAFwk::StartOptions& startOptions, ani_object optionsObj) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "StartAbilityInner called"); + auto context = GetContext(env, optionsObj); + ErrCode errCode = ERR_OK; + if (!context) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); + errCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return EtsErrorUtil::CreateError(env, static_cast(errCode)); + } + errCode = static_cast(AbilityErrorCode::ERROR_OK); + return EtsErrorUtil::CreateError(env, static_cast(errCode)); +} + +ani_object CreateEtsAppServiceExtensionContext(ani_env *env, std::shared_ptr context) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "CreateEtsAppServiceExtensionContext called"); + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object contextObj = nullptr; + if ((env->FindClass(CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", "J:V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status: %{public}d", status); + return nullptr; + } + std::unique_ptr etsContext = + std::make_unique(context); + if ((status = env->Object_New(cls, method, &contextObj, + reinterpret_cast(etsContext.release()))) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status: %{public}d", status); + return nullptr; + } + std::array AppServiceExtensionContext = { + ani_native_function { "nativeConnectServiceExtensionAbility", + "L@ohos/app/ability/Want/Want;Lability/ConnectOptions/ConnectOptions;:D", + reinterpret_cast(EtsAppServiceExtensionContext::OnConnectAbility) }, + ani_native_function { "nativeDisconnectServiceExtensionAbility", + "D;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAppServiceExtensionContext::OnDisconnectAbility) }, + ani_native_function { "nativeStartAbility", + "L@ohos/app/ability/Want/Want;L@ohos/app/ability/StartOptions/StartOptions;" + "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAppServiceExtensionContext::OnStartAbility) }, + ani_native_function { "nativeTerminateSelf", + "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAppServiceExtensionContext::OnTerminateSelf) }, + }; + if ((status = env->Class_BindNativeMethods(cls, AppServiceExtensionContext.data(), + AppServiceExtensionContext.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_SetFieldByName_Long(contextObj, "nativeContext", (ani_long)context.get())) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status: %{public}d", status); + return nullptr; + } + OHOS::AbilityRuntime::ContextUtil::CreateEtsBaseContext(env, cls, contextObj, context); + OHOS::AbilityRuntime::CreateEtsExtensionContext(env, cls, contextObj, context, context->GetAbilityInfo()); + return contextObj; +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ets/BUILD.gn b/frameworks/ets/ets/BUILD.gn index a4eeaf6ce8a00d7b5029441b91d7bd248678e125..db1a3f9d19fb1329f82de43ccc9b34e18f9333d2 100644 --- a/frameworks/ets/ets/BUILD.gn +++ b/frameworks/ets/ets/BUILD.gn @@ -1059,6 +1059,22 @@ ohos_prebuilt_etc("application_state_observer_abc_etc") { deps = [ ":application_state_observer_abc" ] } +generate_static_abc("ability_runtime_app_service_extension_context_abc") { + base_url = "./" + files = [ "./application/AppServiceExtensionContext.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_app_service_extension_context_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_app_service_extension_context_abc_etc") { + source = "$target_out_dir/ability_runtime_app_service_extension_context_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_app_service_extension_context_abc" ] +} + group("ets_packages") { deps = [ ":ability_application_abc_etc", @@ -1081,6 +1097,7 @@ group("ets_packages") { ":ability_runtime_ability_state_data_abc_etc", ":ability_runtime_ability_utils_abc_etc", ":ability_runtime_app_manager_abc_etc", + ":ability_runtime_app_service_extension_context_abc_etc", ":ability_runtime_app_state_data_abc_etc", ":ability_runtime_application_context_abc_etc", ":ability_runtime_auto_fill_type_abc_etc", diff --git a/frameworks/ets/ets/application/AppServiceExtensionContext.ets b/frameworks/ets/ets/application/AppServiceExtensionContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..3da56372340fb3aa03addc0914c25156a2aa9916 --- /dev/null +++ b/frameworks/ets/ets/application/AppServiceExtensionContext.ets @@ -0,0 +1,84 @@ +/* + * 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 { BusinessError } from '@ohos.base'; +import AsyncCallbackWrapper from '../utils/AbilityUtils'; +import ExtensionContext from 'application.ExtensionContext'; +import { ConnectOptions } from 'ability.connectOptions'; +import Want from '@ohos.app.ability.Want'; +import StartOptions from '@ohos.app.ability.StartOptions'; + +export default class AppServiceExtensionContext extends ExtensionContext { + + public native nativeConnectServiceExtensionAbility(want: Want, callback: ConnectOptions): number; + public native nativeDisconnectServiceExtensionAbility(sconnection: number, + callback: AsyncCallbackWrapper): void; + public native nativeStartAbility(want: Want, options: StartOptions, callback: AsyncCallbackWrapper): void; + public native nativeTerminateSelf(callback: AsyncCallbackWrapper): void; + + connectServiceExtensionAbility(want: Want, callback: ConnectOptions): number { + return this.nativeConnectServiceExtensionAbility(want, callback); + } + + disconnectServiceExtensionAbility(connection: number): Promise { + let p = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null) => { + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeDisconnectServiceExtensionAbility(connection, myCall); + }); + }); + return p; + } + + startAbility(want: Want, options: StartOptions): Promise { + let p = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null) => { + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeStartAbility(want, options, myCall); + }); + }); + return p; + } + + terminateSelf(): Promise { + let p = new Promise((resolve:(data: undefined)=>void, reject:(err: BusinessError)=>void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null) => { + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeTerminateSelf(myCall); + }); + }); + return p; + } +} \ No newline at end of file