From 269adb4c024b1cc52d5255cbb6da344b12bc8954 Mon Sep 17 00:00:00 2001 From: zhangzezhong Date: Mon, 4 Aug 2025 10:50:31 +0800 Subject: [PATCH] ani add UIAbilityContext and UIExtensionContext method Signed-off-by: zhangzezhong --- .../ui_ability/include/ets_ability_context.h | 18 ++ .../ui_ability/src/ets_ability_context.cpp | 235 +++++++++++++++- .../include/ets_ui_extension_context.h | 20 ++ .../src/ets_ui_extension_context.cpp | 266 ++++++++++++++++++ .../ets/ets/application/UIAbilityContext.ets | 118 ++++++++ .../ets/application/UIExtensionContext.ets | 67 ++++- frameworks/native/ability/native/BUILD.gn | 3 + 7 files changed, 725 insertions(+), 2 deletions(-) diff --git a/frameworks/ets/ani/ui_ability/include/ets_ability_context.h b/frameworks/ets/ani/ui_ability/include/ets_ability_context.h index 186f4439b07..0680a77766b 100644 --- a/frameworks/ets/ani/ui_ability/include/ets_ability_context.h +++ b/frameworks/ets/ani/ui_ability/include/ets_ability_context.h @@ -89,6 +89,14 @@ public: const std::shared_ptr &config); static void OpenAtomicService( ani_env *env, ani_object aniObj, ani_string aniAppId, ani_object callbackObj, ani_object optionsObj); + static ani_long ConnectServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_int aniAccountId, ani_object connectOptionsObj); + static void StopServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_int aniAccountId, ani_object callbackObj); + static void StopServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callbackObj); + static void StartServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_int aniAccountId, ani_object callbackObj); static void Clean(ani_env *env, ani_object object); static ani_object SetEtsAbilityContext(ani_env *env, std::shared_ptr context); @@ -103,9 +111,11 @@ public: public: static void SetAbilityInstanceInfo(ani_env *env, ani_object aniObj, ani_string labelObj, ani_object iconObj, ani_object callback); + static void SetMissionIcon(ani_env *env, ani_object aniObj, ani_object pixelMapObj, ani_object callbackObj); private: void OnSetAbilityInstanceInfo(ani_env *env, ani_object aniObj, ani_string labelObj, ani_object iconObj, ani_object callback); + void OnSetMissionIcon(ani_env *env, ani_object aniObj, ani_object pixelMapObj, ani_object callbackObj); #endif private: void InheritWindowMode(ani_env *env, ani_object aniObj, AAFwk::Want &want); @@ -139,6 +149,14 @@ private: ani_env *env, ani_object aniObj, ani_string aniType, ani_ref aniWantParam, ani_object startCallback); void OnOpenAtomicService( ani_env *env, ani_object aniObj, ani_string aniAppId, ani_object callbackObj, ani_object optionsObj); + ani_long OnConnectServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_int aniAccountId, ani_object connectOptionsObj); + void OnStopServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_int aniAccountId, ani_object callbackObj); + void OnStopServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callbackObj); + void OnStartServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_int aniAccountId, ani_object callbackObj); void UnWrapOpenLinkOptions(ani_env *env, ani_object optionsObj, AAFwk::OpenLinkOptions &openLinkOptions, AAFwk::Want &want); diff --git a/frameworks/ets/ani/ui_ability/src/ets_ability_context.cpp b/frameworks/ets/ani/ui_ability/src/ets_ability_context.cpp index e069362a5fd..0869f372f96 100644 --- a/frameworks/ets/ani/ui_ability/src/ets_ability_context.cpp +++ b/frameworks/ets/ani/ui_ability/src/ets_ability_context.cpp @@ -35,6 +35,8 @@ #include "ets_ui_extension_callback.h" #include "hilog_tag_wrapper.h" #include "hitrace_meter.h" +#include "ipc_skeleton.h" +#include "tokenid_kit.h" #include "want.h" #ifdef SUPPORT_GRAPHICS #include "pixel_map_taihe_ani.h" @@ -451,6 +453,55 @@ void EtsAbilityContext::OpenAtomicService( etsContext->OnOpenAtomicService(env, aniObj, aniAppId, callbackObj, optionsObj); } +ani_long EtsAbilityContext::ConnectServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_int aniAccountId, ani_object connectOptionsObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "ConnectServiceExtensionAbilityWithAccount called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return FAILED_CODE; + } + return etsContext->OnConnectServiceExtensionAbilityWithAccount(env, aniObj, wantObj, + aniAccountId, connectOptionsObj); +} + +void EtsAbilityContext::StopServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_int aniAccountId, ani_object callbackObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "StopServiceExtensionAbilityWithAccount called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnStopServiceExtensionAbilityWithAccount(env, aniObj, wantObj, aniAccountId, callbackObj); +} + +void EtsAbilityContext::StopServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callbackObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "StopServiceExtensionAbility called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnStopServiceExtensionAbility(env, aniObj, wantObj, callbackObj); +} + +void EtsAbilityContext::StartServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_int aniAccountId, ani_object callbackObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "StartServiceExtensionAbilityWithAccount called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnStartServiceExtensionAbilityWithAccount(env, aniObj, wantObj, aniAccountId, callbackObj); +} + #ifdef SUPPORT_SCREEN void EtsAbilityContext::SetAbilityInstanceInfo(ani_env *env, ani_object aniObj, ani_string labelObj, ani_object iconObj, ani_object callback) @@ -463,6 +514,18 @@ void EtsAbilityContext::SetAbilityInstanceInfo(ani_env *env, ani_object aniObj, } etsContext->OnSetAbilityInstanceInfo(env, aniObj, labelObj, iconObj, callback); } + +void EtsAbilityContext::SetMissionIcon(ani_env *env, ani_object aniObj, ani_object pixelMapObj, + ani_object callbackObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "SetMissionIcon called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnSetMissionIcon(env, aniObj, pixelMapObj, callbackObj); +} #endif int32_t EtsAbilityContext::GenerateRequestCode() @@ -1118,6 +1181,140 @@ void EtsAbilityContext::OnOpenAtomicService( OpenAtomicServiceInner(env, aniObj, want, startOptions, appId, callbackObj); } +ani_long EtsAbilityContext::OnConnectServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_int aniAccountId, ani_object connectOptionsObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "OnConnectServiceExtensionAbilityWithAccount call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null env"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return FAILED_CODE; + } + auto selfToken = IPCSkeleton::GetSelfTokenID(); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { + TAG_LOGE(AAFwkTag::CONTEXT, "non system app forbidden to call"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); + return FAILED_CODE; + } + AAFwk::Want want; + if (!OHOS::AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::CONTEXT, "Failed to UnwrapWant"); + EtsErrorUtil::ThrowInvalidParamError(env, "Failed to UnwrapWant"); + return FAILED_CODE; + } + ani_vm *etsVm = nullptr; + if (env->GetVM(&etsVm) != ANI_OK || etsVm == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "Failed to getVM"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return FAILED_CODE; + } + sptr connection = sptr::MakeSptr(etsVm); + connection->SetConnectionRef(connectOptionsObj); + int32_t connectId = InsertConnection(connection, want, aniAccountId); + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + RemoveConnection(connectId); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return FAILED_CODE; + } + auto innerErrCode = context->ConnectAbilityWithAccount(want, aniAccountId, connection); + int32_t errcode = static_cast(GetJsErrorCodeByNativeError(innerErrCode)); + if (errcode) { + connection->CallEtsFailed(errcode); + RemoveConnection(connectId); + return FAILED_CODE; + } + return static_cast(connectId); +} + +void EtsAbilityContext::OnStopServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_int aniAccountId, ani_object callbackObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "OnStopServiceExtensionAbilityWithAccount call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null env"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INNER), nullptr); + return; + } + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::CONTEXT, "Failed to UnwrapWant"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateInvalidParamError(env, "Failed to UnwrapWant"), nullptr); + return; + } + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "context is nullptr"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT), nullptr); + return; + } + auto innerErrCode = context->StopServiceExtensionAbility(want, aniAccountId); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(innerErrCode)), nullptr); +} + +void EtsAbilityContext::OnStopServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callbackObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "OnStopServiceExtensionAbility call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null env"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INNER), nullptr); + return; + } + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::CONTEXT, "Failed to UnwrapWant"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateInvalidParamError(env, "Failed to UnwrapWant"), nullptr); + return; + } + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "context is nullptr"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT), nullptr); + return; + } + auto innerErrCode = context->StopServiceExtensionAbility(want); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(innerErrCode)), nullptr); +} + +void EtsAbilityContext::OnStartServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_int aniAccountId, ani_object callbackObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "OnStartServiceExtensionAbilityWithAccount call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null env"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INNER), nullptr); + return; + } + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::CONTEXT, "Failed to UnwrapWant"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateInvalidParamError(env, "Failed to UnwrapWant"), nullptr); + return; + } + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "context is nullptr"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT), nullptr); + return; + } + auto innerErrCode = context->StartServiceExtensionAbility(want, aniAccountId); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(innerErrCode)), nullptr); +} + void EtsAbilityContext::AddFreeInstallObserver(ani_env *env, const AAFwk::Want &want, ani_object callback, const std::shared_ptr &context, bool isAbilityResult, bool isOpenLink) { @@ -1423,7 +1620,6 @@ void EtsAbilityContext::OpenAtomicServiceInner(ani_env *env, ani_object aniObj, } } - #ifdef SUPPORT_SCREEN void EtsAbilityContext::OnSetAbilityInstanceInfo(ani_env *env, ani_object aniObj, ani_string labelObj, ani_object iconObj, ani_object callback) @@ -1464,6 +1660,28 @@ void EtsAbilityContext::OnSetAbilityInstanceInfo(ani_env *env, ani_object aniObj } AppExecFwk::AsyncCallback(env, callback, errorObj, nullptr); } + +void EtsAbilityContext::OnSetMissionIcon(ani_env *env, ani_object aniObj, ani_object pixelMapObj, + ani_object callbackObj) +{ + auto pixelMap = OHOS::Media::PixelMapTaiheAni::GetNativePixelMap(env, pixelMapObj); + if (pixelMap == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "Unwrap pixelMap failed"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM), nullptr); + return; + } + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "context is nullptr"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT), nullptr); + return; + } + auto innerErrCode = context->SetMissionIcon(pixelMap); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(innerErrCode)), nullptr); +} #endif namespace { @@ -1529,12 +1747,27 @@ bool BindNativeMethods(ani_env *env, ani_class &cls) reinterpret_cast(EtsAbilityContext::StartAbilityByType) }, ani_native_function { "nativeOpenAtomicService", SIGNATURE_OPEN_ATOMIC_SERVICE, reinterpret_cast(EtsAbilityContext::OpenAtomicService) }, + ani_native_function { "nativeConnectServiceExtensionAbilityWithAccount", + "L@ohos/app/ability/Want/Want;ILability/connectOptions/ConnectOptions;:J", + reinterpret_cast(EtsAbilityContext::ConnectServiceExtensionAbilityWithAccount) }, + ani_native_function { "nativeStopServiceExtensionAbilityWithAccount", + "L@ohos/app/ability/Want/Want;ILutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAbilityContext::StopServiceExtensionAbilityWithAccount) }, + ani_native_function { "nativeStopServiceExtensionAbility", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAbilityContext::StopServiceExtensionAbility) }, + ani_native_function { "nativeStartServiceExtensionAbilityWithAccount", + "L@ohos/app/ability/Want/Want;ILutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAbilityContext::StartServiceExtensionAbilityWithAccount) }, ani_native_function { "nativeChangeAbilityVisibility", "ZLutils/AbilityUtils/AsyncCallbackWrapper;:V", reinterpret_cast(EtsAbilityContext::NativeChangeAbilityVisibility) }, #ifdef SUPPORT_GRAPHICS ani_native_function { "nativeSetAbilityInstanceInfo", "Lstd/core/String;L@ohos/multimedia/image/image/PixelMap;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", reinterpret_cast(EtsAbilityContext::SetAbilityInstanceInfo) }, + ani_native_function { "nativeSetMissionIcon", + "L@ohos/multimedia/image/image/PixelMap;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAbilityContext::SetMissionIcon) }, #endif }; if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { diff --git a/frameworks/ets/ani/ui_extension_ability/include/ets_ui_extension_context.h b/frameworks/ets/ani/ui_extension_ability/include/ets_ui_extension_context.h index 4df327ef93b..8cae81d7021 100644 --- a/frameworks/ets/ani/ui_extension_ability/include/ets_ui_extension_context.h +++ b/frameworks/ets/ani/ui_extension_ability/include/ets_ui_extension_context.h @@ -71,6 +71,13 @@ public: static void StartAbilityForResult(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object callback); static void StartAbilityForResultWithOptions(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object startOptionsObj, ani_object callback); + static void StartServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_int aniAccountId, ani_object callbackObj); + static void StartAbilityForResultAsCaller(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callbackObj, ani_object optionsObj); + static void StartServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_object callbackObj); + static void SetHostPageOverlayForbidden(ani_env *env, ani_object aniObj, ani_boolean aniIsForbidden); static void SetColorMode(ani_env *env, ani_object aniObj, ani_enum_item aniColorMode); static void ReportDrawnCompleted(ani_env *env, ani_object aniObj, ani_object callback); @@ -89,11 +96,24 @@ private: ani_object connectOptionsObj); void OnDisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_long connectId, ani_object callback); + void OnStartServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_int aniAccountId, ani_object callbackObj); + void OnStartAbilityForResultAsCaller(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callbackObj, ani_object optionsObj); + void OnStartServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_object callbackObj); + void OnSetHostPageOverlayForbidden(ani_env *env, ani_object aniObj, ani_boolean aniIsForbidden); + RuntimeTask CreateRuntimeTask(ani_vm *etsVm, ani_ref callbackRef); static bool CheckConnectionParam(ani_env *env, ani_object connectOptionsObj, sptr& connection, AAFwk::Want& want); void OnSetColorMode(ani_env *env, ani_object aniCls, ani_enum_item aniColorMode); void OnReportDrawnCompleted(ani_env *env, ani_object aniCls, ani_object callback); +#ifdef SUPPORT_SCREEN + void InitDisplayId(AAFwk::Want &want); + void InitDisplayId(AAFwk::Want &want, AAFwk::StartOptions &startOptions, ani_env *env, ani_object optionsObj); +#endif + protected: std::weak_ptr context_; sptr freeInstallObserver_ = nullptr; diff --git a/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension_context.cpp b/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension_context.cpp index 59228da3ffe..ed6132221d8 100644 --- a/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension_context.cpp +++ b/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension_context.cpp @@ -25,6 +25,8 @@ #include "ets_context_utils.h" #include "ets_error_utils.h" #include "ets_extension_context.h" +#include "ipc_skeleton.h" +#include "tokenid_kit.h" #include "ui_extension_context.h" @@ -162,6 +164,69 @@ void EtsUIExtensionContext::StartAbilityForResultWithOptions(ani_env *env, ani_o etsUiExtensionContext->OnStartAbilityForResult(env, aniObj, wantObj, startOptionsObj, callback); } +void EtsUIExtensionContext::StartServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_int aniAccountId, ani_object callbackObj) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "StartServiceExtensionAbilityWithAccount called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + auto etsUiExtensionContext = GetEtsUIExtensionContext(env, aniObj); + if (etsUiExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsUiExtensionContext"); + return; + } + etsUiExtensionContext->OnStartServiceExtensionAbilityWithAccount(env, aniObj, wantObj, aniAccountId, callbackObj); +} + +void EtsUIExtensionContext::StartAbilityForResultAsCaller(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callbackObj, ani_object optionsObj) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "StartAbilityForResultAsCaller called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + auto etsUiExtensionContext = GetEtsUIExtensionContext(env, aniObj); + if (etsUiExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsUiExtensionContext"); + return; + } + etsUiExtensionContext->OnStartAbilityForResultAsCaller(env, aniObj, wantObj, callbackObj, optionsObj); +} + +void EtsUIExtensionContext::StartServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_object callbackObj) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "StartServiceExtensionAbility called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + auto etsUiExtensionContext = GetEtsUIExtensionContext(env, aniObj); + if (etsUiExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsUiExtensionContext"); + return; + } + etsUiExtensionContext->OnStartServiceExtensionAbility(env, aniObj, wantObj, callbackObj); +} + +void EtsUIExtensionContext::SetHostPageOverlayForbidden(ani_env *env, ani_object aniObj, ani_boolean aniIsForbidden) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "SetHostPageOverlayForbidden called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + auto etsUiExtensionContext = GetEtsUIExtensionContext(env, aniObj); + if (etsUiExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsUiExtensionContext"); + return; + } + etsUiExtensionContext->OnSetHostPageOverlayForbidden(env, aniObj, aniIsForbidden); +} + void EtsUIExtensionContext::OnTerminateSelf(ani_env *env, ani_object obj, ani_object callback) { ani_object aniObject = nullptr; @@ -486,6 +551,150 @@ bool EtsUIExtensionContext::CheckConnectionParam(ani_env *env, ani_object connec return true; } +void EtsUIExtensionContext::OnStartServiceExtensionAbilityWithAccount(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_int aniAccountId, ani_object callbackObj) +{ + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to UnwrapWant"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateInvalidParamError(env, "Failed to UnwrapWant"), nullptr); + return; + } + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "context is nullptr"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT), nullptr); + return; + } + + auto errCode = context->StartServiceExtensionAbility(want, aniAccountId); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(errCode)), nullptr); +} + +RuntimeTask EtsUIExtensionContext::CreateRuntimeTask(ani_vm *etsVm, ani_ref callbackRef) +{ + return [etsVm, callbackRef] (int resultCode, const AAFwk::Want &want, bool isInner) { + ani_env* env = nullptr; + if (etsVm->GetEnv(ANI_VERSION_1, &env) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetEnv failed in callback"); + return; + } + + ani_object abilityResult = AppExecFwk::WrapAbilityResult(env, resultCode, want); + if (abilityResult == nullptr) { + TAG_LOGW(AAFwkTag::UI_EXT, "null abilityResult"); + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INNER), nullptr); + env->GlobalReference_Delete(callbackRef); + return; + } + + int errCode = isInner ? resultCode : 0; + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + EtsErrorUtil::CreateErrorByNativeErr(env, errCode), abilityResult); + env->GlobalReference_Delete(callbackRef); + }; +} + +void EtsUIExtensionContext::OnStartAbilityForResultAsCaller(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callbackObj, ani_object optionsObj) +{ + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to UnwrapWant"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateInvalidParamError(env, "Failed to UnwrapWant"), nullptr); + return; + } + if (!want.HasParameter(AAFwk::Want::PARAM_BACK_TO_OTHER_MISSION_STACK)) { + want.SetParam(AAFwk::Want::PARAM_BACK_TO_OTHER_MISSION_STACK, true); + } + ani_boolean isUndefined = false; + ani_status status = ANI_OK; + if ((status = env->Reference_IsUndefined(optionsObj, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Reference_IsUndefined status: %{public}d", status); + return; + } + AAFwk::StartOptions startOptions; + if (!isUndefined) { + if (!AppExecFwk::UnwrapStartOptions(env, optionsObj, startOptions)) { + TAG_LOGE(AAFwkTag::UI_EXT, "UnwrapStartOptions filed"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateInvalidParamError(env, "startOptions filed"), nullptr); + return; + } + } + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "context is nullptr"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT), nullptr); + return; + } +#ifdef SUPPORT_SCREEN + (isUndefined) ? InitDisplayId(want) : InitDisplayId(want, startOptions, env, optionsObj); +#endif + ani_vm *etsVm = nullptr; + if ((status = env->GetVM(&etsVm)) != ANI_OK || etsVm == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetVM failed, status: %{public}d", status); + return; + } + ani_ref callbackRef = nullptr; + env->GlobalReference_Create(callbackObj, &callbackRef); + RuntimeTask task = CreateRuntimeTask(etsVm, callbackRef); + want.SetParam(AAFwk::Want::PARAM_RESV_FOR_RESULT, true); + int curRequestCode = context->GenerateCurRequestCode(); + (isUndefined) ? + context->StartAbilityForResultAsCaller(want, curRequestCode, std::move(task)) : + context->StartAbilityForResultAsCaller(want, startOptions, curRequestCode, std::move(task)); +} + +void EtsUIExtensionContext::OnStartServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_object callbackObj) +{ + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to UnwrapWant"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateInvalidParamError(env, "Failed to UnwrapWant"), nullptr); + return; + } + + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "context is nullptr"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT), nullptr); + return; + } + auto errCode = context->StartServiceExtensionAbility(want); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(errCode)), nullptr); +} + +void EtsUIExtensionContext::OnSetHostPageOverlayForbidden(ani_env *env, ani_object aniObj, ani_boolean aniIsForbidden) +{ + bool isNotAllow = static_cast(aniIsForbidden); + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "context is nullptr"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return; + } + + auto selfToken = IPCSkeleton::GetSelfTokenID(); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); + return; + } + + context->isNotAllow = isNotAllow ? 1 : 0; + TAG_LOGD(AAFwkTag::UI_EXT, "SetHostPageOverlayForbidden ok, isNotAllow: %{public}d", isNotAllow); +} + void EtsUIExtensionContext::Clean(ani_env *env, ani_object object) { ani_long ptr = 0; @@ -586,6 +795,51 @@ bool EtsUIExtensionContext::BindNativePtrCleaner(ani_env *env) return true; } +#ifdef SUPPORT_SCREEN +void EtsUIExtensionContext::InitDisplayId(AAFwk::Want &want) +{ + auto context = context_.lock(); + if (!context) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + return; + } + + auto window = context->GetWindow(); + if (window == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null window"); + return; + } + + TAG_LOGI(AAFwkTag::UI_EXT, "window displayId %{public}" PRIu64, window->GetDisplayId()); + want.SetParam(AAFwk::Want::PARAM_RESV_DISPLAY_ID, static_cast(window->GetDisplayId())); +} + +void EtsUIExtensionContext::InitDisplayId(AAFwk::Want &want, AAFwk::StartOptions &startOptions, + ani_env *env, ani_object optionsObj) +{ + auto context = context_.lock(); + if (!context) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + return; + } + + auto window = context->GetWindow(); + if (window == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null window"); + return; + } + + ani_double displayId = 0.0; + if (AppExecFwk::GetFieldDoubleByName(env, optionsObj, "displayId", displayId)) { + TAG_LOGI(AAFwkTag::UI_EXT, "startOption displayId %{public}d", startOptions.GetDisplayID()); + return; + } + + TAG_LOGI(AAFwkTag::UI_EXT, "window displayId %{public}" PRIu64, window->GetDisplayId()); + startOptions.SetDisplayID(window->GetDisplayId()); +} +#endif + ani_object CreateEtsUIExtensionContext(ani_env *env, std::shared_ptr context) { TAG_LOGD(AAFwkTag::UI_EXT, "called"); @@ -629,6 +883,18 @@ ani_object CreateEtsUIExtensionContext(ani_env *env, std::shared_ptr(EtsUIExtensionContext::StartAbilityForResultWithOptions) }, + ani_native_function { "nativeStartServiceExtensionAbilityWithAccount", + "L@ohos/app/ability/Want/Want;ILutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsUIExtensionContext::StartServiceExtensionAbilityWithAccount) }, + ani_native_function { "nativeStartAbilityForResultAsCaller", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;L@ohos/app/" + "ability/StartOptions/StartOptions;:V", + reinterpret_cast(EtsUIExtensionContext::StartAbilityForResultAsCaller) }, + ani_native_function { "nativeStartServiceExtensionAbility", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsUIExtensionContext::StartServiceExtensionAbility) }, + ani_native_function { "nativeSetHostPageOverlayForbidden", "Z:V", + reinterpret_cast(EtsUIExtensionContext::SetHostPageOverlayForbidden) }, ani_native_function{"setColorMode", "L@ohos/app/ability/ConfigurationConstant/ConfigurationConstant/ColorMode;:V", reinterpret_cast(EtsUIExtensionContext::SetColorMode)}, diff --git a/frameworks/ets/ets/application/UIAbilityContext.ets b/frameworks/ets/ets/application/UIAbilityContext.ets index d4798301488..40e440d1d1c 100644 --- a/frameworks/ets/ets/application/UIAbilityContext.ets +++ b/frameworks/ets/ets/application/UIAbilityContext.ets @@ -139,6 +139,20 @@ export default class UIAbilityContext extends Context { private native nativeSetAbilityInstanceInfo(label: string, icon: image.PixelMap, callback: AsyncCallbackWrapper): void; private native nativeOpenAtomicService(appId: string, callback: AsyncCallbackWrapper, options?: AtomicServiceOptions): void; + + private native nativeConnectServiceExtensionAbilityWithAccount(want: Want, accountId: int, + options: ConnectOptions): long; + + private native nativeStopServiceExtensionAbilityWithAccount(want: Want, accountId: int, + callback: AsyncCallbackWrapper): void; + + private native nativeStopServiceExtensionAbility(want: Want, callback: AsyncCallbackWrapper): void; + + private native nativeStartServiceExtensionAbilityWithAccount(want: Want, accountId: int, + callback: AsyncCallbackWrapper): void; + + private native nativeSetMissionIcon(icon: image.PixelMap, callback: AsyncCallbackWrapper): void; + startAbility(want: Want, callback: AsyncCallback): void { let myCall = new AsyncCallbackWrapper(callback); taskpool.execute((): void => { @@ -519,4 +533,108 @@ hideAbility(): Promise { }); return p; } + + connectServiceExtensionAbilityWithAccount(want: Want, accountId: int, options: ConnectOptions): long { + return this.nativeConnectServiceExtensionAbilityWithAccount(want, accountId, options); + } + + stopServiceExtensionAbilityWithAccount(want: Want, accountId: int, callback: AsyncCallback): void { + let syncCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStopServiceExtensionAbilityWithAccount(want, accountId, syncCall); + }); + } + + stopServiceExtensionAbilityWithAccount(want: Want, accountId: int): Promise { + let p = new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let callback = new AsyncCallbackWrapper((err: BusinessError | null) => { + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeStopServiceExtensionAbilityWithAccount(want, accountId, callback); + }).catch((err: Error): void => { + reject(err as BusinessError); + }); + }); + return p; + } + + stopServiceExtensionAbility(want: Want, callback: AsyncCallback): void { + let syncCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStopServiceExtensionAbility(want, syncCall); + }); + } + + stopServiceExtensionAbility(want: Want): Promise { + let p = new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let callback = new AsyncCallbackWrapper((err: BusinessError | null) => { + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeStopServiceExtensionAbility(want, callback); + }).catch((err: Error): void => { + reject(err as BusinessError); + }); + }); + return p; + } + + startServiceExtensionAbilityWithAccount(want: Want, accountId: int, callback: AsyncCallback): void { + let syncCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartServiceExtensionAbilityWithAccount(want, accountId, syncCall); + }); + } + + startServiceExtensionAbilityWithAccount(want: Want, accountId: int): Promise { + let p = new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let callback = new AsyncCallbackWrapper((err: BusinessError | null) => { + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeStartServiceExtensionAbilityWithAccount(want, accountId, callback); + }).catch((err: Error): void => { + reject(err as BusinessError); + }); + }); + return p; + } + + setMissionIcon(icon: image.PixelMap, callback: AsyncCallback): void { + let syncCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeSetMissionIcon(icon, syncCall); + }); + } + + setMissionIcon(icon: image.PixelMap): Promise { + let p = new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let callback = new AsyncCallbackWrapper((err: BusinessError | null) => { + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeSetMissionIcon(icon, callback); + }).catch((err: Error): void => { + reject(err as BusinessError); + }); + }); + return p; + } } diff --git a/frameworks/ets/ets/application/UIExtensionContext.ets b/frameworks/ets/ets/application/UIExtensionContext.ets index fc684e9764f..b6955ccb25c 100644 --- a/frameworks/ets/ets/application/UIExtensionContext.ets +++ b/frameworks/ets/ets/application/UIExtensionContext.ets @@ -58,10 +58,15 @@ export default class UIExtensionContext extends ExtensionContext { native nativeStartAbility(want: Want, options: StartOptions, callback:AsyncCallbackWrapper): void; private native nativeConnectServiceExtensionAbility(want: Want, options: ConnectOptions): long; private native nativeDisconnectServiceExtensionAbilitySync(connection: long, callback: AsyncCallbackWrapper): void; - private native nativeStartAbilityForResultAsCaller(want: Want, callback: AsyncCallbackWrapper, options?: StartOptions): void; private native nativeStartAbilityForResult(want: Want, callback:AsyncCallbackWrapper): void; private native nativeStartAbilityForResult(want: Want, startOptions: StartOptions, callback:AsyncCallbackWrapper): void; + private native nativeStartServiceExtensionAbilityWithAccount(want: Want, accountId: int, + callback: AsyncCallbackWrapper): void; + private native nativeStartAbilityForResultAsCaller(want: Want, + callback: AsyncCallbackWrapper, options?: StartOptions): void; + private native nativeStartServiceExtensionAbility(want: Want, callback: AsyncCallbackWrapper): void; + private native nativeSetHostPageOverlayForbidden(isForbidden: boolean): void; native setColorMode(colorMode: ConfigurationConstant.ColorMode): void; native nativeReportDrawnCompleted(callback:AsyncCallbackWrapper): void; @@ -215,4 +220,64 @@ export default class UIExtensionContext extends ExtensionContext { this.nativeReportDrawnCompleted(myCall); }); } + + startServiceExtensionAbilityWithAccount(want: Want, accountId: int): 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.nativeStartServiceExtensionAbilityWithAccount(want, accountId, myCall); + }).catch((err: Error): void => { + reject(err as BusinessError); + }); + }); + return p; + } + + startAbilityForResultAsCaller(want: Want, options?: StartOptions): Promise { + let p = new Promise((resolve: (data: AbilityResult) => void, + reject: (err: BusinessError) => void): void => { + let myCall = + new AsyncCallbackWrapper((err: BusinessError | null, data: AbilityResult | undefined) => { + if (err == null || err.code == 0) { + resolve(data as AbilityResult); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeStartAbilityForResultAsCaller(want, myCall, options); + }).catch((err: Error): void => { + reject(err as BusinessError); + }); + }); + return p; + } + + startServiceExtensionAbility(want: Want): 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.nativeStartServiceExtensionAbility(want, myCall); + }).catch((err: Error): void => { + reject(err as BusinessError); + }); + }); + return p; + } + + setHostPageOverlayForbidden(isForbidden: boolean) : void { + this.nativeSetHostPageOverlayForbidden(isForbidden); + } } \ No newline at end of file diff --git a/frameworks/native/ability/native/BUILD.gn b/frameworks/native/ability/native/BUILD.gn index c08f25d7acb..0e776deebb8 100644 --- a/frameworks/native/ability/native/BUILD.gn +++ b/frameworks/native/ability/native/BUILD.gn @@ -919,6 +919,9 @@ ohos_shared_library("ui_ability_ani") { "ability_base:base", "ability_base:configuration", "ability_base:want", + "access_token:libaccesstoken_sdk", + "access_token:libtoken_callback_sdk", + "access_token:libtokenid_sdk", "bundle_framework:appexecfwk_base", "bundle_framework:bms_ani_common", "c_utils:utils", -- Gitee