From 82342ac0e818f452917736249e778ffff5cfd06d Mon Sep 17 00:00:00 2001 From: zhangzezhong Date: Tue, 8 Jul 2025 16:00:59 +0800 Subject: [PATCH] add ets interface code Signed-off-by: zhangzezhong --- bundle.json | 11 + .../ets_environment/src/ets_environment.cpp | 16 +- frameworks/ets/ani/BUILD.gn | 6 + .../include/ets_ability_delegator.h | 88 +- .../include/ets_ability_delegator_registry.h | 22 + .../include/ets_ability_monitor.h | 8 +- .../include/ets_ability_stage_monitor.h | 42 + .../src/ets_ability_delegator.cpp | 926 +++++++++++++++--- .../src/ets_ability_delegator_registry.cpp | 25 +- .../src/ets_ability_delegator_utils.cpp | 89 +- .../src/ets_ability_monitor.cpp | 6 +- frameworks/ets/ani/ability_manager/BUILD.gn | 68 ++ .../include/ets_ability_manager.h | 26 + .../src/ets_ability_manager.cpp | 164 ++++ frameworks/ets/ani/ani_common/BUILD.gn | 12 + .../include/ani_common_ability_state_data.h | 31 + .../include/ani_common_configuration.h | 4 +- .../include/ani_common_execute_param.h | 28 + .../include/ani_common_execute_result.h | 30 + .../include/ani_common_start_options.h | 15 + .../ani/ani_common/include/ani_common_util.h | 24 + .../ani/ani_common/include/ani_common_want.h | 4 + .../include/ets_application_context_utils.h | 33 +- .../ani_common/include/ets_context_utils.h | 4 + .../include}/ets_extension_context.h | 0 .../include}/ets_free_install_observer.h | 0 .../src/ani_common_ability_state_data.cpp | 155 +++ .../src/ani_common_execute_param.cpp | 122 +++ .../src/ani_common_execute_result.cpp | 178 ++++ .../src/ani_common_start_options.cpp | 264 ++++- .../ani/ani_common/src/ani_common_util.cpp | 646 +++++++++++- .../ani/ani_common/src/ani_common_want.cpp | 91 +- .../src/ets_application_context_utils.cpp | 482 ++++++++- .../ani/ani_common/src/ets_context_utils.cpp | 190 +++- .../src/ets_data_struct_converter.cpp | 62 +- .../ani/ani_common/src/ets_error_utils.cpp | 3 +- .../ani_common/src}/ets_extension_context.cpp | 32 + .../src}/ets_free_install_observer.cpp | 0 .../ets/ani/ani_wantagent_common/BUILD.gn | 50 + .../ani_common_want_agent.cpp | 102 ++ .../ani_common_want_agent.h | 29 + frameworks/ets/ani/app_manager/BUILD.gn | 79 ++ .../ani/app_manager/include/ets_app_manager.h | 26 + .../include/ets_app_manager_utils.h | 52 + .../ani/app_manager/src/ets_app_manager.cpp | 396 ++++++++ .../app_manager/src/ets_app_manager_utils.cpp | 685 +++++++++++++ frameworks/ets/ani/application/BUILD.gn | 62 ++ .../ani/application/include/ets_application.h | 33 + .../ani/application/src/ets_application.cpp | 302 ++++++ .../insight_intent_driver/BUILD.gn | 69 ++ .../include/ets_insight_intent_driver.h | 26 + .../src/ets_insight_intent_driver.cpp | 227 +++++ .../context_native_constructor.cpp | 17 + .../include/ets_service_extension.h | 12 + .../include/ets_service_extension_context.h | 67 ++ .../src/ets_service_extension.cpp | 211 +++- .../src/ets_service_extension_context.cpp | 394 ++++++++ .../ui_ability/include}/ets_ability_context.h | 41 +- .../ani/ui_ability/include}/ets_ui_ability.h | 58 +- .../ui_ability/src}/ets_ability_context.cpp | 541 +++++++--- .../ani/ui_ability/src}/ets_ui_ability.cpp | 217 +++- .../include/ets_ui_extension.h | 13 +- .../ets_ui_extension_content_session.h | 25 +- .../include/ets_ui_extension_context.h | 27 +- .../src/ets_ui_extension.cpp | 89 +- .../src/ets_ui_extension_content_session.cpp | 229 ++++- .../src/ets_ui_extension_context.cpp | 292 ++++-- .../include/ets_uri_perm_mgr.h | 6 +- .../src/ets_uri_perm_mgr.cpp | 14 +- frameworks/ets/ani/wantagent/BUILD.gn | 61 ++ .../ani/wantagent/include/ani_want_agent.h | 101 ++ .../ets/ani/wantagent/src/ani_want_agent.cpp | 698 +++++++++++++ .../ets/@ohos.app.ability.AbilityConstant.ets | 24 + ...@ohos.app.ability.InsightIntentContext.ets | 54 + ...ohos.app.ability.InsightIntentExecutor.ets | 147 +++ .../ets/@ohos.app.ability.OpenLinkOptions.ets | 24 + ...os.app.ability.ServiceExtensionAbility.ets | 8 + .../ets/@ohos.app.ability.StartOptions.ets | 22 +- .../ets/ets/@ohos.app.ability.UIAbility.ets | 6 + ....app.ability.UIExtensionContentSession.ets | 33 + ...s.app.ability.abilityDelegatorRegistry.ets | 13 + .../ets/@ohos.app.ability.abilityManager.ets | 72 ++ .../ets/ets/@ohos.app.ability.appManager.ets | 180 ++++ .../ets/ets/@ohos.app.ability.application.ets | 78 ++ .../ets/@ohos.app.ability.insightIntent.ets | 43 + .../@ohos.app.ability.insightIntentDriver.ets | 67 ++ .../ets/ets/@ohos.app.ability.wantAgent.ets | 344 +++++++ frameworks/ets/ets/BUILD.gn | 343 ++++++- .../ets/ets/application/AbilityDelegator.ets | 318 ++++++ .../ets/application/AbilityStageContext.ets | 12 +- .../ets/application/AbilityStageMonitor.ets | 24 + .../ets/ets/application/AbilityStateData.ets | 26 + .../ets/ets/application/AppStateData.ets | 21 + .../ets/application/ApplicationContext.ets | 175 ++++ frameworks/ets/ets/application/Context.ets | 33 + .../ets/ets/application/ExtensionContext.ets | 8 +- .../ets/ets/application/MultiAppMode.ets | 19 + .../ets/ets/application/ProcessData.ets | 22 + .../ets/application/ProcessInformation.ets | 38 + .../ets/ets/application/RunningAppClone.ets | 25 + .../ets/application/RunningMultiAppInfo.ets | 32 + .../application/RunningMultiInstanceInfo.ets | 21 + .../application/ServiceExtensionContext.ets | 149 ++- .../ets/ets/application/UIAbilityContext.ets | 129 ++- .../ets/application/UIExtensionContext.ets | 61 ++ frameworks/ets/ets/wantAgent/triggerInfo.ets | 35 + .../ets/ets/wantAgent/wantAgentInfo.ets | 44 + .../js_ability_delegator.cpp | 7 +- frameworks/native/ability/native/BUILD.gn | 67 +- .../native/ability_runtime/js_ui_ability.cpp | 80 +- .../ets_insight_intent_executor.cpp | 505 ++++++++++ .../ets_insight_intent_executor_instance.cpp | 54 + .../insight_intent_executor.cpp | 4 + .../insight_intent_executor_mgr.cpp | 8 +- .../ability/native/js_service_extension.cpp | 58 -- .../ability/native/service_extension.cpp | 53 + .../native/ability/native/ui_ability.cpp | 24 + frameworks/native/appkit/BUILD.gn | 1 + .../ability_delegator/ability_delegator.cpp | 6 +- .../iability_stage_monitor.cpp | 6 +- .../ability_runtime/app/ets_ability_stage.cpp | 4 +- .../app/ets_ability_stage_context.cpp | 1 - .../ets_insight_intent_context.cpp | 168 ++++ .../ani_base_context/src/ani_base_context.cpp | 11 +- .../ets_insight_intent_context.h | 57 ++ .../native/ability_runtime/js_ui_ability.h | 2 +- .../ets_insight_intent_executor.h | 120 +++ .../ets_insight_intent_executor_instance.h | 29 + .../insight_intent_executor.h | 6 + .../insight_intent_executor_info.h | 1 + .../ability/native/js_service_extension.h | 6 - .../native/ability/native/service_extension.h | 26 + .../kits/native/ability/native/ui_ability.h | 4 + .../ability_delegator/ability_delegator.h | 6 +- .../ability_delegator_infos.h | 11 +- .../iability_stage_monitor.h | 8 +- .../ability_runtime/app/ets_ability_stage.h | 2 +- .../app/ets_ability_stage_context.h | 1 + .../BUILD.gn | 9 +- .../ui_ability_test.cpp | 67 ++ 140 files changed, 12435 insertions(+), 785 deletions(-) create mode 100644 frameworks/ets/ani/ability_delegator/include/ets_ability_stage_monitor.h create mode 100644 frameworks/ets/ani/ability_manager/BUILD.gn create mode 100644 frameworks/ets/ani/ability_manager/include/ets_ability_manager.h create mode 100644 frameworks/ets/ani/ability_manager/src/ets_ability_manager.cpp create mode 100644 frameworks/ets/ani/ani_common/include/ani_common_ability_state_data.h create mode 100644 frameworks/ets/ani/ani_common/include/ani_common_execute_param.h create mode 100644 frameworks/ets/ani/ani_common/include/ani_common_execute_result.h rename {interfaces/kits/native/ability/ability_runtime => frameworks/ets/ani/ani_common/include}/ets_extension_context.h (100%) rename {interfaces/kits/native/ability/native => frameworks/ets/ani/ani_common/include}/ets_free_install_observer.h (100%) create mode 100644 frameworks/ets/ani/ani_common/src/ani_common_ability_state_data.cpp create mode 100644 frameworks/ets/ani/ani_common/src/ani_common_execute_param.cpp create mode 100644 frameworks/ets/ani/ani_common/src/ani_common_execute_result.cpp rename frameworks/{native/ability/ability_runtime => ets/ani/ani_common/src}/ets_extension_context.cpp (74%) rename frameworks/{native/ability/native => ets/ani/ani_common/src}/ets_free_install_observer.cpp (100%) create mode 100644 frameworks/ets/ani/ani_wantagent_common/BUILD.gn create mode 100644 frameworks/ets/ani/ani_wantagent_common/ani_common_want_agent.cpp create mode 100644 frameworks/ets/ani/ani_wantagent_common/ani_common_want_agent.h create mode 100644 frameworks/ets/ani/app_manager/BUILD.gn create mode 100644 frameworks/ets/ani/app_manager/include/ets_app_manager.h create mode 100644 frameworks/ets/ani/app_manager/include/ets_app_manager_utils.h create mode 100644 frameworks/ets/ani/app_manager/src/ets_app_manager.cpp create mode 100644 frameworks/ets/ani/app_manager/src/ets_app_manager_utils.cpp create mode 100644 frameworks/ets/ani/application/BUILD.gn create mode 100644 frameworks/ets/ani/application/include/ets_application.h create mode 100644 frameworks/ets/ani/application/src/ets_application.cpp create mode 100644 frameworks/ets/ani/insight_intent/insight_intent_driver/BUILD.gn create mode 100644 frameworks/ets/ani/insight_intent/insight_intent_driver/include/ets_insight_intent_driver.h create mode 100644 frameworks/ets/ani/insight_intent/insight_intent_driver/src/ets_insight_intent_driver.cpp create mode 100644 frameworks/ets/ani/service_extension_ability/include/ets_service_extension_context.h create mode 100644 frameworks/ets/ani/service_extension_ability/src/ets_service_extension_context.cpp rename {interfaces/kits/native/ability/native/ability_runtime => frameworks/ets/ani/ui_ability/include}/ets_ability_context.h (60%) rename {interfaces/kits/native/ability/native/ability_runtime => frameworks/ets/ani/ui_ability/include}/ets_ui_ability.h (74%) rename frameworks/{native/ability/native/ability_runtime => ets/ani/ui_ability/src}/ets_ability_context.cpp (47%) rename frameworks/{native/ability/native/ability_runtime => ets/ani/ui_ability/src}/ets_ui_ability.cpp (78%) create mode 100644 frameworks/ets/ani/wantagent/BUILD.gn create mode 100644 frameworks/ets/ani/wantagent/include/ani_want_agent.h create mode 100644 frameworks/ets/ani/wantagent/src/ani_want_agent.cpp create mode 100644 frameworks/ets/ets/@ohos.app.ability.InsightIntentContext.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.InsightIntentExecutor.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.OpenLinkOptions.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.abilityManager.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.appManager.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.application.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.insightIntent.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.insightIntentDriver.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.wantAgent.ets create mode 100644 frameworks/ets/ets/application/AbilityStageMonitor.ets create mode 100644 frameworks/ets/ets/application/AbilityStateData.ets create mode 100644 frameworks/ets/ets/application/AppStateData.ets create mode 100644 frameworks/ets/ets/application/MultiAppMode.ets create mode 100644 frameworks/ets/ets/application/ProcessData.ets create mode 100644 frameworks/ets/ets/application/ProcessInformation.ets create mode 100644 frameworks/ets/ets/application/RunningAppClone.ets create mode 100644 frameworks/ets/ets/application/RunningMultiAppInfo.ets create mode 100644 frameworks/ets/ets/application/RunningMultiInstanceInfo.ets create mode 100644 frameworks/ets/ets/wantAgent/triggerInfo.ets create mode 100644 frameworks/ets/ets/wantAgent/wantAgentInfo.ets create mode 100644 frameworks/native/ability/native/insight_intent_executor/ets_insight_intent_executor.cpp create mode 100644 frameworks/native/ability/native/insight_intent_executor/ets_insight_intent_executor_instance.cpp create mode 100644 frameworks/native/insight_intent/insight_intent_context/ets_insight_intent_context.cpp create mode 100644 interfaces/inner_api/insight_intent/insight_intent_context/ets_insight_intent_context.h create mode 100644 interfaces/kits/native/ability/native/insight_intent_executor/ets_insight_intent_executor.h create mode 100644 interfaces/kits/native/ability/native/insight_intent_executor/ets_insight_intent_executor_instance.h diff --git a/bundle.json b/bundle.json index 7061fe242fb..e039ef051df 100644 --- a/bundle.json +++ b/bundle.json @@ -127,6 +127,7 @@ "//foundation/ability/ability_runtime/interfaces/inner_api:innerkits_target", "//foundation/ability/ability_runtime/frameworks/native/ability/native:ability_thread", "//foundation/ability/ability_runtime/frameworks/native/ability/native:extension_module", + "//foundation/ability/ability_runtime/frameworks/native/ability/native:insight_intent_executor_ani", "//foundation/ability/ability_runtime/frameworks/native/ability/native:service_extension_ani", "//foundation/ability/ability_runtime/frameworks/native/ability/native:ui_ability_ani", "//foundation/ability/ability_runtime/frameworks/native/ability/native:ui_extension_ani", @@ -342,6 +343,7 @@ "header": { "header_base": "//foundation/ability/ability_runtime/frameworks/ets/ani/ani_common/include", "header_files": [ + "ani_common_ability_state_data.h", "ani_common_start_options.h", "ani_common_want.h", "ets_native_reference.h" @@ -357,6 +359,15 @@ }, "name": "//foundation/ability/ability_runtime/frameworks/js/napi/inner/napi_ability_common:napi_ability_common" }, + { + "header": { + "header_base": "//foundation/ability/ability_runtime/frameworks/ets/ani/ani_wantagent_common", + "header_files": [ + "ani_common_want_agent.h" + ] + }, + "name": "//foundation/ability/ability_runtime/frameworks/ets/ani/ani_wantagent_common:ani_wantagent_common" + }, { "header": { "header_base": "//foundation/ability/ability_runtime/frameworks/js/napi/inner/napi_wantagent_common", diff --git a/ets_environment/frameworks/ets_environment/src/ets_environment.cpp b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp index 446d1318252..1a0e9bb2116 100644 --- a/ets_environment/frameworks/ets_environment/src/ets_environment.cpp +++ b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp @@ -48,6 +48,9 @@ using ANIGetCreatedVMsType = ani_status (*)(ani_vm **vms_buffer, ani_size vms_bu const char ETS_SDK_NSNAME[] = "ets_sdk"; const char ETS_SYS_NSNAME[] = "ets_system"; + +constexpr const char* CLASSNAME_STRING = "Lstd/core/String;"; +constexpr const char* CLASSNAME_LINKER = "Lstd/core/AbcRuntimeLinker;"; } // namespace ETSRuntimeAPI ETSEnvironment::lazyApis_ {}; @@ -248,7 +251,14 @@ bool ETSEnvironment::Initialize(void *napiEnv, const std::string &aotPath) ani_env *ETSEnvironment::GetAniEnv() { - return vmEntry_.aniEnv_; + if (vmEntry_.aniVm_ == nullptr) { + return nullptr; + } + ani_env* env = nullptr; + if (vmEntry_.aniVm_->GetEnv(ANI_VERSION_1, &env) != ANI_OK) { + return nullptr; + } + return env; } bool ETSEnvironment::HandleUncaughtError() @@ -384,7 +394,7 @@ bool ETSEnvironment::LoadAbcLinker(ani_env *env, const std::string &modulePath, } ani_status status = ANI_ERROR; ani_class stringCls = nullptr; - if ((status = env->FindClass("Lstd/core/String;", &stringCls)) != ANI_OK) { + if ((status = env->FindClass(CLASSNAME_STRING, &stringCls)) != ANI_OK) { TAG_LOGE(AAFwkTag::ETSRUNTIME, "FindClass failed, status: %{public}d", status); return false; } @@ -407,7 +417,7 @@ bool ETSEnvironment::LoadAbcLinker(ani_env *env, const std::string &modulePath, TAG_LOGE(AAFwkTag::ETSRUNTIME, "Array_Set_Ref failed, status: %{public}d", status); return false; } - if ((status = env->FindClass("Lstd/core/AbcRuntimeLinker;", &abcCls)) != ANI_OK) { + if ((status = env->FindClass(CLASSNAME_LINKER, &abcCls)) != ANI_OK) { TAG_LOGE(AAFwkTag::ETSRUNTIME, "FindClass failed, status: %{public}d", status); return false; } diff --git a/frameworks/ets/ani/BUILD.gn b/frameworks/ets/ani/BUILD.gn index 2d2fb6e34bf..66495ae24bf 100644 --- a/frameworks/ets/ani/BUILD.gn +++ b/frameworks/ets/ani/BUILD.gn @@ -17,8 +17,14 @@ import("//foundation/ability/ability_runtime/ability_runtime.gni") group("ani_packages") { deps = [ "${ability_runtime_path}/frameworks/ets/ani/ability_delegator:ability_delegator_registry_ani_kit", + "${ability_runtime_path}/frameworks/ets/ani/ability_manager:ability_manager_ani_kit", "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_path}/frameworks/ets/ani/ani_wantagent_common:ani_wantagent_common", + "${ability_runtime_path}/frameworks/ets/ani/application:application_ani", + "${ability_runtime_path}/frameworks/ets/ani/app_manager:app_manager_ani", + "${ability_runtime_path}/frameworks/ets/ani/insight_intent/insight_intent_driver:insight_intent_driver_ani_kit", "${ability_runtime_path}/frameworks/ets/ani/native_constructor:context_ani", "${ability_runtime_path}/frameworks/ets/ani/uri_permission_manager:uri_permission_manager_ani_kit", + "${ability_runtime_path}/frameworks/ets/ani/wantagent:aniwantagent", ] } diff --git a/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator.h b/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator.h index 9a6e093e35a..e12f6373798 100644 --- a/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator.h +++ b/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator.h @@ -19,54 +19,98 @@ #include #include "ability_delegator.h" #include "ani.h" -#include "context.h" #include "ets_ability_delegator_registry.h" #include "ets_ability_monitor.h" +#include "ets_ability_stage_monitor.h" #include "iability_monitor.h" +#include "ets_runtime.h" #include "want.h" namespace OHOS { namespace AbilityDelegatorEts { using namespace OHOS::AbilityRuntime; class EtsAbilityDelegator { public: - static EtsAbilityDelegator& GetInstance() - { - static EtsAbilityDelegator instance; - return instance; - } EtsAbilityDelegator(); ~EtsAbilityDelegator(); - static void ExecuteShellCommand(ani_env* env, [[maybe_unused]]ani_object object, - ani_string cmd, ani_double timeoutSecs, ani_object callback); + static void ExecuteShellCommand(ani_env *env, ani_string cmd, ani_double timeoutSecs, ani_object callback); - static void FinishTest(ani_env* env, [[maybe_unused]]ani_object object, - ani_string msg, ani_double code, ani_object callback); + static void FinishTest(ani_env *env, ani_string msg, ani_double code, ani_object callback); - static ani_object CreateEtsBaseContext(ani_env* aniEnv, ani_class contextClass, - std::shared_ptr context); + static ani_object SetAppContext(ani_env *env, const std::shared_ptr &context); - static ani_object GetAppContext(ani_env* env, [[maybe_unused]]ani_object object, ani_class clss); + static ani_object GetAppContext(ani_env *env, ani_class clss); - static void PrintSync(ani_env *env, [[maybe_unused]]ani_class aniClass, ani_string msg); + static void PrintSync(ani_env *env, ani_string msg); - static void AddAbilityMonitor(ani_env *env, [[maybe_unused]]ani_class aniClass, - ani_object monitorObj, ani_object callback); + static void AddAbilityMonitor(ani_env *env, ani_object monitorObj, ani_object callback); - static void StartAbility(ani_env* env, [[maybe_unused]]ani_object object, ani_object wantObj, ani_object callback); + static void AddAbilityMonitorSync(ani_env *env, ani_object monitorObj); + + static void RemoveAbilityMonitor(ani_env *env, ani_object monitorObj, ani_object callback); + + static void RemoveAbilityMonitorSync(ani_env *env, ani_object monitorObj); + + static void WaitAbilityMonitor(ani_env *env, ani_object monitorOb0, ani_double timeout, ani_object callback); + + static void AddAbilityStageMonitor(ani_env *env, ani_object stageMonitorObj, ani_object callback); + + static void AddAbilityStageMonitorSync(ani_env *env, ani_object stageMonitorObj); + + static void RemoveAbilityStageMonitor(ani_env *env, ani_object stageMonitorObj, ani_object callback); + + static void RemoveAbilityStageMonitorSync(ani_env *env, ani_object stageMonitorObj); + + static void WaitAbilityStageMonitor(ani_env *env, ani_object stageMonitorObj, ani_double timeout, + ani_object callback); + + static void DoAbilityForeground(ani_env *env, ani_object abilityObj, ani_object callback); + + static void DoAbilityBackground(ani_env *env, ani_object abilityObj, ani_object callback); + + static void Print(ani_env *env, ani_string msg, ani_object callback); + + static ani_double GetAbilityState(ani_env *env, ani_object abilityObj); + + static void StartAbility(ani_env *env, ani_object wantObj, ani_object callback); + + static ani_ref GetCurrentTopAbility(ani_env* env, ani_object callback); private: - [[maybe_unused]] void RetrieveStringFromAni(ani_env *env, ani_string string, std::string &resString); + static void RetrieveStringFromAni(ani_env *env, ani_string string, std::string &resString); - ani_object WrapShellCmdResult(ani_env* env, std::unique_ptr result); + static ani_object WrapShellCmdResult(ani_env *env, std::unique_ptr result); - bool ParseMonitorPara(ani_env *env, ani_object monitorObj, + static bool ParseMonitorPara(ani_env *env, ani_object monitorObj, std::shared_ptr &monitorImpl); - bool ParseMonitorParaInner(ani_env *env, ani_object monitorObj, + static bool ParseMonitorParaInner(ani_env *env, ani_object monitorObj, std::shared_ptr &monitorImpl); + static bool ParseStageMonitorPara(ani_env *env, ani_object stageMonitorObj, + std::shared_ptr &stageMonitor, bool &isExisted); + + static bool ParseStageMonitorParaInner(ani_env *env, ani_object stageMonitorObj, + std::shared_ptr &stageMonitor); + + static void AddStageMonitorRecord(ani_env *env, ani_object stageMonitorObj, + const std::shared_ptr &stageMonitor); + + static void RemoveStageMonitorRecord(ani_env *env, ani_object stageMonitorObj); + + static bool ParseWaitAbilityStageMonitorPara(ani_env *env, ani_object stageMonitorObj, + std::shared_ptr &stageMonitor); + + static bool ParseAbilityCommonPara(ani_env *env, ani_object abilityObj, sptr &remoteObject); + + static void AbilityLifecycleStateToEts(const AbilityDelegator::AbilityState &lifeState, + AbilityLifecycleState &abilityLifeState); + + static bool CheckPropertyValue(ani_env *env, int &resultCode, ani_object &resultAniOj, + std::shared_ptr etsProperty); + + static void CleanAndFindMonitorRecord(ani_env *env, ani_object monitorObj); }; } // namespace AbilityDelegatorEts } // namespace OHOS -#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_DELEGATOR_H +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_DELEGATOR_H diff --git a/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator_registry.h b/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator_registry.h index 866fcd7948d..972e6298240 100644 --- a/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator_registry.h +++ b/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator_registry.h @@ -20,6 +20,28 @@ namespace OHOS { namespace AbilityDelegatorEts { +enum class AbilityLifecycleState { + /** + * Indicates that the ability has not been initialized. + */ + UNINITIALIZED, + /** + * Indicates that the ability is in the created state. + */ + CREATE, + /** + * Indicates that the ability is in the foreground state. + */ + FOREGROUND, + /** + * Indicates that the ability is in the background state. + */ + BACKGROUND, + /** + * Indicates that the ability is in the destroyed state. + */ + DESTROY, +}; void EtsAbilityDelegatorRegistryInit(ani_env *env); } // namespace AbilityDelegatorEts } // namespace OHOS diff --git a/frameworks/ets/ani/ability_delegator/include/ets_ability_monitor.h b/frameworks/ets/ani/ability_delegator/include/ets_ability_monitor.h index b04a9f4371d..d5e7e0c6349 100644 --- a/frameworks/ets/ani/ability_delegator/include/ets_ability_monitor.h +++ b/frameworks/ets/ani/ability_delegator/include/ets_ability_monitor.h @@ -130,11 +130,11 @@ private: const std::weak_ptr &abilityObj); private: - ani_vm* vm_ = nullptr; + ani_vm *vm_ = nullptr; std::string abilityName_; std::string moduleName_; std::unique_ptr etsAbilityMonitor_; }; -} // namespace AbilityDelegatorJs -} // namespace OHOS -#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_MONITOR_H +} // namespace AbilityDelegatorJs +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_MONITOR_H diff --git a/frameworks/ets/ani/ability_delegator/include/ets_ability_stage_monitor.h b/frameworks/ets/ani/ability_delegator/include/ets_ability_stage_monitor.h new file mode 100644 index 00000000000..8d7e275e56f --- /dev/null +++ b/frameworks/ets/ani/ability_delegator/include/ets_ability_stage_monitor.h @@ -0,0 +1,42 @@ +/* + * 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_ABILITY_STAGE_MONITOR_H +#define OHOS_ABILITY_RUNTIME_ETS_ABILITY_STAGE_MONITOR_H + +#include "iability_stage_monitor.h" + +namespace OHOS { +namespace AbilityDelegatorEts { +using namespace OHOS::AppExecFwk; +class EtsAbilityStageMonitor : public IAbilityStageMonitor { +public: + /** + * A constructor used to create a AbilityStageMonitor instance with the input parameter passed. + * + * @param moduleName Indicates the specified module name. + * @param srcEntrance Indicates the abilityStage source path. + */ + EtsAbilityStageMonitor(const std::string &moduleName, const std::string &srcEntrance) + : IAbilityStageMonitor(moduleName, srcEntrance) {} + + /** + * Default deconstructor used to deconstruct. + */ + ~EtsAbilityStageMonitor() = default; +}; +} // namespace AbilityDelegatorEts +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_STAGE_MONITOR_H diff --git a/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator.cpp b/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator.cpp index 94b6bd5ec58..a3d8746e9f3 100644 --- a/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator.cpp +++ b/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator.cpp @@ -33,26 +33,25 @@ namespace AbilityDelegatorEts { using namespace OHOS::AbilityRuntime; -std::map, std::shared_ptr> g_monitorRecord; -std::map, sptr, std::owner_less<>> g_abilityRecord; +std::map, + std::shared_ptr, + std::owner_less>> g_monitorRecord; +std::map, + std::shared_ptr, + std::owner_less>> g_stageMonitorRecord; +std::map, sptr, std::owner_less<>> g_abilityRecord; std::mutex g_mtxMonitorRecord; +std::mutex g_mtxStageMonitorRecord; std::mutex g_mutexAbilityRecord; -enum ERROR_CODE { - INCORRECT_PARAMETERS = 401, -}; - -#ifdef ENABLE_ERRCODE -constexpr int COMMON_FAILED = 16000100; -#else -constexpr int COMMON_FAILED = -1; -#endif - namespace { -constexpr const char* AREA_MODE_ENUM_NAME = "L@ohos/app/ability/contextConstant/contextConstant/AreaMode;"; constexpr const char* CONTEXT_CLASS_NAME = "Lapplication/Context/Context;"; constexpr const char* SHELL_CMD_RESULT_CLASS_NAME = "Lapplication/shellCmdResult/ShellCmdResultImpl;"; constexpr const char* ABILITY_MONITOR_INNER_CLASS_NAME = "Lapplication/AbilityMonitor/AbilityMonitorInner;"; +constexpr const char* ABILITY_STAGE_MONITOR_INNER_CLASS_NAME = + "Lapplication/AbilityStageMonitor/AbilityStageMonitorInner;"; +constexpr const char* ABILITY_STAGE_CLASS_NAME = "L@ohos/app/ability/AbilityStage/AbilityStage;"; +constexpr int COMMON_FAILED = 16000100; } EtsAbilityDelegator::EtsAbilityDelegator() @@ -60,7 +59,7 @@ EtsAbilityDelegator::EtsAbilityDelegator() auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); if (delegator) { auto clearFunc = [](const std::shared_ptr &baseProperty) { - auto property = std::static_pointer_cast(baseProperty); + auto property = std::static_pointer_cast(baseProperty); if (!property) { TAG_LOGE(AAFwkTag::DELEGATOR, "invalid property type"); return; @@ -82,66 +81,44 @@ EtsAbilityDelegator::EtsAbilityDelegator() EtsAbilityDelegator::~EtsAbilityDelegator() = default; -ani_object EtsAbilityDelegator::CreateEtsBaseContext(ani_env* aniEnv, ani_class contextClass, - std::shared_ptr context) +ani_object EtsAbilityDelegator::SetAppContext(ani_env *env, const std::shared_ptr &context) { - if (aniEnv == nullptr || context == nullptr) { - TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv or context"); - return {}; + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null env or context"); + return nullptr; } + ani_class cls = nullptr; ani_object contextObj = nullptr; ani_method method = nullptr; - ani_status status = aniEnv->Class_FindMethod(contextClass, "", ":V", &method); + ani_status status = env->FindClass(CONTEXT_CLASS_NAME, &cls); if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod ctor failed status: %{public}d", status); - return {}; - } - if ((status = aniEnv->Object_New(contextClass, method, &contextObj)) != ANI_OK) { - TAG_LOGE(AAFwkTag::DELEGATOR, "Object_New failed status: %{public}d", status); - return {}; - } - ani_field areaField = nullptr; - if (aniEnv->Class_FindField(contextClass, "area", &areaField) != ANI_OK) { - TAG_LOGE(AAFwkTag::DELEGATOR, "find area failed"); - return {}; - } - ani_enum_item areaModeItem {}; - OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts(aniEnv, - AREA_MODE_ENUM_NAME, context->GetArea(), areaModeItem); - if (aniEnv->Object_SetField_Ref(contextObj, areaField, (ani_ref)areaModeItem) != ANI_OK) { - TAG_LOGE(AAFwkTag::DELEGATOR, "Object_SetField_Int failed"); - return {}; + TAG_LOGE(AAFwkTag::DELEGATOR, "FindClass status: %{public}d", status); + return nullptr; } - ani_field filesDirField = nullptr; - if (aniEnv->Class_FindField(contextClass, "filesDir", &filesDirField) != ANI_OK) { - TAG_LOGE(AAFwkTag::DELEGATOR, "find filesDir failed"); - return {}; + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod status: %{public}d", status); + return nullptr; } - auto filesDir = context->GetFilesDir(); - ani_string filesDir_string{}; - aniEnv->String_NewUTF8(filesDir.c_str(), filesDir.size(), &filesDir_string); - if (aniEnv->Object_SetField_Ref(contextObj, filesDirField, reinterpret_cast(filesDir_string)) != ANI_OK) { - TAG_LOGE(AAFwkTag::DELEGATOR, "Object_SetField_Ref failed"); - return {}; + if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_New status: %{public}d", status); + return nullptr; } - ani_field tempDirField = nullptr; - if (aniEnv->Class_FindField(contextClass, "tempDir", &tempDirField) != ANI_OK) { - TAG_LOGE(AAFwkTag::DELEGATOR, "find find tempDir failed"); - return {}; + + auto workContext = new (std::nothrow) std::weak_ptr(context); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null workContext"); + return nullptr; } - auto tempDir = context->GetTempDir(); - ani_string tempDirString{}; - aniEnv->String_NewUTF8(tempDir.c_str(), tempDir.size(), &tempDirString); - if (aniEnv->Object_SetField_Ref(contextObj, tempDirField, reinterpret_cast(tempDirString)) != ANI_OK) { - TAG_LOGE(AAFwkTag::DELEGATOR, "Object_SetField_Ref failed"); - return {}; + ani_long nativeContextLong = reinterpret_cast(workContext); + if (!ContextUtil::SetNativeContextLong(env, contextObj, nativeContextLong)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "SetNativeContextLong failed"); + delete workContext; + workContext = nullptr; + return nullptr; } - ContextUtil::BindApplicationInfo(aniEnv, contextClass, contextObj, context); - ContextUtil::BindResourceManager(aniEnv, contextClass, contextObj, context); return contextObj; } - -ani_object EtsAbilityDelegator::WrapShellCmdResult(ani_env* env, std::unique_ptr result) +ani_object EtsAbilityDelegator::WrapShellCmdResult(ani_env *env, std::unique_ptr result) { TAG_LOGD(AAFwkTag::DELEGATOR, "WrapShellCmdResult called"); if (result == nullptr || env == nullptr) { @@ -167,12 +144,12 @@ ani_object EtsAbilityDelegator::WrapShellCmdResult(ani_env* env, std::unique_ptr return {}; } TAG_LOGD(AAFwkTag::DELEGATOR, "Object_New success"); - ani_field filed = nullptr; + ani_field filed = nullptr; status = env->Class_FindField(cls, "stdResult", &filed); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindField failed status: %{public}d", status); } - ani_string aniStringVal {}; + ani_string aniStringVal = nullptr; std::string strResult = result->GetStdResult(); status = env->String_NewUTF8(strResult.c_str(), strResult.size(), &aniStringVal); if (status != ANI_OK) { @@ -190,14 +167,14 @@ ani_object EtsAbilityDelegator::WrapShellCmdResult(ani_env* env, std::unique_ptr return object; } -ani_object EtsAbilityDelegator::GetAppContext(ani_env* env, [[maybe_unused]]ani_object object, ani_class clss) +ani_object EtsAbilityDelegator::GetAppContext(ani_env *env, ani_class clss) { TAG_LOGD(AAFwkTag::DELEGATOR, "GetAppContext call"); if (env == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); return {}; } - ani_class cls; + ani_class cls = nullptr; ani_object nullobj = nullptr; if (ANI_OK != env->FindClass(CONTEXT_CLASS_NAME, &cls)) { TAG_LOGE(AAFwkTag::DELEGATOR, "FindClass Context Failed"); @@ -213,13 +190,17 @@ ani_object EtsAbilityDelegator::GetAppContext(ani_env* env, [[maybe_unused]]ani_ TAG_LOGE(AAFwkTag::DELEGATOR, "null context"); return nullobj; } - ani_object objectContext = CreateEtsBaseContext(env, cls, context); + ani_object contextObj = SetAppContext(env, context); + if (contextObj == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null contextObj"); + return nullobj; + } + ContextUtil::CreateEtsBaseContext(env, cls, contextObj, context); TAG_LOGD(AAFwkTag::DELEGATOR, "GetAppContext end"); - return objectContext; + return contextObj; } -void EtsAbilityDelegator::ExecuteShellCommand(ani_env *env, [[maybe_unused]]ani_object object, - ani_string cmd, ani_double timeoutSecs, ani_object callback) +void EtsAbilityDelegator::ExecuteShellCommand(ani_env *env, ani_string cmd, ani_double timeoutSecs, ani_object callback) { TAG_LOGD(AAFwkTag::DELEGATOR, "ExecuteShellCommand called"); if (env == nullptr) { @@ -227,7 +208,7 @@ void EtsAbilityDelegator::ExecuteShellCommand(ani_env *env, [[maybe_unused]]ani_ return; } std::string stdCmd = ""; - if (!OHOS::AppExecFwk::GetStdString(env, cmd, stdCmd)) { + if (!AppExecFwk::GetStdString(env, cmd, stdCmd)) { TAG_LOGE(AAFwkTag::DELEGATOR, "GetStdString Failed"); AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM); return; @@ -240,7 +221,7 @@ void EtsAbilityDelegator::ExecuteShellCommand(ani_env *env, [[maybe_unused]]ani_ } int resultCode = 0; auto result = delegator->ExecuteShellCommand(stdCmd, static_cast(timeoutSecs)); - ani_object objValue = GetInstance().WrapShellCmdResult(env, std::move(result)); + ani_object objValue = WrapShellCmdResult(env, std::move(result)); if (objValue == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "null objValue"); resultCode = COMMON_FAILED; @@ -258,21 +239,12 @@ void EtsAbilityDelegator::ExecuteShellCommand(ani_env *env, [[maybe_unused]]ani_ TAG_LOGE(AAFwkTag::DELEGATOR, "Object_New failed status: %{public}d", status); } } - ani_ref callbackRef = nullptr; - ani_status createStatus = env->GlobalReference_Create(callback, &callbackRef); - if (createStatus != ANI_OK) { - TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", createStatus); - AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); - return; - } - OHOS::AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), - OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), + AppExecFwk::AsyncCallback(env, callback, AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), objValue); return; } -void EtsAbilityDelegator::FinishTest(ani_env* env, [[maybe_unused]]ani_object object, - ani_string msg, ani_double code, ani_object callback) +void EtsAbilityDelegator::FinishTest(ani_env *env, ani_string msg, ani_double code, ani_object callback) { TAG_LOGD(AAFwkTag::DELEGATOR, "called"); if (env == nullptr) { @@ -280,7 +252,7 @@ void EtsAbilityDelegator::FinishTest(ani_env* env, [[maybe_unused]]ani_object ob return; } std::string stdMsg = ""; - if (!OHOS::AppExecFwk::GetStdString(env, msg, stdMsg)) { + if (!AppExecFwk::GetStdString(env, msg, stdMsg)) { TAG_LOGE(AAFwkTag::DELEGATOR, "GetStdString Failed"); AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM); return; @@ -293,28 +265,20 @@ void EtsAbilityDelegator::FinishTest(ani_env* env, [[maybe_unused]]ani_object ob } else { delegator->FinishUserTest(stdMsg, static_cast(code)); } - ani_ref callbackRef = nullptr; - auto status = env->GlobalReference_Create(callback, &callbackRef); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", status); - AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); - return; - } - OHOS::AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), - OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), + AppExecFwk::AsyncCallback(env, callback, AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), nullptr); TAG_LOGD(AAFwkTag::DELEGATOR, "FinishTest END"); return; } -void EtsAbilityDelegator::PrintSync(ani_env *env, [[maybe_unused]]ani_class aniClass, ani_string msg) +void EtsAbilityDelegator::PrintSync(ani_env *env, ani_string msg) { TAG_LOGD(AAFwkTag::DELEGATOR, "PrintSync"); if (env == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); return; } - std::string msgStr; + std::string msgStr = ""; ani_size sz {}; env->String_GetUTF8Size(msg, &sz); msgStr.resize(sz + 1); @@ -351,18 +315,16 @@ void EtsAbilityDelegator::RetrieveStringFromAni(ani_env *env, ani_string str, st res.resize(sz); } -void EtsAbilityDelegator::AddAbilityMonitor(ani_env *env, [[maybe_unused]]ani_class aniClass, - ani_object monitorObj, ani_object callback) +void EtsAbilityDelegator::AddAbilityMonitor(ani_env *env, ani_object monitorObj, ani_object callback) { if (env == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); return; } std::shared_ptr monitorImpl = nullptr; - if (!GetInstance().ParseMonitorPara(env, monitorObj, monitorImpl)) { + if (!ParseMonitorPara(env, monitorObj, monitorImpl)) { TAG_LOGE(AAFwkTag::DELEGATOR, "ParseMonitorPara failed"); - AbilityRuntime::EtsErrorUtil::ThrowError(env, INCORRECT_PARAMETERS, - "Parse param monitor failed, monitor must be Monitor."); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM); return; } auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); @@ -373,20 +335,36 @@ void EtsAbilityDelegator::AddAbilityMonitor(ani_env *env, [[maybe_unused]]ani_cl } else { delegator->AddAbilityMonitor(monitorImpl); } - ani_ref callbackRef = nullptr; - ani_status status = env->GlobalReference_Create(callback, &callbackRef); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "Create Gloabl ref for delegator failed %{public}d", status); - AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + AppExecFwk::AsyncCallback(env, callback, AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), + nullptr); + return; +} + +void EtsAbilityDelegator::AddAbilityMonitorSync(ani_env *env, ani_object monitorObj) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "AddAbilityMonitorSync"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); return; } - OHOS::AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), - OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), - nullptr); + std::shared_ptr monitorImpl = nullptr; + if (!ParseMonitorPara(env, monitorObj, monitorImpl)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "ParseMonitorPara failed"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + "Parse param monitor failed, monitor must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); + if (delegator) { + delegator->AddAbilityMonitor(monitorImpl); + } else { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, COMMON_FAILED, "Calling AddAbilityMonitorSync failed."); + } return; } -void EtsAbilityDelegator::StartAbility(ani_env* env, [[maybe_unused]]ani_object object, - ani_object wantObj, ani_object callback) +void EtsAbilityDelegator::StartAbility(ani_env *env, ani_object wantObj, ani_object callback) { TAG_LOGD(AAFwkTag::DELEGATOR, "StartAbility"); if (env == nullptr) { @@ -395,7 +373,7 @@ void EtsAbilityDelegator::StartAbility(ani_env* env, [[maybe_unused]]ani_object } AAFwk::Want want; if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { - TAG_LOGE(AAFwkTag::DELEGATOR, "UnwrapWant failed"); + TAG_LOGE(AAFwkTag::DELEGATOR, "UnwrapWant failed"); AbilityRuntime::EtsErrorUtil::ThrowError(env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), "Parse want failed, want must be Want."); @@ -413,31 +391,467 @@ void EtsAbilityDelegator::StartAbility(ani_env* env, [[maybe_unused]]ani_object TAG_LOGE(AAFwkTag::DELEGATOR, "start ability failed: %{public}d", result); resultCode = result; } + AppExecFwk::AsyncCallback(env, callback, AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), + nullptr); + return; +} + +ani_ref EtsAbilityDelegator::GetCurrentTopAbility(ani_env* env, ani_object callback) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "called"); + ani_object objValue = nullptr; + int32_t resultCode = COMMON_FAILED; + std::string resultMsg = "Calling GetCurrentTopAbility failed."; + do { + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator( + AbilityRuntime::Runtime::Language::ETS); + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "delegator is nullptr"); + break; + } + auto property = delegator->GetCurrentTopAbility(); + auto etsbaseProperty = std::static_pointer_cast(property); + if (etsbaseProperty == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "property is nullptr"); + break; + } + auto ability = etsbaseProperty->object_.lock(); + if (ability == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid property"); + break; + } + resultCode = 0; + resultMsg = ""; + std::unique_lock lck(g_mutexAbilityRecord); + g_abilityRecord.emplace(etsbaseProperty->object_, etsbaseProperty->token_); + objValue = ability->aniObj; + } while (0); ani_ref callbackRef = nullptr; auto status = env->GlobalReference_Create(callback, &callbackRef); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", status); AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return objValue; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + AbilityRuntime::EtsErrorUtil::CreateError(env, resultCode, resultMsg), objValue); + return objValue; +} + +void EtsAbilityDelegator::RemoveAbilityMonitor(ani_env *env, ani_object monitorObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "RemoveAbilityMonitor called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + std::shared_ptr monitorImpl = nullptr; + if (!ParseMonitorPara(env, monitorObj, monitorImpl)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "ParseMonitorPara failed"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + "Parse monitor failed, removeAbilityMonitor must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); + int resultCode = 0; + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + resultCode = COMMON_FAILED; + } else { + delegator->RemoveAbilityMonitor(monitorImpl); + CleanAndFindMonitorRecord(env, monitorObj); + } + AppExecFwk::AsyncCallback(env, callback, AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), + nullptr); + return; +} + +void EtsAbilityDelegator::RemoveAbilityMonitorSync(ani_env *env, ani_object monitorObj) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "RemoveAbilityMonitorSync called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + std::shared_ptr monitorImpl = nullptr; + if (!ParseMonitorPara(env, monitorObj, monitorImpl)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "ParseMonitorPara failed"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + "Parse monitor failed, RemoveAbilityMonitorSync must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, COMMON_FAILED, "Calling RemoveAbilityMonitorSync failed."); + return; + } + delegator->RemoveAbilityMonitor(monitorImpl); + CleanAndFindMonitorRecord(env, monitorObj); + return; +} + +void EtsAbilityDelegator::WaitAbilityMonitor(ani_env *env, ani_object monitorObj, ani_double timeout, + ani_object callback) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "WaitAbilityMonitor called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + std::shared_ptr monitorImpl = nullptr; + if (!ParseMonitorPara(env, monitorObj, monitorImpl)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + "Parse monitor want failed, WaitAbilityMonitor must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + std::shared_ptr property = (static_cast(timeout) > 0) ? + delegator->WaitAbilityMonitor(monitorImpl, static_cast(timeout)) : + delegator->WaitAbilityMonitor(monitorImpl); + int resultCode = 0; + ani_object resultAniOj = nullptr; + auto etsbaseProperty = std::static_pointer_cast(property); + if (!etsbaseProperty || etsbaseProperty->object_.expired()) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid etsbaseProperty"); + resultCode = COMMON_FAILED; + } else { + std::unique_lock lck(g_mutexAbilityRecord); + g_abilityRecord.emplace(etsbaseProperty->object_, etsbaseProperty->token_); + resultAniOj = etsbaseProperty->object_.lock()->aniObj; + } + AppExecFwk::AsyncCallback(env, callback, AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), + resultAniOj); + return; +} + +void EtsAbilityDelegator::AddAbilityStageMonitor(ani_env *env, ani_object stageMonitorObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "AddAbilityStageMonitor called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + bool isExisted = false; + std::shared_ptr stageMonitor = nullptr; + if (!ParseStageMonitorPara(env, stageMonitorObj, stageMonitor, isExisted)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + "Parse parameters failed, monitor must be Monitor and isExited must be boolean."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); + int resultCode = 0; + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + resultCode = COMMON_FAILED; + } else { + delegator->AddAbilityStageMonitor(stageMonitor); + if (!isExisted) { + AddStageMonitorRecord(env, stageMonitorObj, stageMonitor); + } + AppExecFwk::AsyncCallback(env, callback, AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), + nullptr); + } + return; +} + +void EtsAbilityDelegator::AddAbilityStageMonitorSync(ani_env *env, ani_object stageMonitorObj) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "AddAbilityStageMonitorSync called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + bool isExisted = false; + std::shared_ptr stageMonitor = nullptr; + if (!ParseStageMonitorPara(env, stageMonitorObj, stageMonitor, isExisted)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + "Parse parameters failed, monitor must be Monitor and isExited must be boolean."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); + if (delegator) { + delegator->AddAbilityStageMonitor(stageMonitor); + if (!isExisted) { + AddStageMonitorRecord(env, stageMonitorObj, stageMonitor); + } + } else { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, COMMON_FAILED, "Calling AddAbilityStageMonitorSync failed."); + } + return; +} + +void EtsAbilityDelegator::RemoveAbilityStageMonitor(ani_env *env, ani_object stageMonitorObj, ani_object callback) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "RemoveAbilityStageMonitor called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + bool isExisted = false; + std::shared_ptr stageMonitor = nullptr; + if (!ParseStageMonitorPara(env, stageMonitorObj, stageMonitor, isExisted)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + "Parse monitor failed, removeAbilityMonitor must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); + int resultCode = 0; + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + resultCode = COMMON_FAILED; + } else { + delegator->RemoveAbilityStageMonitor(stageMonitor); + } + AppExecFwk::AsyncCallback(env, callback, AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), + nullptr); + if (isExisted) { + RemoveStageMonitorRecord(env, stageMonitorObj); + } + return; +} + +void EtsAbilityDelegator::RemoveAbilityStageMonitorSync(ani_env *env, ani_object stageMonitorObj) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "RemoveAbilityStageMonitorSync called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + bool isExisted = false; + std::shared_ptr stageMonitor = nullptr; + if (!ParseStageMonitorPara(env, stageMonitorObj, stageMonitor, isExisted)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + "Parse monitor failed, removeAbilityMonitor must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); + if (delegator) { + delegator->RemoveAbilityStageMonitor(stageMonitor); + } else { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, COMMON_FAILED, "Calling RemoveAbilityStageMonitorSync failed."); + } + + if (isExisted) { + RemoveStageMonitorRecord(env, stageMonitorObj); + } + return; +} + +void EtsAbilityDelegator::WaitAbilityStageMonitor(ani_env *env, ani_object stageMonitorObj, ani_double timeout, + ani_object callback) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "WaitAbilityStageMonitor called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + std::shared_ptr stageMonitor = nullptr; + if (!ParseWaitAbilityStageMonitorPara(env, stageMonitorObj, stageMonitor)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + "Parse monitor failed, removeAbilityMonitor must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); + if (!delegator) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + std::shared_ptr result; + result = (static_cast(timeout) > 0) ? + delegator->WaitAbilityStageMonitor(stageMonitor, static_cast(timeout)) : + delegator->WaitAbilityStageMonitor(stageMonitor); + int resultCode = 0; + ani_object resultAniOj = nullptr; + auto etsbaseProperty = std::static_pointer_cast(result); + if (CheckPropertyValue(env, resultCode, resultAniOj, etsbaseProperty)) { + resultAniOj = etsbaseProperty->object_.lock()->aniObj; + } + AppExecFwk::AsyncCallback(env, callback, AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), + resultAniOj); + return; +} + +void EtsAbilityDelegator::DoAbilityForeground(ani_env *env, ani_object abilityObj, ani_object callback) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "DoAbilityForeground called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); return; } - OHOS::AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), - OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), + sptr remoteObject = nullptr; + if (!ParseAbilityCommonPara(env, abilityObj, remoteObject)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + "Parse remoteObject failed, remoteObject must be RemoteObject."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); + int resultCode = 0; + if (!delegator) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + resultCode = COMMON_FAILED; + } else { + if (!delegator->DoAbilityForeground(remoteObject)) { + resultCode = COMMON_FAILED; + } + } + AppExecFwk::AsyncCallback(env, callback, AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), nullptr); return; } + +void EtsAbilityDelegator::DoAbilityBackground(ani_env *env, ani_object abilityObj, ani_object callback) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "DoAbilityBackground called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + sptr remoteObject = nullptr; + if (!ParseAbilityCommonPara(env, abilityObj, remoteObject)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + "Parse remoteObject failed, remoteObject must be RemoteObject."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); + int resultCode = 0; + if (!delegator) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + resultCode = COMMON_FAILED; + } else { + if (!delegator->DoAbilityBackground(remoteObject)) { + resultCode = COMMON_FAILED; + } + } + AppExecFwk::AsyncCallback(env, callback, AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), + nullptr); + return; +} + +void EtsAbilityDelegator::Print(ani_env *env, ani_string msg, ani_object callback) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "Print called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + std::string strMsg = ""; + if (!AppExecFwk::GetStdString(env, msg, strMsg)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "GetStdString Failed"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + "Parse msg failed, msg must be string."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); + int resultCode = 0; + if (!delegator) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + resultCode = COMMON_FAILED; + } else { + delegator->Print(strMsg); + } + AppExecFwk::AsyncCallback(env, callback, AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), + nullptr); + return; +} + +ani_double EtsAbilityDelegator::GetAbilityState(ani_env *env, ani_object abilityObj) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "GetAbilityState called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return COMMON_FAILED; + } + sptr remoteObject = nullptr; + if (!ParseAbilityCommonPara(env, abilityObj, remoteObject)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + return COMMON_FAILED; + } + + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); + if (!delegator) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + return COMMON_FAILED; + } + AbilityDelegator::AbilityState lifeState = delegator->GetAbilityState(remoteObject); + AbilityLifecycleState abilityLifeState = AbilityLifecycleState::UNINITIALIZED; + AbilityLifecycleStateToEts(lifeState, abilityLifeState); + return static_cast(abilityLifeState); +} + +void EtsAbilityDelegator::AbilityLifecycleStateToEts( + const AbilityDelegator::AbilityState &lifeState, AbilityLifecycleState &abilityLifeState) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "lifeState: %{public}d", static_cast(lifeState)); + switch (lifeState) { + case AbilityDelegator::AbilityState::STARTED: + abilityLifeState = AbilityLifecycleState::CREATE; + break; + case AbilityDelegator::AbilityState::FOREGROUND: + abilityLifeState = AbilityLifecycleState::FOREGROUND; + break; + case AbilityDelegator::AbilityState::BACKGROUND: + abilityLifeState = AbilityLifecycleState::BACKGROUND; + break; + case AbilityDelegator::AbilityState::STOPPED: + abilityLifeState = AbilityLifecycleState::DESTROY; + break; + default: + abilityLifeState = AbilityLifecycleState::UNINITIALIZED; + break; + } +} + bool EtsAbilityDelegator::ParseMonitorPara(ani_env *env, ani_object monitorObj, std::shared_ptr &monitorImpl) { - TAG_LOGI(AAFwkTag::DELEGATOR, "monitorRecord size: %{public}zu", g_monitorRecord.size()); if (env == nullptr || monitorObj == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "env or monitorObj is nullptr"); return false; } { std::unique_lock lck(g_mtxMonitorRecord); - for (auto iter = g_monitorRecord.begin(); iter != g_monitorRecord.end(); ++iter) { - std::shared_ptr etsMonitor = iter->first; - ani_boolean result = ANI_FALSE; + TAG_LOGI(AAFwkTag::DELEGATOR, "monitorRecord size: %{public}zu", g_monitorRecord.size()); + for (auto iter = g_monitorRecord.begin(); iter != g_monitorRecord.end();) { + if (iter->first.expired()) { + TAG_LOGE(AAFwkTag::DELEGATOR, "g_monitorRecord expired"); + iter = g_monitorRecord.erase(iter); + continue; + } + std::shared_ptr etsMonitor = iter->first.lock(); + if (etsMonitor == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "etsMonitor is nullptr"); + iter = g_monitorRecord.erase(iter); + continue; + } + ani_boolean result = false; ani_status status = env->Reference_StrictEquals(reinterpret_cast(monitorObj), reinterpret_cast(etsMonitor->aniObj), &result); if (status != ANI_OK) { @@ -447,6 +861,7 @@ bool EtsAbilityDelegator::ParseMonitorPara(ani_env *env, ani_object monitorObj, monitorImpl = iter->second; return monitorImpl ? true : false; } + ++iter; } } if (!ParseMonitorParaInner(env, monitorObj, monitorImpl)) { @@ -463,32 +878,32 @@ bool EtsAbilityDelegator::ParseMonitorParaInner(ani_env *env, ani_object monitor TAG_LOGE(AAFwkTag::DELEGATOR, "env or monitorObj is nullptr"); return false; } - ani_class monitorCls; + ani_class monitorCls = nullptr; ani_status status = env->FindClass(ABILITY_MONITOR_INNER_CLASS_NAME, &monitorCls); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "FindClass failed status: %{public}d", status); return false; } - ani_ref moduleNameRef; + ani_ref moduleNameRef = nullptr; status = env->Object_GetPropertyByName_Ref(monitorObj, "moduleName", &moduleNameRef); if (ANI_OK != status) { TAG_LOGE(AAFwkTag::DELEGATOR, "Object_GetField_Ref "); AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); return false; } - std::string strModuleName; + std::string strModuleName = ""; ani_string aniModuleString = static_cast(moduleNameRef); - GetInstance().RetrieveStringFromAni(env, aniModuleString, strModuleName); - ani_ref abilityNameRef; + RetrieveStringFromAni(env, aniModuleString, strModuleName); + ani_ref abilityNameRef = nullptr; status = env->Object_GetPropertyByName_Ref(monitorObj, "abilityName", &abilityNameRef); if (ANI_OK != status) { TAG_LOGE(AAFwkTag::DELEGATOR, "Object_GetField_Ref "); AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); return false; } - std::string strAbilityName; + std::string strAbilityName = ""; ani_string aniAbilityName = static_cast(abilityNameRef); - GetInstance().RetrieveStringFromAni(env, aniAbilityName, strAbilityName); + RetrieveStringFromAni(env, aniAbilityName, strAbilityName); std::shared_ptr abilityMonitor = nullptr; if (strModuleName.empty()) { @@ -499,7 +914,7 @@ bool EtsAbilityDelegator::ParseMonitorParaInner(ani_env *env, ani_object monitor abilityMonitor->SetEtsAbilityMonitor(env, monitorObj); } monitorImpl = abilityMonitor; - std::shared_ptr reference = std::make_shared(); + std::shared_ptr reference = std::make_shared(); if (reference != nullptr) { reference->aniObj = monitorObj; } @@ -508,5 +923,266 @@ bool EtsAbilityDelegator::ParseMonitorParaInner(ani_env *env, ani_object monitor return true; } +bool EtsAbilityDelegator::ParseStageMonitorPara(ani_env *env, ani_object stageMonitorObj, + std::shared_ptr &stageMonitor, bool &isExisted) +{ + if (env == nullptr || stageMonitorObj == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env or stageMonitorObj is nullptr"); + return false; + } + isExisted = false; + { + std::unique_lock lck(g_mtxStageMonitorRecord); + TAG_LOGI(AAFwkTag::DELEGATOR, "stageMonitorRecord size: %{public}zu", g_stageMonitorRecord.size()); + for (auto iter = g_stageMonitorRecord.begin(); iter != g_stageMonitorRecord.end();) { + if (iter->first.expired()) { + TAG_LOGE(AAFwkTag::DELEGATOR, "g_stageMonitorRecord expired"); + iter = g_stageMonitorRecord.erase(iter); + continue; + } + std::shared_ptr etsMonitor = iter->first.lock(); + if (etsMonitor == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "etsMonitor is nullptr"); + iter = g_stageMonitorRecord.erase(iter); + continue; + } + ani_boolean result = false; + ani_status status = env->Reference_StrictEquals(reinterpret_cast(stageMonitorObj), + reinterpret_cast(etsMonitor->aniObj), &result); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Reference_StrictEquals failed status: %{public}d", status); + } + if (result) { + TAG_LOGW(AAFwkTag::DELEGATOR, "abilityStage monitor exist"); + isExisted = true; + stageMonitor = iter->second; + return stageMonitor ? true : false; + } + ++iter; + } + } + if (!ParseStageMonitorParaInner(env, stageMonitorObj, stageMonitor)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "ParseStageMonitorParaInner failed"); + return false; + } + return true; +} + +bool EtsAbilityDelegator::ParseStageMonitorParaInner(ani_env *env, ani_object stageMonitorObj, + std::shared_ptr &stageMonitor) +{ + if (env == nullptr || stageMonitorObj == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env or stageMonitorObj is nullptr"); + return false; + } + ani_class monitorCls = nullptr; + ani_status status = env->FindClass(ABILITY_STAGE_MONITOR_INNER_CLASS_NAME, &monitorCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "FindClass failed status: %{public}d", status); + return false; + } + ani_ref moduleNameRef = nullptr; + status = env->Object_GetPropertyByName_Ref(stageMonitorObj, "moduleName", &moduleNameRef); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_GetField_Ref failed status: %{public}d", status); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return false; + } + std::string strModuleName = ""; + ani_string aniModuleString = static_cast(moduleNameRef); + RetrieveStringFromAni(env, aniModuleString, strModuleName); + TAG_LOGD(AAFwkTag::DELEGATOR, "strModuleName %{public}s ", strModuleName.c_str()); + ani_ref srcEntranceRef = nullptr; + status = env->Object_GetPropertyByName_Ref(stageMonitorObj, "srcEntrance", &srcEntranceRef); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_GetField_Ref "); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return false; + } + std::string srcEntrance = ""; + ani_string aniSrcEntranceRef = static_cast(srcEntranceRef); + RetrieveStringFromAni(env, aniSrcEntranceRef, srcEntrance); + TAG_LOGD(AAFwkTag::DELEGATOR, "srcEntrance %{public}s ", srcEntrance.c_str()); + stageMonitor = std::make_shared(strModuleName, srcEntrance); + return true; +} + +void EtsAbilityDelegator::AddStageMonitorRecord(ani_env *env, ani_object stageMonitorObj, + const std::shared_ptr &stageMonitor) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "AddStageMonitorRecord called"); + if (env == nullptr || stageMonitor == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env or stageMonitor is nullptr"); + return; + } + if (!AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + return; + } + std::shared_ptr reference = std::make_shared(); + reference->aniObj = stageMonitorObj; + { + std::unique_lock lck(g_mtxStageMonitorRecord); + g_stageMonitorRecord.emplace(reference, stageMonitor); + TAG_LOGI(AAFwkTag::DELEGATOR, "end, size: %{public}zu", g_stageMonitorRecord.size()); + } +} + +void EtsAbilityDelegator::RemoveStageMonitorRecord(ani_env *env, ani_object stageMonitorObj) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + if (!AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + return; + } + std::unique_lock lck(g_mtxStageMonitorRecord); + for (auto iter = g_stageMonitorRecord.begin(); iter != g_stageMonitorRecord.end();) { + if (iter->first.expired()) { + TAG_LOGE(AAFwkTag::DELEGATOR, "g_stageMonitorRecord expired"); + iter = g_stageMonitorRecord.erase(iter); + continue; + } + std::shared_ptr etsMonitor = iter->first.lock(); + if (etsMonitor == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "etsMonitor is nullptr"); + iter = g_stageMonitorRecord.erase(iter); + continue; + } + ani_boolean result = false; + ani_status status = env->Reference_StrictEquals(reinterpret_cast(stageMonitorObj), + reinterpret_cast(etsMonitor->aniObj), &result); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Reference_StrictEquals failed status: %{public}d", status); + } + if (result) { + g_stageMonitorRecord.erase(iter); + TAG_LOGI(AAFwkTag::DELEGATOR, "end, size: %{public}zu", g_stageMonitorRecord.size()); + break; + } + ++iter; + } +} + +bool EtsAbilityDelegator::ParseWaitAbilityStageMonitorPara(ani_env *env, ani_object stageMonitorObj, + std::shared_ptr &stageMonitor) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "ParseWaitAbilityStageMonitorPara called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return false; + } + bool isExisted = false; + if (!ParseStageMonitorPara(env, stageMonitorObj, stageMonitor, isExisted)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + return false; + } + if (!isExisted) { + AddStageMonitorRecord(env, stageMonitorObj, stageMonitor); + } + return true; +} + +bool EtsAbilityDelegator::ParseAbilityCommonPara(ani_env *env, ani_object abilityObj, + sptr &remoteObject) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "g_abilityRecord size: %{public}zu", g_abilityRecord.size()); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return false; + } + std::unique_lock lck(g_mutexAbilityRecord); + for (auto iter = g_abilityRecord.begin(); iter != g_abilityRecord.end();) { + if (iter->first.expired()) { + TAG_LOGE(AAFwkTag::DELEGATOR, "g_abilityRecord expired"); + iter = g_abilityRecord.erase(iter); + continue; + } + std::shared_ptr etsMonitor = iter->first.lock(); + if (etsMonitor == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "etsMonitor is null"); + iter = g_abilityRecord.erase(iter); + continue; + } + ani_boolean result = false; + ani_status status = env->Reference_StrictEquals(reinterpret_cast(etsMonitor->aniObj), + reinterpret_cast(abilityObj), &result); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Reference_StrictEquals failed status: %{public}d", status); + } + if (result) { + remoteObject = iter->second; + TAG_LOGI(AAFwkTag::DELEGATOR, "ability exist"); + return remoteObject ? true : false; + } + ++iter; + } + TAG_LOGE(AAFwkTag::DELEGATOR, "ability not exist"); + remoteObject = nullptr; + return false; +} + +bool EtsAbilityDelegator::CheckPropertyValue(ani_env *env, int &resultCode, ani_object &resultAniOj, + std::shared_ptr etsProperty) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return false; + } + if (!etsProperty || etsProperty->object_.expired()) { + TAG_LOGE(AAFwkTag::DELEGATOR, "waitAbilityStageMonitor failed"); + resultCode = COMMON_FAILED; + ani_class cls = nullptr; + ani_status status = env->FindClass(ABILITY_STAGE_CLASS_NAME, &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "find AbilityDelegator failed status: %{public}d", status); + } + ani_method method = nullptr; + status = env->Class_FindMethod(cls, "", ":V", &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod ctor failed status: %{public}d", status); + } + if (env->Object_New(cls, method, &resultAniOj) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_New failed status: %{public}d", status); + } + return false; + } + return true; +} + +void EtsAbilityDelegator::CleanAndFindMonitorRecord(ani_env *env, ani_object monitorObj) +{ + if (env == nullptr || monitorObj == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env or monitorObj is nullptr"); + return; + } + std::unique_lock lck(g_mtxMonitorRecord); + for (auto iter = g_monitorRecord.begin(); iter != g_monitorRecord.end();) { + if (iter->first.expired()) { + TAG_LOGE(AAFwkTag::DELEGATOR, "g_monitorRecord expired"); + iter = g_monitorRecord.erase(iter); + continue; + } + std::shared_ptr etsMonitor = iter->first.lock(); + if (etsMonitor == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "etsMonitor is null"); + iter = g_monitorRecord.erase(iter); + continue; + } + ani_boolean result = false; + ani_status status = env->Reference_StrictEquals(reinterpret_cast(monitorObj), + reinterpret_cast(etsMonitor->aniObj), &result); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Reference_StrictEquals failed status: %{public}d", status); + } + if (result) { + g_monitorRecord.erase(iter); + break; + } + ++iter; + } +} } // namespace AbilityDelegatorEts } // namespace OHOS diff --git a/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator_registry.cpp b/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator_registry.cpp index 7de571a73b3..76673d5ff46 100644 --- a/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator_registry.cpp +++ b/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator_registry.cpp @@ -28,7 +28,14 @@ namespace AbilityDelegatorEts { std::unique_ptr etsReference; std::mutex etsReferenceMutex; -static ani_object GetAbilityDelegator(ani_env *env, [[maybe_unused]]ani_class aniClass) +namespace { +constexpr const char* ETS_DELEGATOR_REGISTRY_NAMESPACE = + "L@ohos/app/ability/abilityDelegatorRegistry/abilityDelegatorRegistry;"; +constexpr const char* ETS_DELEGATOR_REGISTRY_SIGNATURE_DELEAGTOR = ":Lapplication/AbilityDelegator/AbilityDelegator;"; +constexpr const char* ETS_DELEGATOR_REGISTRY_SIGNATURE_ATGS = + ":Lapplication/abilityDelegatorArgs/AbilityDelegatorArgs;";; +} +static ani_object GetAbilityDelegator(ani_env *env) { if (env == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "null env"); @@ -48,14 +55,14 @@ static ani_object GetAbilityDelegator(ani_env *env, [[maybe_unused]]ani_class an TAG_LOGE(AAFwkTag::DELEGATOR, "value is nullptr"); return {}; } - ani_boolean isValue; + ani_boolean isValue = false; env->Reference_IsNullishValue(value, &isValue); if (isValue) { TAG_LOGE(AAFwkTag::DELEGATOR, "Reference_IsNullishValue"); return {}; } etsReference = std::make_unique(); - ani_ref result; + ani_ref result = nullptr; auto status = env->GlobalReference_Create(value, &(result)); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", status); @@ -68,7 +75,7 @@ static ani_object GetAbilityDelegator(ani_env *env, [[maybe_unused]]ani_class an } } -static ani_object GetArguments(ani_env *env, [[maybe_unused]]ani_class aniClass) +static ani_object GetArguments(ani_env *env) { if (env == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "null env"); @@ -96,16 +103,18 @@ void EtsAbilityDelegatorRegistryInit(ani_env *env) TAG_LOGE(AAFwkTag::DELEGATOR, "ResetError failed"); } - ani_namespace ns; - status = env->FindNamespace("L@ohos/app/ability/abilityDelegatorRegistry/abilityDelegatorRegistry;", &ns); + ani_namespace ns = nullptr; + status = env->FindNamespace(ETS_DELEGATOR_REGISTRY_NAMESPACE, &ns); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "FindNamespace abilityDelegatorRegistry failed status: %{public}d", status); return; } std::array kitFunctions = { - ani_native_function {"getAbilityDelegator", nullptr, reinterpret_cast(GetAbilityDelegator)}, - ani_native_function {"getArguments", nullptr, reinterpret_cast(GetArguments)}, + ani_native_function {"getAbilityDelegator", ETS_DELEGATOR_REGISTRY_SIGNATURE_DELEAGTOR, + reinterpret_cast(GetAbilityDelegator)}, + ani_native_function {"getArguments", ETS_DELEGATOR_REGISTRY_SIGNATURE_ATGS, + reinterpret_cast(GetArguments)}, }; status = env->Namespace_BindNativeFunctions(ns, kitFunctions.data(), kitFunctions.size()); diff --git a/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator_utils.cpp b/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator_utils.cpp index 6d7aed80ad5..0f0a4fc9edd 100644 --- a/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator_utils.cpp +++ b/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator_utils.cpp @@ -19,14 +19,34 @@ #include "ets_ability_delegator.h" #include "hilog_tag_wrapper.h" - namespace OHOS { namespace AbilityDelegatorEts { namespace { constexpr const char* ABILITY_DELEGATOR_CLASS_NAME = "Lapplication/AbilityDelegator/AbilityDelegatorInner;"; constexpr const char* RECORD_CLASS_NAME = "Lescompat/Record;"; +constexpr const char* VOID_CONTEXT = ":Lapplication/Context/Context;"; +constexpr const char* STRING_NUMBER_ASYNCCALLBACK = "Lstd/core/String;DLutils/AbilityUtils/AsyncCallbackWrapper;:V"; +constexpr const char* STRING_VOID = "Lstd/core/String;:V"; +constexpr const char* MONITOR_ASYNCCALLBACK_VOID = + "Lapplication/AbilityMonitor/AbilityMonitor;Lutils/AbilityUtils/AsyncCallbackWrapper;:V"; +constexpr const char* WANT_ASYNCCALLBACK = "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V"; constexpr const char* ARGS_ABILITY_DELEGATOR_CLASS_NAME = "Lapplication/abilityDelegatorArgs/AbilityDelegatorArgsInner;"; +constexpr const char* SIGNATURE_MONITOR_VOID = "Lapplication/AbilityMonitor/AbilityMonitor;:V"; +constexpr const char* SIGNATURE_MONITOR_NUMBER_ASYNCCALLBACK = + "Lapplication/AbilityMonitor/AbilityMonitor;DLutils/AbilityUtils/AsyncCallbackWrapper;:V"; +constexpr const char* STAGEMONITOR_ASYNCCALLBACK_VOID = + "Lapplication/AbilityStageMonitor/AbilityStageMonitor;Lutils/AbilityUtils/AsyncCallbackWrapper;:V"; +constexpr const char* STAGEMONITOR_VOID = + "Lapplication/AbilityStageMonitor/AbilityStageMonitor;:V"; +constexpr const char* SIGNATURE_STAGEMONITOR_NUMBER_ASYNCCALLBACK = + "Lapplication/AbilityStageMonitor/AbilityStageMonitor;DLutils/AbilityUtils/AsyncCallbackWrapper;:V"; +constexpr const char* STAGEMONITOR_UIABILITY_ASYNCCALLBACK = + "L@ohos/app/ability/UIAbility/UIAbility;Lutils/AbilityUtils/AsyncCallbackWrapper;:V"; +constexpr const char* STRING_ASYNCCALLBACK_VOID = "Lstd/core/String;Lutils/AbilityUtils/AsyncCallbackWrapper;:V"; +constexpr const char* STRING_UIABILITY_NUMBER = "L@ohos/app/ability/UIAbility/UIAbility;:D"; +constexpr const char* STRING_CALLBACK_UIABILITY = + "Lutils/AbilityUtils/AsyncCallbackWrapper;:L@ohos/app/ability/UIAbility/UIAbility;"; } bool BindFunctions(ani_env *aniEnv, ani_class abilityDelegator) @@ -35,16 +55,45 @@ bool BindFunctions(ani_env *aniEnv, ani_class abilityDelegator) return false; } std::array functions = { - ani_native_function {"getAppContext", nullptr, reinterpret_cast(EtsAbilityDelegator::GetAppContext)}, - ani_native_function {"nativeExecuteShellCommand", nullptr, + ani_native_function {"getAppContext", VOID_CONTEXT, + reinterpret_cast(EtsAbilityDelegator::GetAppContext)}, + ani_native_function {"nativeExecuteShellCommand", STRING_NUMBER_ASYNCCALLBACK, reinterpret_cast(EtsAbilityDelegator::ExecuteShellCommand)}, - ani_native_function {"nativeFinishTest", nullptr, reinterpret_cast(EtsAbilityDelegator::FinishTest)}, - ani_native_function {"printSync", nullptr, reinterpret_cast(EtsAbilityDelegator::PrintSync)}, - ani_native_function {"nativeAddAbilityMonitor", nullptr, + ani_native_function {"nativeFinishTest", STRING_NUMBER_ASYNCCALLBACK, + reinterpret_cast(EtsAbilityDelegator::FinishTest)}, + ani_native_function {"printSync", STRING_VOID, reinterpret_cast(EtsAbilityDelegator::PrintSync)}, + ani_native_function {"nativeAddAbilityMonitor", MONITOR_ASYNCCALLBACK_VOID, reinterpret_cast(EtsAbilityDelegator::AddAbilityMonitor)}, - ani_native_function {"nativeStartAbility", - "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + ani_native_function {"nativeStartAbility", WANT_ASYNCCALLBACK, reinterpret_cast(EtsAbilityDelegator::StartAbility)}, + ani_native_function {"addAbilityMonitorSync", SIGNATURE_MONITOR_VOID, + reinterpret_cast(EtsAbilityDelegator::AddAbilityMonitorSync)}, + ani_native_function {"removeAbilityMonitorAsync", MONITOR_ASYNCCALLBACK_VOID, + reinterpret_cast(EtsAbilityDelegator::RemoveAbilityMonitor)}, + ani_native_function {"removeAbilityMonitorSync", SIGNATURE_MONITOR_VOID, + reinterpret_cast(EtsAbilityDelegator::RemoveAbilityMonitorSync)}, + ani_native_function {"waitAbilityMonitorAsync", SIGNATURE_MONITOR_NUMBER_ASYNCCALLBACK, + reinterpret_cast(EtsAbilityDelegator::WaitAbilityMonitor)}, + ani_native_function {"addAbilityStageMonitorAsync", STAGEMONITOR_ASYNCCALLBACK_VOID, + reinterpret_cast(EtsAbilityDelegator::AddAbilityStageMonitor)}, + ani_native_function {"addAbilityStageMonitorSync", STAGEMONITOR_VOID, + reinterpret_cast(EtsAbilityDelegator::AddAbilityStageMonitorSync)}, + ani_native_function {"removeAbilityStageMonitorAsync", STAGEMONITOR_ASYNCCALLBACK_VOID, + reinterpret_cast(EtsAbilityDelegator::RemoveAbilityStageMonitor)}, + ani_native_function {"removeAbilityStageMonitorSync", STAGEMONITOR_VOID, + reinterpret_cast(EtsAbilityDelegator::RemoveAbilityStageMonitorSync)}, + ani_native_function {"waitAbilityStageMonitorAsync", SIGNATURE_STAGEMONITOR_NUMBER_ASYNCCALLBACK, + reinterpret_cast(EtsAbilityDelegator::WaitAbilityStageMonitor)}, + ani_native_function {"doAbilityForegroundAsync", STAGEMONITOR_UIABILITY_ASYNCCALLBACK, + reinterpret_cast(EtsAbilityDelegator::DoAbilityForeground)}, + ani_native_function {"doAbilityBackgroundAsync", STAGEMONITOR_UIABILITY_ASYNCCALLBACK, + reinterpret_cast(EtsAbilityDelegator::DoAbilityBackground)}, + ani_native_function {"printAsync", STRING_ASYNCCALLBACK_VOID, + reinterpret_cast(EtsAbilityDelegator::Print)}, + ani_native_function {"getAbilityState", STRING_UIABILITY_NUMBER, + reinterpret_cast(EtsAbilityDelegator::GetAbilityState)}, + ani_native_function {"nativeGetCurrentTopAbility", STRING_CALLBACK_UIABILITY, + reinterpret_cast(EtsAbilityDelegator::GetCurrentTopAbility)} }; ani_status status = aniEnv->Class_BindNativeMethods(abilityDelegator, functions.data(), functions.size()); if (status != ANI_OK) { @@ -100,7 +149,7 @@ void SetBundleName(ani_env *aniEnv, ani_class arguments, ani_object argumentObje return; } ani_status status = ANI_ERROR; - ani_string aniStr; + ani_string aniStr = nullptr; // Get a ani_string from std::string status = aniEnv->String_NewUTF8(bundleName.c_str(), bundleName.length(), &aniStr); if (status != ANI_OK) { @@ -110,7 +159,7 @@ void SetBundleName(ani_env *aniEnv, ani_class arguments, ani_object argumentObje TAG_LOGD(AAFwkTag::DELEGATOR, "String_NewUTF8 success"); // find the setter method - ani_method nameSetter; + ani_method nameSetter = nullptr; status = aniEnv->Class_FindMethod(arguments, "bundleName", nullptr, &nameSetter); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status); @@ -136,25 +185,25 @@ void SetParameters(ani_env *aniEnv, ani_class arguments, ani_object argumentObje return; } ani_status status = ANI_ERROR; - ani_class recordCls; + ani_class recordCls = nullptr; status = aniEnv->FindClass(RECORD_CLASS_NAME, &recordCls); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "FindClass failed status: %{public}d", status); return; } - ani_method recordGetMethod; + ani_method recordGetMethod = nullptr; status = aniEnv->Class_FindMethod(recordCls, "$_get", "Lstd/core/Object;:Lstd/core/Object;", &recordGetMethod); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status); return; } - ani_method recordSetMethod; + ani_method recordSetMethod = nullptr; status = aniEnv->Class_FindMethod(recordCls, "$_set", "Lstd/core/Object;Lstd/core/Object;:V", &recordSetMethod); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status); return; } - ani_ref parameterRef; + ani_ref parameterRef = nullptr; status = aniEnv->Object_CallMethodByName_Ref(argumentObject, "parameters", ":Lescompat/Record;", ¶meterRef); if (status != ANI_OK) { @@ -165,8 +214,8 @@ void SetParameters(ani_env *aniEnv, ani_class arguments, ani_object argumentObje for (auto iter = paras.begin(); iter != paras.end(); ++iter) { std::string key = iter->first; std::string value = iter->second; - ani_string ani_key; - ani_string ani_value; + ani_string ani_key = nullptr; + ani_string ani_value = nullptr; status = aniEnv->String_NewUTF8(key.c_str(), key.length(), &ani_key); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "String_NewUTF8 key failed status: %{public}d", status); @@ -193,7 +242,7 @@ void SetTestCaseNames(ani_env *aniEnv, ani_class arguments, ani_object argumentO return; } ani_status status = ANI_ERROR; - ani_string aniStr; + ani_string aniStr = nullptr; status = aniEnv->String_NewUTF8(testcaseNames.c_str(), testcaseNames.length(), &aniStr); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "String_NewUTF8 failed status: %{public}d", status); @@ -202,7 +251,7 @@ void SetTestCaseNames(ani_env *aniEnv, ani_class arguments, ani_object argumentO TAG_LOGD(AAFwkTag::DELEGATOR, "String_NewUTF8 success"); // find the setter method - ani_method nameSetter; + ani_method nameSetter = nullptr; status = aniEnv->Class_FindMethod(arguments, "testCaseNames", nullptr, &nameSetter); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status); @@ -227,7 +276,7 @@ void SetTestRunnerClassName(ani_env *aniEnv, ani_class arguments, ani_object arg return; } ani_status status = ANI_ERROR; - ani_string aniStr; + ani_string aniStr = nullptr; status = aniEnv->String_NewUTF8(className.c_str(), className.length(), &aniStr); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "String_NewUTF8 failed status: %{public}d", status); @@ -236,7 +285,7 @@ void SetTestRunnerClassName(ani_env *aniEnv, ani_class arguments, ani_object arg TAG_LOGD(AAFwkTag::DELEGATOR, "String_NewUTF8 success"); // find the setter method - ani_method nameSetter; + ani_method nameSetter = nullptr; status = aniEnv->Class_FindMethod(arguments, "testRunnerClassName", nullptr, &nameSetter); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status); diff --git a/frameworks/ets/ani/ability_delegator/src/ets_ability_monitor.cpp b/frameworks/ets/ani/ability_delegator/src/ets_ability_monitor.cpp index 903830f7f8c..84e2ce4d31c 100644 --- a/frameworks/ets/ani/ability_delegator/src/ets_ability_monitor.cpp +++ b/frameworks/ets/ani/ability_delegator/src/ets_ability_monitor.cpp @@ -184,7 +184,7 @@ std::shared_ptr EtsAbilityMonitor::GetRuntimeObj TAG_LOGE(AAFwkTag::DELEGATOR, "abilityObj is expired"); return nullptr; } - auto etsbaseProperty = std::static_pointer_cast(baseProperty); + auto etsbaseProperty = std::static_pointer_cast(baseProperty); auto runtimeObj = etsbaseProperty->object_.lock(); if (!runtimeObj) { TAG_LOGE(AAFwkTag::DELEGATOR, "runtimeObj is nullptr"); @@ -192,5 +192,5 @@ std::shared_ptr EtsAbilityMonitor::GetRuntimeObj } return runtimeObj; } -} // namespace AbilityDelegatorJs -} // namespace OHOS +} // namespace AbilityDelegatorJs +} // namespace OHOS diff --git a/frameworks/ets/ani/ability_manager/BUILD.gn b/frameworks/ets/ani/ability_manager/BUILD.gn new file mode 100644 index 00000000000..53c1823c0b7 --- /dev/null +++ b/frameworks/ets/ani/ability_manager/BUILD.gn @@ -0,0 +1,68 @@ +# 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("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("ability_manager_ani_kit") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/interfaces/kits/native/ability/native", + "${ability_runtime_path}/interfaces/inner_api/runtime/include", + "${ability_runtime_services_path}/common/include", + ] + + configs = [] + + public_configs = [] + + sources = [ "./src/ets_ability_manager.cpp" ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_native_path}/ability/native:ability_business_error", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] + + external_deps = [ + "ability_base:base", + "ability_base:configuration", + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "ipc:ipc_core", + "napi:ace_napi", + "runtime_core:ani", + "samgr:samgr_proxy", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/ability_manager/include/ets_ability_manager.h b/frameworks/ets/ani/ability_manager/include/ets_ability_manager.h new file mode 100644 index 00000000000..e2c36d01a89 --- /dev/null +++ b/frameworks/ets/ani/ability_manager/include/ets_ability_manager.h @@ -0,0 +1,26 @@ +/* + * 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_ABILITY_MANAGER_H +#define OHOS_ABILITY_RUNTIME_ETS_ABILITY_MANAGER_H + +#include "ani.h" + +namespace OHOS { +namespace AbilityRuntime { +void EtsAbilityManagerRegistryInit(ani_env *env); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_MANAGER_H diff --git a/frameworks/ets/ani/ability_manager/src/ets_ability_manager.cpp b/frameworks/ets/ani/ability_manager/src/ets_ability_manager.cpp new file mode 100644 index 00000000000..b3e1fe3bf1e --- /dev/null +++ b/frameworks/ets/ani/ability_manager/src/ets_ability_manager.cpp @@ -0,0 +1,164 @@ +/* + * 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_ability_manager.h" + +#include "ability_business_error.h" +#include "ability_manager_client.h" +#include "ability_manager_errors.h" +#include "ability_manager_interface.h" +#include "ani_common_ability_state_data.h" +#include "ani_common_want.h" +#include "ets_error_utils.h" +#include "hilog_tag_wrapper.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* ETS_ABILITY_MANAGER_NAMESPACE = "L@ohos/app/ability/abilityManager/abilityManager;"; +constexpr const char* ETS_ABILITY_MANAGER_SIGNATURE_ARRAY = ":Lescompat/Array;"; +constexpr const char* ETS_ABILITY_MANAGER_SIGNATURE_CALLBACK = "Lutils/AbilityUtils/AsyncCallbackWrapper;:V"; +constexpr int32_t ERR_FAILURE = -1; +} + +sptr GetAbilityManagerInstance() +{ + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + sptr abilityManagerObj = + systemAbilityManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + return iface_cast(abilityManagerObj); +} +static ani_object GetForegroundUIAbilities(ani_env *env) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "call GetForegroundUIAbilities"); + + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return nullptr; + } + + sptr abilityManager = GetAbilityManagerInstance(); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityManager is null"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return nullptr; + } + std::vector list; + int32_t ret = abilityManager->GetForegroundUIAbilities(list); + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "failed: ret=%{public}d", ret); + AbilityRuntime::AbilityErrorCode code = AbilityRuntime::GetJsErrorCodeByNativeError(ret); + AbilityRuntime::EtsErrorUtil::ThrowError(env, code); + return nullptr; + } + TAG_LOGD(AAFwkTag::ABILITYMGR, "GetForegroundUIAbilities succeeds, list.size=%{public}zu", list.size()); + ani_object aniArray = AppExecFwk::CreateAniAbilityStateDataArray(env, list); + if (aniArray == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null aniArray"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return nullptr; + } + return aniArray; +} + +static void GetTopAbility(ani_env *env, ani_object callback) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "call GetTopAbility"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return; + } +#ifdef ENABLE_ERRCODE + auto selfToken = IPCSkeleton::GetSelfTokenID(); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "not system app"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); + return; + } +#endif + AppExecFwk::ElementName elementName = AAFwk::AbilityManagerClient::GetInstance()->GetTopAbility(); + int resultCode = 0; + ani_object elementNameobj = AppExecFwk::WrapElementName(env, elementName); + if (elementNameobj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null elementNameobj"); + resultCode = ERR_FAILURE; + } + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateErrorByNativeErr(env, resultCode), + elementNameobj); + return; +} + +void EtsAbilityManagerRegistryInit(ani_env *env) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "call EtsAbilityManagerRegistryInit"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return; + } + ani_status status = ANI_ERROR; + if (env->ResetError() != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "ResetError failed"); + } + ani_namespace ns = nullptr; + status = env->FindNamespace(ETS_ABILITY_MANAGER_NAMESPACE, &ns); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "FindNamespace abilityManager failed status : %{public}d", status); + return; + } + std::array methods = { + ani_native_function { + "nativeGetForegroundUIAbilities", ETS_ABILITY_MANAGER_SIGNATURE_ARRAY, + reinterpret_cast(GetForegroundUIAbilities) + }, + ani_native_function {"nativeGetTopAbility", ETS_ABILITY_MANAGER_SIGNATURE_CALLBACK, + reinterpret_cast(GetTopAbility)}, + }; + status = env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Namespace_BindNativeFunctions failed status : %{public}d", status); + } + if (env->ResetError() != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "ResetError failed"); + } +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "in AbilityManagerEts.ANI_Constructor"); + if (vm == nullptr || result == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null vm or result"); + return ANI_INVALID_ARGS; + } + + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "GetEnv failed, status=%{public}d", status); + return ANI_NOT_FOUND; + } + EtsAbilityManagerRegistryInit(env); + *result = ANI_VERSION_1; + TAG_LOGD(AAFwkTag::ABILITYMGR, "AbilityManagerEts.ANI_Constructor finished"); + return ANI_OK; +} +} +} // namespace AbilityManagerEts +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/BUILD.gn b/frameworks/ets/ani/ani_common/BUILD.gn index 5053411f2be..199ca933e0c 100644 --- a/frameworks/ets/ani/ani_common/BUILD.gn +++ b/frameworks/ets/ani/ani_common/BUILD.gn @@ -30,6 +30,7 @@ ohos_shared_library("ani_common") { include_dirs = [ "./include", + "${ability_runtime_innerkits_path}/app_manager/include/appmgr", "${ability_runtime_path}/frameworks/ets/ani/enum_convert", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", @@ -41,7 +42,10 @@ ohos_shared_library("ani_common") { sources = [ "src/ani_common_ability_result.cpp", + "src/ani_common_ability_state_data.cpp", "src/ani_common_configuration.cpp", + "src/ani_common_execute_param.cpp", + "src/ani_common_execute_result.cpp", "src/ani_common_start_options.cpp", "src/ani_common_util.cpp", "src/ani_common_want.cpp", @@ -49,6 +53,8 @@ ohos_shared_library("ani_common") { "src/ets_context_utils.cpp", "src/ets_data_struct_converter.cpp", "src/ets_error_utils.cpp", + "src/ets_extension_context.cpp", + "src/ets_free_install_observer.cpp", ] cflags = [] @@ -59,7 +65,11 @@ ohos_shared_library("ani_common") { deps = [ "${ability_runtime_innerkits_path}/ability_manager:ability_manager", "${ability_runtime_innerkits_path}/ability_manager:ability_start_options", + "${ability_runtime_innerkits_path}/ability_manager:process_options", + "${ability_runtime_innerkits_path}/ability_manager:start_window_option", + "${ability_runtime_innerkits_path}/app_manager:app_manager", "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_native_path}/ability/native:abilitykit_native", "${ability_runtime_native_path}/ability/native:ability_business_error", "${ability_runtime_native_path}/appkit:app_context", "${ability_runtime_native_path}/appkit:application_context_manager", @@ -76,6 +86,8 @@ ohos_shared_library("ani_common") { "common_event_service:cesfwk_innerkits", "eventhandler:libeventhandler", "hilog:libhilog", + "hitrace:hitrace_meter", + "image_framework:image_ani", "ipc:ipc_core", "ipc:ipc_napi", "json:nlohmann_json_static", diff --git a/frameworks/ets/ani/ani_common/include/ani_common_ability_state_data.h b/frameworks/ets/ani/ani_common/include/ani_common_ability_state_data.h new file mode 100644 index 00000000000..9a6d68f555a --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_ability_state_data.h @@ -0,0 +1,31 @@ +/* + * 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_RUNNTIME_ANICOMMON_ABILITY_STATE_DATA_H +#define OHOS_ABILITY_RUNNTIME_ANICOMMON_ABILITY_STATE_DATA_H + +#include "ani_common_util.h" +#include "ability_state_data.h" + +namespace OHOS { +namespace AppExecFwk { + ani_object WrapAbilityStateData(ani_env *env, const AbilityStateData &data); + ani_object WrapAbilityStateDataInner(ani_env *env, ani_class cls, ani_object object, + const AbilityStateData &data); + ani_object CreateAniAbilityStateDataArray(ani_env *env, const std::vector &list); +} // namespace AppExecFwk +} // namespace OHOS + +#endif // OHOS_ABILITY_RUNNTIME_ANICOMMON_ABILITY_STATE_DATA_H \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/include/ani_common_configuration.h b/frameworks/ets/ani/ani_common/include/ani_common_configuration.h index 039b86e5119..0bfaea6b61c 100644 --- a/frameworks/ets/ani/ani_common/include/ani_common_configuration.h +++ b/frameworks/ets/ani/ani_common/include/ani_common_configuration.h @@ -23,6 +23,6 @@ namespace OHOS { namespace AppExecFwk { ani_object WrapConfiguration(ani_env *env, const AppExecFwk::Configuration &configuration); bool UnwrapConfiguration(ani_env *env, ani_object param, Configuration &config); -} // namespace AppExecFwk -} // namespace OHOS +} // namespace AppExecFwk +} // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_ANI_COMMON_CONFIGURATION_H diff --git a/frameworks/ets/ani/ani_common/include/ani_common_execute_param.h b/frameworks/ets/ani/ani_common/include/ani_common_execute_param.h new file mode 100644 index 00000000000..2626868b433 --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_execute_param.h @@ -0,0 +1,28 @@ +/* + * 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_ANI_COMMON_EXECUTE_PARAM_H +#define OHOS_ABILITY_RUNTIME_ANI_COMMON_EXECUTE_PARAM_H + +#include "insight_intent_execute_param.h" +#include "ani_common_util.h" + +namespace OHOS { +namespace AbilityRuntime { + +bool UnwrapExecuteParam(ani_env *env, ani_object param, AppExecFwk::InsightIntentExecuteParam &executeParam); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANI_COMMON_EXECUTE_PARAM_H diff --git a/frameworks/ets/ani/ani_common/include/ani_common_execute_result.h b/frameworks/ets/ani/ani_common/include/ani_common_execute_result.h new file mode 100644 index 00000000000..b669a37e95a --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_execute_result.h @@ -0,0 +1,30 @@ +/* + * 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_ANI_COMMON_EXECUTE_RESULT_H +#define OHOS_ABILITY_RUNTIME_ANI_COMMON_EXECUTE_RESULT_H + +#include "insight_intent_execute_result.h" +#include "ani_common_util.h" + +namespace OHOS { +namespace AbilityRuntime { + +bool UnwrapExecuteResult(ani_env *env, ani_object ¶m, AppExecFwk::InsightIntentExecuteResult &executeResult); +ani_object WrapExecuteResult(ani_env *env, const AppExecFwk::InsightIntentExecuteResult &executeResult); +ani_object CreateNullExecuteResult(ani_env *env); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANI_COMMON_EXECUTE_RESULT_H diff --git a/frameworks/ets/ani/ani_common/include/ani_common_start_options.h b/frameworks/ets/ani/ani_common/include/ani_common_start_options.h index cdf3e73bb66..de202218897 100644 --- a/frameworks/ets/ani/ani_common/include/ani_common_start_options.h +++ b/frameworks/ets/ani/ani_common/include/ani_common_start_options.h @@ -18,9 +18,24 @@ #include "start_options.h" #include "ani_common_util.h" +#ifdef START_WINDOW_OPTIONS_WITH_PIXELMAP +#include "pixel_map_ani.h" +#include "image_ani_utils.h" +#endif namespace OHOS { namespace AppExecFwk { +bool UnwrapStartOptionsWithProcessOption(ani_env *env, ani_object param, AAFwk::StartOptions &startOptions); bool UnwrapStartOptions(ani_env *env, ani_object param, AAFwk::StartOptions &startOptions); +bool UnwrapProcessOptions(ani_env *env, ani_object param, std::shared_ptr &processOptions); + +#ifdef START_WINDOW_OPTIONS_WITH_PIXELMAP +bool UnwrapPixelMapByPropertyName( + ani_env *env, ani_object EnvObject, const char *propertyName, std::shared_ptr &value); +bool UnwrapPixelMapFromAni(ani_env *env, ani_object param, std::shared_ptr &value); +#endif + +bool UnwrapStartWindowOption(ani_env *env, ani_object param, + std::shared_ptr &startWindowOption); } // namespace AppExecFwk } // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_ANI_COMMON_START_OPTIONS_H \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/include/ani_common_util.h b/frameworks/ets/ani/ani_common/include/ani_common_util.h index 63dff5f2f1d..02d3c64b663 100644 --- a/frameworks/ets/ani/ani_common/include/ani_common_util.h +++ b/frameworks/ets/ani/ani_common/include/ani_common_util.h @@ -22,6 +22,7 @@ namespace OHOS { namespace AppExecFwk { +struct RunningProcessInfo; bool GetFieldDoubleByName(ani_env *env, ani_object object, const char *name, double &value); bool SetFieldDoubleByName(ani_env *env, ani_class cls, ani_object object, const char *name, double value); @@ -46,10 +47,33 @@ bool GetStdString(ani_env *env, ani_string str, std::string &value); ani_string GetAniString(ani_env *env, const std::string &str); bool GetAniStringArray(ani_env *env, const std::vector &values, ani_array_ref *value); +bool SetOptionalFieldInt(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, int value); + ani_object CreateDouble(ani_env *env, ani_double value); ani_object CreateBoolean(ani_env *env, ani_boolean value); +ani_object CreateLong(ani_env *env, ani_long value); +ani_object CreateInt(ani_env *env, ani_int value); bool AsyncCallback(ani_env *env, ani_object call, ani_object error, ani_object result); +bool GetPropertyRef(ani_env *env, ani_object obj, const char *name, ani_ref &ref, ani_boolean &isUndefined); +bool IsExistsField(ani_env *env, ani_object param, const char *name); + +bool WrapArrayString(ani_env *env, ani_object &arrayObj, const std::vector &values); +bool UnwrapArrayString(ani_env *env, const ani_object &arrayObj, std::vector &stringList); +ani_object CreateRunningProcessInfoArray(ani_env *env, std::vector infos); +ani_object CreateEmptyArray(ani_env *env); + +bool IsExistsProperty(ani_env *env, ani_object param, const char *name); +bool GetStringProperty(ani_env *env, ani_object param, const char *name, std::string &value); +bool GetStringArrayProperty(ani_env *env, ani_object param, const char *name, std::vector &value); +bool GetDoublePropertyObject(ani_env *env, ani_object param, const char *name, double &value); +bool GetDoublePropertyValue(ani_env *env, ani_object param, const char *name, double &value); +bool GetRefProperty(ani_env *env, ani_object param, const char *name, ani_ref &value); + +bool SetDoublePropertyObject(ani_env *env, ani_object param, const char *name, double value); +bool SetDoublePropertyValue(ani_env *env, ani_object param, const char *name, double value); +bool SetStringArrayProperty(ani_env *env, ani_object param, const char *name, const std::vector &values); +bool SetRefProperty(ani_env *env, ani_object param, const char *name, ani_ref value); } // namespace AppExecFwk } // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_ANI_COMMON_UTIL_H diff --git a/frameworks/ets/ani/ani_common/include/ani_common_want.h b/frameworks/ets/ani/ani_common/include/ani_common_want.h index a2d1bd125db..4a77835fb82 100644 --- a/frameworks/ets/ani/ani_common/include/ani_common_want.h +++ b/frameworks/ets/ani/ani_common/include/ani_common_want.h @@ -33,6 +33,10 @@ ani_ref WrapWantParams(ani_env *env, const AAFwk::WantParams &wantParams); bool UnwrapWantParams(ani_env *env, ani_ref param, AAFwk::WantParams &wantParams); bool UnWrapAbilityResult(ani_env *env, ani_object param, int &resultCode, AAFwk::Want &want); + +ani_object WrapElementName(ani_env *env, const AppExecFwk::ElementName &elementNameParam); +ani_object WrapElementNameInner(ani_env *env, ani_class elementNameObj, ani_object object, + const AppExecFwk::ElementName &elementNameParam); } // namespace AppExecFwk } // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_ANI_COMMON_WANT_H diff --git a/frameworks/ets/ani/ani_common/include/ets_application_context_utils.h b/frameworks/ets/ani/ani_common/include/ets_application_context_utils.h index a51804e5fe9..39bf4846e2d 100644 --- a/frameworks/ets/ani/ani_common/include/ets_application_context_utils.h +++ b/frameworks/ets/ani/ani_common/include/ets_application_context_utils.h @@ -28,16 +28,41 @@ namespace OHOS { namespace AbilityRuntime { class EtsApplicationContextUtils { public: - explicit EtsApplicationContextUtils() {} + explicit EtsApplicationContextUtils(std::weak_ptr &&applicationContext) + : applicationContext_(std::move(applicationContext)) + { + } virtual ~EtsApplicationContextUtils() = default; - static void SetSupportedProcessCacheSync([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, - ani_boolean value); - static std::shared_ptr GeApplicationContext(ani_env *env, ani_object aniObj); + static void RestartApp(ani_env *env, ani_object aniObj, ani_object wantObj); + static void SetFont(ani_env *env, ani_object aniObj, ani_string font); + static void SetColorMode(ani_env *env, ani_object aniObj, ani_enum_item colorMode); + static void SetLanguage(ani_env *env, ani_object aniObj, ani_string language); + static void SetFontSizeScale(ani_env *env, ani_object aniObj, ani_double fontSizeScale); + static void ClearUpApplicationData(ani_env *env, ani_object aniObj, ani_object callback); + static void GetRunningProcessInformation(ani_env *env, ani_object aniObj, ani_object callback); + static void killAllProcesses(ani_env *env, ani_object aniObj, ani_boolean clearPageStack, ani_object callback); + static void PreloadUIExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object callback); + static void SetSupportedProcessCacheSync(ani_env *env, ani_object aniObj, ani_boolean value); + static void Clean(ani_env *env, ani_object object); + static EtsApplicationContextUtils* GeApplicationContext(ani_env *env, ani_object aniObj); static ani_object SetApplicationContext(ani_env* aniEnv, const std::shared_ptr &applicationContext); static ani_object CreateEtsApplicationContext(ani_env* aniEnv, const std::shared_ptr &applicationContext); static void BindApplicationContextFunc(ani_env* aniEnv); +protected: + std::weak_ptr applicationContext_; +private: + void OnRestartApp(ani_env *env, ani_object aniObj, ani_object wantObj); + void OnSetFont(ani_env *env, ani_object aniObj, ani_string font); + void OnSetColorMode(ani_env *env, ani_object aniObj, ani_enum_item colorMode); + void OnSetLanguage(ani_env *env, ani_object aniObj, ani_string language); + void OnSetFontSizeScale(ani_env *env, ani_object aniObj, ani_double fontSizeScale); + void OnClearUpApplicationData(ani_env *env, ani_object aniObj, ani_object callback); + void OnGetRunningProcessInformation(ani_env *env, ani_object aniObj, ani_object callback); + void OnkillAllProcesses(ani_env *env, ani_object aniObj, ani_boolean clearPageStack, ani_object callback); + void OnPreloadUIExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object callback); + void OnSetSupportedProcessCacheSync(ani_env *env, ani_object aniObj, ani_boolean value); }; } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/ets/ani/ani_common/include/ets_context_utils.h b/frameworks/ets/ani/ani_common/include/ets_context_utils.h index 89767501dab..159b325bd34 100644 --- a/frameworks/ets/ani/ani_common/include/ets_context_utils.h +++ b/frameworks/ets/ani/ani_common/include/ets_context_utils.h @@ -31,6 +31,10 @@ void CreateEtsBaseContext(ani_env *aniEnv, ani_class contextClass, ani_object co ani_object GetApplicationContextSync(ani_env *env, ani_object aniObj); void SwitchArea(ani_env *env, ani_object obj, ani_enum_item areaModeItem); ani_enum_item GetArea(ani_env *env, ani_object obj); +ani_object CreateModuleResourceManagerSync(ani_env *env, ani_object aniObj, + ani_string bundleName, ani_string moduleName); +void Clean(ani_env *env, ani_object object); +bool SetNativeContextLong(ani_env *env, ani_object aniObj, ani_long nativeContextLong); } } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/kits/native/ability/ability_runtime/ets_extension_context.h b/frameworks/ets/ani/ani_common/include/ets_extension_context.h similarity index 100% rename from interfaces/kits/native/ability/ability_runtime/ets_extension_context.h rename to frameworks/ets/ani/ani_common/include/ets_extension_context.h diff --git a/interfaces/kits/native/ability/native/ets_free_install_observer.h b/frameworks/ets/ani/ani_common/include/ets_free_install_observer.h similarity index 100% rename from interfaces/kits/native/ability/native/ets_free_install_observer.h rename to frameworks/ets/ani/ani_common/include/ets_free_install_observer.h diff --git a/frameworks/ets/ani/ani_common/src/ani_common_ability_state_data.cpp b/frameworks/ets/ani/ani_common/src/ani_common_ability_state_data.cpp new file mode 100644 index 00000000000..29abfa3e4e4 --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_ability_state_data.cpp @@ -0,0 +1,155 @@ +/* + * 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 "ani_common_ability_state_data.h" + +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +ani_object WrapAbilityStateDataInner(ani_env *env, ani_class cls, ani_object object, + const AbilityStateData &data) +{ + if (env == nullptr || cls == nullptr || object == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid args"); + return nullptr; + } + + if (!SetFieldStringByName(env, cls, object, "moduleName", data.moduleName)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set moduleName failed"); + return nullptr; + } + + if (!SetFieldStringByName(env, cls, object, "bundleName", data.bundleName)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set bundleName failed"); + return nullptr; + } + + if (!SetFieldStringByName(env, cls, object, "abilityName", data.abilityName)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set abilityName failed"); + return nullptr; + } + + if (!SetFieldIntByName(env, cls, object, "pid", data.pid)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set pid failed"); + return nullptr; + } + + if (!SetFieldIntByName(env, cls, object, "uid", data.uid)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set uid failed"); + return nullptr; + } + + if (!SetFieldIntByName(env, cls, object, "state", data.abilityState)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set state failed"); + return nullptr; + } + + if (!SetFieldIntByName(env, cls, object, "abilityType", data.abilityType)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set type failed"); + return nullptr; + } + + if (!SetFieldBoolByName(env, cls, object, "isAtomicService", data.isAtomicService)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set isAtomicService failed"); + return nullptr; + } + + if (data.appCloneIndex != -1 && !SetOptionalFieldInt(env, cls, object, "appCloneIndex", data.appCloneIndex)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set appCloneIndex failed"); + return nullptr; + } + + return object; +} + +ani_object WrapAbilityStateData(ani_env *env, const AbilityStateData &data) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return nullptr; + } + + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method ctor = nullptr; + ani_object object = nullptr; + static const char *className = "Lapplication/AbilityStateData/AbilityStateData;"; + + if ((status = env->FindClass(className, &cls)) != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "FindClass status : %{public}d or null cls", status); + return nullptr; + } + + if ((status = env->Class_FindMethod(cls, "", ":V", &ctor)) != ANI_OK || ctor == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Class_FindMethod status : %{public}d or null ctor", status); + return nullptr; + } + + if ((status = env->Object_New(cls, ctor, &object)) != ANI_OK || object == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Object_New status : %{public}d or null object", status); + return nullptr; + } + + return WrapAbilityStateDataInner(env, cls, object, data); +} + +ani_object CreateAniAbilityStateDataArray(ani_env *env, const std::vector &list) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "call CreateAniAbilityStateDataArray, list.size=%{public}zu", list.size()); + + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return nullptr; + } + + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method ctor = nullptr; + ani_object object = nullptr; + static const char *className = "Lescompat/Array;"; + + if ((status = env->FindClass(className, &cls)) != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "FindClass status : %{public}d or null cls", status); + return nullptr; + } + + if ((status = env->Class_FindMethod(cls, "", "I:V", &ctor)) != ANI_OK || ctor == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Class_FindMethod status : %{public}d or null ctor", status); + return nullptr; + } + + if ((status = env->Object_New(cls, ctor, &object, list.size())) != ANI_OK || object == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Object_New status : %{public}d or null object", status); + return nullptr; + } + + ani_size index = 0; + for (const auto &data : list) { + ani_object obj = WrapAbilityStateData(env, data); + if (obj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null obj"); + return nullptr; + } + if (ANI_OK != env->Object_CallMethodByName_Void(object, "$_set", "ILstd/core/Object;:V", index, obj)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Object_CallMethodByName_Void failed"); + return nullptr; + } + index++; + } + return object; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/src/ani_common_execute_param.cpp b/frameworks/ets/ani/ani_common/src/ani_common_execute_param.cpp new file mode 100644 index 00000000000..2c624320c1e --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_execute_param.cpp @@ -0,0 +1,122 @@ +/* + * 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 "ani_common_execute_param.h" + +#include "hilog_tag_wrapper.h" +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "ani_enum_convert.h" + +namespace OHOS { +namespace AbilityRuntime { +using namespace OHOS::AppExecFwk; + +bool UnwrapExecuteParam(ani_env *env, ani_object param, AppExecFwk::InsightIntentExecuteParam &executeParam) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return false; + } + if (param == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null param"); + return false; + } + + std::string bundleName {""}; + if (!GetStringProperty(env, param, "bundleName", bundleName)) { + TAG_LOGE(AAFwkTag::INTENT, "Wrong argument type bundleName"); + return false; + } + executeParam.bundleName_ = bundleName; + + std::string moduleName {""}; + if (!GetStringProperty(env, param, "moduleName", moduleName)) { + TAG_LOGE(AAFwkTag::INTENT, "Wrong argument type moduleName"); + return false; + } + executeParam.moduleName_ = moduleName; + + std::string abilityName {""}; + if (!GetStringProperty(env, param, "abilityName", abilityName)) { + TAG_LOGE(AAFwkTag::INTENT, "Wrong argument type abilityName"); + return false; + } + executeParam.abilityName_ = abilityName; + + std::string insightIntentName {""}; + if (!GetStringProperty(env, param, "insightIntentName", insightIntentName)) { + TAG_LOGE(AAFwkTag::INTENT, "Wrong argument type insightIntentName"); + return false; + } + executeParam.insightIntentName_ = insightIntentName; + + ani_ref aniIntentParam = nullptr; + if (!GetRefProperty(env, param, "insightIntentParam", aniIntentParam)) { + TAG_LOGE(AAFwkTag::INTENT, "null aniIntentParam"); + return false; + } + auto wp = std::make_shared(); + if (!UnwrapWantParams(env, aniIntentParam, *wp)) { + TAG_LOGE(AAFwkTag::INTENT, "unwrap want fail"); + return false; + } + executeParam.insightIntentParam_ = wp; + + int32_t executeMode = 0; + ani_ref executeModeRef = nullptr; + if (!GetRefProperty(env, param, "executeMode", executeModeRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "Wrong argument type executeMode"); + return false; + } + AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative(env, + static_cast(executeModeRef), executeMode); + executeParam.executeMode_ = executeMode; + + double displayIdD = 0.0; + int32_t displayId = INVALID_DISPLAY_ID; + if (executeMode == ExecuteMode::UI_ABILITY_FOREGROUND && + IsExistsProperty(env, param, "displayId")) { + if (GetDoublePropertyObject(env, param, "displayId", displayIdD)) { + displayId = static_cast(displayIdD); + if (displayId < 0) { + TAG_LOGE(AAFwkTag::INTENT, "invalid displayId"); + return false; + } + TAG_LOGI(AAFwkTag::INTENT, "displayId %{public}d", displayId); + executeParam.displayId_ = displayId; + } + } + if (IsExistsProperty(env, param, "uris")) { + std::vector uris; + if (!GetStringArrayProperty(env, param, "uris", uris)) { + TAG_LOGE(AAFwkTag::INTENT, "Wrong argument uris fail"); + return false; + } + executeParam.uris_ = uris; + } + if (IsExistsProperty(env, param, "flags")) { + double flags = 0.0; + if (!GetDoublePropertyObject(env, param, "flags", flags)) { + TAG_LOGE(AAFwkTag::INTENT, "Wrong argument flags fail"); + return false; + } + executeParam.flags_ = static_cast(flags); + } + + return true; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/ani_common/src/ani_common_execute_result.cpp b/frameworks/ets/ani/ani_common/src/ani_common_execute_result.cpp new file mode 100644 index 00000000000..875c6fac091 --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_execute_result.cpp @@ -0,0 +1,178 @@ +/* + * 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 "ani_common_execute_result.h" + +#include "hilog_tag_wrapper.h" +#include "insight_intent_execute_result.h" +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "want_params.h" +#include + +namespace OHOS { +namespace AbilityRuntime { +using namespace OHOS::AppExecFwk; +bool UnwrapResultOfExecuteResult(ani_env *env, ani_object ¶m, InsightIntentExecuteResult &executeResult) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return false; + } + ani_status status = ANI_OK; + ani_ref wantParamRef = nullptr; + if (!GetRefProperty(env, param, "result", wantParamRef)) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return false; + } + + auto wantParams = std::make_shared(); + if (!UnwrapWantParams(env, wantParamRef, *wantParams)) { + TAG_LOGE(AAFwkTag::INTENT, "failed to unwrap want parameter"); + return false; + } + + if (!executeResult.CheckResult(wantParams)) { + TAG_LOGE(AAFwkTag::INTENT, "Check wp fail"); + return false; + } + executeResult.result = wantParams; + + return true; +} + +bool UnwrapExecuteResult(ani_env *env, ani_object ¶m, InsightIntentExecuteResult &executeResult) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return false; + } + + if (param == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "param is nullptr"); + return false; + } + + ani_double code = 0; + if (!GetDoublePropertyValue(env, param, "code", code)) { + TAG_LOGE(AAFwkTag::INTENT, "parse code fail"); + return false; + } + executeResult.code = static_cast(code); + + if (IsExistsProperty(env, param, "result")) { + if (!UnwrapResultOfExecuteResult(env, param, executeResult)) { + TAG_LOGE(AAFwkTag::INTENT, "unwrap execute result fail"); + return false; + } + } + + if (IsExistsProperty(env, param, "uris")) { + std::vector uris; + if (!GetStringArrayProperty(env, param, "uris", uris)) { + TAG_LOGE(AAFwkTag::INTENT, "unwrap uris is null"); + return false; + } + executeResult.uris = uris; + } + + if (IsExistsProperty(env, param, "flags")) { + double flags = 0.0; + if (!GetDoublePropertyObject(env, param, "flags", flags)) { + TAG_LOGE(AAFwkTag::INTENT, "unwrap flags is null"); + return false; + } + executeResult.flags = static_cast(flags); + } + + return true; +} + +ani_object WrapExecuteResult(ani_env *env, const AppExecFwk::InsightIntentExecuteResult &executeResult) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return nullptr; + } + + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method ctor = nullptr; + ani_object objValue = {}; + + if ((status = env->FindClass("L@ohos/app/ability/insightIntent/insightIntent/ExecuteResultInner;", + &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + + if ((status = env->Class_FindMethod(cls, "", nullptr, &ctor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + + if ((status = env->Object_New(cls, ctor, &objValue)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + + if (!SetDoublePropertyValue(env, objValue, "code", static_cast(executeResult.code))) { + TAG_LOGE(AAFwkTag::INTENT, "SetDoubleProperty failded"); + return nullptr; + } + if (executeResult.result != nullptr) { + SetRefProperty(env, objValue, "result", WrapWantParams(env, *executeResult.result)); + } + if (executeResult.uris.size() > 0) { + SetStringArrayProperty(env, objValue, "uris", executeResult.uris); + } + SetDoublePropertyObject(env, objValue, "flags", static_cast(executeResult.flags)); + + return objValue; +} + +ani_object CreateNullExecuteResult(ani_env *env) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return nullptr; + } + + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method ctor = nullptr; + ani_object objValue = {}; + + if ((status = env->FindClass("L@ohos/app/ability/insightIntent/insightIntent/ExecuteResultInner;", + &cls)) + != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + + if ((status = env->Class_FindMethod(cls, "", nullptr, &ctor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + + if ((status = env->Object_New(cls, ctor, &objValue)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + + return objValue; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/ani_common/src/ani_common_start_options.cpp b/frameworks/ets/ani/ani_common/src/ani_common_start_options.cpp index cc5710c4839..f7138f6996c 100644 --- a/frameworks/ets/ani/ani_common/src/ani_common_start_options.cpp +++ b/frameworks/ets/ani/ani_common/src/ani_common_start_options.cpp @@ -13,11 +13,128 @@ * limitations under the License. */ +#include "ability_info.h" #include "ani_common_start_options.h" #include "hilog_tag_wrapper.h" +#include "ani_enum_convert.h" +#include "int_wrapper.h" +#include "process_options.h" +#include "start_window_option.h" +#include "parcel.h" namespace OHOS { namespace AppExecFwk { + +bool UnwrapStartOptionsWithProcessOption(ani_env* env, ani_object param, AAFwk::StartOptions &startOptions) +{ + TAG_LOGD(AAFwkTag::ANI, "UnwrapStartOptionsWithProcessOption called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + if (!UnwrapStartOptions(env, param, startOptions)) { + TAG_LOGE(AAFwkTag::ANI, "Unwrap UnwrapStartOptions failed"); + return false; + } + if (!UnwrapProcessOptions(env, param, startOptions.processOptions)) { + TAG_LOGE(AAFwkTag::ANI, "Unwrap processOptions failed"); + return false; + } + if (!UnwrapStartWindowOption(env, param, startOptions.startWindowOption)) { + TAG_LOGE(AAFwkTag::ANI, "Unwrap startWindowOption failed"); + return false; + } + return true; +} + +void UnwrapStartOptionsWindowOptions(ani_env *env, ani_object param, AAFwk::StartOptions &startOptions) +{ + ani_double windowLeft = 0.0; + if (GetFieldDoubleByName(env, param, "windowLeft", windowLeft)) { + TAG_LOGD(AAFwkTag::ANI, "windowLeft:%{public}f", windowLeft); + startOptions.SetWindowLeft(windowLeft); + startOptions.windowLeftUsed_ = true; + } + + ani_double windowTop = 0.0; + if (GetFieldDoubleByName(env, param, "windowTop", windowTop)) { + TAG_LOGD(AAFwkTag::ANI, "windowTop:%{public}f", windowTop); + startOptions.SetWindowTop(windowTop); + startOptions.windowTopUsed_ = true; + } + + ani_double windowWidth = 0.0; + if (GetFieldDoubleByName(env, param, "windowWidth", windowWidth)) { + TAG_LOGD(AAFwkTag::ANI, "windowWidth:%{public}f", windowWidth); + startOptions.SetWindowWidth(windowWidth); + startOptions.windowWidthUsed_ = true; + } + + ani_double windowHeight = 0.0; + if (GetFieldDoubleByName(env, param, "windowHeight", windowHeight)) { + TAG_LOGD(AAFwkTag::ANI, "windowHeight:%{public}f", windowHeight); + startOptions.SetWindowHeight(windowHeight); + startOptions.windowHeightUsed_ = true; + } + + ani_double minWindowWidth = 0.0; + if (GetFieldDoubleByName(env, param, "minWindowWidth", minWindowWidth)) { + TAG_LOGD(AAFwkTag::ANI, "minWindowWidth:%{public}f", minWindowWidth); + startOptions.SetMinWindowWidth(minWindowWidth); + startOptions.minWindowWidthUsed_ = true; + } + + ani_double minWindowHeight = 0.0; + if (GetFieldDoubleByName(env, param, "minWindowHeight", minWindowHeight)) { + TAG_LOGD(AAFwkTag::ANI, "minWindowHeight:%{public}f", minWindowHeight); + startOptions.SetMinWindowHeight(minWindowHeight); + startOptions.minWindowHeightUsed_ = true; + } + + ani_double maxWindowWidth = 0.0; + if (GetFieldDoubleByName(env, param, "maxWindowWidth", maxWindowWidth)) { + TAG_LOGD(AAFwkTag::ANI, "maxWindowWidth:%{public}f", maxWindowWidth); + startOptions.SetMaxWindowWidth(maxWindowWidth); + startOptions.maxWindowWidthUsed_ = true; + } + + ani_double maxWindowHeight = 0.0; + if (GetFieldDoubleByName(env, param, "maxWindowHeight", maxWindowHeight)) { + TAG_LOGD(AAFwkTag::ANI, "maxWindowHeight:%{public}f", maxWindowHeight); + startOptions.SetMaxWindowHeight(maxWindowHeight); + startOptions.maxWindowHeightUsed_ = true; + } +} + +bool SetSupportWindowModes(ani_env *env, ani_object param, AAFwk::StartOptions &startOptions) +{ + ani_ref supportWindowModesRef = nullptr; + ani_boolean hasValue = true; + if (GetPropertyRef(env, param, "supportWindowModes", supportWindowModesRef, hasValue) && !hasValue) { + ani_array_ref supportWindowModesArr = reinterpret_cast(supportWindowModesRef); + ani_size supportWindowModesLen = 0; + if (env->Array_GetLength(supportWindowModesArr, &supportWindowModesLen) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "Array_GetLength failed"); + return false; + } + for (size_t i = 0; i < supportWindowModesLen; ++i) { + ani_ref supportWindowModeRef = nullptr; + int32_t supportWindowMode = 0; + if (env->Array_Get_Ref(supportWindowModesArr, i, &supportWindowModeRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "Array_Get_Ref failed"); + return false; + } + AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative( + env, reinterpret_cast(supportWindowModeRef), supportWindowMode); + TAG_LOGD(AAFwkTag::ANI, "supportWindowMode:%{public}d", supportWindowMode); + startOptions.supportWindowModes_.emplace_back( + static_cast(supportWindowMode)); + } + } + return true; +} + + bool UnwrapStartOptions(ani_env *env, ani_object param, AAFwk::StartOptions &startOptions) { TAG_LOGD(AAFwkTag::ANI, "UnwrapStartOptions called"); @@ -25,11 +142,154 @@ bool UnwrapStartOptions(ani_env *env, ani_object param, AAFwk::StartOptions &sta TAG_LOGE(AAFwkTag::ANI, "null env"); return false; } + + ani_double windowMode = 0.0; + if (GetFieldDoubleByName(env, param, "windowMode", windowMode)) { + TAG_LOGD(AAFwkTag::ANI, "windowMode:%{public}f", windowMode); + startOptions.SetWindowMode(windowMode); + } + ani_double displayId = 0.0; if (GetFieldDoubleByName(env, param, "displayId", displayId)) { startOptions.SetDisplayID(static_cast(displayId)); } + + bool withAnimation = true; + if (GetFieldBoolByName(env, param, "withAnimation", withAnimation)) { + TAG_LOGD(AAFwkTag::ANI, "withAnimation:%{public}hhu", withAnimation); + startOptions.SetWithAnimation(withAnimation); + } + + UnwrapStartOptionsWindowOptions(env, param, startOptions); + + bool windowFocused = true; + if (GetFieldBoolByName(env, param, "windowFocused", windowFocused)) { + TAG_LOGD(AAFwkTag::ANI, "windowFocused:%{public}hhu", windowFocused); + startOptions.SetWindowFocused(windowFocused); + } + + if (!SetSupportWindowModes(env, param, startOptions)) { + TAG_LOGE(AAFwkTag::ANI, "SetSupportWindowModes failed"); + return false; + } + + return true; +} + +bool UnwrapProcessOptions(ani_env* env, ani_object param, std::shared_ptr &processOptions) +{ + auto option = std::make_shared(); + + ani_boolean isProcessModeUndefined = true; + ani_ref processModeRef = nullptr; + if (!GetPropertyRef(env, param, "processMode", processModeRef, isProcessModeUndefined)) { + TAG_LOGE(AAFwkTag::ANI, "Unwrap processMode failed"); + return false; + } + + ani_boolean isStartupVisibilityUndefined = true; + ani_ref startupVisibilityRef = nullptr; + if (!GetPropertyRef(env, param, "startupVisibility", startupVisibilityRef, isStartupVisibilityUndefined)) { + TAG_LOGE(AAFwkTag::ANI, "Unwrap startupVisibility failed"); + return false; + } + + if (isProcessModeUndefined && isStartupVisibilityUndefined) { + return true; + } + + int32_t processMode = 0; + if (isProcessModeUndefined) { + TAG_LOGE(AAFwkTag::ANI, "Unwrap processMode failed"); + return false; + } + AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative( + env, reinterpret_cast(processModeRef), processMode); + TAG_LOGD(AAFwkTag::ANI, "processMode: %{public}d", processMode); + option->processMode = AAFwk::ProcessOptions::ConvertInt32ToProcessMode(processMode); + if (option->processMode == AAFwk::ProcessMode::UNSPECIFIED) { + TAG_LOGE(AAFwkTag::ANI, "Convert processMode failed"); + return false; + } + + int32_t startupVisibility = 0; + if (isStartupVisibilityUndefined) { + TAG_LOGE(AAFwkTag::ANI, "Unwrap startupVisibility failed"); + return false; + } + AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative( + env, reinterpret_cast(startupVisibilityRef), startupVisibility); + TAG_LOGD(AAFwkTag::ANI, "startupVisibility: %{public}d", startupVisibility); + option->startupVisibility = AAFwk::ProcessOptions::ConvertInt32ToStartupVisibility(startupVisibility); + if (option->startupVisibility == AAFwk::StartupVisibility::UNSPECIFIED) { + TAG_LOGE(AAFwkTag::ANI, "Convert startupVisibility failed"); + return false; + } + + processOptions = option; + return true; +} + +#ifdef START_WINDOW_OPTIONS_WITH_PIXELMAP +bool UnwrapPixelMapFromAni(ani_env *env, ani_object param, std::shared_ptr &value) +{ + auto pixelMap = OHOS::Media::ImageAniUtils::GetPixelMapFromEnvSp(env, param); + if (!pixelMap) { + TAG_LOGE(AAFwkTag::ANI, "Unwrap pixelMap failed"); + return false; + } + + value = pixelMap; + return true; +} + +bool UnwrapPixelMapByPropertyName( + ani_env *env, ani_object param, const char *propertyName, std::shared_ptr &value) +{ + ani_ref envValue = nullptr; + if (!GetFieldRefByName(env, param, propertyName, envValue)) { + TAG_LOGE(AAFwkTag::ANI, "Get PixelMap failed"); + return false; + } + if (envValue == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "UnwrapPixelMapByPropertyName failed"); + return false; + } + return UnwrapPixelMapFromAni(env, reinterpret_cast(envValue), value); +} +#endif + +bool UnwrapStartWindowOption(ani_env *env, ani_object param, + std::shared_ptr &startWindowOption) +{ + auto option = std::make_shared(); + std::string startWindowBackgroundColor; + if (IsExistsField(env, param, "startWindowBackgroundColor")) { + if (!GetFieldStringByName(env, param, "startWindowBackgroundColor", startWindowBackgroundColor)) { + TAG_LOGE(AAFwkTag::JSNAPI, "Unwrap startWindowBackgroundColor failed"); + return false; + } + option->startWindowBackgroundColor = startWindowBackgroundColor; + } + if (!startWindowBackgroundColor.empty()) { + option->hasStartWindow = true; + } +#ifdef START_WINDOW_OPTIONS_WITH_PIXELMAP + std::shared_ptr startWindowIcon = nullptr; + if (IsExistsField(env, param, "startWindowIcon")) { + if (!UnwrapPixelMapByPropertyName(env, param, "startWindowIcon", startWindowIcon)) { + TAG_LOGE(AAFwkTag::ANI, "Unwrap startWindowIcon failed"); + return false; + } + option->startWindowIcon = startWindowIcon; + } + + if (startWindowIcon != nullptr) { + option->hasStartWindow = true; + } +#endif + startWindowOption = option; return true; } -} // namespace AppExecFwk -} // namespace OHOS \ No newline at end of file +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/src/ani_common_util.cpp b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp index cecb72225a3..47ca8896109 100644 --- a/frameworks/ets/ani/ani_common/src/ani_common_util.cpp +++ b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp @@ -12,19 +12,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include "ani_common_util.h" -#include +#include "ani_enum_convert.h" +#include "running_process_info.h" #include "hilog_tag_wrapper.h" #include "securec.h" namespace OHOS { namespace AppExecFwk { +namespace { constexpr const char* CLASSNAME_DOUBLE = "Lstd/core/Double;"; constexpr const char* CLASSNAME_BOOL = "Lstd/core/Boolean;"; constexpr const char* CLASSNAME_ARRAY = "Lescompat/Array;"; +constexpr const char* CLASSNAME_LONG = "Lstd/core/Long;"; +constexpr const char* CLASSNAME_INT = "Lstd/core/Int;"; constexpr const char* CLASSNAME_ASYNC_CALLBACK_WRAPPER = "Lutils/AbilityUtils/AsyncCallbackWrapper;"; +constexpr const char* SET_OBJECT_VOID_SIGNATURE = "ILstd/core/Object;:V"; +constexpr const char* CLASSNAME_INNER = "Lapplication/ProcessInformation/ProcessInformationInner;"; +constexpr const char* ENUMNAME_PROCESS = "L@ohos/app/ability/appManager/appManager/ProcessState;"; +constexpr const char* ENUMNAME_BUNDLE = "L@ohos/bundle/bundleManager/bundleManager/BundleType;"; +} bool GetFieldDoubleByName(ani_env *env, ani_object object, const char *name, double &value) { @@ -104,7 +114,7 @@ bool GetFieldBoolByName(ani_env *env, ani_object object, const char *name, bool } ani_boolean aniValue = ANI_FALSE; if ((status = env->Object_CallMethodByName_Boolean( - reinterpret_cast(field), "booleanValue", nullptr, &aniValue)) != ANI_OK) { + reinterpret_cast(field), "unboxed", nullptr, &aniValue)) != ANI_OK) { TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); return false; } @@ -397,7 +407,7 @@ ani_string GetAniString(ani_env *env, const std::string &str) ani_string aniStr = nullptr; ani_status status = env->String_NewUTF8(str.c_str(), str.size(), &aniStr); if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); return nullptr; } return aniStr; @@ -453,6 +463,31 @@ ani_object CreateBoolean(ani_env *env, ani_boolean value) return obj; } +ani_object CreateLong(ani_env *env, ani_long value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return nullptr; + } + ani_class cls = nullptr; + ani_status status = env->FindClass(CLASSNAME_LONG, &cls); + if (status != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "FindClass status: %{public}d, or null class", status); + return nullptr; + } + ani_method method = nullptr; + if ((status = env->Class_FindMethod(cls, "", "J:V", &method)) != ANI_OK || method == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "Class_FindMethod status: %{public}d, or null method", status); + return nullptr; + } + ani_object object = nullptr; + if ((status = env->Object_New(cls, method, &object, value)) != ANI_OK || object == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "Object_New status: %{public}d, or null object", status); + return nullptr; + } + return object; +} + bool AsyncCallback(ani_env *env, ani_object call, ani_object error, ani_object result) { if (env == nullptr) { @@ -523,7 +558,7 @@ bool GetStringOrUndefined(ani_env *env, ani_object param, const char *name, std: ani_ref obj = nullptr; ani_boolean isUndefined = true; ani_status status = ANI_ERROR; - + if (env == nullptr || param == nullptr || name == nullptr) { TAG_LOGE(AAFwkTag::ANI, "null env or param or name"); return false; @@ -547,5 +582,604 @@ bool GetStringOrUndefined(ani_env *env, ani_object param, const char *name, std: } return true; } -} // namespace AppExecFwk -} // namespace OHOS + +bool GetPropertyRef(ani_env *env, ani_object obj, const char *name, ani_ref &ref, ani_boolean &isUndefined) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + ani_status status = env->Object_GetPropertyByName_Ref(obj, name, &ref); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "Failed to get property '%{public}s', status: %{public}d", name, status); + return false; + } + status = env->Reference_IsUndefined(ref, &isUndefined); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "Failed to check undefined for '%{public}s', status: %{public}d", name, status); + return false; + } + return true; +} + +ani_object CreateInt(ani_env *env, ani_int value) +{ + ani_class cls; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(CLASSNAME_INT, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "FindClass status : %{public}d", status); + return nullptr; + } + ani_method ctor; + if ((status = env->Class_FindMethod(cls, "", "I:V", &ctor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "Class_FindMethod status : %{public}d", status); + return nullptr; + } + ani_object object; + if ((status = env->Object_New(cls, ctor, &object, value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "Object_New status : %{public}d", status); + return nullptr; + } + return object; +} + +bool SetOptionalFieldInt(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, int value) +{ + ani_field field = nullptr; + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK || field == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "Class_FindField failed or null field, status=%{public}d, fieldName=%{public}s", + status, fieldName.c_str()); + return false; + } + ani_object intObj = CreateInt(env, value); + if (intObj == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null intObj"); + return false; + } + status = env->Object_SetField_Ref(object, field, intObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "Object_SetField_Ref failed, status=%{public}d, fieldName=%{public}s", + status, fieldName.c_str()); + return false; + } + return true; +} + +bool IsExistsField(ani_env *env, ani_object param, const char *name) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + + ani_ref resRef = nullptr; + ani_status status; + ani_boolean isUndefined = true; + + if ((status = env->Object_GetFieldByName_Ref(param, name, &resRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(resRef, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + if (isUndefined) { + return false; + } + return true; +} + +bool WrapArrayString(ani_env *env, ani_object &arrayObj, const std::vector &values) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "env null or arrayObj null"); + return false; + } + ani_class arrayCls = nullptr; + ani_method arrayCtor; + ani_string aniStr = nullptr; + ani_status status = ANI_ERROR; + status = env->FindClass(CLASSNAME_ARRAY, &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, values.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + + for (size_t i = 0; i < values.size(); i++) { + aniStr = nullptr; + status = env->String_NewUTF8(values[i].c_str(), values[i].size(), &aniStr); + if (aniStr == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null aniStr"); + return false; + } + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", SET_OBJECT_VOID_SIGNATURE, i, aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + } + return true; +} + +bool UnwrapArrayString(ani_env *env, const ani_object &arrayObj, std::vector &stringList) +{ + if (env == nullptr || arrayObj == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "env null or arrayObj null"); + return false; + } + stringList.clear(); + ani_size size = 0; + ani_status status = ANI_ERROR; + if ((status = env->Array_GetLength(reinterpret_cast(arrayObj), &size)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + ani_ref ref; + ani_size idx; + for (idx = 0; idx < size; idx++) { + if ((status = env->Array_Get_Ref(reinterpret_cast(arrayObj), idx, &ref)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d, index: %{public}zu", status, idx); + return false; + } + if (ref == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null ref"); + return false; + } + std::string str = ""; + if (!OHOS::AppExecFwk::GetStdString(env, reinterpret_cast(ref), str)) { + TAG_LOGE(AAFwkTag::ANI, "GetStdString failed, index: %{public}zu", idx); + return false; + } + stringList.push_back(str); + } + return true; +} + +bool SetProcessInformation(ani_env *env, ani_object object, const AppExecFwk::RunningProcessInfo &processInfo) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + ani_status status = ANI_OK; + if ((status = env->Object_SetPropertyByName_Double(object, "pid", processInfo.pid_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "pid failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetPropertyByName_Double(object, "uid", processInfo.uid_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "uid failed status:%{public}d", status); + return false; + } + status = env->Object_SetPropertyByName_Ref(object, "processName", + AppExecFwk::GetAniString(env, processInfo.processName_)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "processName failed status:%{public}d", status); + return false; + } + ani_object arrayObj = nullptr; + WrapArrayString(env, arrayObj, processInfo.bundleNames); + status = env->Object_SetPropertyByName_Ref(object, "bundleNames", arrayObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "bundleNames failed status:%{public}d", status); + return false; + } + ani_enum_item stateItem {}; + AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts(env, + ENUMNAME_PROCESS, processInfo.state_, stateItem); + if ((status = env->Object_SetPropertyByName_Ref(object, "state", stateItem)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "state failed status:%{public}d", status); + return false; + } + ani_enum_item bundleTypeItem {}; + AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts(env, + ENUMNAME_BUNDLE, + processInfo.bundleType, bundleTypeItem); + if ((status = env->Object_SetPropertyByName_Ref(object, "bundleType", bundleTypeItem)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "bundleType failed status:%{public}d", status); + return false; + } + status = env->Object_SetPropertyByName_Ref(object, "appCloneIndex", + CreateDouble(env, processInfo.appCloneIndex)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "appCloneIndex failed status:%{public}d", status); + return false; + } + return true; +} + +ani_object WrapProcessInformation(ani_env *env, const AppExecFwk::RunningProcessInfo &processInfo) +{ + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method {}; + ani_object object = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return nullptr; + } + if ((status = env->FindClass(CLASSNAME_INNER, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "FindClass failed status: %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "find ctor failed status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "Object_New ProcessInformationInner failed status: %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null object"); + return nullptr; + } + if (!SetProcessInformation(env, object, processInfo)) { + TAG_LOGE(AAFwkTag::ANI, "SetProcessInformation failed"); + return nullptr; + } + return object; +} + +ani_object CreateRunningProcessInfoArray(ani_env *env, std::vector infos) +{ + ani_class arrayCls = nullptr; + ani_status status = ANI_OK; + + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return nullptr; + } + + status = env->FindClass(CLASSNAME_ARRAY, &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "FindClass failed status: %{public}d", status); + return nullptr; + } + + ani_method arrayCtor; + status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "find ctor failed status: %{public}d", status); + return nullptr; + } + + ani_object arrayObj; + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, infos.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "Object_New array status: %{public}d", status); + return arrayObj; + } + ani_size index = 0; + for (auto &processInfo : infos) { + ani_object aniInfo = WrapProcessInformation(env, processInfo); + if (aniInfo == nullptr) { + TAG_LOGW(AAFwkTag::ANI, "null aniInfo"); + break; + } + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, aniInfo); + if (status != ANI_OK) { + TAG_LOGW(AAFwkTag::ANI, "Object_CallMethodByName_Void failed status: %{public}d", status); + break; + } + index++; + } + return arrayObj; +} + +ani_object CreateEmptyArray(ani_env *env) +{ + ani_status status = ANI_OK; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return nullptr; + } + ani_class arrayCls = nullptr; + status = env->FindClass(CLASSNAME_ARRAY, &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "FindClass failed status: %{public}d", status); + return nullptr; + } + ani_method arrayCtor; + status = env->Class_FindMethod(arrayCls, "", ":V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "find ctor failed status: %{public}d", status); + return nullptr; + } + ani_object arrayObj; + status = env->Object_New(arrayCls, arrayCtor, &arrayObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "Object_New array failed status: %{public}d", status); + return nullptr; + } + return arrayObj; +} + +bool IsExistsProperty(ani_env *env, ani_object param, const char *name) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + + ani_ref resRef = nullptr; + ani_status status = ANI_ERROR; + ani_boolean isUndefined = true; + + if ((status = env->Object_GetPropertyByName_Ref(param, name, &resRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(resRef, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + return !isUndefined; +} + +bool GetStringProperty(ani_env *env, ani_object param, const char *name, std::string &value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + + ani_ref obj = nullptr; + ani_boolean isUndefined = true; + ani_status status = ANI_ERROR; + + if ((status = env->Object_GetPropertyByName_Ref(param, name, &obj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(obj, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + if (isUndefined) { + TAG_LOGE(AAFwkTag::ANI, "%{public}s : undefined", name); + return false; + } + if (!GetStdString(env, reinterpret_cast(obj), value)) { + TAG_LOGE(AAFwkTag::ANI, "GetStdString failed"); + return false; + } + return true; +} + +bool GetStringArrayProperty(ani_env *env, ani_object param, const char *name, std::vector &value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + + ani_ref arrayObj = nullptr; + ani_boolean isUndefined = true; + ani_status status = ANI_ERROR; + ani_double length = 0.0; + std::string str; + + if ((status = env->Object_GetPropertyByName_Ref(param, name, &arrayObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(arrayObj, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + if (isUndefined) { + TAG_LOGE(AAFwkTag::ANI, "%{public}s : undefined", name); + return false; + } + + status = env->Object_GetPropertyByName_Double(reinterpret_cast(arrayObj), "length", &length); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + + for (int i = 0; i < static_cast(length); i++) { + ani_ref stringEntryRef; + status = env->Object_CallMethodByName_Ref(reinterpret_cast(arrayObj), + "$_get", "I:Lstd/core/Object;", &stringEntryRef, (ani_int)i); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d, index: %{public}d", status, i); + return false; + } + + str = ""; + if (!GetStdString(env, reinterpret_cast(stringEntryRef), str)) { + TAG_LOGE(AAFwkTag::ANI, "GetStdString failed, index: %{public}d", i); + return false; + } + + value.push_back(str); + TAG_LOGI(AAFwkTag::ANI, "GetStdString index: %{public}d %{public}s", i, str.c_str()); + } + + return true; +} + +bool GetDoublePropertyObject(ani_env *env, ani_object param, const char *name, double &value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + + ani_ref obj = nullptr; + ani_status status = ANI_ERROR; + if (!GetRefProperty(env, param, name, obj)) { + TAG_LOGW(AAFwkTag::ANI, "%{public}s : undefined", name); + return false; + } + if ((status = env->Object_CallMethodByName_Double( + reinterpret_cast(obj), "doubleValue", nullptr, &value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + return true; +} +bool GetDoublePropertyValue(ani_env *env, ani_object param, const char *name, double &value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + + ani_status status = ANI_ERROR; + ani_double res = 0.0; + if ((status = env->Object_GetPropertyByName_Double(param, name, &res)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + value = static_cast(res); + return true; +} + +bool GetRefProperty(ani_env *env, ani_object param, const char *name, ani_ref &value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + + ani_status status = ANI_ERROR; + ani_boolean isUndefined = true; + + if ((status = env->Object_GetPropertyByName_Ref(param, name, &value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(value, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + return !isUndefined; +} + +bool SetDoublePropertyObject(ani_env *env, ani_object param, const char *name, double value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + + ani_object obj = CreateDouble(env, static_cast(value)); + if (obj == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null obj"); + return false; + } + + ani_status status = ANI_ERROR; + if ((status = env->Object_SetPropertyByName_Ref(param, name, obj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + return true; +} + +bool SetDoublePropertyValue(ani_env *env, ani_object param, const char *name, double value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + + ani_status status = ANI_ERROR; + if ((status = env->Object_SetPropertyByName_Double(param, name, value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + return true; +} + +bool SetStringArrayProperty(ani_env *env, ani_object param, const char *name, const std::vector &values) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + + ani_class arrayCls = nullptr; + ani_method arrayCtor = nullptr; + ani_object arrayObj = nullptr; + ani_string string = nullptr; + + ani_status status = env->FindClass(CLASSNAME_ARRAY, &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + + status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, values.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + + for (size_t i = 0; i < values.size(); i++) { + string = nullptr; + status = env->String_NewUTF8(values[i].c_str(), values[i].size(), &string); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", i, string); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + } + status = env->Object_SetPropertyByName_Ref(param, name, arrayObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + + return true; +} + +bool SetRefProperty(ani_env *env, ani_object param, const char *name, ani_ref value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + + ani_status status = ANI_ERROR; + if ((status = env->Object_SetPropertyByName_Ref(param, name, value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + return true; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/frameworks/ets/ani/ani_common/src/ani_common_want.cpp b/frameworks/ets/ani/ani_common/src/ani_common_want.cpp index 3b29cf68608..0bd6ec9160f 100644 --- a/frameworks/ets/ani/ani_common/src/ani_common_want.cpp +++ b/frameworks/ets/ani/ani_common/src/ani_common_want.cpp @@ -37,6 +37,11 @@ namespace OHOS { namespace AppExecFwk { using namespace OHOS::AbilityRuntime; namespace { +constexpr const char* ABILITY_WANT_CLASS_NAME = "L@ohos/app/ability/Want/Want;"; +constexpr const char* TOOL_CLASS_NAME = "L@ohos/app/ability/Want/RecordSerializeTool;"; +constexpr const char* INNER_CLASS_NAME = "Lability/abilityResult/AbilityResultInner;"; +constexpr const char* ELEMENTNAME_CLASS_NAME = "LbundleManager/ElementName/ElementName;"; + bool InnerWrapWantParams(ani_env* env, ani_class wantCls, ani_object wantObject, const AAFwk::WantParams& wantParams) { ani_ref wantParamRef = WrapWantParams(env, wantParams); @@ -69,8 +74,8 @@ ani_object WrapWant(ani_env *env, const AAFwk::Want &want) ani_status status = ANI_ERROR; ani_method method = nullptr; ani_object object = nullptr; - if ((status = env->FindClass("L@ohos/app/ability/Want/Want;", &cls)) != ANI_OK) { - TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + if ((status = env->FindClass(ABILITY_WANT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); return nullptr; } if (cls == nullptr) { @@ -78,11 +83,11 @@ ani_object WrapWant(ani_env *env, const AAFwk::Want &want) return nullptr; } if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { - TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); return nullptr; } if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { - TAG_LOGE(AAFwkTag::ANI, "status : %{public}d", status); + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); return nullptr; } if (object == nullptr) { @@ -113,8 +118,8 @@ ani_ref WrapWantParams(ani_env *env, const AAFwk::WantParams &wantParams) } ani_status status = ANI_ERROR; ani_class cls = nullptr; - if ((status = env->FindClass("L@ohos/app/ability/Want/RecordSerializeTool;", &cls)) != ANI_OK) { - TAG_LOGE(AAFwkTag::ANI, "FindClass RecordSerializeTool failed, status : %{public}d", status); + if ((status = env->FindClass(TOOL_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "FindClass RecordSerializeTool failed, status: %{public}d", status); return nullptr; } if (cls == nullptr) { @@ -124,7 +129,7 @@ ani_ref WrapWantParams(ani_env *env, const AAFwk::WantParams &wantParams) ani_static_method parseNoThrowMethod = nullptr; status = env->Class_FindStaticMethod(cls, "parseNoThrow", nullptr, &parseNoThrowMethod); if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::ANI, "failed to get parseNoThrow method, status : %{public}d", status); + TAG_LOGE(AAFwkTag::ANI, "failed to get parseNoThrow method, status: %{public}d", status); return nullptr; } @@ -133,14 +138,14 @@ ani_ref WrapWantParams(ani_env *env, const AAFwk::WantParams &wantParams) ani_string wantParamsAniString; status = env->String_NewUTF8(wantParamsString.c_str(), wantParamsString.length(), &wantParamsAniString); if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::ANI, "String_NewUTF8 wantParamsString failed, status : %{public}d", status); + TAG_LOGE(AAFwkTag::ANI, "String_NewUTF8 wantParamsString failed, status: %{public}d", status); return nullptr; } ani_ref wantParamsRef = nullptr; status = env->Class_CallStaticMethod_Ref(cls, parseNoThrowMethod, &wantParamsRef, wantParamsAniString); if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::ANI, "failed to call parseNoThrow method, status : %{public}d", status); + TAG_LOGE(AAFwkTag::ANI, "failed to call parseNoThrow method, status: %{public}d", status); return nullptr; } return wantParamsRef; @@ -248,8 +253,8 @@ bool UnwrapWantParams(ani_env *env, ani_ref param, AAFwk::WantParams &wantParams } ani_status status = ANI_ERROR; ani_class cls = nullptr; - if ((status = env->FindClass("L@ohos/app/ability/Want/RecordSerializeTool;", &cls)) != ANI_OK) { - TAG_LOGE(AAFwkTag::ANI, "FindClass RecordSerializeTool failed, status : %{public}d", status); + if ((status = env->FindClass(TOOL_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "FindClass RecordSerializeTool failed, status: %{public}d", status); return false; } if (cls == nullptr) { @@ -259,13 +264,13 @@ bool UnwrapWantParams(ani_env *env, ani_ref param, AAFwk::WantParams &wantParams ani_static_method stringifyMethod = nullptr; status = env->Class_FindStaticMethod(cls, "stringifyNoThrow", nullptr, &stringifyMethod); if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::ANI, "failed to get stringifyNoThrow method, status : %{public}d", status); + TAG_LOGE(AAFwkTag::ANI, "failed to get stringifyNoThrow method, status: %{public}d", status); return false; } ani_ref wantParamsAniString; status = env->Class_CallStaticMethod_Ref(cls, stringifyMethod, &wantParamsAniString, param); if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::ANI, "failed to call stringifyNoThrow method, status : %{public}d", status); + TAG_LOGE(AAFwkTag::ANI, "failed to call stringifyNoThrow method, status: %{public}d", status); return false; } std::string wantParamsString; @@ -288,7 +293,7 @@ bool UnwrapWantParams(ani_env *env, ani_ref param, AAFwk::WantParams &wantParams bool GetAbilityResultClass(ani_env *env, ani_class &cls) { - ani_status status = env->FindClass("Lability/abilityResult/AbilityResultInner;", &cls); + ani_status status = env->FindClass(INNER_CLASS_NAME, &cls); if (status != ANI_OK || cls == nullptr) { TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); return false; @@ -356,5 +361,63 @@ bool UnWrapAbilityResult(ani_env *env, ani_object param, int &resultCode, AAFwk: } return UnwrapWant(env, reinterpret_cast(wantRef), want); } + +ani_object WrapElementName(ani_env *env, const AppExecFwk::ElementName &elementNameParam) +{ + TAG_LOGD(AAFwkTag::ANI, "WrapElementName"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return nullptr; + } + ani_class elementNameObj = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object object = nullptr; + if ((status = env->FindClass(ELEMENTNAME_CLASS_NAME, &elementNameObj)) != ANI_OK || elementNameObj == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "FindClass status: %{public}d or null elementNameObj", status); + return nullptr; + } + if ((status = env->Class_FindMethod(elementNameObj, "", ":V", &method)) != ANI_OK || method == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "Class_FindMethod status: %{public}d or null method", status); + return nullptr; + } + if ((status = env->Object_New(elementNameObj, method, &object)) != ANI_OK || object == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "Object_New status: %{public}d or null object", status); + return nullptr; + } + return WrapElementNameInner(env, elementNameObj, object, elementNameParam); +} + +ani_object WrapElementNameInner(ani_env *env, ani_class elementNameObj, ani_object object, + const AppExecFwk::ElementName &elementNameParam) +{ + TAG_LOGD(AAFwkTag::ANI, "WrapElementNameInner"); + if (env == nullptr || elementNameObj == nullptr || object == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "invalid args"); + return nullptr; + } + if (!SetFieldStringByName(env, elementNameObj, object, "bundleName", elementNameParam.GetBundleName())) { + TAG_LOGE(AAFwkTag::ANI, "set bundleName failed"); + return nullptr; + } + if (!SetFieldStringByName(env, elementNameObj, object, "abilityName", elementNameParam.GetAbilityName())) { + TAG_LOGE(AAFwkTag::ANI, "set abilityName failed"); + return nullptr; + } + if (!SetFieldStringByName(env, elementNameObj, object, "deviceId", elementNameParam.GetDeviceID())) { + TAG_LOGE(AAFwkTag::ANI, "set deviceId failed"); + } + if (!SetFieldStringByName(env, elementNameObj, object, "moduleName", elementNameParam.GetModuleName())) { + TAG_LOGE(AAFwkTag::ANI, "set moduleName failed"); + } + if (!SetFieldStringByName(env, elementNameObj, object, "uri", elementNameParam.GetURI())) { + TAG_LOGE(AAFwkTag::ANI, "set uri failed"); + } + if (!SetFieldStringByName(env, elementNameObj, object, "shortName", elementNameParam.GetURI())) { + TAG_LOGE(AAFwkTag::ANI, "set shortName failed"); + } + return object; +} + } // namespace AppExecFwk } // namespace OHOS diff --git a/frameworks/ets/ani/ani_common/src/ets_application_context_utils.cpp b/frameworks/ets/ani/ani_common/src/ets_application_context_utils.cpp index edeef8a43c9..e158c752f5c 100644 --- a/frameworks/ets/ani/ani_common/src/ets_application_context_utils.cpp +++ b/frameworks/ets/ani/ani_common/src/ets_application_context_utils.cpp @@ -12,67 +12,416 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "ets_application_context_utils.h" #include "ani_enum_convert.h" #include "application_context_manager.h" -#include "ets_application_context_utils.h" #include "ets_context_utils.h" +#include "ets_error_utils.h" #include "ets_native_reference.h" #include "hilog_tag_wrapper.h" namespace OHOS { namespace AbilityRuntime { namespace { +static std::once_flag g_bindNativeMethodsFlag; constexpr const char* ETS_APPLICATION_CONTEXT_CLASS_NAME = "Lapplication/ApplicationContext/ApplicationContext;"; +constexpr const char* CLEANER_CLASS = "Lapplication/ApplicationContext/Cleaner;"; +constexpr double FOUNT_SIZE = 0.0; +} +void EtsApplicationContextUtils::Clean(ani_env *env, ani_object object) +{ + TAG_LOGD(AAFwkTag::APPKIT, "Clean Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + ani_long ptr = 0; + ani_status status = env->Object_GetFieldByName_Long(object, "ptr", &ptr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "ptr GetField status: %{public}d", status); + return; + } + if (ptr != 0) { + delete reinterpret_cast(ptr); + } } -void EtsApplicationContextUtils::SetSupportedProcessCacheSync([[maybe_unused]]ani_env *env, - [[maybe_unused]]ani_object aniObj, ani_boolean value) +void EtsApplicationContextUtils::OnRestartApp(ani_env *env, ani_object aniObj, ani_object wantObj) { - TAG_LOGD(AAFwkTag::APPKIT, "SetSupportedProcessCacheSync Call"); if (env == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null env"); return; } - auto applicationContext = GeApplicationContext(env, aniObj); + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext"); + return; + } + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::APPKIT, "Parse want failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param want failed, want must be Want."); + return; + } + auto errCode = applicationContext->RestartApp(want); + switch (errCode) { + case ERR_INVALID_VALUE: + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + break; + case AAFwk::ERR_RESTART_APP_INCORRECT_ABILITY: + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_RESTART_APP_INCORRECT_ABILITY); + break; + case AAFwk::ERR_RESTART_APP_FREQUENT: + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_RESTART_APP_FREQUENT); + break; + case AAFwk::NOT_TOP_ABILITY: + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_NOT_TOP_ABILITY); + break; + default: + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + } + TAG_LOGD(AAFwkTag::APPKIT, "RestartApp errCode is %{public}d", errCode); +} + +void EtsApplicationContextUtils::OnSetFont(ani_env *env, ani_object aniObj, ani_string font) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext"); + return; + } + std::string stdFont = ""; + if (!AppExecFwk::GetStdString(env, font, stdFont)) { + TAG_LOGE(AAFwkTag::APPKIT, "Parse font failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param font failed, font must be string."); + return; + } + TAG_LOGD(AAFwkTag::APPKIT, "SetFont font %{public}s", stdFont.c_str()); + applicationContext->SetFont(stdFont); +} + +void EtsApplicationContextUtils::OnSetColorMode(ani_env *env, ani_object aniObj, ani_enum_item colorMode) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext"); + return; + } + ani_int mode = 0; + if (!AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative(env, colorMode, mode)) { + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param colorMode failed, colorMode must be number."); + TAG_LOGE(AAFwkTag::APPKIT, "Parse colorMode failed"); + return; + } + TAG_LOGD(AAFwkTag::APPKIT, "colorMode is %{public}d", mode); + applicationContext->SetColorMode(static_cast(mode)); +} + +void EtsApplicationContextUtils::OnSetLanguage(ani_env *env, ani_object aniObj, ani_string language) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext"); + return; + } + std::string stdLanguage = ""; + if (!AppExecFwk::GetStdString(env, language, stdLanguage)) { + TAG_LOGE(AAFwkTag::APPKIT, "Parse language failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param language failed, language must be string."); + return; + } + applicationContext->SetLanguage(stdLanguage); + TAG_LOGD(AAFwkTag::APPKIT, "stdLanguage language %{public}s", stdLanguage.c_str()); +} + +void EtsApplicationContextUtils::OnSetFontSizeScale(ani_env *env, ani_object aniObj, ani_double fontSizeScale) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext"); + return; + } + + double stdFontSizeScale = static_cast(fontSizeScale); + TAG_LOGD(AAFwkTag::APPKIT, "fontSizeScale: %{public}f", stdFontSizeScale); + if (fontSizeScale < FOUNT_SIZE) { + TAG_LOGE(AAFwkTag::APPKIT, "invalid size"); + EtsErrorUtil::ThrowInvalidParamError(env, "Invalid font size."); + return; + } + applicationContext->SetFontSizeScale(stdFontSizeScale); +} + +void EtsApplicationContextUtils::OnClearUpApplicationData(ani_env *env, ani_object aniObj, ani_object callback) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "nativeContext is null"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, + (ani_int)AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT, + "applicationContext if already released."), nullptr); + return; + } + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK), nullptr); + applicationContext->ClearUpApplicationData(); +} + +void EtsApplicationContextUtils::OnGetRunningProcessInformation(ani_env *env, ani_object aniObj, ani_object callback) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + ani_object emptyArray = AppExecFwk::CreateEmptyArray(env); + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "nativeContext is null"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, + (ani_int)AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT, + "applicationContext if already released."), emptyArray); + return; + } + std::vector infos; + AppExecFwk::RunningProcessInfo processInfo; + ErrCode innerErrCode = applicationContext->GetProcessRunningInformation(processInfo); + if (innerErrCode == ERR_OK) { + infos.emplace_back(processInfo); + ani_object aniInfosRef = AppExecFwk::CreateRunningProcessInfoArray(env, infos); + if (aniInfosRef == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null array"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, + (ani_int)AbilityErrorCode::ERROR_CODE_INNER, "Initiate array failed."), emptyArray); + } else { + AppExecFwk::AsyncCallback(env, callback, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK), aniInfosRef); + } + } else { + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, + (ani_int)AbilityErrorCode::ERROR_CODE_INNER, "Get process infos failed."), emptyArray); + } +} + +void EtsApplicationContextUtils::OnkillAllProcesses(ani_env *env, ani_object aniObj, + ani_boolean clearPageStack, ani_object callback) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "env is nullptr"); + return; + } + ani_object aniObject = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK); + auto context = applicationContext_.lock(); + if (!context) { + TAG_LOGE(AAFwkTag::APPKIT, "nativeContextLong is nullptr"); + aniObject = EtsErrorUtil::CreateError(env, (ani_int)AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT, + "applicationContext is already released."); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); + return; + } + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); + context->KillProcessBySelf(clearPageStack); +} + +void EtsApplicationContextUtils::OnPreloadUIExtensionAbility(ani_env *env, + ani_object aniObj, ani_object wantObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "PreloadUIExtensionAbility Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + AAFwk::Want want; + if (!OHOS::AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::APPKIT, "Parse want failed"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env, + "Parse param want failed, want must be Want."), nullptr); + return; + } + auto context = applicationContext_.lock(); + if (!context) { + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateErrorByNativeErr(env, + (int32_t)AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT), nullptr); + return; + } + auto hostBundleName = context->GetBundleName(); + TAG_LOGD(AAFwkTag::APPKIT, "HostBundleName is %{public}s", hostBundleName.c_str()); + auto innerErrCode = AAFwk::AbilityManagerClient::GetInstance()->PreloadUIExtensionAbility(want, hostBundleName); + if (innerErrCode == ERR_OK) { + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, + AbilityErrorCode::ERROR_OK), nullptr); + } else { + TAG_LOGE(AAFwkTag::APPKIT, "OnPreloadUIExtensionAbility failed %{public}d", innerErrCode); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateErrorByNativeErr(env, innerErrCode), nullptr); + } +} + +void EtsApplicationContextUtils::OnSetSupportedProcessCacheSync(ani_env *env, ani_object aniObj, ani_boolean value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + auto applicationContext = applicationContext_.lock(); if (applicationContext == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext"); - AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); return; } int32_t errCode = applicationContext->SetSupportedProcessCacheSelf(value); if (errCode == AAFwk::ERR_CAPABILITY_NOT_SUPPORT) { - AbilityRuntime::EtsErrorUtil::ThrowError(env, - AbilityRuntime::AbilityErrorCode::ERROR_CODE_CAPABILITY_NOT_SUPPORT); + EtsErrorUtil::ThrowError(env, + AbilityErrorCode::ERROR_CODE_CAPABILITY_NOT_SUPPORT); } else if (errCode != ERR_OK) { - AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); } } -std::shared_ptr EtsApplicationContextUtils::GeApplicationContext(ani_env *env, ani_object aniObj) +void EtsApplicationContextUtils::RestartApp(ani_env *env, ani_object aniObj, ani_object wantObj) { - if (env == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null env"); - return nullptr; + TAG_LOGD(AAFwkTag::APPKIT, "RestartApp Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return; } - ani_status status = ANI_ERROR; - ani_class cls {}; - if ((status = env->FindClass(ETS_APPLICATION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { - TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); - return nullptr; + etsContext->OnRestartApp(env, aniObj, wantObj); +} + +void EtsApplicationContextUtils::SetFont(ani_env *env, ani_object aniObj, ani_string font) +{ + TAG_LOGD(AAFwkTag::APPKIT, "SetFont Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return; } - ani_field contextField = nullptr; - if ((status = env->Class_FindField(cls, "nativeContext", &contextField)) != ANI_OK) { - TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + etsContext->OnSetFont(env, aniObj, font); +} + +void EtsApplicationContextUtils::SetColorMode(ani_env *env, ani_object aniObj, ani_enum_item colorMode) +{ + TAG_LOGD(AAFwkTag::APPKIT, "SetColorMode Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return; + } + etsContext->OnSetColorMode(env, aniObj, colorMode); +} + +void EtsApplicationContextUtils::SetLanguage(ani_env *env, ani_object aniObj, ani_string language) +{ + TAG_LOGD(AAFwkTag::APPKIT, "SetLanguage Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return; + } + etsContext->OnSetLanguage(env, aniObj, language); +} + +void EtsApplicationContextUtils::SetFontSizeScale(ani_env *env, ani_object aniObj, ani_double fontSizeScale) +{ + TAG_LOGD(AAFwkTag::APPKIT, "SetFontSizeScale Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return; + } + etsContext->OnSetFontSizeScale(env, aniObj, fontSizeScale); +} + +void EtsApplicationContextUtils::ClearUpApplicationData(ani_env *env, ani_object aniObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "ClearUpApplicationData Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return; + } + etsContext->OnClearUpApplicationData(env, aniObj, callback); +} + +void EtsApplicationContextUtils::GetRunningProcessInformation(ani_env *env, ani_object aniObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "GetRunningProcessInformation Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return; + } + etsContext->OnGetRunningProcessInformation(env, aniObj, callback); +} + +void EtsApplicationContextUtils::killAllProcesses(ani_env *env, ani_object aniObj, + ani_boolean clearPageStack, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "killAllProcesses Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return; + } + etsContext->OnkillAllProcesses(env, aniObj, clearPageStack, callback); +} + +void EtsApplicationContextUtils::PreloadUIExtensionAbility(ani_env *env, + ani_object aniObj, ani_object wantObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "PreloadUIExtensionAbility Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return; + } + etsContext->OnPreloadUIExtensionAbility(env, aniObj, wantObj, callback); +} + +void EtsApplicationContextUtils::SetSupportedProcessCacheSync(ani_env *env, ani_object aniObj, ani_boolean value) +{ + TAG_LOGD(AAFwkTag::APPKIT, "SetSupportedProcessCacheSync Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return; + } + etsContext->OnSetSupportedProcessCacheSync(env, aniObj, value); +} + +EtsApplicationContextUtils* EtsApplicationContextUtils::GeApplicationContext(ani_env *env, ani_object aniObj) +{ + if (env == nullptr || aniObj == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env or aniObj"); return nullptr; } - ani_long nativeContextLong; - if ((status = env->Object_GetField_Long(aniObj, contextField, &nativeContextLong)) != ANI_OK) { - TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + ani_long etsApplicationContextPtr = 0; + ani_status status = env->Object_GetFieldByName_Long(aniObj, "etsApplicationContextPtr", &etsApplicationContextPtr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "etsApplicationContextPtr GetField status: %{public}d", status); return nullptr; } - auto weakContext = reinterpret_cast*>(nativeContextLong); - return weakContext != nullptr ? weakContext->lock() : nullptr; + auto etsContext = reinterpret_cast(etsApplicationContextPtr); + return etsContext; } ani_object EtsApplicationContextUtils::SetApplicationContext(ani_env* aniEnv, @@ -94,28 +443,30 @@ ani_object EtsApplicationContextUtils::SetApplicationContext(ani_env* aniEnv, return nullptr; } ani_method method {}; - if ((status = aniEnv->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + if ((status = aniEnv->Class_FindMethod(cls, "", "J:V", &method)) != ANI_OK) { TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); return nullptr; } - ani_object contextObj = nullptr; - if ((status = aniEnv->Object_New(cls, method, &contextObj)) != ANI_OK) { - TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + auto etsContext = new (std::nothrow) EtsApplicationContextUtils(applicationContext); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "workContext nullptr"); return nullptr; } - ani_field field = nullptr; - if ((status = aniEnv->Class_FindField(cls, "nativeContext", &field)) != ANI_OK) { + ani_object contextObj = nullptr; + if ((status = aniEnv->Object_New(cls, method, &contextObj, reinterpret_cast(etsContext))) != ANI_OK) { TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + delete etsContext; + etsContext = nullptr; return nullptr; } - auto workContext = new (std::nothrow) std::weak_ptr(applicationContext); + auto workContext = new (std::nothrow) std::weak_ptr(etsContext->applicationContext_); if (workContext == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "workContext nullptr"); + TAG_LOGE(AAFwkTag::CONTEXT, "null workContext"); return nullptr; } - ani_long nativeContextLong = (ani_long)workContext; - if ((status = aniEnv->Object_SetField_Long(contextObj, field, nativeContextLong)) != ANI_OK) { - TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + ani_long nativeContextLong = reinterpret_cast(workContext); + if (!ContextUtil::SetNativeContextLong(aniEnv, contextObj, nativeContextLong)) { + TAG_LOGE(AAFwkTag::APPKIT, "SetNativeContextLong failed"); delete workContext; workContext = nullptr; return nullptr; @@ -135,15 +486,52 @@ void EtsApplicationContextUtils::BindApplicationContextFunc(ani_env* aniEnv) TAG_LOGE(AAFwkTag::APPKIT, "FindClass ApplicationContext failed status: %{public}d", status); return; } - std::array applicationContextFunctions = { - ani_native_function {"setSupportedProcessCacheSync", "Z:V", - reinterpret_cast(EtsApplicationContextUtils::SetSupportedProcessCacheSync)}, - }; - status = aniEnv->Class_BindNativeMethods(contextClass, applicationContextFunctions.data(), - applicationContextFunctions.size()); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::APPKIT, "Class_BindNativeMethods failed status: %{public}d", status); - } + std::call_once(g_bindNativeMethodsFlag, [&status, aniEnv, contextClass]() { + std::array applicationContextFunctions = { + ani_native_function {"setSupportedProcessCacheSync", "Z:V", + reinterpret_cast(EtsApplicationContextUtils::SetSupportedProcessCacheSync)}, + ani_native_function {"nativekillAllProcessesSync", "ZLutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplicationContextUtils::killAllProcesses)}, + ani_native_function {"nativepreloadUIExtensionAbilitySync", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplicationContextUtils::PreloadUIExtensionAbility)}, + ani_native_function {"nativegetRunningProcessInformation", + "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplicationContextUtils::GetRunningProcessInformation)}, + ani_native_function {"nativeclearUpApplicationData", + "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplicationContextUtils::ClearUpApplicationData)}, + ani_native_function {"nativesetLanguage", "Lstd/core/String;:V", + reinterpret_cast(EtsApplicationContextUtils::SetLanguage)}, + ani_native_function {"nativesetFontSizeScale", "D:V", + reinterpret_cast(EtsApplicationContextUtils::SetFontSizeScale)}, + ani_native_function {"nativesetColorMode", + "L@ohos/app/ability/ConfigurationConstant/ConfigurationConstant/ColorMode;:V", + reinterpret_cast(EtsApplicationContextUtils::SetColorMode)}, + ani_native_function {"nativesetFont", "Lstd/core/String;:V", + reinterpret_cast(EtsApplicationContextUtils::SetFont)}, + ani_native_function {"nativerestartApp", "L@ohos/app/ability/Want/Want;:V", + reinterpret_cast(EtsApplicationContextUtils::RestartApp)}, + }; + if ((status = aniEnv->Class_BindNativeMethods(contextClass, applicationContextFunctions.data(), + applicationContextFunctions.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_BindNativeMethods failed status: %{public}d", status); + return; + } + ani_class cleanerCls = nullptr; + if ((status = aniEnv->FindClass(CLEANER_CLASS, &cleanerCls)) != ANI_OK || cleanerCls == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "Cleaner FindClass failed status: %{public}d, or null cleanerCls", status); + return; + } + std::array cleanerMethods = { + ani_native_function {"clean", nullptr, reinterpret_cast(EtsApplicationContextUtils::Clean) }, + }; + if ((status = aniEnv->Class_BindNativeMethods(cleanerCls, cleanerMethods.data(), + cleanerMethods.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_BindNativeMethods failed status: %{public}d", status); + return; + } + }); } ani_object EtsApplicationContextUtils::CreateEtsApplicationContext(ani_env* aniEnv, @@ -163,7 +551,7 @@ ani_object EtsApplicationContextUtils::CreateEtsApplicationContext(ani_env* aniE } auto etsReference = std::make_shared(); etsReference->aniObj = applicationContextObject; - AbilityRuntime::ApplicationContextManager::GetApplicationContextManager().SetEtsGlobalObject(etsReference); + ApplicationContextManager::GetApplicationContextManager().SetEtsGlobalObject(etsReference); BindApplicationContextFunc(aniEnv); ani_class applicationContextClass = nullptr; if ((status = aniEnv->FindClass(ETS_APPLICATION_CONTEXT_CLASS_NAME, &applicationContextClass)) != ANI_OK) { diff --git a/frameworks/ets/ani/ani_common/src/ets_context_utils.cpp b/frameworks/ets/ani/ani_common/src/ets_context_utils.cpp index c0a3797ec81..f1c97c5bef4 100644 --- a/frameworks/ets/ani/ani_common/src/ets_context_utils.cpp +++ b/frameworks/ets/ani/ani_common/src/ets_context_utils.cpp @@ -24,14 +24,18 @@ #include "ets_error_utils.h" #include "ets_native_reference.h" #include "hilog_tag_wrapper.h" +#include "ipc_skeleton.h" #include "resourceManager.h" +#include "tokenid_kit.h" namespace OHOS { namespace AbilityRuntime { namespace ContextUtil { namespace { +static std::once_flag g_bindNativeMethodsFlag; constexpr const char* CONTEXT_CLASS_NAME = "Lapplication/Context/Context;"; constexpr const char* AREA_MODE_ENUM_NAME = "L@ohos/app/ability/contextConstant/contextConstant/AreaMode;"; +constexpr const char* CLEANER_CLASS = "Lapplication/Context/Cleaner;"; void BindContextDir(ani_env *aniEnv, ani_object contextObj, std::shared_ptr context) { @@ -82,6 +86,63 @@ void BindContextDir(ani_env *aniEnv, ani_object contextObj, std::shared_ptrObject_GetFieldByName_Long(object, "ptr", &ptr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "ptr GetField status: %{public}d", status); + return; + } + if (ptr != 0) { + delete reinterpret_cast(ptr); + } +} + +bool SetNativeContextLong(ani_env *env, ani_object aniObj, ani_long nativeContextLong) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return false; + } + auto status = env->Object_SetFieldByName_Long(aniObj, "nativeContext", nativeContextLong); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "nativeContextLong SetField status: %{public}d", status); + return false; + } + ani_class contextCls = nullptr; + if (env->FindClass(CONTEXT_CLASS_NAME, &contextCls) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "FindClass Context failed"); + return false; + } + ani_method method = nullptr; + if ((status = env->Class_FindMethod(contextCls, "", ":V", &method)) != ANI_OK || + method == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "ctor FindMethod status: %{public}d, or null method", status); + return false; + } + ani_object contextObj = nullptr; + if ((status = env->Object_New(contextCls, method, &contextObj)) != ANI_OK || contextObj == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_New status: %{public}d, or null contextObj", status); + return false; + } + if ((status = env->Class_FindMethod(contextCls, "setEtsContextPtr", "J:V", &method)) != ANI_OK || + method == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "setEtsContextPtr FindMethod status: %{public}d, or null method", status); + return false; + } + if ((status = env->Object_CallMethod_Void(contextObj, method, nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "call contextObj method failed, status: %{public}d", status); + return false; + } + return true; +} + void BindApplicationInfo(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, std::shared_ptr context) { @@ -131,20 +192,6 @@ void BindParentProperty(ani_env *aniEnv, ani_class contextClass, ani_object cont BindApplicationInfo(aniEnv, contextClass, contextObj, context); BindResourceManager(aniEnv, contextClass, contextObj, context); BindContextDir(aniEnv, contextObj, context); - - ani_field areaField; - if (ANI_OK != aniEnv->Class_FindField(contextClass, "area", &areaField)) { - TAG_LOGE(AAFwkTag::APPKIT, "find area failed"); - return; - } - auto area = context->GetArea(); - ani_enum_item areaModeItem = nullptr; - OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts( - aniEnv, "L@ohos/app/ability/contextConstant/contextConstant/AreaMode;", area, areaModeItem); - if (aniEnv->Object_SetField_Ref(contextObj, areaField, (ani_ref)areaModeItem) != ANI_OK) { - TAG_LOGE(AAFwkTag::APPKIT, "Object_SetField_Int failed"); - return; - } } void BindNativeFunction(ani_env *aniEnv) @@ -158,26 +205,76 @@ void BindNativeFunction(ani_env *aniEnv) TAG_LOGE(AAFwkTag::APPKIT, "FindClass Context failed"); return; } - std::array contextFunctions = { - ani_native_function {"getApplicationContextSync", ":Lapplication/ApplicationContext/ApplicationContext;", - reinterpret_cast(AbilityRuntime::ContextUtil::GetApplicationContextSync)}, - ani_native_function {"switchArea", nullptr, - reinterpret_cast(AbilityRuntime::ContextUtil::SwitchArea)}, - ani_native_function {"getArea", nullptr, - reinterpret_cast(AbilityRuntime::ContextUtil::GetArea)} - }; - ani_status status = aniEnv->Class_BindNativeMethods(contextCls, contextFunctions.data(), - contextFunctions.size()); + ani_status status = ANI_ERROR; + std::call_once(g_bindNativeMethodsFlag, [&status, aniEnv, contextCls]() { + std::array contextFunctions = { + ani_native_function {"getApplicationContextSync", ":Lapplication/ApplicationContext/ApplicationContext;", + reinterpret_cast(AbilityRuntime::ContextUtil::GetApplicationContextSync)}, + ani_native_function {"switchArea", nullptr, + reinterpret_cast(AbilityRuntime::ContextUtil::SwitchArea)}, + ani_native_function {"getArea", nullptr, + reinterpret_cast(AbilityRuntime::ContextUtil::GetArea)}, + ani_native_function {"createModuleResourceManagerSync", "Lstd/core/String;Lstd/core/String;" + ":L@ohos/resourceManager/resourceManager/ResourceManager;", + reinterpret_cast(AbilityRuntime::ContextUtil::CreateModuleResourceManagerSync)}, + }; + status = aniEnv->Class_BindNativeMethods(contextCls, contextFunctions.data(), + contextFunctions.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_BindNativeMethods failed status: %{public}d", status); + return; + } + ani_class cleanerCls = nullptr; + if ((status = aniEnv->FindClass(CLEANER_CLASS, &cleanerCls)) != ANI_OK || cleanerCls == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "Cleaner FindClass failed status: %{public}d, or null cleanerCls", status); + return; + } + std::array cleanerMethods = { + ani_native_function {"clean", nullptr, reinterpret_cast(Clean) }, + }; + if ((status = aniEnv->Class_BindNativeMethods(cleanerCls, + cleanerMethods.data(), cleanerMethods.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_BindNativeMethods failed status: %{public}d", status); + return; + } + }); +} + +bool SetHapModuleInfo( + ani_env *env, ani_class cls, ani_object contextObj, const std::shared_ptr &context) +{ + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env or context"); + return false; + } + auto hapModuleInfo = context->GetHapModuleInfo(); + if (hapModuleInfo == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "hapModuleInfo is nullptr"); + return false; + } + ani_ref hapModuleInfoRef = AppExecFwk::CommonFunAni::ConvertHapModuleInfo(env, *hapModuleInfo); + if (hapModuleInfoRef == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "hapModuleInfoRef is nullptr"); + return false; + } + ani_status status = ANI_OK; + status = env->Object_SetPropertyByName_Ref(contextObj, "currentHapModuleInfo", hapModuleInfoRef); if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::APPKIT, "Class_BindNativeMethods failed status: %{public}d", status); + TAG_LOGE(AAFwkTag::APPKIT, "Object_SetPropertyByName_Ref failed, status: %{public}d", status); + return false; } + return true; } void CreateEtsBaseContext(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, std::shared_ptr context) { - if (aniEnv == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null aniEnv"); + if (aniEnv == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null aniEnv or null context"); + return; + } + if (!SetHapModuleInfo(aniEnv, contextClass, contextObj, context)) { + TAG_LOGE(AAFwkTag::APPKIT, "SetHapModuleInfo fail"); } BindParentProperty(aniEnv, contextClass, contextObj, context); BindNativeFunction(aniEnv); @@ -209,6 +306,43 @@ std::shared_ptr GetBaseContext(ani_env *env, ani_object aniObj) return weakContext != nullptr ? weakContext->lock() : nullptr; } +bool CheckCallerIsSystemApp() +{ + auto selfToken = IPCSkeleton::GetSelfTokenID(); + return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken); +} + +ani_object CreateModuleResourceManagerSync(ani_env *env, ani_object aniObj, + ani_string bundleName, ani_string moduleName) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return nullptr; + } + std::string stdBundleName = ""; + AppExecFwk::GetStdString(env, bundleName, stdBundleName); + std::string stdModuleName = ""; + AppExecFwk::GetStdString(env, moduleName, stdModuleName); + auto context = GetBaseContext(env, aniObj); + if (!context) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return nullptr; + } + if (!CheckCallerIsSystemApp()) { + TAG_LOGE(AAFwkTag::APPKIT, "not system-app"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); + return nullptr; + } + auto resourceManager = context->CreateModuleResourceManager(stdBundleName, stdModuleName); + if (resourceManager == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null resourceManager"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return nullptr; + } + return Global::Resource::ResMgrAddon::CreateResMgr(env, "", resourceManager, context); +} + ani_object GetApplicationContext(ani_env *env, const std::shared_ptr applicationContext) { if (env == nullptr) { @@ -285,4 +419,4 @@ ani_enum_item GetArea(ani_env *env, ani_object obj) } } } // namespace AbilityRuntime -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/src/ets_data_struct_converter.cpp b/frameworks/ets/ani/ani_common/src/ets_data_struct_converter.cpp index cbc75e33cba..2cb892fa9ac 100644 --- a/frameworks/ets/ani/ani_common/src/ets_data_struct_converter.cpp +++ b/frameworks/ets/ani/ani_common/src/ets_data_struct_converter.cpp @@ -24,7 +24,8 @@ namespace { constexpr const char *CLASSNAME_LAUNCHPARAM = "L@ohos/app/ability/AbilityConstant/LaunchParamImpl;"; constexpr const char *CLASSNAME_LAUNCHREASON = "L@ohos/app/ability/AbilityConstant/AbilityConstant/LaunchReason;"; constexpr const char *CLASSNAME_LAST_EXITREASION = "L@ohos/app/ability/AbilityConstant/AbilityConstant/LastExitReason;"; - +constexpr const char* LAST_EXIT_DETAIL_INFO_IMPL_CLASS_NAME = + "L@ohos/app/ability/AbilityConstant/LastExitDetailInfoImpl;"; ani_string GetAniString(ani_env *env, const std::string &str) { if (env == nullptr) { @@ -34,16 +35,58 @@ ani_string GetAniString(ani_env *env, const std::string &str) ani_string aniStr = nullptr; ani_status status = env->String_NewUTF8(str.c_str(), str.size(), &aniStr); if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to getAniString, status : %{public}d", status); + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to getAniString, status: %{public}d", status); return nullptr; } return aniStr; } +ani_object CreateEtsLastExitDetailInfo(ani_env* env, const AAFwk::LastExitDetailInfo& lastExitDetailInfo) +{ + ani_status status = ANI_ERROR; + ani_class cls = nullptr; + if ((status = env->FindClass(LAST_EXIT_DETAIL_INFO_IMPL_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "status: %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null cls"); + return nullptr; + } + ani_method method = nullptr; + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "status: %{public}d", status); + return nullptr; + } + if (method == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null method"); + return nullptr; + } + ani_object object = nullptr; + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "status: %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null object"); + return nullptr; + } + env->Object_SetPropertyByName_Double(object, "pid", lastExitDetailInfo.pid); + env->Object_SetPropertyByName_Ref(object, "processName", GetAniString(env, lastExitDetailInfo.processName)); + env->Object_SetPropertyByName_Double(object, "uid", lastExitDetailInfo.uid); + env->Object_SetPropertyByName_Double(object, "exitSubReason", lastExitDetailInfo.exitSubReason); + env->Object_SetPropertyByName_Ref(object, "exitMsg", GetAniString(env, lastExitDetailInfo.exitMsg)); + env->Object_SetPropertyByName_Double(object, "rss", lastExitDetailInfo.rss); + env->Object_SetPropertyByName_Double(object, "pss", lastExitDetailInfo.pss); + env->Object_SetPropertyByName_Double(object, "timestamp", lastExitDetailInfo.timestamp); + + return object; +} + bool WrapLaunchParamInner(ani_env *env, const AAFwk::LaunchParam &launchParam, ani_object &object) { ani_status status = ANI_ERROR; - ani_enum_item launchReasonItem {}; + ani_enum_item launchReasonItem = nullptr; OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts( env, CLASSNAME_LAUNCHREASON, launchParam.launchReason, launchReasonItem); if ((status = env->Object_SetPropertyByName_Ref(object, "launchReason", launchReasonItem)) != ANI_OK) { @@ -51,13 +94,18 @@ bool WrapLaunchParamInner(ani_env *env, const AAFwk::LaunchParam &launchParam, a return false; } - ani_enum_item lastExitReasonItem {}; + ani_enum_item lastExitReasonItem = nullptr; OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts( env, CLASSNAME_LAST_EXITREASION, launchParam.lastExitReason, lastExitReasonItem); if ((status = env->Object_SetPropertyByName_Ref(object, "lastExitReason", lastExitReasonItem)) != ANI_OK) { TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to set lastExitReason"); return false; } + if ((status = env->Object_SetPropertyByName_Ref(object, "lastExitDetailInfo", + CreateEtsLastExitDetailInfo(env, launchParam.lastExitDetailInfo))) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to set lastExitDetailInfo"); + return false; + } return true; } } // namespace @@ -72,7 +120,7 @@ bool WrapLaunchParam(ani_env *env, const AAFwk::LaunchParam &launchParam, ani_ob return false; } if ((status = env->FindClass(CLASSNAME_LAUNCHPARAM, &cls)) != ANI_OK) { - TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to find lanchParam Class, status : %{public}d", status); + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to find lanchParam Class, status: %{public}d", status); return false; } if (cls == nullptr) { @@ -80,7 +128,7 @@ bool WrapLaunchParam(ani_env *env, const AAFwk::LaunchParam &launchParam, ani_ob return false; } if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { - TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to find method, status : %{public}d", status); + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to find method, status: %{public}d", status); return false; } if (method == nullptr) { @@ -88,7 +136,7 @@ bool WrapLaunchParam(ani_env *env, const AAFwk::LaunchParam &launchParam, ani_ob return false; } if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { - TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to create object, status : %{public}d", status); + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to create object, status: %{public}d", status); return false; } if (object == nullptr) { diff --git a/frameworks/ets/ani/ani_common/src/ets_error_utils.cpp b/frameworks/ets/ani/ani_common/src/ets_error_utils.cpp index 72cf499ada5..1773b8a2091 100644 --- a/frameworks/ets/ani/ani_common/src/ets_error_utils.cpp +++ b/frameworks/ets/ani/ani_common/src/ets_error_utils.cpp @@ -25,6 +25,7 @@ constexpr const char *ERR_MSG_NOT_MAINTHREAD = "Caller error. Caller from non-ma constexpr const char *ERR_MSG_INVALID_NUM_PARAMS = "Parameter error. The number of parameters is invalid."; constexpr const char *NOT_SYSTEM_APP = "The application is not system-app, can not use system-api."; constexpr const char *BUSINESS_ERROR_CLASS = "L@ohos/base/BusinessError;"; +constexpr const char *ERROR_CLASS_NAME = "Lescompat/Error;"; } // namespace void EtsErrorUtil::ThrowError(ani_env *env, ani_object err) @@ -182,7 +183,7 @@ ani_object EtsErrorUtil::WrapError(ani_env *env, const std::string &msg) return nullptr; } ani_class cls = nullptr; - if ((status = env->FindClass("Lescompat/Error;", &cls)) != ANI_OK) { + if ((status = env->FindClass(ERROR_CLASS_NAME, &cls)) != ANI_OK) { TAG_LOGE(AAFwkTag::ANI, "FindClass failed %{public}d", status); return nullptr; } diff --git a/frameworks/native/ability/ability_runtime/ets_extension_context.cpp b/frameworks/ets/ani/ani_common/src/ets_extension_context.cpp similarity index 74% rename from frameworks/native/ability/ability_runtime/ets_extension_context.cpp rename to frameworks/ets/ani/ani_common/src/ets_extension_context.cpp index 008cfc12993..3cdb9f65397 100644 --- a/frameworks/native/ability/ability_runtime/ets_extension_context.cpp +++ b/frameworks/ets/ani/ani_common/src/ets_extension_context.cpp @@ -15,6 +15,7 @@ #include "ets_extension_context.h" +#include "ani_common_configuration.h" #include "common_fun_ani.h" #include "hilog_tag_wrapper.h" @@ -60,6 +61,32 @@ bool SetExtensionAbilityInfo(ani_env *aniEnv, ani_class contextClass, ani_object return true; } +bool SetConfiguration( + ani_env *env, ani_class cls, ani_object contextObj, const std::shared_ptr &context) +{ + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "aniEnv or context is nullptr"); + return false; + } + + ani_field field = nullptr; + auto configuration = context->GetConfiguration(); + ani_ref configurationRef = OHOS::AppExecFwk::WrapConfiguration(env, *configuration); + + ani_status status = env->Class_FindField(cls, "config", &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return false; + } + + status = env->Object_SetField_Ref(contextObj, field, configurationRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return false; + } + return true; +} + void CreateEtsExtensionContext(ani_env *aniEnv, ani_class contextClass, ani_object &contextObj, std::shared_ptr context, std::shared_ptr abilityInfo) { @@ -73,6 +100,11 @@ void CreateEtsExtensionContext(ani_env *aniEnv, ani_class contextClass, ani_obje TAG_LOGE(AAFwkTag::CONTEXT, "SetExtensionAbilityInfo fail"); return; } + + if (!SetConfiguration(aniEnv, contextClass, contextObj, context)) { + TAG_LOGE(AAFwkTag::CONTEXT, "SetConfiguration fail"); + return; + } } } // namespace AbilityRuntime } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/ability/native/ets_free_install_observer.cpp b/frameworks/ets/ani/ani_common/src/ets_free_install_observer.cpp similarity index 100% rename from frameworks/native/ability/native/ets_free_install_observer.cpp rename to frameworks/ets/ani/ani_common/src/ets_free_install_observer.cpp diff --git a/frameworks/ets/ani/ani_wantagent_common/BUILD.gn b/frameworks/ets/ani/ani_wantagent_common/BUILD.gn new file mode 100644 index 00000000000..a2c56476a19 --- /dev/null +++ b/frameworks/ets/ani/ani_wantagent_common/BUILD.gn @@ -0,0 +1,50 @@ +# 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("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +config("ani_wantagent_common_public_config") { + include_dirs = [ "./" ] +} + +ohos_shared_library("ani_wantagent_common") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + branch_protector_ret = "pac_ret" + + public_configs = [ ":ani_wantagent_common_public_config" ] + + sources = [ "ani_common_want_agent.cpp" ] + + deps = [ + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_innerkits_path}/wantagent:wantagent_innerkits", + ] + + external_deps = [ + "hilog:libhilog", + "runtime_core:ani", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/ani_wantagent_common/ani_common_want_agent.cpp b/frameworks/ets/ani/ani_wantagent_common/ani_common_want_agent.cpp new file mode 100644 index 00000000000..d1dff160f68 --- /dev/null +++ b/frameworks/ets/ani/ani_wantagent_common/ani_common_want_agent.cpp @@ -0,0 +1,102 @@ +/* + * 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 "ani_common_want_agent.h" + +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +namespace { +constexpr const char* WANT_AGENT_CLASS = "L@ohos/app/ability/wantAgent/wantAgent/WantAgentCls;"; + +ani_object CreateWantAgent(ani_env *env, ani_long ptr) +{ + ani_class cls = nullptr; + ani_status status = env->FindClass(WANT_AGENT_CLASS, &cls); + if (status != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "FindClass status: %{public}d, or null cls", status); + return nullptr; + } + ani_method method = nullptr; + if ((status = env->Class_FindMethod(cls, "", "J:V", &method)) != ANI_OK || method == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Class_FindMethod status: %{public}d, or null method", status); + return nullptr; + } + ani_object obj = nullptr; + if ((status = env->Object_New(cls, method, &obj, ptr)) != ANI_OK || obj == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Object_New status: %{public}d, or null obj", status); + return nullptr; + } + return obj; +} +} // namespace + +ani_object WrapWantAgent(ani_env *env, WantAgent *wantAgent) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "WrapWantAgent called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null env"); + return nullptr; + } + if (wantAgent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null wantAgent"); + return nullptr; + } + ani_long pWantAgent = (ani_long)wantAgent; + ani_object wantAgentCls = CreateWantAgent(env, pWantAgent); + if (wantAgentCls == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null wantAgent"); + return nullptr; + } + return wantAgentCls; +} + +void UnwrapWantAgent(ani_env *env, ani_object agent, void** result) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "UnwrapWantAgent called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null env"); + return; + } + if (agent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null agent"); + return; + } + ani_class cls = nullptr; + ani_status status = env->FindClass(WANT_AGENT_CLASS, &cls); + if (status != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "FindClass status: %{public}d, or null cls", status); + return; + } + ani_field wantAgentPtrField = nullptr; + if ((status = env->Class_FindField(cls, "wantAgentPtr", &wantAgentPtrField)) != ANI_OK || + wantAgentPtrField == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Class_FindField status: %{public}d, or null wantAgentPtrField", status); + return; + } + ani_long wantAgentPtr = 0; + if ((status = env->Object_GetField_Long(agent, wantAgentPtrField, &wantAgentPtr)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "wantAgentPtr GetField status: %{public}d", status); + return; + } + if (wantAgentPtr == 0) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null wantAgentPtr"); + return; + } + *result = reinterpret_cast(wantAgentPtr); +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/frameworks/ets/ani/ani_wantagent_common/ani_common_want_agent.h b/frameworks/ets/ani/ani_wantagent_common/ani_common_want_agent.h new file mode 100644 index 00000000000..bca1b7613f1 --- /dev/null +++ b/frameworks/ets/ani/ani_wantagent_common/ani_common_want_agent.h @@ -0,0 +1,29 @@ +/* + * 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_ANI_COMMON_WANT_AGENT_H +#define OHOS_ABILITY_RUNTIME_ANI_COMMON_WANT_AGENT_H + +#include "ani.h" +#include "want_agent.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace OHOS::AbilityRuntime::WantAgent; +ani_object WrapWantAgent(ani_env *env, WantAgent *wantAgent); +void UnwrapWantAgent(ani_env *env, ani_object agent, void** result); +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANI_COMMON_WANT_AGENT_H diff --git a/frameworks/ets/ani/app_manager/BUILD.gn b/frameworks/ets/ani/app_manager/BUILD.gn new file mode 100644 index 00000000000..af3ae03d123 --- /dev/null +++ b/frameworks/ets/ani/app_manager/BUILD.gn @@ -0,0 +1,79 @@ +# 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("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("app_manager_ani") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", + "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", + "${ability_runtime_path}/interfaces/kits/native/ability/native", + "${ability_runtime_path}/interfaces/inner_api/runtime/include", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", + ] + + configs = [] + + public_configs = [] + + sources = [ + "./src/ets_app_manager.cpp", + "./src/ets_app_manager_utils.cpp", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/app_manager:app_manager", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] + + external_deps = [ + "ability_base:base", + "ability_base:configuration", + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "ipc:ipc_core", + "napi:ace_napi", + "runtime_core:ani", + "samgr:samgr_proxy", + ] + + if (ability_runtime_graphics) { + external_deps += [ "access_token:libtokenid_sdk" ] + defines = [ "SUPPORT_SCREEN" ] + } + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/app_manager/include/ets_app_manager.h b/frameworks/ets/ani/app_manager/include/ets_app_manager.h new file mode 100644 index 00000000000..a6cfa96e156 --- /dev/null +++ b/frameworks/ets/ani/app_manager/include/ets_app_manager.h @@ -0,0 +1,26 @@ +/* + * 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_MANAGER_H +#define OHOS_ABILITY_RUNTIME_ETS_APP_MANAGER_H + +#include "ets_runtime.h" + +namespace OHOS { +namespace AppManagerEts { +void EtsAppManagerRegistryInit(ani_env *env); +} // namespace AppManagerEts +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_APP_MANAGER_H diff --git a/frameworks/ets/ani/app_manager/include/ets_app_manager_utils.h b/frameworks/ets/ani/app_manager/include/ets_app_manager_utils.h new file mode 100644 index 00000000000..ccf6d953783 --- /dev/null +++ b/frameworks/ets/ani/app_manager/include/ets_app_manager_utils.h @@ -0,0 +1,52 @@ +/* + * 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_MANAGER_UTILS_H +#define OHOS_ABILITY_RUNTIME_ETS_APP_MANAGER_UTILS_H + +#include + +#include "ani.h" +#include "app_state_data.h" +#include "ets_runtime.h" +#include "process_data.h" +#include "running_multi_info.h" +#include "running_process_info.h" + +namespace OHOS { +namespace AppManagerEts { +ani_object NewArrayClass(ani_env *env, const std::vector &data); +ani_object WrapAppStateData(ani_env *env, const AppExecFwk::AppStateData &appStateData); +void SetAppStateData(ani_env *env, ani_object object, const AppExecFwk::AppStateData &appStateData); +ani_object CreateAppStateDataArray(ani_env *env, const std::vector &data); +ani_object CreateRunningMultiInstanceInfoArray(ani_env *env, + const std::vector &infos); +ani_object CreateRunningAppCloneArray(ani_env *env, const std::vector &infos); +void SetRunningMultiAppInfo( + ani_env *env, ani_object object, const AppExecFwk::RunningMultiAppInfo &runningMultiAppInfo); +ani_object WrapRunningMultiAppInfo(ani_env *env, const AppExecFwk::RunningMultiAppInfo &runningMultiAppInfo); +ani_object WrapRunningMultiInstanceInfo(ani_env *env, const AppExecFwk::RunningMultiInstanceInfo &instanceInfo); +void SetRunningMultiInstanceInfo( + ani_env *env, ani_object object, const AppExecFwk::RunningMultiInstanceInfo &instanceInfo); +ani_object WrapRunningAppClone(ani_env *env, const AppExecFwk::RunningAppClone &runningAppClone); +void SetRunningAppClone(ani_env *env, ani_object object, const AppExecFwk::RunningAppClone &runningAppClone); +ani_object WrapProcessData(ani_env *env, const AppExecFwk::ProcessData &processData); +void SetProcessData(ani_env *env, ani_object object, const AppExecFwk::ProcessData &processData); +bool UnWrapArrayString(ani_env *env, ani_object arrayObj, std::vector &stringList); +ani_object CreateEmptyAniArray(ani_env *env); +ani_object CreateEmptyMultiAppInfo(ani_env *env); +ani_object CreateDoubleAniArray(ani_env *env, const std::vector &dataArry); +} // namespace AppManagerEts +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_APP_MANAGER_UTILS_H diff --git a/frameworks/ets/ani/app_manager/src/ets_app_manager.cpp b/frameworks/ets/ani/app_manager/src/ets_app_manager.cpp new file mode 100644 index 00000000000..6e89d5611b2 --- /dev/null +++ b/frameworks/ets/ani/app_manager/src/ets_app_manager.cpp @@ -0,0 +1,396 @@ +/* + * 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_manager.h" + +#include "ability_manager_client.h" +#include "ability_manager_interface.h" +#include "ani_common_util.h" +#include "ani_enum_convert.h" +#include "app_mgr_constants.h" +#include "app_mgr_interface.h" +#include "ets_app_manager_utils.h" +#include "ets_error_utils.h" +#include "hilog_tag_wrapper.h" +#include "if_system_ability_manager.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#ifdef SUPPORT_GRAPHICS +#ifdef SUPPORT_SCREEN +#include "tokenid_kit.h" +#endif +#endif + +namespace OHOS { +namespace AppManagerEts { +namespace { +constexpr const char* APP_MANAGER_SPACE_NAME = "L@ohos/app/ability/appManager/appManager;"; +} + +class EtsAppManager final { +public: + static void PreloadApplication(ani_env *env, ani_object callback, ani_string aniBundleName, ani_double aniUserId, + ani_enum_item aniMode, ani_object aniAppIndex); + static void GetRunningProcessInformation(ani_env *env, ani_object callback); + static void GetForegroundApplications(ani_env *env, ani_object callback); + static void GetRunningMultiAppInfo(ani_env *env, ani_string aniBundleName, ani_object callback); + static void GetRunningProcessInfoByBundleNameAndUserId(ani_env *env, ani_string aniBundleName, + ani_double aniUserId, ani_object callback); + static void GetRunningProcessInfoByBundleName(ani_env *env, ani_string aniBundleName, ani_object callback); +private: + static sptr GetAppManagerInstance(); +#ifdef SUPPORT_SCREEN + static bool CheckCallerIsSystemApp(); +#endif + static ani_double OnOnApplicationStateInner( + ani_env *env, ani_string type, ani_object observer, ani_object aniBundleNameList); +}; + +sptr EtsAppManager::GetAppManagerInstance() +{ + sptr systemAbilityManager = + OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + sptr appObject = systemAbilityManager->GetSystemAbility(OHOS::APP_MGR_SERVICE_ID); + return OHOS::iface_cast(appObject); +} + +#ifdef SUPPORT_SCREEN +bool EtsAppManager::CheckCallerIsSystemApp() +{ + auto selfToken = IPCSkeleton::GetSelfTokenID(); + return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken); +} +#endif + +void EtsAppManager::PreloadApplication(ani_env *env, ani_object callback, ani_string aniBundleName, + ani_double aniUserId, ani_enum_item aniMode, ani_object aniAppIndex) +{ + TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env is null"); + return; + } + std::string bundleName; + if (!OHOS::AppExecFwk::GetStdString(env, aniBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "param bundlename err"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr( + env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM)), nullptr); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication userId:%{public}f, bundleName %{public}s", + aniUserId, bundleName.c_str()); + int32_t userId = static_cast(aniUserId); + + ani_int mode = 0; + if (!AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative(env, aniMode, mode)) { + TAG_LOGE(AAFwkTag::APPMGR, "param mode err"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr( + env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM)), nullptr); + return; + } + + ani_status status = ANI_OK; + int32_t appIndex = 0; + ani_boolean isUndefined = false; + if ((status = env->Reference_IsUndefined(aniAppIndex, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to check undefined status : %{public}d", status); + return; + } + ani_double dval = 0.0; + if (!isUndefined) { + if ((status = env->Object_CallMethodByName_Double(aniAppIndex, "doubleValue", nullptr, &dval)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_CallMethodByName_Double status : %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "aniAppIndex: %{public}f", dval); + appIndex = static_cast(dval); + } + TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication userId:%{public}d, mode:%{public}d, appIndex:%{public}d", + userId, mode, appIndex); + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr( + env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), nullptr); + return; + } + auto ret = appMgr->PreloadApplication(bundleName, userId, static_cast(mode), appIndex); + TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication ret %{public}d", ret); + + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), nullptr); + TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication END"); +} + +void EtsAppManager::GetRunningProcessInformation(ani_env *env, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInformation called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_object emptyArray = CreateEmptyAniArray(env); + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr( + env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + return; + } + std::vector infos; + auto ret = appMgr->GetAllRunningProcesses(infos); + TAG_LOGD(AAFwkTag::APPMGR, "GetAllRunningProcesses ret:%{public}d, size:%{public}zu", ret, infos.size()); + if (ret != ERR_OK) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), emptyArray); + return; + } + ani_object aniInfosRef = CreateRunningProcessInfoArray(env, infos); + if (aniInfosRef == nullptr) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr( + env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + } else { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), aniInfosRef); + } + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInformation finished"); +} + +void EtsAppManager::GetForegroundApplications(ani_env *env, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPMGR, "GetForegroundApplications called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_object emptyArray = CreateEmptyAniArray(env); + auto appManager = GetAppManagerInstance(); + if (appManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr( + env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + return; + } + std::vector appStateData; + int32_t ret = appManager->GetForegroundApplications(appStateData); + TAG_LOGD(AAFwkTag::APPMGR, "GetForegroundApplications ret:%{public}d, size:%{public}zu", ret, appStateData.size()); + if (ret != ERR_OK) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), emptyArray); + return; + } + ani_object appStateDataObj = CreateAppStateDataArray(env, appStateData); + if (appStateDataObj == nullptr) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr( + env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + } else { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), + appStateDataObj); + } + TAG_LOGD(AAFwkTag::APPMGR, "GetForegroundApplications end"); +} + +void EtsAppManager::GetRunningMultiAppInfo(ani_env *env, ani_string aniBundleName, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningMultiAppInfo called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_object emptyMultiAppInfo = CreateEmptyMultiAppInfo(env); +#ifdef SUPPORT_SCREEN + if (!CheckCallerIsSystemApp()) { + TAG_LOGE(AAFwkTag::APPMGR, "Non-system app"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateError( + env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP), emptyMultiAppInfo); + return; + } +#endif + std::string bundleName; + if (!OHOS::AppExecFwk::GetStdString(env, aniBundleName, bundleName) || bundleName.empty()) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + "Parse param bundleName failed, must be a string."), emptyMultiAppInfo); + return; + } + auto appManager = GetAppManagerInstance(); + if (appManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager nullptr"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr( + env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyMultiAppInfo); + return; + } + AppExecFwk::RunningMultiAppInfo info; + int32_t innerErrorCode = ERR_OK; + innerErrorCode = appManager->GetRunningMultiAppInfoByBundleName(bundleName, info); + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningMultiAppInfoByBundleName ret: %{public}d", innerErrorCode); + if (innerErrorCode != ERR_OK) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, innerErrorCode), emptyMultiAppInfo); + return; + } + ani_object appinfoObj = WrapRunningMultiAppInfo(env, info); + if (appinfoObj == nullptr) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr( + env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyMultiAppInfo); + } else { + AppExecFwk::AsyncCallback( + env, callback, OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, innerErrorCode), appinfoObj); + } + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningMultiAppInfo end"); +} + +void EtsAppManager::GetRunningProcessInfoByBundleNameAndUserId( + ani_env *env, ani_string aniBundleName, ani_double aniUserId, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInfoByBundleNameAndUserId called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_object emptyArray = CreateEmptyAniArray(env); + if (aniBundleName == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "aniBundleName null ptr"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr( + env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM)), emptyArray); + return; + } + std::string bundleName; + if (!OHOS::AppExecFwk::GetStdString(env, aniBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr( + env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM)), emptyArray); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInfoByBundleNameAndUserId userid:%{public}f", aniUserId); + int32_t userId = static_cast(aniUserId); + auto appManager = GetAppManagerInstance(); + if (appManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager nullptr"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr( + env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + return; + } + std::vector infos; + int32_t ret = appManager->GetRunningProcessInformation(bundleName, userId, infos); + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInformation ret: %{public}d, size:%{public}zu", ret, infos.size()); + if (ret != ERR_OK) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), emptyArray); + return; + } + ani_object aniInfos = CreateRunningProcessInfoArray(env, infos); + if (aniInfos == nullptr) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr( + env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + } else { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), aniInfos); + } + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInfoByBundleNameAndUserId finished"); +} + +void EtsAppManager::GetRunningProcessInfoByBundleName(ani_env *env, ani_string aniBundleName, ani_object callback) +{ + int userId = IPCSkeleton::GetCallingUid() / AppExecFwk::Constants::BASE_USER_RANGE; + GetRunningProcessInfoByBundleNameAndUserId(env, aniBundleName, static_cast(userId), callback); +} + +void EtsAppManagerRegistryInit(ani_env *env) +{ + TAG_LOGD(AAFwkTag::APPMGR, "EtsAppManagerRegistryInit call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_status status = ANI_ERROR; + if (env->ResetError() != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "ResetError failed"); + } + ani_namespace ns; + status = env->FindNamespace(APP_MANAGER_SPACE_NAME, &ns); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "FindNamespace appManager failed status : %{public}d", status); + return; + } + std::array kitFunctions = { + ani_native_function{ + "nativePreloadApplication", nullptr, reinterpret_cast(EtsAppManager::PreloadApplication)}, + ani_native_function{"nativeGetRunningProcessInformation", + nullptr, + reinterpret_cast(EtsAppManager::GetRunningProcessInformation)}, + ani_native_function{"nativeGetForegroundApplications", + nullptr, + reinterpret_cast(EtsAppManager::GetForegroundApplications)}, + ani_native_function{ + "nativeGetRunningMultiAppInfo", nullptr, reinterpret_cast(EtsAppManager::GetRunningMultiAppInfo)}, + ani_native_function{"nativeGetRunningProcessInfoByBundleName", + nullptr, + reinterpret_cast(EtsAppManager::GetRunningProcessInfoByBundleName)}, + ani_native_function{"nativeGetRunningProcessInfoByBundleNameAndUserId", + nullptr, + reinterpret_cast(EtsAppManager::GetRunningProcessInfoByBundleNameAndUserId)}}; + status = env->Namespace_BindNativeFunctions(ns, kitFunctions.data(), kitFunctions.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Namespace_BindNativeFunctions failed status : %{public}d", status); + } + if (env->ResetError() != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "ResetError failed"); + } + TAG_LOGD(AAFwkTag::APPMGR, "EtsAppManagerRegistryInit end"); +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::APPMGR, "in AppManagerEts.ANI_Constructor"); + if (vm == nullptr || result == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null vm or result"); + return ANI_INVALID_ARGS; + } + + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed, status=%{public}d", status); + return ANI_NOT_FOUND; + } + EtsAppManagerRegistryInit(env); + *result = ANI_VERSION_1; + TAG_LOGD(AAFwkTag::APPMGR, "AppManagerEts.ANI_Constructor finished"); + return ANI_OK; +} +} // extern "C" +} // namespace AppManagerEts +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/app_manager/src/ets_app_manager_utils.cpp b/frameworks/ets/ani/app_manager/src/ets_app_manager_utils.cpp new file mode 100644 index 00000000000..c832ce121c4 --- /dev/null +++ b/frameworks/ets/ani/app_manager/src/ets_app_manager_utils.cpp @@ -0,0 +1,685 @@ +/* + * 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_manager_utils.h" + +#include +#include + +#include "ani_common_util.h" +#include "ani_enum_convert.h" +#include "ets_error_utils.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AppManagerEts { +namespace { +constexpr const char* DATA_CLASS_NAME = "Lapplication/AppStateData/AppStateData;"; +constexpr const char* CLASSNAME_ARRAY = "Lescompat/Array;"; +constexpr const char* INFO_INNER_CLASS_NAME = "Lapplication/RunningMultiAppInfo/RunningMultiAppInfoInner;"; +constexpr const char* INSTANCE_INNER_CLASS_NAME = "Lapplication/RunningMultiAppInfo/RunningMultiInstanceInfoInner;"; +constexpr const char* CLONE_INNER_CLASS_NAME = "Lapplication/RunningMultiAppInfo/RunningAppCloneInner;"; +constexpr const char *PROCESS_DATA_CLASS_NAME = "Lapplication/ProcessData/ProcessData;"; +constexpr const char *MULTI_APP_MODE_ENUM_NAME = "Lapplication/MultiAppMode/MultiAppMode;"; +} // namespace + +ani_object WrapAppStateData(ani_env *env, const AppExecFwk::AppStateData &appStateData) +{ + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object object = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + if ((status = env->FindClass(DATA_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + SetAppStateData(env, object, appStateData); + return object; +} + +void SetAppStateData(ani_env *env, ani_object object, const AppExecFwk::AppStateData &appStateData) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return; + } + ani_status status = ANI_OK; + status = env->Object_SetFieldByName_Ref( + object, "bundleName", OHOS::AppExecFwk::GetAniString(env, appStateData.bundleName)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } + status = env->Object_SetFieldByName_Double(object, "uid", static_cast(appStateData.uid)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } + status = env->Object_SetFieldByName_Double(object, "state", static_cast(appStateData.state)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } + status = env->Object_SetFieldByName_Boolean(object, "isSplitScreenMode", appStateData.isSplitScreenMode); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } + status = env->Object_SetFieldByName_Boolean(object, "isFloatingWindowMode", appStateData.isFloatingWindowMode); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } +} + +ani_object CreateAppStateDataArray(ani_env *env, const std::vector &data) +{ + ani_class arrayCls = nullptr; + ani_status status = ANI_OK; + status = env->FindClass(CLASSNAME_ARRAY, &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + + ani_method arrayCtor = nullptr; + status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + + ani_object arrayObj = nullptr; + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, data.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return arrayObj; + } + + ani_size index = 0; + for (auto &appStateData : data) { + ani_ref aniData = WrapAppStateData(env, appStateData); + if (aniData == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null aniData"); + break; + } + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, aniData); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + break; + } + index++; + } + return arrayObj; +} + +ani_object NewArrayClass(ani_env *env, const std::vector &data) +{ + ani_class arrayCls = nullptr; + ani_status status = ANI_OK; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + status = env->FindClass(CLASSNAME_ARRAY, &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + + ani_method arrayCtor = nullptr; + status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + + ani_object arrayObj = nullptr; + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, data.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return arrayObj; + } + + ani_size index = 0; + for (auto &item : data) { + ani_string aniString; + status = env->String_NewUTF8(item.c_str(), item.size(), &aniString); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + break; + } + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, aniString); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + break; + } + index++; + } + return arrayObj; +} + +ani_object CreateEmptyAniArray(ani_env *env) +{ + ani_class arrayCls = nullptr; + ani_status status = ANI_OK; + + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + + status = env->FindClass(CLASSNAME_ARRAY, &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "FindClass failed status : %{public}d", status); + return nullptr; + } + + ani_method arrayCtor = nullptr; + status = env->Class_FindMethod(arrayCls, "", ":V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "find ctor failed status : %{public}d", status); + return nullptr; + } + + ani_object arrayObj = nullptr; + status = env->Object_New(arrayCls, arrayCtor, &arrayObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_New array failed status : %{public}d", status); + return arrayObj; + } + return arrayObj; +} + +ani_object CreateEmptyMultiAppInfo(ani_env *env) +{ + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object object = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + if ((status = env->FindClass(INFO_INNER_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "FindClass failed status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "find ctor failed status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_New failed status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + return object; +} + +ani_object CreateRunningMultiInstanceInfoArray(ani_env *env, + const std::vector &infos) +{ + ani_class arrayCls = nullptr; + ani_status status = ANI_OK; + + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + + status = env->FindClass(CLASSNAME_ARRAY, &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + + ani_method arrayCtor = nullptr; + status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + + ani_object arrayObj = nullptr; + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, infos.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return arrayObj; + } + + ani_size index = 0; + for (auto &instanceInfo : infos) { + ani_ref ani_info = WrapRunningMultiInstanceInfo(env, instanceInfo); + if (ani_info == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null ani_info"); + break; + } + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, ani_info); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + break; + } + index++; + } + return arrayObj; +} + +ani_object CreateRunningAppCloneArray(ani_env *env, const std::vector &infos) +{ + ani_class arrayCls = nullptr; + ani_status status = ANI_OK; + + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + + status = env->FindClass(CLASSNAME_ARRAY, &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + + ani_method arrayCtor = nullptr; + status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + + ani_object arrayObj = nullptr; + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, infos.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return arrayObj; + } + + ani_size index = 0; + for (auto &runningAppclone : infos) { + ani_ref ani_info = WrapRunningAppClone(env, runningAppclone); + if (ani_info == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null ani_info"); + break; + } + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, ani_info); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + break; + } + index++; + } + return arrayObj; +} + +void SetRunningMultiAppInfo(ani_env *env, ani_object object, const AppExecFwk::RunningMultiAppInfo &runningMultiAppInfo) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return; + } + ani_status status = env->Object_SetPropertyByName_Ref( + object, "bundleName", OHOS::AppExecFwk::GetAniString(env, runningMultiAppInfo.bundleName)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } + ani_enum_item modeItem = nullptr; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts( + env, MULTI_APP_MODE_ENUM_NAME, runningMultiAppInfo.mode, modeItem); + status = env->Object_SetPropertyByName_Ref(object, "mode", modeItem); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } + status = env->Object_SetPropertyByName_Ref(object, + "runningMultiInstances", + CreateRunningMultiInstanceInfoArray(env, runningMultiAppInfo.runningMultiIntanceInfos)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } + status = env->Object_SetPropertyByName_Ref( + object, "runningAppClones", CreateRunningAppCloneArray(env, runningMultiAppInfo.runningAppClones)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } +} + +ani_object WrapRunningMultiAppInfo(ani_env *env, const AppExecFwk::RunningMultiAppInfo &runningMultiAppInfo) +{ + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object object = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + if ((status = env->FindClass(INFO_INNER_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + SetRunningMultiAppInfo(env, object, runningMultiAppInfo); + return object; +} + +ani_object WrapRunningMultiInstanceInfo(ani_env *env, const AppExecFwk::RunningMultiInstanceInfo &instanceInfo) +{ + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object object = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + if ((status = env->FindClass(INSTANCE_INNER_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + SetRunningMultiInstanceInfo(env, object, instanceInfo); + return object; +} + +void SetRunningMultiInstanceInfo( + ani_env *env, ani_object object, const AppExecFwk::RunningMultiInstanceInfo &instanceInfo) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return; + } + ani_status status = env->Object_SetPropertyByName_Ref( + object, "instanceKey", OHOS::AppExecFwk::GetAniString(env, instanceInfo.instanceKey)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } +} + +ani_object WrapRunningAppClone(ani_env *env, const AppExecFwk::RunningAppClone &runningAppClone) +{ + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object object = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + if ((status = env->FindClass(CLONE_INNER_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + SetRunningAppClone(env, object, runningAppClone); + return object; +} + +void SetRunningAppClone(ani_env *env, ani_object object, const AppExecFwk::RunningAppClone &runningAppClone) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return; + } + ani_status status = env->Object_SetPropertyByName_Double(object, "appCloneIndex", runningAppClone.appCloneIndex); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } + status = env->Object_SetPropertyByName_Double(object, "uid", runningAppClone.uid); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } + ani_class arrayCls = nullptr; + status = env->FindClass(CLASSNAME_ARRAY, &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return; + } + ani_method arrayCtor; + status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return; + } + ani_object arrayObj; + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, runningAppClone.pids.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return; + } + ani_size index = 0; + for (auto &pid : runningAppClone.pids) { + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ID;:V", index, pid); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + break; + } + index++; + } + status = env->Object_SetPropertyByName_Ref(object, "pids", arrayObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } +} + +ani_object WrapProcessData(ani_env *env, const AppExecFwk::ProcessData &processData) +{ + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object object = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + if ((status = env->FindClass(PROCESS_DATA_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + SetProcessData(env, object, processData); + return object; +} + +void SetProcessData(ani_env *env, ani_object object, const AppExecFwk::ProcessData &processData) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return; + } + ani_status status = env->Object_SetFieldByName_Ref( + object, "bundleName", OHOS::AppExecFwk::GetAniString(env, processData.bundleName)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } + status = env->Object_SetFieldByName_Double(object, "pid", processData.pid); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } + status = env->Object_SetFieldByName_Double(object, "uid", processData.uid); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } + status = env->Object_SetFieldByName_Double(object, "state", static_cast(processData.state)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } + status = env->Object_SetFieldByName_Boolean(object, "isContinuousTask", processData.isContinuousTask); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } + status = env->Object_SetFieldByName_Boolean(object, "isKeepAlive", processData.isKeepAlive); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + } +} + +bool UnWrapArrayString(ani_env *env, ani_object arrayObj, std::vector &stringList) +{ + if (env == nullptr || arrayObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null or arrayObj null"); + return false; + } + stringList.clear(); + ani_size size = 0; + ani_status status = ANI_ERROR; + if ((status = env->Array_GetLength(reinterpret_cast(arrayObj), &size)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return false; + } + ani_ref ref = nullptr; + ani_size idx = 0; + for (idx = 0; idx < size; idx++) { + if ((status = env->Array_Get_Ref(reinterpret_cast(arrayObj), idx, &ref)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d, index: %{public}zu", status, idx); + return false; + } + std::string str = ""; + if (!OHOS::AppExecFwk::GetStdString(env, reinterpret_cast(ref), str)) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetStdString failed, index: %{public}zu", idx); + return false; + } + stringList.push_back(str); + } + return true; +} + +ani_object CreateDoubleAniArray(ani_env * env, const std::vector &dataArry) +{ + ani_class arrayCls = nullptr; + ani_status status = ANI_OK; + + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + + status = env->FindClass(CLASSNAME_ARRAY, &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + + ani_method arrayCtor = nullptr; + status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + + ani_object arrayObj = nullptr; + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, dataArry.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return arrayObj; + } + + for (size_t i = 0; i < dataArry.size(); i++) { + ani_object intObj = AppExecFwk::CreateDouble(env, static_cast(dataArry[i])); + if (intObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "intObj nullptr"); + return nullptr; + } + ani_status status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", i, intObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + } + return arrayObj; +} +} // namespace AppManagerEts +} // namespace OHOS diff --git a/frameworks/ets/ani/application/BUILD.gn b/frameworks/ets/ani/application/BUILD.gn new file mode 100644 index 00000000000..b9be6b35a2f --- /dev/null +++ b/frameworks/ets/ani/application/BUILD.gn @@ -0,0 +1,62 @@ +# 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("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("application_ani") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/interfaces/inner_api/runtime/include", + "${ability_runtime_path}/interfaces/inner_api/error_utils/include", + "${ability_runtime_path}/interfaces/kits/native/ability/native", + ] + + sources = [ "./src/ets_application.cpp" ] + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/ani_base_context:ani_base_context", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_native_path}/appkit:app_context_utils", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_native_path}/appkit:application_context_manager", + "${ability_runtime_services_path}/common:perm_verification", + ] + + external_deps = [ + "ability_base:configuration", + "bundle_framework:appexecfwk_core", + "hilog:libhilog", + "json:nlohmann_json_static", + "ipc:ipc_core", + "napi:ace_napi", + "runtime_core:ani", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/application/include/ets_application.h b/frameworks/ets/ani/application/include/ets_application.h new file mode 100644 index 00000000000..835754ac5c5 --- /dev/null +++ b/frameworks/ets/ani/application/include/ets_application.h @@ -0,0 +1,33 @@ +/* + * 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_APPLICATION_H +#define OHOS_ABILITY_RUNTIME_ETS_APPLICATION_H + +#include "ani.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsApplication { +public: + static void CreateModuleContext(ani_env *env, + ani_object contextObj, ani_string bundleName, ani_string moduleName, ani_object callback); + static void CreateBundleContext(ani_env *env, + ani_object contextObj, ani_string bundleName, ani_object callback); +}; +void ApplicationInit(ani_env *env); +} // namespace AbilityRuntime +} // namespace OHOS +#endif //OHOS_ABILITY_RUNTIME_ETS_APPLICATION_H \ No newline at end of file diff --git a/frameworks/ets/ani/application/src/ets_application.cpp b/frameworks/ets/ani/application/src/ets_application.cpp new file mode 100644 index 00000000000..aafc8797dcb --- /dev/null +++ b/frameworks/ets/ani/application/src/ets_application.cpp @@ -0,0 +1,302 @@ +/* + * 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_application.h" + +#include "ani_base_context.h" +#include "ani_common_util.h" +#include "application_context.h" +#include "application_context_manager.h" +#include "context_impl.h" +#include "ets_application_context_utils.h" +#include "ets_context_utils.h" +#include "ets_error_utils.h" +#include "hilog_tag_wrapper.h" +#include "permission_verification.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* PERMISSION_GET_BUNDLE_INFO = "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED"; +constexpr const char* CONTEXT_CLASS_NAME = "Lapplication/Context/Context;"; +constexpr const char* APPLICATION_SPACE_NAME = "L@ohos/app/ability/application/application;"; +} + +ani_object CreateEmptyContextObject(ani_env *env) +{ + ani_class cls = nullptr; + ani_status status = env->FindClass(CONTEXT_CLASS_NAME, &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "find Context failed status: %{public}d", status); + return nullptr; + } + ani_method method = nullptr; + status = env->Class_FindMethod(cls, "", ":V", &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_FindMethod ctor failed status: %{public}d", status); + return nullptr; + } + ani_object objValue = nullptr; + if (env->Object_New(cls, method, &objValue) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_New failed status: %{public}d", status); + return nullptr; + } + return objValue; +} + +bool CheckIsSystemAppOrPermisson(ani_env *env, ani_object callback) +{ + auto emptyObject = CreateEmptyContextObject(env); + if (!AAFwk::PermissionVerification::GetInstance()->IsSystemAppCall()) { + TAG_LOGE(AAFwkTag::APPKIT, "no system app"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, + static_cast(AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP), + "The application is not system-app, can not use system-api."), emptyObject); + return false; + } + if (!AAFwk::PermissionVerification::GetInstance()->VerifyGetBundleInfoPrivilegedPermission()) { + TAG_LOGE(AAFwkTag::APPKIT, "no permission"); + AppExecFwk::AsyncCallback(env, callback, + EtsErrorUtil::CreateNoPermissionError(env, PERMISSION_GET_BUNDLE_INFO), emptyObject); + return false; + } + return true; +} + +bool SetNativeContextLong(ani_env *env, std::shared_ptr context, ani_class& cls, ani_object& contextObj) +{ + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "env or context is null"); + return false; + } + ani_status status = ANI_ERROR; + ani_method method {}; + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + return false; + } + if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + return false; + } + ani_field field = nullptr; + if ((status = env->Class_FindField(cls, "nativeContext", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + return false; + } + auto workContext = new (std::nothrow) std::weak_ptr(context); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "workContext nullptr"); + return false; + } + ani_long nativeContextLong = reinterpret_cast(workContext); + if (!ContextUtil::SetNativeContextLong(env, contextObj, nativeContextLong)) { + TAG_LOGE(AAFwkTag::APPKIT, "SetNativeContextLong failed"); + delete workContext; + workContext = nullptr; + return false; + } + return true; +} + +void SetCreateCompleteCallback(ani_env *env, std::shared_ptr> contextPtr, ani_object callback) +{ + if (env == nullptr || contextPtr == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "env or contextPtr is nullptr"); + return; + } + auto context = *contextPtr; + if (!context) { + TAG_LOGE(AAFwkTag::APPKIT, "failed to create context"); + auto emptyObject = CreateEmptyContextObject(env); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, + AbilityErrorCode::ERROR_CODE_INVALID_PARAM), emptyObject); + return; + } + ani_class cls {}; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + return; + } + ani_object contextObj = nullptr; + if (!SetNativeContextLong(env, context, cls, contextObj)) { + TAG_LOGE(AAFwkTag::APPKIT, "set nativeContextLong failed"); + return; + } + ContextUtil::CreateEtsBaseContext(env, cls, contextObj, context); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK), contextObj); +} + +std::shared_ptr GetContextByStageMode(ani_env *env, ani_object &contextObj, + ani_object callback, ani_object emptyObject) +{ + ani_boolean stageMode = false; + ani_status status = IsStageContext(env, contextObj, stageMode); + if (status != ANI_OK || !stageMode) { + TAG_LOGE(AAFwkTag::APPKIT, "not stageMode"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env, + "Parse param context failed, must be a context of stageMode."), emptyObject); + return nullptr; + } + auto context = GetStageModeContext(env, contextObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env, + "Parse param context failed, must not be nullptr."), emptyObject); + return nullptr; + } + return context; +} + +void EtsApplication::CreateModuleContext(ani_env *env, + ani_object contextObj, ani_string bundleName, ani_string moduleName, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "CreateModuleContext Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + ani_object emptyObject = CreateEmptyContextObject(env); + std::string stdBundleName = ""; + std::string stdModuleName = ""; + AppExecFwk::GetStdString(env, bundleName, stdBundleName); + AppExecFwk::GetStdString(env, moduleName, stdModuleName); + auto context = GetContextByStageMode(env, contextObj, callback, emptyObject); + if (context == nullptr) { + return; + } + auto inputContextPtr = Context::ConvertTo(context); + if (inputContextPtr == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "Convert to context failed"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env, + "Parse param context failed, must be a context."), emptyObject); + return; + } + std::shared_ptr> moduleContext = std::make_shared>(); + std::shared_ptr contextImpl = std::make_shared(); + if (contextImpl == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null contextImpl"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env, + "create context failed."), emptyObject); + return; + } + contextImpl->SetProcessName(context->GetProcessName()); + if (stdBundleName.empty()) { + *moduleContext = contextImpl->CreateModuleContext(stdModuleName, inputContextPtr); + } else { + if (!CheckIsSystemAppOrPermisson(env, callback)) { + TAG_LOGE(AAFwkTag::APPKIT, "CheckCaller failed"); + } + *moduleContext = contextImpl->CreateModuleContext(stdBundleName, stdModuleName, inputContextPtr); + } + SetCreateCompleteCallback(env, moduleContext, callback); +} + +void EtsApplication::CreateBundleContext(ani_env *env, + ani_object contextObj, ani_string bundleName, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "CreateBundleContext Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + ani_object emptyObject = CreateEmptyContextObject(env); + if (!CheckIsSystemAppOrPermisson(env, callback)) { + TAG_LOGE(AAFwkTag::APPKIT, "CheckCaller failed"); + return; + } + std::string stdBundleName = ""; + AppExecFwk::GetStdString(env, bundleName, stdBundleName); + auto context = GetContextByStageMode(env, contextObj, callback, emptyObject); + if (context == nullptr) { + return; + } + auto inputContextPtr = Context::ConvertTo(context); + if (inputContextPtr == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "Convert to context failed"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env, + "Parse param context failed, must be a context."), emptyObject); + return; + } + auto bundleContext = std::make_shared>(); + std::shared_ptr contextImpl = std::make_shared(); + if (contextImpl == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null contextImpl"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env, + "create context failed."), emptyObject); + return; + } + contextImpl->SetProcessName(context->GetProcessName()); + contextImpl->CreateBundleContext(*bundleContext, stdBundleName, inputContextPtr); + SetCreateCompleteCallback(env, bundleContext, callback); +} + +void ApplicationInit(ani_env *env) +{ + TAG_LOGD(AAFwkTag::APPKIT, "ApplicationInit Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + ani_status status = ANI_ERROR; + ani_namespace ns; + status = env->FindNamespace(APPLICATION_SPACE_NAME, &ns); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "FindNamespace application failed status: %{public}d", status); + return; + } + std::array methods = { + ani_native_function { + "nativeCreateModuleContext", + "Lapplication/Context/Context;Lstd/core/String;Lstd/core/String;" + "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplication::CreateModuleContext) + }, + ani_native_function { + "nativeCreateBundleContext", + "Lapplication/Context/Context;Lstd/core/String;" + "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplication::CreateBundleContext) + }, + }; + status = env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Namespace_BindNativeFunctions failed status: %{public}d", status); + } +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::APPKIT, "in ApplicationETS.ANI_Constructor"); + if (vm == nullptr || result == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null vm or result"); + return ANI_INVALID_ARGS; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed, status: %{public}d", status); + return ANI_NOT_FOUND; + } + ApplicationInit(env); + *result = ANI_VERSION_1; + TAG_LOGD(AAFwkTag::APPKIT, "AbilityManagerEts.ANI_Constructor finished"); + return ANI_OK; +} +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/insight_intent/insight_intent_driver/BUILD.gn b/frameworks/ets/ani/insight_intent/insight_intent_driver/BUILD.gn new file mode 100644 index 00000000000..10a6e89f0d2 --- /dev/null +++ b/frameworks/ets/ani/insight_intent/insight_intent_driver/BUILD.gn @@ -0,0 +1,69 @@ +# 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("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("insight_intent_driver_ani_kit") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", + "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/interfaces/kits/native/ability/native", + "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", + "${ability_runtime_path}/interfaces/inner_api/runtime/include", + ] + + configs = [] + + public_configs = [] + + sources = [ + "./src/ets_insight_intent_driver.cpp", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_native_path}/ability/native:abilitykit_native", + "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] + + external_deps = [ + "ability_base:want", + "bundle_framework:appexecfwk_base", + "c_utils:utils", + "hilog:libhilog", + "json:nlohmann_json_static", + "runtime_core:ani", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} \ No newline at end of file diff --git a/frameworks/ets/ani/insight_intent/insight_intent_driver/include/ets_insight_intent_driver.h b/frameworks/ets/ani/insight_intent/insight_intent_driver/include/ets_insight_intent_driver.h new file mode 100644 index 00000000000..045b2ca0408 --- /dev/null +++ b/frameworks/ets/ani/insight_intent/insight_intent_driver/include/ets_insight_intent_driver.h @@ -0,0 +1,26 @@ +/* + * 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_INSIGHT_INTENT_DRIVER_H +#define OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_DRIVER_H + +#include "ani.h" + +namespace OHOS { +namespace AbilityRuntime { +void EtsInsightIntentDriverInit(ani_env *env, [[maybe_unused]]ani_class aniClass, + ani_object exparam, ani_object callback, ani_boolean isCallback); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_DRIVER_H diff --git a/frameworks/ets/ani/insight_intent/insight_intent_driver/src/ets_insight_intent_driver.cpp b/frameworks/ets/ani/insight_intent/insight_intent_driver/src/ets_insight_intent_driver.cpp new file mode 100644 index 00000000000..c032d318bff --- /dev/null +++ b/frameworks/ets/ani/insight_intent/insight_intent_driver/src/ets_insight_intent_driver.cpp @@ -0,0 +1,227 @@ +/* + * 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_insight_intent_driver.h" + +#include + +#include "ability_business_error.h" +#include "ability_manager_client.h" +#include "event_handler.h" +#include "event_runner.h" +#include "hilog_tag_wrapper.h" +#include "insight_intent_callback_interface.h" +#include "insight_intent_host_client.h" +#include "insight_intent_execute_result.h" +#include "ani_common_execute_param.h" +#include "ani_common_execute_result.h" +#include "ani_common_util.h" +#include "ets_error_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +using namespace OHOS::AppExecFwk; +namespace { +constexpr const char *DRIVER_CLASS_NAME = "L@ohos/app/ability/insightIntentDriver/insightIntentDriver;"; +} +class EtsInsightIntentExecuteCallbackClient : public InsightIntentExecuteCallbackInterface, + public std::enable_shared_from_this { +public: + EtsInsightIntentExecuteCallbackClient(ani_vm *vm, ani_ref callbackRef, ani_ref promiseRef) + : vm_(vm), callbackRef_(callbackRef), promiseRef_(promiseRef) {} + + virtual ~EtsInsightIntentExecuteCallbackClient() + { + ani_env *env = AttachCurrentThread(); + if (env != nullptr) { + if (promiseRef_) { + env->GlobalReference_Delete(promiseRef_); + promiseRef_ = nullptr; + } + if (callbackRef_) { + env->GlobalReference_Delete(callbackRef_); + callbackRef_ = nullptr; + } + DetachCurrentThread(); + } + } + + void ProcessInsightIntentExecute(int32_t resultCode, + AppExecFwk::InsightIntentExecuteResult executeResult) override + { + ani_env *env = AttachCurrentThread(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "GetEnv failed"); + return; + } + + ani_object error; + ani_object result; + if (resultCode != 0) { + error = EtsErrorUtil::CreateErrorByNativeErr(env, resultCode); + result = CreateNullExecuteResult(env); + } else { + error = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK); + result = WrapExecuteResult(env, executeResult); + } + if (callbackRef_) { + AsyncCallback(env, static_cast(callbackRef_), error, result); + } + if (promiseRef_) { + AsyncCallback(env, static_cast(promiseRef_), error, result); + } + DetachCurrentThread(); + } + + ani_env *AttachCurrentThread() + { + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if ((status = vm_->GetEnv(ANI_VERSION_1, &env)) == ANI_OK) { + return env; + } + + ani_option interopEnabled { "--interop=disable", nullptr }; + ani_options aniArgs { 1, &interopEnabled }; + if ((status = vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + isAttachThread_ = true; + return env; + } + + void DetachCurrentThread() + { + if (isAttachThread_) { + vm_->DetachCurrentThread(); + isAttachThread_ = false; + } + } + +private: + ani_vm *vm_ = nullptr; + ani_ref callbackRef_ = nullptr; + ani_ref promiseRef_ = nullptr; + bool isAttachThread_ = false; +}; + +class EtsInsightIntentDriver { +public: + EtsInsightIntentDriver() = default; + ~EtsInsightIntentDriver() = default; + + static void OnExecute(ani_env *env, ani_object exparam, ani_object callback, ani_boolean isCallback) + { + TAG_LOGD(AAFwkTag::INTENT, "OnExecute called"); + ani_object error; + if (exparam == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "invalid param"); + error = EtsErrorUtil::CreateInvalidParamError(env, "invalid param"); + AsyncCallback(env, callback, error, CreateNullExecuteResult(env)); + return; + } + + InsightIntentExecuteParam param; + if (!UnwrapExecuteParam(env, exparam, param)) { + TAG_LOGE(AAFwkTag::INTENT, "parse execute param failed"); + error = EtsErrorUtil::CreateInvalidParamError(env, + "Parameter error: Parse param failed, param must be a ExecuteParam."); + AsyncCallback(env, callback, error, CreateNullExecuteResult(env)); + return; + } + + ani_ref callbackRef = nullptr; + if (env->GlobalReference_Create(callback, &callbackRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "GlobalReference_Create failed"); + error = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast( + AbilityErrorCode::ERROR_CODE_INNER)); + AsyncCallback(env, callback, error, CreateNullExecuteResult(env)); + return; + } + + ani_vm *vm = nullptr; + if (env->GetVM(&vm) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "GetVM failed"); + error = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast( + AbilityErrorCode::ERROR_CODE_INNER)); + AsyncCallback(env, callback, error, CreateNullExecuteResult(env)); + return; + } + + std::shared_ptr client; + if (isCallback) { + client = std::make_shared(vm, callbackRef, nullptr); + } else { + client = std::make_shared(vm, nullptr, callbackRef); + } + uint64_t key = InsightIntentHostClient::GetInstance()->AddInsightIntentExecute(client); + auto err = AbilityManagerClient::GetInstance()->ExecuteIntent(key, + InsightIntentHostClient::GetInstance(), param); + if (err != 0) { + error = EtsErrorUtil::CreateErrorByNativeErr(env, err); + AsyncCallback(env, callback, error, CreateNullExecuteResult(env)); + InsightIntentHostClient::GetInstance()->RemoveInsightIntentExecute(key); + } + return; + } +}; + +void EtsInsightIntentDriverInit(ani_env *env) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentDriverInit called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return; + } + + ani_namespace ns; + ani_status status = env->FindNamespace(DRIVER_CLASS_NAME, &ns); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "FindNamespace insightIntentDriver failed status: %{public}d", status); + return; + } + + std::array kitFunctions = { + ani_native_function {"nativeExecuteSync", nullptr, + reinterpret_cast(EtsInsightIntentDriver::OnExecute)}, + }; + + status = env->Namespace_BindNativeFunctions(ns, kitFunctions.data(), kitFunctions.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "bind nativeExecuteSync failed status: %{public}d", status); + } +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::INTENT, "ANI_Constructor"); + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGD(AAFwkTag::INTENT, "GetEnv failed status: %{public}d", status); + return ANI_NOT_FOUND; + } + + EtsInsightIntentDriverInit(env); + *result = ANI_VERSION_1; + TAG_LOGD(AAFwkTag::INTENT, "ANI_Constructor finish"); + return ANI_OK; +} +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/native_constructor/context_native_constructor.cpp b/frameworks/ets/ani/native_constructor/context_native_constructor.cpp index fac3b89d47a..5472fc36036 100644 --- a/frameworks/ets/ani/native_constructor/context_native_constructor.cpp +++ b/frameworks/ets/ani/native_constructor/context_native_constructor.cpp @@ -19,6 +19,8 @@ namespace OHOS { namespace AbilityRuntime { void ContextConstructor() {} +void AbilityStageContextConstructor() {} + void ExtensionContextConstructor() {} void UIAbilityContextConstructor() {} @@ -79,6 +81,21 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) TAG_LOGE(AAFwkTag::ETSRUNTIME, "Cannot bind native ctor to class %{public}s.", uiAbilityClassName); return ANI_ERROR; }; + + ani_class abilityStageContextClass = nullptr; + static const char *abilityStageContextClassName = "Lapplication/AbilityStageContext/AbilityStageContext;"; + if (ANI_OK != env->FindClass(abilityStageContextClassName, &abilityStageContextClass)) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Not found class %{public}s.", abilityStageContextClassName); + return ANI_NOT_FOUND; + } + std::array classMethodsAbilityStage = { + ani_native_function {"", ":V", reinterpret_cast(AbilityStageContextConstructor)}, + }; + if (ANI_OK != env->Class_BindNativeMethods(abilityStageContextClass, classMethodsAbilityStage.data(), + classMethodsAbilityStage.size())) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Cannot bind native ctor to class %{public}s.", abilityStageContextClassName); + return ANI_ERROR; + }; *result = ANI_VERSION_1; return ANI_OK; } diff --git a/frameworks/ets/ani/service_extension_ability/include/ets_service_extension.h b/frameworks/ets/ani/service_extension_ability/include/ets_service_extension.h index 6caa046462f..7c820cae6eb 100644 --- a/frameworks/ets/ani/service_extension_ability/include/ets_service_extension.h +++ b/frameworks/ets/ani/service_extension_ability/include/ets_service_extension.h @@ -18,6 +18,9 @@ #include "configuration.h" #include "ets_native_reference.h" #include "ets_runtime.h" +#include "insight_intent_execute_param.h" +#include "insight_intent_execute_result.h" +#include "insight_intent_executor_info.h" #include "service_extension.h" namespace OHOS { @@ -115,6 +118,13 @@ public: */ virtual void OnCommand(const AAFwk::Want &want, bool restart, int startId) override; + /** + * @brief Called back when Service is started by intent driver. + * + * @param want Indicates request to handle. + */ + bool HandleInsightIntent(const AAFwk::Want &want) override; + /** * @brief Called when this extension enters the STATE_STOP state. * @@ -142,6 +152,8 @@ private: void ConfigurationUpdated(); ani_ref CallObjectMethod(bool withResult, const char *name, const char *signature, ...); sptr OnConnectInner(ani_env *env, ani_object &aniRemoteobj, bool &isAsyncCallback); + void BindContext(ani_env *env, std::shared_ptr want); + ani_object CreateETSContext(ani_env *env, std::shared_ptr context); ETSRuntime &etsRuntime_; std::unique_ptr etsObj_; diff --git a/frameworks/ets/ani/service_extension_ability/include/ets_service_extension_context.h b/frameworks/ets/ani/service_extension_ability/include/ets_service_extension_context.h new file mode 100644 index 00000000000..13f04d7eac5 --- /dev/null +++ b/frameworks/ets/ani/service_extension_ability/include/ets_service_extension_context.h @@ -0,0 +1,67 @@ +/* + * 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_SERVICE_EXTENSION_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_ETS_SERVICE_EXTENSION_CONTEXT_H + +#include +#include +#include + +#include "ets_free_install_observer.h" +#include "ets_runtime.h" +#include "hilog_tag_wrapper.h" +#include "ohos_application.h" +#include "service_extension.h" +#include "service_extension_context.h" + +namespace OHOS { +namespace AbilityRuntime { + +class EtsServiceExtensionContext final { +public: + explicit EtsServiceExtensionContext(std::shared_ptr context) + : context_(std::move(context)) {} + ~EtsServiceExtensionContext() = default; + + static void Finalizer(ani_env *env, ani_object obj); + static EtsServiceExtensionContext *GetEtsAbilityContext(ani_env *env, ani_object obj); + static void TerminateSelf(ani_env *env, ani_object obj, ani_object callback); + static void StartAbility(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object call); + static void StartAbilityWithOption( + ani_env *env, ani_object aniObj, ani_object wantObj, ani_object opt, ani_object call); + static void StartServiceExtensionAbility(ani_env *env, ani_object obj, ani_object wantObj, ani_object callbackobj); + static void StopServiceExtensionAbility( + ani_env *env, ani_object aniObj, ani_object wantObj, ani_object callbackobj); + + std::weak_ptr GetAbilityContext() + { + return context_; + } +private: + void OnTerminateSelf(ani_env *env, ani_object obj, ani_object callback); + void OnStartServiceExtensionAbility(ani_env *env, ani_object obj, ani_object wantObj, ani_object callbackobj); + void OnStopServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object callbackobj); + void OnStartAbility(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object opt, ani_object call); + void AddFreeInstallObserver(ani_env *env, const AAFwk::Want &want, + ani_object callbackObj, std::shared_ptr context); + + std::weak_ptr context_; + sptr freeInstallObserver_ = nullptr; +}; + +ani_object CreateEtsServiceExtensionContext(ani_env *env, 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/service_extension_ability/src/ets_service_extension.cpp b/frameworks/ets/ani/service_extension_ability/src/ets_service_extension.cpp index c8146d941de..0a4e879a049 100644 --- a/frameworks/ets/ani/service_extension_ability/src/ets_service_extension.cpp +++ b/frameworks/ets/ani/service_extension_ability/src/ets_service_extension.cpp @@ -15,13 +15,20 @@ #include "ets_service_extension.h" +#include "ability_business_error.h" #include "ability_info.h" #include "ability_manager_client.h" +#include "ani_common_configuration.h" #include "ani_common_want.h" #include "ani_remote_object.h" #include "configuration_utils.h" +#include "ets_service_extension_context.h" #include "hilog_tag_wrapper.h" #include "hitrace_meter.h" +#include "insight_intent_execute_param.h" +#include "insight_intent_execute_result.h" +#include "insight_intent_executor_info.h" +#include "insight_intent_executor_mgr.h" #include "js_service_extension_context.h" #ifdef WINDOWS_PLATFORM @@ -35,6 +42,8 @@ namespace AbilityRuntime { using namespace OHOS::AppExecFwk; namespace { constexpr const char *CLASSNAME_SERVICE_ABILITY = "L@ohos/app/ability/ServiceExtensionAbility/ServiceExtensionAbility;"; +constexpr const char *SERVICE_EXTENSION_CONTEXT_CLASS_NAME = + "Lapplication/ServiceExtensionContext/ServiceExtensionContext;"; constexpr const char *NATIVE_ONCONNECT_CALLBACK_SIGNATURE = "L@ohos/rpc/rpc/RemoteObject;:Z"; constexpr const char *ON_CREATE_SIGNATURE = "L@ohos/app/ability/Want/Want;:V"; constexpr const char *VOID_SIGNATURE = ":V"; @@ -43,6 +52,8 @@ constexpr const char *CHECK_PROMISE_SIGNATURE = "Lstd/core/Object;:Z"; constexpr const char *CALL_PROMISE_SIGNATURE = "Lstd/core/Promise;:Z"; constexpr const char *ON_DISCONNECT_SIGNATURE = "L@ohos/app/ability/Want/Want;:V"; constexpr const char *ON_REQUEST_SIGNATURE = "L@ohos/app/ability/Want/Want;D:V"; +constexpr const char *ON_CONFIGURATION_UPDATE_SIGNATURE = "L@ohos/app/ability/Configuration/Configuration;:V"; +constexpr const char *ON_DUMP_SIGNATURE = "Lescompat/Array;:Lescompat/Array;"; void DisconnectPromiseCallback(ani_env *env, ani_object aniObj) { @@ -119,7 +130,7 @@ void EtsServiceExtension::Init(const std::shared_ptr &record TAG_LOGE(AAFwkTag::SERVICE_EXT, "init failed, some obj null"); return; } - Extension::Init(record, application, handler, token); + ServiceExtension::Init(record, application, handler, token); if (Extension::abilityInfo_ == nullptr || Extension::abilityInfo_->srcEntrance.empty()) { TAG_LOGE(AAFwkTag::SERVICE_EXT, "EtsServiceExtension Init abilityInfo error"); return; @@ -160,6 +171,7 @@ void EtsServiceExtension::Init(const std::shared_ptr &record TAG_LOGE(AAFwkTag::SERVICE_EXT, "Class_BindNativeMethods is fail %{public}d", status); return; } + BindContext(env, record->GetWant()); } void EtsServiceExtension::OnStart(const AAFwk::Want &want) @@ -362,6 +374,58 @@ void EtsServiceExtension::OnCommand(const AAFwk::Want &want, bool restart, int s return; } +bool EtsServiceExtension::HandleInsightIntent(const AAFwk::Want &want) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "HandleInsightIntent called"); + auto callback = std::make_unique(); + callback.reset(InsightIntentExecutorAsyncCallback::Create()); + if (callback == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null callback"); + return false; + } + auto executeParam = std::make_shared(); + bool ret = AppExecFwk::InsightIntentExecuteParam::GenerateFromWant(want, *executeParam); + if (!ret) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Generate execute param failed"); + InsightIntentExecutorMgr::TriggerCallbackInner(std::move(callback), + static_cast(AbilityErrorCode::ERROR_CODE_INVALID_PARAM)); + return false; + } + TAG_LOGD(AAFwkTag::SERVICE_EXT, "Insight bundleName: %{public}s, moduleName: %{public}s, abilityName: %{public}s" + "insightIntentName: %{public}s, executeMode: %{public}d, intentId: %{public}" PRIu64 "", + executeParam->bundleName_.c_str(), executeParam->moduleName_.c_str(), executeParam->abilityName_.c_str(), + executeParam->insightIntentName_.c_str(), executeParam->executeMode_, executeParam->insightIntentId_); + auto asyncCallback = [weak = weak_from_this(), intentId = executeParam->insightIntentId_] + (AppExecFwk::InsightIntentExecuteResult result) { + TAG_LOGD(AAFwkTag::SERVICE_EXT, "intentId %{public}" PRIu64"", intentId); + auto extension = weak.lock(); + if (extension == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null extension"); + return; + } + auto ret = extension->OnInsightIntentExecuteDone(intentId, result); + if (!ret) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "OnInsightIntentExecuteDone failed"); + } + }; + callback->Push(asyncCallback); + InsightIntentExecutorInfo executorInfo; + ret = GetInsightIntentExecutorInfo(want, executeParam, executorInfo); + if (!ret) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Get Intent executor failed"); + InsightIntentExecutorMgr::TriggerCallbackInner(std::move(callback), + static_cast(AbilityErrorCode::ERROR_CODE_INVALID_PARAM)); + return false; + } + ret = DelayedSingleton::GetInstance()->ExecuteInsightIntent( + etsRuntime_, executorInfo, std::move(callback)); + if (!ret) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Execute insight intent failed"); + return false; + } + return true; +} + ani_ref EtsServiceExtension::CallObjectMethod(bool withResult, const char *name, const char *signature, ...) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name); @@ -396,11 +460,150 @@ ani_ref EtsServiceExtension::CallObjectMethod(bool withResult, const char *name, va_end(args); return nullptr; } -void EtsServiceExtension::OnConfigurationUpdated(const AppExecFwk::Configuration &configuration) {} -void EtsServiceExtension::ConfigurationUpdated() {} +ani_object EtsServiceExtension::CreateETSContext(ani_env *env, std::shared_ptr context) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "CreateETSContext"); + return CreateEtsServiceExtensionContext(env, context); +} + +void EtsServiceExtension::BindContext(ani_env *env, std::shared_ptr want) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "BindContext"); + if (env == nullptr || want == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Want info is null or env is null"); + return; + } + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to get context"); + return; + } + ani_object contextObj = CreateETSContext(env, context); + if (contextObj == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null contextObj"); + return; + } + // bind EtsServiceExtension + ani_field contextField; + auto status = env->Class_FindField(etsObj_->aniCls, "context", &contextField); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Class_GetField context failed"); + return; + } + ani_ref contextRef = nullptr; + if (env->GlobalReference_Create(contextObj, &contextRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "GlobalReference_Create contextObj failed"); + return; + } + if (env->Object_SetField_Ref(etsObj_->aniObj, contextField, contextRef) != ANI_OK) { + TAG_LOGD(AAFwkTag::SERVICE_EXT, "Object_SetField_Ref contextObj failed"); + } + TAG_LOGD(AAFwkTag::SERVICE_EXT, "BindContext end"); +} + +void EtsServiceExtension::OnConfigurationUpdated(const AppExecFwk::Configuration &configuration) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "OnConfigurationUpdated"); + ServiceExtension::OnConfigurationUpdated(configuration); + ConfigurationUpdated(); +} + +void EtsServiceExtension::ConfigurationUpdated() +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "ConfigurationUpdated"); + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "env nullptr"); + return; + } + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); + return; + } + auto fullConfig = context->GetConfiguration(); + if (fullConfig == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null configuration"); + return; + } + ani_status status = ANI_ERROR; + ani_object aniConfiguration = OHOS::AppExecFwk::WrapConfiguration(env, *fullConfig); + status = env->Object_CallMethodByName_Void( + etsObj_->aniObj, "onConfigurationUpdate", ON_CONFIGURATION_UPDATE_SIGNATURE, aniConfiguration); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "CALL Object_CallMethod failed, status: %{public}d", status); + return; + } + ani_ref contextRef = nullptr; + if ((status = env->Object_GetFieldByName_Ref(etsObj_->aniObj, "context", &contextRef)) != ANI_OK || + contextRef == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to get field, status : %{public}d", status); + return; + } + ani_class cls = nullptr; + ani_field configField = nullptr; + if ((status = env->FindClass(SERVICE_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to find class, status : %{public}d", status); + return; + } + if ((status = env->Class_FindField(cls, "config", &configField)) != ANI_OK || configField == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to find field, status : %{public}d", status); + return; + } + if ((status = env->Object_SetFieldByName_Ref(reinterpret_cast(contextRef), "config", + aniConfiguration)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to set field, status : %{public}d", status); + return; + } +} + +void EtsServiceExtension::Dump(const std::vector ¶ms, std::vector &info) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "Dump"); + Extension::Dump(params, info); + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "env nullptr"); + return; + } + ani_object arrayObj = nullptr; + if (!WrapArrayString(env, arrayObj, params)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "WrapArrayString failed"); + arrayObj = nullptr; + return; + } + if (etsObj_ == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null etsObj_"); + return; + } + if (etsObj_->aniObj == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Not found ServiceExtension Obj"); + return; + } + if (etsObj_->aniCls == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Not found ServiceExtension class"); + return; + } -void EtsServiceExtension::Dump(const std::vector ¶ms, std::vector &info) {} + ani_status status = ANI_ERROR; + ani_ref dumpInfoRef = nullptr; + if ((status = env->Object_CallMethodByName_Ref(etsObj_->aniObj, "onDump", ON_DUMP_SIGNATURE, &dumpInfoRef, + arrayObj)) != ANI_OK || dumpInfoRef == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Object_CallMethod_Ref FAILED: %{public}d", status); + return; + } + std::vector dumpInfoStrArray; + ani_object dumpInfoObj = reinterpret_cast(dumpInfoRef); + if (!UnwrapArrayString(env, dumpInfoObj, dumpInfoStrArray)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "UnwrapArrayString failed"); + return; + } + for (auto dumpInfoStr:dumpInfoStrArray) { + info.push_back(dumpInfoStr); + } + TAG_LOGD(AAFwkTag::SERVICE_EXT, "Dump info size: %{public}zu", info.size()); +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/ets/ani/service_extension_ability/src/ets_service_extension_context.cpp b/frameworks/ets/ani/service_extension_ability/src/ets_service_extension_context.cpp new file mode 100644 index 00000000000..45bcf7738a8 --- /dev/null +++ b/frameworks/ets/ani/service_extension_ability/src/ets_service_extension_context.cpp @@ -0,0 +1,394 @@ +/* + * 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_service_extension_context.h" + +#include "ability_manager_client.h" +#include "ani_common_start_options.h" +#include "ani_common_want.h" +#include "common_fun_ani.h" +#include "ets_context_utils.h" +#include "ets_error_utils.h" +#include "ets_extension_context.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char *SERVICE_EXTENSION_CONTEXT_CLASS_NAME = + "Lapplication/ServiceExtensionContext/ServiceExtensionContext;"; +constexpr const char *CLEANER_CLASS_NAME = + "Lapplication/ServiceExtensionContext/Cleaner;"; +constexpr const int ANI_ALREADY_BINDED = 8; + +bool BindNativeMethods(ani_env *env, ani_class &cls) +{ + ani_status status = ANI_ERROR; + std::array functions = { + ani_native_function { "nativeTerminateSelf", "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsServiceExtensionContext::TerminateSelf) }, + ani_native_function { "nativeStartAbility", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsServiceExtensionContext::StartAbility) }, + ani_native_function { "nativeStartAbility", "L@ohos/app/ability/Want/Want;" + "L@ohos/app/ability/StartOptions/StartOptions;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsServiceExtensionContext::StartAbilityWithOption) }, + ani_native_function { "nativeStartServiceExtensionAbility", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsServiceExtensionContext::StartServiceExtensionAbility) }, + ani_native_function { "nativeStopServiceExtensionAbility", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsServiceExtensionContext::StopServiceExtensionAbility) }, + }; + if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK + && status != ANI_ALREADY_BINDED) { + TAG_LOGE(AAFwkTag::UI_EXT, "bind method status : %{public}d", status); + return false; + } + ani_class cleanerCls = nullptr; + status = env->FindClass(CLEANER_CLASS_NAME, &cleanerCls); + if (status != ANI_OK || cleanerCls == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to find class, status : %{public}d", status); + return false; + } + std::array CleanerMethods = { + ani_native_function { "clean", nullptr, reinterpret_cast(EtsServiceExtensionContext::Finalizer) }, + }; + if ((status = env->Class_BindNativeMethods(cleanerCls, CleanerMethods.data(), CleanerMethods.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "bind method status : %{public}d", status); + return false; + } + return true; +} +} // namespace + +void EtsServiceExtensionContext::Finalizer(ani_env *env, ani_object obj) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "TerminateSelf"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return; + } + ani_long nativeEtsContextPtr; + if (env->Object_GetFieldByName_Long(obj, "nativeEtsContext", &nativeEtsContextPtr) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to get nativeEtsContext"); + return; + } + if (nativeEtsContextPtr != 0) { + delete reinterpret_cast(nativeEtsContextPtr); + } +} + +void EtsServiceExtensionContext::TerminateSelf(ani_env *env, ani_object aniObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "TerminateSelf"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return; + } + auto etsServiceExtensionContext = EtsServiceExtensionContext::GetEtsAbilityContext(env, aniObj); + if (etsServiceExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null etsServiceExtensionContext"); + return; + } + etsServiceExtensionContext->OnTerminateSelf(env, aniObj, callback); +} + +void EtsServiceExtensionContext::StartServiceExtensionAbility( + ani_env *env, ani_object aniObj, ani_object wantObj, ani_object callbackobj) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "StartServiceExtensionAbility"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return; + } + auto etsServiceExtensionContext = EtsServiceExtensionContext::GetEtsAbilityContext(env, aniObj); + if (etsServiceExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null etsServiceExtensionContext"); + return; + } + etsServiceExtensionContext->OnStartServiceExtensionAbility(env, aniObj, wantObj, callbackobj); +} + +void EtsServiceExtensionContext::StartAbility(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object call) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "StartAbility"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return; + } + auto etsServiceExtensionContext = EtsServiceExtensionContext::GetEtsAbilityContext(env, aniObj); + if (etsServiceExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null etsServiceExtensionContext"); + return; + } + etsServiceExtensionContext->OnStartAbility(env, aniObj, wantObj, nullptr, call); +} + +void EtsServiceExtensionContext::StartAbilityWithOption( + ani_env *env, ani_object aniObj, ani_object wantObj, ani_object opt, ani_object call) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "StartAbilityWithOption"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return; + } + auto etsServiceExtensionContext = EtsServiceExtensionContext::GetEtsAbilityContext(env, aniObj); + if (etsServiceExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null etsServiceExtensionContext"); + return; + } + etsServiceExtensionContext->OnStartAbility(env, aniObj, wantObj, opt, call); +} + +void EtsServiceExtensionContext::StopServiceExtensionAbility( + ani_env *env, ani_object aniObj, ani_object wantObj, ani_object callbackobj) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "OnStopServiceExtensionAbility"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return; + } + auto etsServiceExtensionContext = EtsServiceExtensionContext::GetEtsAbilityContext(env, aniObj); + if (etsServiceExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null etsServiceExtensionContext"); + return; + } + etsServiceExtensionContext->OnStopServiceExtensionAbility(env, aniObj, wantObj, callbackobj); +} + +EtsServiceExtensionContext *EtsServiceExtensionContext::GetEtsAbilityContext( + ani_env *env, ani_object aniObj) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "GetEtsAbilityContext"); + ani_class cls = nullptr; + ani_long nativeContextLong; + 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(SERVICE_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to find class, status : %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeEtsContext", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to find filed, status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_GetField_Long(aniObj, contextField, &nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to get filed, status : %{public}d", status); + return nullptr; + } + auto weakContext = reinterpret_cast(nativeContextLong); + return weakContext; +} + +void EtsServiceExtensionContext::OnTerminateSelf(ani_env *env, ani_object obj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "OnTerminateSelf"); + ani_object aniObject = nullptr; + ErrCode ret = ERR_INVALID_VALUE; + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "context is nullptr"); + ret = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = EtsErrorUtil::CreateError(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); + return; + } + ret = context->TerminateAbility(); + AppExecFwk::AsyncCallback(env, callback, + EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), nullptr); +} + +void EtsServiceExtensionContext::OnStartServiceExtensionAbility( + ani_env *env, ani_object aniObj, ani_object wantObj, ani_object callbackobj) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "OnStartServiceExtensionAbility"); + ani_object aniObject = nullptr; + ErrCode ret = ERR_OK; + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "context is nullptr"); + ret = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = EtsErrorUtil::CreateError(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callbackobj, aniObject, nullptr); + return; + } + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "UnwrapWant failed"); + aniObject = EtsErrorUtil::CreateInvalidParamError(env, "UnwrapWant failed"); + AppExecFwk::AsyncCallback(env, callbackobj, aniObject, nullptr); + return; + } + ret = context->StartServiceExtensionAbility(want); + aniObject = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callbackobj, aniObject, nullptr); +} + +void EtsServiceExtensionContext::OnStopServiceExtensionAbility( + ani_env *env, ani_object aniObj, ani_object wantObj, ani_object callbackobj) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "OnStopServiceExtensionAbility"); + ani_object aniObject = nullptr; + ErrCode ret = ERR_OK; + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "context is nullptr"); + ret = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = EtsErrorUtil::CreateError(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callbackobj, aniObject, nullptr); + return; + } + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "UnwrapWant failed"); + aniObject = EtsErrorUtil::CreateInvalidParamError(env, "UnwrapWant failed"); + AppExecFwk::AsyncCallback(env, callbackobj, aniObject, nullptr); + return; + } + ret = context->StopServiceExtensionAbility(want); + aniObject = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callbackobj, aniObject, nullptr); +} + +void EtsServiceExtensionContext::OnStartAbility( + ani_env *env, ani_object aniObj, ani_object wantObj, ani_object opt, ani_object callbackObj) +{ + ani_object aniObject = nullptr; + AAFwk::Want want; + ErrCode errCode = ERR_OK; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + aniObject = EtsErrorUtil::CreateInvalidParamError(env, "UnwrapWant filed"); + AppExecFwk::AsyncCallback(env, callbackObj, aniObject, nullptr); + return; + } + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "context is nullptr"); + errCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = EtsErrorUtil::CreateError(env, static_cast(errCode)); + AppExecFwk::AsyncCallback(env, callbackObj, aniObject, nullptr); + return; + } + if ((want.GetFlags() & AAFwk::Want::FLAG_INSTALL_ON_DEMAND) == AAFwk::Want::FLAG_INSTALL_ON_DEMAND) { + std::string startTime = std::to_string( + std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) + .count()); + want.SetParam(AAFwk::Want::PARAM_RESV_START_TIME, startTime); + AddFreeInstallObserver(env, want, callbackObj, context); + } + if (opt != nullptr) { + AAFwk::StartOptions startOptions; + if (!AppExecFwk::UnwrapStartOptions(env, opt, startOptions)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "UnwrapStartOptions filed"); + aniObject = EtsErrorUtil::CreateInvalidParamError(env, "UnwrapWant filed"); + AppExecFwk::AsyncCallback(env, callbackObj, aniObject, nullptr); + return; + } + errCode = context->StartAbility(want, startOptions); + } else { + errCode = context->StartAbility(want); + } + aniObject = EtsErrorUtil::CreateErrorByNativeErr(env, errCode); + if ((want.GetFlags() & AAFwk::Want::FLAG_INSTALL_ON_DEMAND) == AAFwk::Want::FLAG_INSTALL_ON_DEMAND) { + if (errCode != ERR_OK && freeInstallObserver_ != nullptr) { + std::string bundleName = want.GetElement().GetBundleName(); + std::string abilityName = want.GetElement().GetAbilityName(); + std::string startTime = want.GetStringParam(AAFwk::Want::PARAM_RESV_START_TIME); + freeInstallObserver_->OnInstallFinished(bundleName, abilityName, startTime, errCode); + } + } else { + AppExecFwk::AsyncCallback(env, callbackObj, aniObject, nullptr); + } +} + +void EtsServiceExtensionContext::AddFreeInstallObserver( + ani_env *env, const AAFwk::Want &want, ani_object callbackObj, std::shared_ptr context) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "AddFreeInstallObserver"); + if (!context) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); + return; + } + if (!env) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return; + } + if (freeInstallObserver_ == nullptr) { + ani_vm *etsVm = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GetVM(&etsVm)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status : %{public}d", status); + return; + } + freeInstallObserver_ = new EtsFreeInstallObserver(etsVm); + if (context->AddFreeInstallObserver(freeInstallObserver_)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "addFreeInstallObserver error"); + return; + } + } + std::string startTime = want.GetStringParam(AAFwk::Want::PARAM_RESV_START_TIME); + TAG_LOGD(AAFwkTag::SERVICE_EXT, "addEtsObserver"); + std::string bundleName = want.GetElement().GetBundleName(); + std::string abilityName = want.GetElement().GetAbilityName(); + freeInstallObserver_->AddEtsObserverObject(env, bundleName, abilityName, startTime, callbackObj); +} + +ani_object CreateEtsServiceExtensionContext(ani_env *env, std::shared_ptr context) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "CreateEtsServiceExtensionContext"); + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env or context"); + return nullptr; + } + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object contextObj = nullptr; + if ((env->FindClass(SERVICE_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to find class, status : %{public}d", status); + return nullptr; + } + if (!BindNativeMethods(env, cls)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to BindNativeMethods"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", "J:V", &method)) != ANI_OK || method == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to find constructor, status : %{public}d", status); + return nullptr; + } + std::unique_ptr workContext = std::make_unique(context); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to create etsServiceExtensionContext"); + return nullptr; + } + auto serviceContextPtr = new std::weak_ptr (workContext->GetAbilityContext()); + if ((status = env->Object_New(cls, method, &contextObj, (ani_long)workContext.release())) != ANI_OK || + contextObj == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to create object, status : %{public}d", status); + return nullptr; + } + if (!ContextUtil::SetNativeContextLong(env, contextObj, (ani_long)(serviceContextPtr))) { + TAG_LOGE(AAFwkTag::CONTEXT, "Failed to setNativeContextLong "); + return nullptr; + } + ContextUtil::CreateEtsBaseContext(env, cls, contextObj, context); + CreateEtsExtensionContext(env, cls, contextObj, context, context->GetAbilityInfo()); + return contextObj; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/interfaces/kits/native/ability/native/ability_runtime/ets_ability_context.h b/frameworks/ets/ani/ui_ability/include/ets_ability_context.h similarity index 60% rename from interfaces/kits/native/ability/native/ability_runtime/ets_ability_context.h rename to frameworks/ets/ani/ui_ability/include/ets_ability_context.h index a19b99d66d7..8274dcf504a 100644 --- a/interfaces/kits/native/ability/native/ability_runtime/ets_ability_context.h +++ b/frameworks/ets/ani/ui_ability/include/ets_ability_context.h @@ -17,22 +17,22 @@ #define OHOS_ABILITY_RUNTIME_SIMULATOR_ETS_ABILITY_CONTEXT_H #include "ability_context.h" +#include "ability_manager_client.h" #include "ani.h" #include "configuration.h" #include "ets_free_install_observer.h" #include "ets_runtime.h" #include "ohos_application.h" +#include "open_link_options.h" namespace OHOS { namespace AbilityRuntime { using OHOSApplication = AppExecFwk::OHOSApplication; class EtsAbilityContext final { public: - static EtsAbilityContext &GetInstance() - { - static EtsAbilityContext instance; - return instance; - } + explicit EtsAbilityContext(std::shared_ptr context) : context_(std::move(context)) {} + ~EtsAbilityContext() = default; + static void StartAbility(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object call); static void StartAbilityWithOptions( ani_env *env, ani_object aniObj, ani_object wantObj, ani_object opt, ani_object call); @@ -42,12 +42,20 @@ public: static void TerminateSelf(ani_env *env, ani_object aniObj, ani_object callback); static void TerminateSelfWithResult(ani_env *env, ani_object aniObj, ani_object abilityResult, ani_object callback); static void ReportDrawnCompleted(ani_env *env, ani_object aniObj, ani_object call); + static void StartServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callbackobj); + static void OpenLink(ani_env *env, ani_object aniObj, ani_string aniLink, + ani_object myCallbackobj, ani_object optionsObj, ani_object callbackobj); + static bool IsTerminating(ani_env *env, ani_object aniObj); + static void MoveAbilityToBackground(ani_env *env, ani_object aniObj, ani_object callbackobj); + static void RequestModalUIExtension(ani_env *env, ani_object aniObj, ani_object pickerWantObj, + ani_object callbackobj); - static ani_object SetAbilityContext(ani_env *env, const std::shared_ptr &context); - static std::shared_ptr GetAbilityContext(ani_env *env, ani_object aniObj); + static void Clean(ani_env *env, ani_object object); + static ani_object SetEtsAbilityContext(ani_env *env, std::shared_ptr context); + static EtsAbilityContext *GetEtsAbilityContext(ani_env *env, ani_object aniObj); private: - static bool AsyncCallback(ani_env *env, ani_object call, ani_object error, ani_object result); void InheritWindowMode(ani_env *env, ani_object aniObj, AAFwk::Want &want); void OnStartAbility(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object opt, ani_object call); void OnStartAbilityForResult( @@ -59,14 +67,27 @@ private: const std::shared_ptr &context, bool isAbilityResult = false, bool isOpenLink = false); void StartAbilityForResultInner(ani_env *env, const AAFwk::StartOptions &startOptions, AAFwk::Want &want, std::shared_ptr context, ani_object startOptionsObj, ani_object callback); + void OnStartServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callbackobj); + void OnOpenLink(ani_env *env, ani_object aniObj, ani_string aniLink, ani_object myCallbackobj, + ani_object optionsObj, ani_object callbackobj, bool haveOptionsParm, bool haveCallBackParm); + bool OnIsTerminating(ani_env *env, ani_object aniObj); + void OnMoveAbilityToBackground(ani_env *env, ani_object aniObj, ani_object callback); + void OnRequestModalUIExtension(ani_env *env, ani_object aniObj, ani_object pickerWantObj, + ani_object callbackObj); + + void UnWrapOpenLinkOptions(ani_env *env, ani_object optionsObj, AAFwk::OpenLinkOptions &openLinkOptions, + AAFwk::Want &want); + void CreateOpenLinkTask(ani_env *env, const ani_object callbackobj, + std::shared_ptr context, AAFwk::Want &want, int &requestCode); int32_t GenerateRequestCode(); + std::weak_ptr context_; static std::mutex requestCodeMutex_; sptr freeInstallObserver_ = nullptr; }; -ani_object CreateEtsAbilityContext( - ani_env *env, const std::shared_ptr &context, const std::shared_ptr &application); +ani_object CreateEtsAbilityContext(ani_env *env, std::shared_ptr context); } // namespace AbilityRuntime } // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_SIMULATOR_ETS_ABILITY_CONTEXT_H diff --git a/interfaces/kits/native/ability/native/ability_runtime/ets_ui_ability.h b/frameworks/ets/ani/ui_ability/include/ets_ui_ability.h similarity index 74% rename from interfaces/kits/native/ability/native/ability_runtime/ets_ui_ability.h rename to frameworks/ets/ani/ui_ability/include/ets_ui_ability.h index a1d5363a859..379ca759485 100644 --- a/interfaces/kits/native/ability/native/ability_runtime/ets_ui_ability.h +++ b/frameworks/ets/ani/ui_ability/include/ets_ui_ability.h @@ -24,10 +24,14 @@ namespace OHOS { namespace AbilityRuntime { +struct InsightIntentExecutorInfo; using AbilityHandler = AppExecFwk::AbilityHandler; using AbilityInfo = AppExecFwk::AbilityInfo; using OHOSApplication = AppExecFwk::OHOSApplication; using Want = AppExecFwk::Want; +using InsightIntentExecuteResult = AppExecFwk::InsightIntentExecuteResult; +using InsightIntentExecuteParam = AppExecFwk::InsightIntentExecuteParam; +using InsightIntentExecutorAsyncCallback = AppExecFwk::InsightIntentExecutorAsyncCallback; class EtsUIAbility : public UIAbility { public: @@ -109,12 +113,24 @@ public: */ void OnSceneCreated() override; + /** + * @brief Called after ability stoped. + * You can override this function to implement your own processing logic. + */ + void OnSceneWillDestroy() override; + /** * @brief Called after ability stoped. * You can override this function to implement your own processing logic. */ void onSceneDestroyed() override; + /** + * @brief Called after ability restored. + * You can override this function to implement your own processing logic. + */ + void OnSceneRestored() override; + /** * @brief Called when this ability enters the STATE_FOREGROUND state. * The ability in the STATE_FOREGROUND state is visible. @@ -136,6 +152,39 @@ public: */ void OnBackground() override; + /** + * @brief Execute insight intent when an ability is in foreground, schedule it to foreground repeatly. + * + * @param want Want. + * @param executeParam insight intent execute param. + * @param callback insight intent async callback. + */ + void ExecuteInsightIntentRepeateForeground(const Want &want, + const std::shared_ptr &executeParam, + std::unique_ptr callback) override; + + /** + * @brief Execute insight intent when an ability didn't started or in background, schedule it to foreground. + * + * @param want Want. + * @param executeParam insight intent execute param. + * @param callback insight intent async callback. + */ + void ExecuteInsightIntentMoveToForeground(const Want &want, + const std::shared_ptr &executeParam, + std::unique_ptr callback) override; + + /** + * @brief Execute insight intent when an ability didn't started, schedule it to background. + * + * @param want Want. + * @param executeParam insight intent execute param. + * @param callback insight intent async callback. + */ + virtual void ExecuteInsightIntentBackground(const AAFwk::Want &want, + const std::shared_ptr &executeParam, + std::unique_ptr callback) override; + protected: void DoOnForeground(const Want &want) override; void ContinuationRestore(const Want &want) override; @@ -146,6 +195,9 @@ private: void GetPageStackFromWant(const Want &want, std::string &pageStack); void AbilityContinuationOrRecover(const Want &want); void UpdateEtsWindowStage(ani_ref windowStage); + inline bool GetInsightIntentExecutorInfo(const Want &want, + const std::shared_ptr &executeParam, + InsightIntentExecutorInfo& executeInfo); std::shared_ptr etsWindowStageObj_; int32_t windowMode_ = 0; @@ -154,13 +206,13 @@ private: private: bool CallObjectMethod(bool withResult, const char *name, const char *signature, ...); ani_object CreateAppWindowStage(); - std::shared_ptr CreateADelegatorAbilityProperty(); + std::shared_ptr CreateADelegatorAbilityProperty(); void SetAbilityContext(std::shared_ptr abilityInfo, std::shared_ptr want, - const std::string &moduleName, const std::string &srcPath, const std::shared_ptr &application); + const std::string &moduleName, const std::string &srcPath); void DoOnForegroundForSceneIsNull(const Want &want); void UpdateAbilityObj(std::shared_ptr abilityInfo, const std::string &moduleName, const std::string &srcPath); - void CreateEtsContext(int32_t screenMode, const std::shared_ptr &application); + void CreateEtsContext(int32_t screenMode); bool BindNativeMethods(); ETSRuntime &etsRuntime_; diff --git a/frameworks/native/ability/native/ability_runtime/ets_ability_context.cpp b/frameworks/ets/ani/ui_ability/src/ets_ability_context.cpp similarity index 47% rename from frameworks/native/ability/native/ability_runtime/ets_ability_context.cpp rename to frameworks/ets/ani/ui_ability/src/ets_ability_context.cpp index 37593fa719e..173ee2e5d2d 100644 --- a/frameworks/native/ability/native/ability_runtime/ets_ability_context.cpp +++ b/frameworks/ets/ani/ui_ability/src/ets_ability_context.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "ability_runtime/ets_ability_context.h" +#include "ets_ability_context.h" #include "ani_common_ability_result.h" #include "ani_common_configuration.h" @@ -32,70 +32,110 @@ namespace AbilityRuntime { std::mutex EtsAbilityContext::requestCodeMutex_; namespace { static std::once_flag g_bindNativeMethodsFlag; -constexpr const char *UI_ABILITY_CONTEXT_CLASS_NAME = "Lapplication/UIAbilityContext/UIAbilityContext;"; -constexpr const char *CLASSNAME_ASYNC_CALLBACK_WRAPPER = "Lutils/AbilityUtils/AsyncCallbackWrapper;"; +constexpr const char* UI_ABILITY_CONTEXT_CLASS_NAME = "Lapplication/UIAbilityContext/UIAbilityContext;"; +constexpr const char* CLEANER_CLASS = "Lapplication/UIAbilityContext/Cleaner;"; +const std::string APP_LINKING_ONLY = "appLinkingOnly"; +constexpr const char* SIGNATURE_OPEN_LINK = "Lstd/core/String;Lutils/AbilityUtils/AsyncCallbackWrapper;" + "L@ohos/app/ability/OpenLinkOptions/OpenLinkOptions;Lutils/AbilityUtils/AsyncCallbackWrapper;:V"; } // namespace -std::shared_ptr EtsAbilityContext::GetAbilityContext(ani_env *env, ani_object aniObj) +void EtsAbilityContext::Clean(ani_env *env, ani_object object) { - if (env == nullptr || aniObj == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null env or aniObj"); - return nullptr; + TAG_LOGD(AAFwkTag::CONTEXT, "Clean called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null env"); + return; } - ani_long nativeContextLong; - ani_status status = env->Object_GetFieldByName_Long(aniObj, "nativeContext", &nativeContextLong); + ani_long ptr = 0; + ani_status status = env->Object_GetFieldByName_Long(object, "ptr", &ptr); if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::CONTEXT, "Object_GetFieldByName_Long status: %{public}d", status); - return nullptr; + TAG_LOGE(AAFwkTag::CONTEXT, "ptr GetField status: %{public}d", status); + return; + } + if (ptr != 0) { + delete reinterpret_cast(ptr); } - auto weakContext = reinterpret_cast *>(nativeContextLong); - return weakContext != nullptr ? weakContext->lock() : nullptr; } -ani_object EtsAbilityContext::SetAbilityContext(ani_env *env, const std::shared_ptr &context) +ani_object EtsAbilityContext::SetEtsAbilityContext(ani_env *env, std::shared_ptr context) { if (env == nullptr || context == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "null env or context"); return nullptr; } ani_class cls = nullptr; - ani_object contextObj = nullptr; - ani_method method = nullptr; ani_status status = env->FindClass(UI_ABILITY_CONTEXT_CLASS_NAME, &cls); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::CONTEXT, "FindClass status: %{public}d", status); + if (status != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "FindClass status: %{public}d, or null cls", status); return nullptr; } - if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { - TAG_LOGE(AAFwkTag::CONTEXT, "Class_FindMethod status: %{public}d", status); + ani_method method = nullptr; + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK || + method == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "ctor FindMethod status: %{public}d, or null method", status); return nullptr; } - if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { - TAG_LOGE(AAFwkTag::CONTEXT, "Object_New status: %{public}d", status); + ani_object contextObj = nullptr; + if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK || contextObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "Object_New status: %{public}d, or null contextObj", status); return nullptr; } - auto workContext = new (std::nothrow) std::weak_ptr(context); + if ((status = env->Class_FindMethod(cls, "setEtsAbilityContextPtr", "J:V", &method)) != ANI_OK || + method == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "setEtsAbilityContextPtr FindMethod status: %{public}d, or null method", status); + return nullptr; + } + std::unique_ptr etsContext = std::make_unique(context); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return nullptr; + } + auto workContext = new (std::nothrow) std::weak_ptr(etsContext->context_); if (workContext == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "workContext nullptr"); + TAG_LOGE(AAFwkTag::CONTEXT, "null workContext"); return nullptr; } - ani_long nativeContextLong = (ani_long)workContext; - if ((status = env->Object_SetFieldByName_Long(contextObj, "nativeContext", nativeContextLong)) != ANI_OK) { - TAG_LOGE(AAFwkTag::CONTEXT, "Object_SetFieldByName_Long status: %{public}d", status); + if (!ContextUtil::SetNativeContextLong(env, contextObj, (ani_long)workContext)) { + TAG_LOGE(AAFwkTag::CONTEXT, "SetNativeContextLong failed"); + delete workContext; + return nullptr; + } + if ((status = env->Object_CallMethod_Void(contextObj, method, (ani_long)etsContext.release())) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "call contextObj method failed, status : %{public}d", status); delete workContext; - workContext = nullptr; return nullptr; } return contextObj; } +EtsAbilityContext* EtsAbilityContext::GetEtsAbilityContext(ani_env *env, ani_object aniObj) +{ + if (env == nullptr || aniObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null env or aniObj"); + return nullptr; + } + ani_long etsAbilityContextPtr = 0; + ani_status status = env->Object_GetFieldByName_Long(aniObj, "etsAbilityContextPtr", &etsAbilityContextPtr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "etsAbilityContextPtr GetField status: %{public}d", status); + return nullptr; + } + auto etsContext = reinterpret_cast(etsAbilityContextPtr); + return etsContext; +} + // to be done: free install void EtsAbilityContext::StartAbility(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object call) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); TAG_LOGD(AAFwkTag::CONTEXT, "StartAbility called"); - GetInstance().OnStartAbility(env, aniObj, wantObj, nullptr, call); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnStartAbility(env, aniObj, wantObj, nullptr, call); } void EtsAbilityContext::StartAbilityWithOptions( @@ -103,14 +143,24 @@ void EtsAbilityContext::StartAbilityWithOptions( { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); TAG_LOGD(AAFwkTag::CONTEXT, "StartAbilityWithOptions called"); - GetInstance().OnStartAbility(env, aniObj, wantObj, opt, call); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnStartAbility(env, aniObj, wantObj, opt, call); } // to be done: free install void EtsAbilityContext::StartAbilityForResult(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object callback) { TAG_LOGD(AAFwkTag::CONTEXT, "StartAbilityForResult called"); - GetInstance().OnStartAbilityForResult(env, aniObj, wantObj, nullptr, callback); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnStartAbilityForResult(env, aniObj, wantObj, nullptr, callback); } // to be done: free install @@ -118,26 +168,114 @@ void EtsAbilityContext::StartAbilityForResultWithOptions( ani_env *env, ani_object aniObj, ani_object wantObj, ani_object startOptionsObj, ani_object callback) { TAG_LOGD(AAFwkTag::CONTEXT, "StartAbilityForResultWithOptions called"); - GetInstance().OnStartAbilityForResult(env, aniObj, wantObj, startOptionsObj, callback); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnStartAbilityForResult(env, aniObj, wantObj, startOptionsObj, callback); } void EtsAbilityContext::TerminateSelf(ani_env *env, ani_object aniObj, ani_object callback) { TAG_LOGD(AAFwkTag::CONTEXT, "TerminateSelf called"); - GetInstance().OnTerminateSelf(env, aniObj, callback); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnTerminateSelf(env, aniObj, callback); } void EtsAbilityContext::TerminateSelfWithResult( ani_env *env, ani_object aniObj, ani_object abilityResult, ani_object callback) { TAG_LOGD(AAFwkTag::CONTEXT, "TerminateSelfWithResult called"); - GetInstance().OnTerminateSelfWithResult(env, aniObj, abilityResult, callback); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnTerminateSelfWithResult(env, aniObj, abilityResult, callback); } void EtsAbilityContext::ReportDrawnCompleted(ani_env *env, ani_object aniObj, ani_object callback) { TAG_LOGD(AAFwkTag::CONTEXT, "ReportDrawnCompleted called"); - GetInstance().OnReportDrawnCompleted(env, aniObj, callback); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnReportDrawnCompleted(env, aniObj, callback); +} + +void EtsAbilityContext::StartServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callbackobj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "StartServiceExtensionAbility called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnStartServiceExtensionAbility(env, aniObj, wantObj, callbackobj); +} + +void EtsAbilityContext::OpenLink(ani_env *env, ani_object aniObj, ani_string aniLink, + ani_object myCallbackobj, ani_object optionsObj, ani_object callbackobj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "OpenLink called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + ani_status status = ANI_ERROR; + ani_boolean isOptionsUndefined = true; + if ((status = env->Reference_IsUndefined(optionsObj, &isOptionsUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + } + ani_boolean isCallbackUndefined = true; + if ((status = env->Reference_IsUndefined(callbackobj, &isCallbackUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + } + etsContext->OnOpenLink(env, aniObj, aniLink, myCallbackobj, optionsObj, callbackobj, isOptionsUndefined, + isCallbackUndefined); +} + +bool EtsAbilityContext::IsTerminating(ani_env *env, ani_object aniObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "IsTerminating called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return false; + } + return etsContext->OnIsTerminating(env, aniObj); +} + +void EtsAbilityContext::MoveAbilityToBackground(ani_env *env, ani_object aniObj, ani_object callbackobj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "MoveAbilityToBackground called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnMoveAbilityToBackground(env, aniObj, callbackobj); +} + +void EtsAbilityContext::RequestModalUIExtension(ani_env *env, ani_object aniObj, ani_object pickerWantObj, + ani_object callbackobj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "RequestModalUIExtension called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnRequestModalUIExtension(env, aniObj, pickerWantObj, callbackobj); } int32_t EtsAbilityContext::GenerateRequestCode() @@ -153,7 +291,7 @@ void EtsAbilityContext::InheritWindowMode(ani_env *env, ani_object aniObj, AAFwk TAG_LOGD(AAFwkTag::CONTEXT, "InheritWindowMode"); #ifdef SUPPORT_SCREEN // only split mode need inherit - auto context = GetAbilityContext(env, aniObj); + auto context = context_.lock(); if (context == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "context null"); return; @@ -168,52 +306,17 @@ void EtsAbilityContext::InheritWindowMode(ani_env *env, ani_object aniObj, AAFwk #endif } -bool EtsAbilityContext::AsyncCallback(ani_env *env, ani_object call, ani_object error, ani_object result) -{ - if (env == nullptr || call == nullptr) { - TAG_LOGE(AAFwkTag::JSNAPI, "env or call is nullptr"); - return false; - } - ani_class clsCall = nullptr; - ani_status status = env->FindClass(CLASSNAME_ASYNC_CALLBACK_WRAPPER, &clsCall); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::CONTEXT, "FindClass status: %{public}d", status); - return false; - } - ani_method method = nullptr; - if ((status = env->Class_FindMethod(clsCall, "invoke", "L@ohos/base/BusinessError;Lstd/core/Object;:V", &method)) != - ANI_OK) { - TAG_LOGE(AAFwkTag::CONTEXT, "Class_FindMethod status: %{public}d", status); - return false; - } - if (error == nullptr) { - ani_ref nullRef = nullptr; - env->GetNull(&nullRef); - error = reinterpret_cast(nullRef); - } - if (result == nullptr) { - ani_ref undefinedRef = nullptr; - env->GetUndefined(&undefinedRef); - result = reinterpret_cast(undefinedRef); - } - if ((status = env->Object_CallMethod_Void(call, method, error, result)) != ANI_OK) { - TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); - return false; - } - return true; -} - void EtsAbilityContext::OnStartAbility( ani_env *env, ani_object aniObj, ani_object wantObj, ani_object opt, ani_object call) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); AAFwk::Want want; - if (!OHOS::AppExecFwk::UnwrapWant(env, wantObj, want)) { + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { EtsErrorUtil::ThrowInvalidParamError(env, "Parse param want failed, must be a Want"); return; } InheritWindowMode(env, aniObj, want); - auto context = EtsAbilityContext::GetAbilityContext(env, aniObj); + auto context = context_.lock(); if (context == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "null context"); EtsErrorUtil::ThrowInvalidParamError(env, "null context"); @@ -229,7 +332,7 @@ void EtsAbilityContext::OnStartAbility( ErrCode innerErrCode = ERR_OK; if (opt != nullptr) { AAFwk::StartOptions startOptions; - if (!OHOS::AppExecFwk::UnwrapStartOptions(env, opt, startOptions)) { + if (!AppExecFwk::UnwrapStartOptionsWithProcessOption(env, opt, startOptions)) { EtsErrorUtil::ThrowInvalidParamError(env, "Parse param startOptions failed, startOptions must be StartOptions."); TAG_LOGE(AAFwkTag::CONTEXT, "invalid options"); @@ -249,23 +352,23 @@ void EtsAbilityContext::OnStartAbility( } return; } - AsyncCallback(env, call, aniObject, nullptr); + AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); } void EtsAbilityContext::OnStartAbilityForResult( ani_env *env, ani_object aniObj, ani_object wantObj, ani_object startOptionsObj, ani_object callback) { - auto context = EtsAbilityContext::GetAbilityContext(env, aniObj); + auto context = context_.lock(); if (context == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "GetAbilityContext is nullptr"); EtsErrorUtil::ThrowErrorByNativeErr(env, static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)); return; } AAFwk::Want want; - OHOS::AppExecFwk::UnwrapWant(env, wantObj, want); + AppExecFwk::UnwrapWant(env, wantObj, want); AAFwk::StartOptions startOptions; if (startOptionsObj) { - OHOS::AppExecFwk::UnwrapStartOptions(env, startOptionsObj, startOptions); + AppExecFwk::UnwrapStartOptions(env, startOptionsObj, startOptions); } TAG_LOGE(AAFwkTag::CONTEXT, "displayId:%{public}d", startOptions.GetDisplayID()); StartAbilityForResultInner(env, startOptions, want, context, startOptionsObj, callback); @@ -313,8 +416,8 @@ void EtsAbilityContext::StartAbilityForResultInner(ani_env *env, const AAFwk::St return; } auto errCode = isInner ? resultCode : 0; - AsyncCallback(env, reinterpret_cast(callbackRef), - OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, errCode), abilityResult); + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + EtsErrorUtil::CreateErrorByNativeErr(env, errCode), abilityResult); }; auto requestCode = GenerateRequestCode(); (startOptionsObj == nullptr) ? context->StartAbilityForResult(want, requestCode, std::move(task)) @@ -327,15 +430,15 @@ void EtsAbilityContext::OnTerminateSelf(ani_env *env, ani_object aniObj, ani_obj if (env == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "null env or aniObj"); ani_object aniObject = EtsErrorUtil::CreateInvalidParamError(env, "env null"); - AsyncCallback(env, callback, aniObject, nullptr); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); return; } ani_object aniObject = nullptr; - auto context = EtsAbilityContext::GetAbilityContext(env, aniObj); + auto context = context_.lock(); if (context == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "null context"); aniObject = EtsErrorUtil::CreateInvalidParamError(env, "context null"); - AsyncCallback(env, callback, aniObject, nullptr); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); return; } ErrCode ret = context->TerminateSelf(); @@ -344,7 +447,7 @@ void EtsAbilityContext::OnTerminateSelf(ani_env *env, ani_object aniObj, ani_obj } else { aniObject = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)); } - AsyncCallback(env, callback, aniObject, nullptr); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); } void EtsAbilityContext::OnTerminateSelfWithResult( @@ -353,20 +456,20 @@ void EtsAbilityContext::OnTerminateSelfWithResult( if (env == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "null env"); ani_object aniObject = EtsErrorUtil::CreateInvalidParamError(env, "env null"); - AsyncCallback(env, callback, aniObject, nullptr); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); return; } ani_object aniObject = nullptr; - auto context = EtsAbilityContext::GetAbilityContext(env, aniObj); + auto context = context_.lock(); if (context == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "GetAbilityContext is nullptr"); aniObject = EtsErrorUtil::CreateInvalidParamError(env, "context null"); - AsyncCallback(env, callback, aniObject, nullptr); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); return; } AAFwk::Want want; int resultCode = 0; - OHOS::AppExecFwk::UnWrapAbilityResult(env, abilityResult, resultCode, want); + AppExecFwk::UnWrapAbilityResult(env, abilityResult, resultCode, want); context->SetTerminating(true); ErrCode ret = context->TerminateAbilityWithResult(want, resultCode); if (ret == static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT) || ret == ERR_OK) { @@ -374,7 +477,7 @@ void EtsAbilityContext::OnTerminateSelfWithResult( } else { aniObject = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)); } - AsyncCallback(env, callback, aniObject, nullptr); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); } void EtsAbilityContext::OnReportDrawnCompleted(ani_env *env, ani_object aniObj, ani_object callback) @@ -382,15 +485,15 @@ void EtsAbilityContext::OnReportDrawnCompleted(ani_env *env, ani_object aniObj, if (env == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "null env"); ani_object aniObject = EtsErrorUtil::CreateInvalidParamError(env, "env null"); - AsyncCallback(env, callback, aniObject, nullptr); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); return; } ani_object aniObject = nullptr; - auto context = GetAbilityContext(env, aniObj); + auto context = context_.lock(); if (context == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "context null"); aniObject = EtsErrorUtil::CreateInvalidParamError(env, "context null"); - AsyncCallback(env, callback, aniObject, nullptr); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); return; } ErrCode ret = context->ReportDrawnCompleted(); @@ -399,7 +502,135 @@ void EtsAbilityContext::OnReportDrawnCompleted(ani_env *env, ani_object aniObj, } else { aniObject = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)); } - AsyncCallback(env, callback, aniObject, nullptr); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); +} + +void EtsAbilityContext::OnStartServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callbackobj) +{ + ani_object errorObject = nullptr; + ErrCode ret = ERR_OK; + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "context is nullptr"); + ret = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + errorObject = EtsErrorUtil::CreateError(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callbackobj, errorObject, nullptr); + return; + } + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::CONTEXT, "UnwrapWant filed"); + errorObject = EtsErrorUtil::CreateInvalidParamError(env, "UnwrapWant filed"); + AppExecFwk::AsyncCallback(env, callbackobj, errorObject, nullptr); + } + ret = context->StartServiceExtensionAbility(want); + if (ret == ERR_OK) { + errorObject = EtsErrorUtil::CreateError(env, static_cast(ret)); + } else { + errorObject = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)); + } + AppExecFwk::AsyncCallback(env, callbackobj, errorObject, nullptr); +} + +void EtsAbilityContext::OnOpenLink(ani_env *env, ani_object aniObj, ani_string aniLink, ani_object myCallbackobj, + ani_object optionsObj, ani_object callbackobj, bool haveOptionsParm, bool haveCallBackParm) +{ + ani_object aniObject = nullptr; + std::string link(""); + AAFwk::OpenLinkOptions openLinkOptions; + AAFwk::Want want; + want.SetParam(APP_LINKING_ONLY, false); + if (!AppExecFwk::GetStdString(env, aniLink, link)) { + TAG_LOGE(AAFwkTag::CONTEXT, "parse link failed"); + aniObject = EtsErrorUtil::CreateInvalidParamError(env, "Parse param link failed, link must be string."); + AppExecFwk::AsyncCallback(env, myCallbackobj, aniObject, nullptr); + return; + } + if (haveOptionsParm) { + TAG_LOGD(AAFwkTag::CONTEXT, "OpenLink Have option"); + EtsAbilityContext::UnWrapOpenLinkOptions(env, optionsObj, openLinkOptions, want); + } + want.SetUri(link); + std::string startTime = std::to_string(std::chrono::duration_cast(std::chrono:: + system_clock::now().time_since_epoch()).count()); + want.SetParam(AAFwk::Want::PARAM_RESV_START_TIME, startTime); + int requestCode = -1; + ErrCode ret = ERR_OK; + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "GetAbilityContext is nullptr"); + ret = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = EtsErrorUtil::CreateError(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, myCallbackobj, aniObject, nullptr); + return; + } + AddFreeInstallObserver(env, want, myCallbackobj, context, false, true); + if (haveCallBackParm) { + TAG_LOGD(AAFwkTag::CONTEXT, "OpenLink Have Callback"); + CreateOpenLinkTask(env, callbackobj, context, want, requestCode); + } + ret = context->OpenLink(want, requestCode); + if (ret == AAFwk::ERR_OPEN_LINK_START_ABILITY_DEFAULT_OK) { + aniObject = EtsErrorUtil::CreateError(env, static_cast(ERR_OK)); + } else { + aniObject = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)); + } + AppExecFwk::AsyncCallback(env, myCallbackobj, aniObject, nullptr); +} + +bool EtsAbilityContext::OnIsTerminating(ani_env *env, ani_object aniObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "NativeIsTerminating"); + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return false; + } + return context->IsTerminating(); +} + +void EtsAbilityContext::OnMoveAbilityToBackground(ani_env *env, ani_object aniObj, ani_object callback) +{ + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + AppExecFwk::AsyncCallback(env, callback, + EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)), nullptr); + return; + } + ErrCode ret = ERR_OK; + ani_object errorObject = nullptr; + ret = context->MoveUIAbilityToBackground(); + errorObject = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callback, errorObject, nullptr); +} + +void EtsAbilityContext::OnRequestModalUIExtension(ani_env *env, ani_object aniObj, ani_object pickerWantObj, + ani_object callbackObj) +{ + ani_object errorObject = nullptr; + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, pickerWantObj, want)) { + TAG_LOGE(AAFwkTag::CONTEXT, "parse want failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param want failed, want must be Want."); + return; + } + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + errorObject = EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)); + AppExecFwk::AsyncCallback(env, callbackObj, errorObject, nullptr); + return; + } + + ErrCode ret = ERR_OK; + ret = AAFwk::AbilityManagerClient::GetInstance()->RequestModalUIExtension(want); + errorObject = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callbackObj, errorObject, nullptr); } void EtsAbilityContext::AddFreeInstallObserver(ani_env *env, const AAFwk::Want &want, ani_object callback, @@ -445,6 +676,69 @@ void EtsAbilityContext::AddFreeInstallObserver(ani_env *env, const AAFwk::Want & freeInstallObserver_->AddEtsObserverObject(env, bundleName, abilityName, startTime, callback, isAbilityResult); } +void EtsAbilityContext::UnWrapOpenLinkOptions(ani_env *env, ani_object optionsObj, + AAFwk::OpenLinkOptions &openLinkOptions, AAFwk::Want &want) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "UnWrapOpenLinkOptions"); + ani_status status = ANI_ERROR; + ani_ref ParamRef = nullptr; + if ((status = env->Object_GetPropertyByName_Ref(optionsObj, "parameters", &ParamRef)) == ANI_OK) { + AAFwk::WantParams wantParam; + if (AppExecFwk::UnwrapWantParams(env, ParamRef, wantParam)) { + want.SetParams(wantParam); + } else { + TAG_LOGE(AAFwkTag::CONTEXT, "UnwrapWantParams failed"); + } + } + if ((status = env->Object_GetPropertyByName_Ref(optionsObj, APP_LINKING_ONLY.c_str(), &ParamRef)) == ANI_OK) { + bool appLinkingOnly = false; + AppExecFwk::GetFieldBoolByName(env, optionsObj, "appLinkingOnly", appLinkingOnly); + openLinkOptions.SetAppLinkingOnly(appLinkingOnly); + want.SetParam(APP_LINKING_ONLY, appLinkingOnly); + } + if (!want.HasParameter(APP_LINKING_ONLY)) { + want.SetParam(APP_LINKING_ONLY, false); + } +} + +void EtsAbilityContext::CreateOpenLinkTask(ani_env *env, const ani_object callbackobj, + std::shared_ptr context, AAFwk::Want &want, int &requestCode) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "CreateOpenLinkTask"); + want.SetParam(AAFwk::Want::PARAM_RESV_FOR_RESULT, true); + ani_vm *etsVm = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GetVM(&etsVm)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return; + } + ani_ref callbackRef = nullptr; + if ((status = env->GlobalReference_Create(callbackobj, &callbackRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return; + } + RuntimeTask task = [etsVm, callbackRef] (int resultCode, const AAFwk::Want &want, bool isInner) { + TAG_LOGD(AAFwkTag::CONTEXT, "start async callback"); + ani_status status = ANI_ERROR; + ani_env *env = nullptr; + if ((status = etsVm->GetEnv(ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return; + } + ani_object abilityResult = AppExecFwk::WrapAbilityResult(env, resultCode, want); + if (abilityResult == nullptr) { + TAG_LOGW(AAFwkTag::CONTEXT, "null abilityResult"); + isInner = true; + resultCode = ERR_INVALID_VALUE; + } + auto errCode = isInner ? resultCode : 0; + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + EtsErrorUtil::CreateErrorByNativeErr(env, errCode), abilityResult); + }; + requestCode = GenerateRequestCode(); + context->InsertResultCallbackTask(requestCode, std::move(task)); +} + namespace { bool BindNativeMethods(ani_env *env, ani_class &cls) { @@ -456,29 +750,57 @@ bool BindNativeMethods(ani_env *env, ani_class &cls) std::call_once(g_bindNativeMethodsFlag, [&status, env, cls]() { std::array functions = { ani_native_function { "nativeStartAbilitySync", - "L@ohos/app/ability/Want/Want;Lapplication/UIAbilityContext/AsyncCallbackWrapper;:V", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", reinterpret_cast(EtsAbilityContext::StartAbility) }, ani_native_function { "nativeStartAbilitySync", - "L@ohos/app/ability/Want/Want;L@ohos/app/ability/StartOptions/StartOptions;Lapplication/" - "UIAbilityContext/AsyncCallbackWrapper;:V", + "L@ohos/app/ability/Want/Want;L@ohos/app/ability/StartOptions/StartOptions;Lutils/AbilityUtils/" + "AsyncCallbackWrapper;:V", reinterpret_cast(EtsAbilityContext::StartAbilityWithOptions) }, ani_native_function { "nativeStartAbilityForResult", - "L@ohos/app/ability/Want/Want;Lapplication/UIAbilityContext/AsyncCallbackWrapper;:V", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", reinterpret_cast(EtsAbilityContext::StartAbilityForResult) }, ani_native_function { "nativeStartAbilityForResult", - "L@ohos/app/ability/Want/Want;L@ohos/app/ability/StartOptions/StartOptions;Lapplication/" - "UIAbilityContext/AsyncCallbackWrapper;:V", + "L@ohos/app/ability/Want/Want;L@ohos/app/ability/StartOptions/StartOptions;Lutils/AbilityUtils/" + "AsyncCallbackWrapper;:V", reinterpret_cast(EtsAbilityContext::StartAbilityForResultWithOptions) }, - ani_native_function { "nativeTerminateSelfSync", "Lapplication/UIAbilityContext/AsyncCallbackWrapper;:V", + ani_native_function { "nativeTerminateSelfSync", "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", reinterpret_cast(EtsAbilityContext::TerminateSelf) }, ani_native_function { "nativeTerminateSelfWithResult", - "Lability/abilityResult/AbilityResult;Lapplication/UIAbilityContext/AsyncCallbackWrapper;:V", + "Lability/abilityResult/AbilityResult;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", reinterpret_cast(EtsAbilityContext::TerminateSelfWithResult) }, - ani_native_function { "nativeReportDrawnCompletedSync", - "Lapplication/UIAbilityContext/AsyncCallbackWrapper;:V", + ani_native_function { "nativeReportDrawnCompletedSync", "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", reinterpret_cast(EtsAbilityContext::ReportDrawnCompleted) }, + ani_native_function { "nativeStartServiceExtensionAbility", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAbilityContext::StartServiceExtensionAbility) }, + ani_native_function { "nativeOpenLink", SIGNATURE_OPEN_LINK, + reinterpret_cast(EtsAbilityContext::OpenLink) }, + ani_native_function { "nativeIsTerminating", ":Z", + reinterpret_cast(EtsAbilityContext::IsTerminating) }, + ani_native_function { "nativeMoveAbilityToBackground", "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAbilityContext::MoveAbilityToBackground) }, + ani_native_function { "nativeRequestModalUIExtension", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAbilityContext::RequestModalUIExtension) }, }; - status = env->Class_BindNativeMethods(cls, functions.data(), functions.size()); + if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "Class_BindNativeMethods failed status: %{public}d", status); + return; + } + + ani_class cleanerCls = nullptr; + if ((status = env->FindClass(CLEANER_CLASS, &cleanerCls)) != ANI_OK || cleanerCls == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "Cleaner FindClass failed status: %{public}d, or null cleanerCls", status); + return; + } + std::array cleanerMethods = { + ani_native_function {"clean", nullptr, reinterpret_cast(EtsAbilityContext::Clean) }, + }; + if ((status = env->Class_BindNativeMethods(cleanerCls, cleanerMethods.data(), cleanerMethods.size())) != + ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "cleanerCls Class_BindNativeMethods failed status: %{public}d", status); + return; + } }); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::CONTEXT, "Class_BindNativeMethods status: %{public}d", status); @@ -488,11 +810,10 @@ bool BindNativeMethods(ani_env *env, ani_class &cls) } } // namespace -ani_object CreateEtsAbilityContext( - ani_env *env, const std::shared_ptr &context, const std::shared_ptr &application) +ani_object CreateEtsAbilityContext(ani_env *env, std::shared_ptr context) { - if (env == nullptr || context == nullptr || application == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null env or context or application"); + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null env or context"); return nullptr; } ani_class cls = nullptr; @@ -500,7 +821,7 @@ ani_object CreateEtsAbilityContext( TAG_LOGE(AAFwkTag::CONTEXT, "BindNativeMethods failed"); return nullptr; } - ani_object contextObj = EtsAbilityContext::SetAbilityContext(env, context); + ani_object contextObj = EtsAbilityContext::SetEtsAbilityContext(env, context); if (contextObj == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "null contextObj"); return nullptr; @@ -524,7 +845,7 @@ ani_object CreateEtsAbilityContext( TAG_LOGE(AAFwkTag::CONTEXT, "null configuration"); return nullptr; } - ani_object configurationObj = OHOS::AppExecFwk::WrapConfiguration(env, *configuration); + ani_object configurationObj = AppExecFwk::WrapConfiguration(env, *configuration); if ((status = env->Object_SetFieldByName_Ref(contextObj, "config", configurationObj)) != ANI_OK) { TAG_LOGE(AAFwkTag::CONTEXT, "Object_SetFieldByName_Ref status: %{public}d", status); return nullptr; diff --git a/frameworks/native/ability/native/ability_runtime/ets_ui_ability.cpp b/frameworks/ets/ani/ui_ability/src/ets_ui_ability.cpp similarity index 78% rename from frameworks/native/ability/native/ability_runtime/ets_ui_ability.cpp rename to frameworks/ets/ani/ui_ability/src/ets_ui_ability.cpp index 206466e8ee8..e7f022019c6 100644 --- a/frameworks/native/ability/native/ability_runtime/ets_ui_ability.cpp +++ b/frameworks/ets/ani/ui_ability/src/ets_ui_ability.cpp @@ -29,6 +29,9 @@ #include "ets_data_struct_converter.h" #include "hilog_tag_wrapper.h" #include "hitrace_meter.h" +#include "insight_intent_executor_info.h" +#include "insight_intent_executor_mgr.h" +#include "insight_intent_execute_param.h" #include "string_wrapper.h" #ifdef WINDOWS_PLATFORM @@ -143,7 +146,7 @@ void EtsUIAbility::Init(std::shared_ptr record, std::string moduleName(abilityInfo->moduleName); moduleName.append("::").append(abilityInfo->name); - SetAbilityContext(abilityInfo, record->GetWant(), moduleName, srcPath, application); + SetAbilityContext(abilityInfo, record->GetWant(), moduleName, srcPath); } bool EtsUIAbility::BindNativeMethods() @@ -186,7 +189,7 @@ void EtsUIAbility::UpdateAbilityObj( } void EtsUIAbility::SetAbilityContext(std::shared_ptr abilityInfo, std::shared_ptr want, - const std::string &moduleName, const std::string &srcPath, const std::shared_ptr &application) + const std::string &moduleName, const std::string &srcPath) { TAG_LOGD(AAFwkTag::UIABILITY, "SetAbilityContext called"); UpdateAbilityObj(abilityInfo, moduleName, srcPath); @@ -195,10 +198,10 @@ void EtsUIAbility::SetAbilityContext(std::shared_ptr abilityInfo, s return; } int32_t screenMode = want->GetIntParam(AAFwk::SCREEN_MODE_KEY, AAFwk::ScreenMode::IDLE_SCREEN_MODE); - CreateEtsContext(screenMode, application); + CreateEtsContext(screenMode); } -void EtsUIAbility::CreateEtsContext(int32_t screenMode, const std::shared_ptr &application) +void EtsUIAbility::CreateEtsContext(int32_t screenMode) { auto env = etsRuntime_.GetAniEnv(); if (env == nullptr) { @@ -206,7 +209,7 @@ void EtsUIAbility::CreateEtsContext(int32_t screenMode, const std::shared_ptr sessionInf TAG_LOGE(AAFwkTag::UIABILITY, "null env"); return; } - ani_object wantObj = OHOS::AppExecFwk::WrapWant(env, want); + ani_object wantObj = AppExecFwk::WrapWant(env, want); if (wantObj == nullptr) { TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); return; @@ -384,6 +387,44 @@ void EtsUIAbility::OnSceneCreated() TAG_LOGD(AAFwkTag::UIABILITY, "OnSceneCreated end"); } +void EtsUIAbility::OnSceneRestored() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + UIAbility::OnSceneRestored(); + TAG_LOGD(AAFwkTag::UIABILITY, "OnSceneRestored called"); + + auto etsAppWindowStage = CreateAppWindowStage(); + if (etsAppWindowStage == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null etsAppWindowStage"); + return; + } + UpdateEtsWindowStage(reinterpret_cast(etsAppWindowStage)); + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + if (etsWindowStageObj_ && etsWindowStageObj_->aniRef) { + env->GlobalReference_Delete(etsWindowStageObj_->aniRef); + } + etsWindowStageObj_ = std::make_shared(); + etsWindowStageObj_->aniObj = etsAppWindowStage; + ani_ref entryObjectRef = nullptr; + env->GlobalReference_Create(etsAppWindowStage, &entryObjectRef); + etsWindowStageObj_->aniRef = entryObjectRef; + CallObjectMethod(false, "onWindowStageRestore", nullptr, etsAppWindowStage); +} + +void EtsUIAbility::OnSceneWillDestroy() +{ + TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); + if (etsWindowStageObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null etsWindowStageObj_"); + return; + } + CallObjectMethod(false, "onWindowStageWillDestroy", nullptr, etsWindowStageObj_->aniRef); +} + void EtsUIAbility::onSceneDestroyed() { TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); @@ -430,7 +471,7 @@ void EtsUIAbility::CallOnForegroundFunc(const Want &want) return; } ani_status status = ANI_ERROR; - ani_ref wantRef = OHOS::AppExecFwk::WrapWant(env, want); + ani_ref wantRef = AppExecFwk::WrapWant(env, want); if (wantRef == nullptr) { TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); return; @@ -514,6 +555,7 @@ void EtsUIAbility::AbilityContinuationOrRecover(const Want &want) launchParam_.lastExitReason); if (IsRestoredInContinuation()) { RestorePageStack(want); + OnSceneRestored(); NotifyContinuationResult(want, true); return; } @@ -569,7 +611,7 @@ void EtsUIAbility::DoOnForegroundForSceneIsNull(const Want &want) scene_ = std::make_shared(); int32_t displayId = AAFwk::DisplayUtil::GetDefaultDisplayId(); if (setting_ != nullptr) { - std::string strDisplayId = setting_->GetProperty(OHOS::AppExecFwk::AbilityStartSetting::WINDOW_DISPLAY_ID_KEY); + std::string strDisplayId = setting_->GetProperty(AppExecFwk::AbilityStartSetting::WINDOW_DISPLAY_ID_KEY); std::regex formatRegex("[0-9]{0,9}$"); std::smatch sm; bool flag = std::regex_match(strDisplayId, sm, formatRegex); @@ -621,6 +663,7 @@ void EtsUIAbility::ContinuationRestore(const Want &want) return; } RestorePageStack(want); + OnSceneRestored(); NotifyContinuationResult(want, true); } @@ -638,9 +681,9 @@ void EtsUIAbility::UpdateEtsWindowStage(ani_ref windowStage) } ani_status status = ANI_ERROR; if (windowStage == nullptr) { - ani_ref undefinedRef = nullptr; - env->GetUndefined(&undefinedRef); - if ((status = env->Object_SetFieldByName_Ref(shellContextRef_->aniObj, "windowStage", undefinedRef)) != + ani_ref nullRef = nullptr; + env->GetNull(&nullRef); + if ((status = env->Object_SetFieldByName_Ref(shellContextRef_->aniObj, "windowStage", nullRef)) != ANI_OK) { TAG_LOGE(AAFwkTag::UIABILITY, "Object_SetFieldByName_Ref status: %{public}d", status); return; @@ -652,6 +695,150 @@ void EtsUIAbility::UpdateEtsWindowStage(ani_ref windowStage) return; } } + +void EtsUIAbility::ExecuteInsightIntentRepeateForeground(const Want &want, + const std::shared_ptr &executeParam, + std::unique_ptr callback) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "ExecuteInsightIntentRepeateForeground called"); + if (executeParam == nullptr) { + TAG_LOGW(AAFwkTag::UIABILITY, "null executeParam"); + RequestFocus(want); + InsightIntentExecutorMgr::TriggerCallbackInner(std::move(callback), ERR_OK); + return; + } + + auto asyncCallback = [weak = weak_from_this(), want](InsightIntentExecuteResult result) { + TAG_LOGD(AAFwkTag::UIABILITY, "request focus"); + auto ability = weak.lock(); + if (ability == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null ability"); + return; + } + ability->RequestFocus(want); + }; + callback->Push(asyncCallback); + + InsightIntentExecutorInfo executeInfo; + auto ret = GetInsightIntentExecutorInfo(want, executeParam, executeInfo); + if (!ret) { + TAG_LOGE(AAFwkTag::UIABILITY, "get intentExecutor failed"); + InsightIntentExecutorMgr::TriggerCallbackInner( + std::move(callback), static_cast(AbilityErrorCode::ERROR_CODE_INVALID_PARAM)); + return; + } + + ret = DelayedSingleton::GetInstance()->ExecuteInsightIntent( + etsRuntime_, executeInfo, std::move(callback)); + if (!ret) { + // callback has removed, release in insight intent executor. + TAG_LOGE(AAFwkTag::UIABILITY, "execute insightIntent failed"); + } +} + +void EtsUIAbility::ExecuteInsightIntentMoveToForeground(const Want &want, + const std::shared_ptr &executeParam, + std::unique_ptr callback) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "ExecuteInsightIntentMoveToForeground called"); + if (executeParam == nullptr) { + TAG_LOGW(AAFwkTag::UIABILITY, "null executeParam"); + OnForeground(want); + InsightIntentExecutorMgr::TriggerCallbackInner(std::move(callback), ERR_OK); + return; + } + + if (abilityInfo_) { + } + UIAbility::OnForeground(want); + + auto asyncCallback = [weak = weak_from_this(), want](InsightIntentExecuteResult result) { + TAG_LOGD(AAFwkTag::UIABILITY, "begin call onForeground"); + auto ability = weak.lock(); + if (ability == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null ability"); + return; + } + ability->CallOnForegroundFunc(want); + }; + callback->Push(asyncCallback); + + InsightIntentExecutorInfo executeInfo; + auto ret = GetInsightIntentExecutorInfo(want, executeParam, executeInfo); + if (!ret) { + TAG_LOGE(AAFwkTag::UIABILITY, "get intentExecutor failed"); + InsightIntentExecutorMgr::TriggerCallbackInner( + std::move(callback), static_cast(AbilityErrorCode::ERROR_CODE_INVALID_PARAM)); + return; + } + + ret = DelayedSingleton::GetInstance()->ExecuteInsightIntent( + etsRuntime_, executeInfo, std::move(callback)); + if (!ret) { + // callback has removed, release in insight intent executor. + TAG_LOGE(AAFwkTag::UIABILITY, "execute insightIntent failed"); + } +} + +void EtsUIAbility::ExecuteInsightIntentBackground(const Want &want, + const std::shared_ptr &executeParam, + std::unique_ptr callback) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "ExecuteInsightIntentBackground called"); + if (executeParam == nullptr) { + TAG_LOGW(AAFwkTag::UIABILITY, "null executeParam"); + InsightIntentExecutorMgr::TriggerCallbackInner(std::move(callback), ERR_OK); + return; + } + + if (abilityInfo_) { + } + + InsightIntentExecutorInfo executeInfo; + auto ret = GetInsightIntentExecutorInfo(want, executeParam, executeInfo); + if (!ret) { + TAG_LOGE(AAFwkTag::UIABILITY, "get intentExecutor failed"); + InsightIntentExecutorMgr::TriggerCallbackInner( + std::move(callback), static_cast(AbilityErrorCode::ERROR_CODE_INVALID_PARAM)); + return; + } + + ret = DelayedSingleton::GetInstance()->ExecuteInsightIntent( + etsRuntime_, executeInfo, std::move(callback)); + if (!ret) { + // callback has removed, release in insight intent executor. + TAG_LOGE(AAFwkTag::UIABILITY, "execute insightIntent failed"); + } +} + +bool EtsUIAbility::GetInsightIntentExecutorInfo(const Want &want, + const std::shared_ptr &executeParam, InsightIntentExecutorInfo &executeInfo) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "GetInsightIntentExecutorInfo called"); + + auto context = GetAbilityContext(); + if (executeParam == nullptr || context == nullptr || abilityInfo_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "param invalid"); + return false; + } + + if (executeParam->executeMode_ == AppExecFwk::ExecuteMode::UI_ABILITY_FOREGROUND &&etsWindowStageObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "param invalid"); + return false; + } + + const WantParams &wantParams = want.GetParams(); + executeInfo.srcEntry = wantParams.GetStringParam("ohos.insightIntent.srcEntry"); + executeInfo.hapPath = abilityInfo_->hapPath; + executeInfo.esmodule = abilityInfo_->compileMode == AppExecFwk::CompileMode::ES_MODULE; + executeInfo.windowMode = windowMode_; + executeInfo.token = context->GetToken(); + if (etsWindowStageObj_ != nullptr) { + executeInfo.etsPageLoader = reinterpret_cast(etsWindowStageObj_->aniRef); + } + executeInfo.executeParam = executeParam; + return true; +} #endif void EtsUIAbility::OnNewWant(const Want &want) @@ -673,7 +860,7 @@ void EtsUIAbility::OnNewWant(const Want &want) TAG_LOGE(AAFwkTag::UIABILITY, "null etsAbilityObj_"); return; } - ani_object wantObj = OHOS::AppExecFwk::WrapWant(env, want); + ani_object wantObj = AppExecFwk::WrapWant(env, want); if (wantObj == nullptr) { TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); return; @@ -756,13 +943,13 @@ bool EtsUIAbility::CallObjectMethod(bool withResult, const char *name, const cha return false; } -std::shared_ptr EtsUIAbility::CreateADelegatorAbilityProperty() +std::shared_ptr EtsUIAbility::CreateADelegatorAbilityProperty() { if (abilityContext_ == nullptr) { TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext_"); return nullptr; } - auto property = std::make_shared(); + auto property = std::make_shared(); property->token_ = abilityContext_->GetToken(); property->name_ = GetAbilityName(); property->moduleName_ = GetModuleName(); @@ -787,4 +974,4 @@ ETS_EXPORT extern "C" OHOS::AbilityRuntime::UIAbility *OHOS_ETS_Ability_Create( const std::unique_ptr &runtime) { return OHOS::AbilityRuntime::EtsUIAbility::Create(runtime); -} \ No newline at end of file +} diff --git a/frameworks/ets/ani/ui_extension_ability/include/ets_ui_extension.h b/frameworks/ets/ani/ui_extension_ability/include/ets_ui_extension.h index 5316b90aad7..156842cfad1 100644 --- a/frameworks/ets/ani/ui_extension_ability/include/ets_ui_extension.h +++ b/frameworks/ets/ani/ui_extension_ability/include/ets_ui_extension.h @@ -23,6 +23,7 @@ #include "ani.h" #include "configuration.h" #include "ets_runtime.h" +#include "insight_intent_executor_info.h" #include "ets_ui_extension_content_session.h" #include "ui_extension.h" #include "ui_extension_context.h" @@ -76,9 +77,6 @@ public: */ void OnStart(const AAFwk::Want &want, sptr sessionInfo) override; - void OnCommandWindow(const AAFwk::Want &want, const sptr &sessionInfo, - AAFwk::WindowCommand winCmd) override; - /** * @brief Called when this ui extension enters the STATE_STOP state. * @@ -145,6 +143,8 @@ private: bool CallObjectMethod(bool withResult, const char *name, const char *signature, ...); ani_status CallOnDisconnect(const AAFwk::Want &want, bool withResult = false); void DestroyWindow(const sptr &sessionInfo) override; + bool ForegroundWindowInitInsightIntentExecutorInfo(const AAFwk::Want &want, + const sptr &sessionInfo, InsightIntentExecutorInfo &executorInfo); bool ForegroundWindowWithInsightIntent(const AAFwk::Want &want, const sptr &sessionInfo, bool needForeground) override; bool HandleSessionCreate(const AAFwk::Want &want, const sptr &sessionInfo) override; @@ -156,13 +156,12 @@ private: const sptr &sessionInfo); static void PromiseCallback(ani_env *env, ani_object aniObj); bool IsEmbeddableStart(int32_t screenMode); + void ExecuteInsightIntentDone(uint64_t intentId, const InsightIntentExecuteResult &result); ETSRuntime &etsRuntime_; std::shared_ptr etsObj_ = nullptr; std::shared_ptr shellContextRef_ = nullptr; std::mutex uiWindowMutex_; - std::map> uiWindowMap_; - std::set foregroundWindows_; std::map contentSessions_; int32_t screenMode_ = AAFwk::IDLE_SCREEN_MODE; std::shared_ptr screenModePtr_; @@ -201,6 +200,6 @@ private: sptr etsUIExtensionAbilityDisplayListener_ = nullptr; #endif }; -} // namespace AbilityRuntime -} // namespace OHOS +} // namespace AbilityRuntime +} // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_ETS_UI_EXTENSION_H diff --git a/frameworks/ets/ani/ui_extension_ability/include/ets_ui_extension_content_session.h b/frameworks/ets/ani/ui_extension_ability/include/ets_ui_extension_content_session.h index c829015e6bd..489cba8286d 100644 --- a/frameworks/ets/ani/ui_extension_ability/include/ets_ui_extension_content_session.h +++ b/frameworks/ets/ani/ui_extension_ability/include/ets_ui_extension_content_session.h @@ -77,10 +77,11 @@ public: static void NativeLoadContent(ani_env *env, ani_object obj, ani_string path, ani_object storage); static void NativeTerminateSelf(ani_env *env, ani_object obj, ani_object callback); static void NativeSetWindowBackgroundColor(ani_env *env, ani_object obj, ani_string color); - static int NativeTerminateSelfWithResult(ani_env *env, ani_object obj, - ani_object abilityResult, ani_object callback); + static int NativeTerminateSelfWithResult( + ani_env *env, ani_object obj, ani_object abilityResult, ani_object callback); static void NativeSetReceiveDataCallback(ani_env *env, ani_object clsObj, ani_object funcObj); - static ani_object NativeGetUIExtensionHostWindowProxy(ani_env* env, ani_object obj); + static void NativeSetReceiveDataForResultCallback(ani_env *env, ani_object clsObj, ani_object funcObj); + static ani_object NativeGetUIExtensionHostWindowProxy(ani_env *env, ani_object obj); void SendData(ani_env *env, ani_object object, ani_object data); void LoadContent(ani_env *env, ani_object object, ani_string path, ani_object storage); @@ -89,23 +90,29 @@ public: void SetWindowBackgroundColor(ani_env *env, ani_string color); ani_object GetUIExtensionHostWindowProxy(ani_env *env, ani_object object); void SetReceiveDataCallback(ani_env *env, ani_object functionObj); - static void CallReceiveDataCallback(ani_vm *vm, ani_ref callbackRef, const AAFwk::WantParams& wantParams); + static void CallReceiveDataCallback(ani_vm *vm, ani_ref callbackRef, const AAFwk::WantParams &wantParams); + void SetReceiveDataForResultCallback(ani_env *env, ani_object object); + static void CallReceiveDataCallbackForResult( + ani_vm *vm, ani_ref callbackRef, const AAFwk::WantParams &wantParams, AAFwk::WantParams &retWantParams); std::shared_ptr GetContext(); sptr GetUIWindow(); - + static bool BindNativePtrCleaner(ani_env *env); + static void Clean(ani_env *env, ani_object object); private: void SetReceiveDataCallbackRegister(ani_env *env, ani_object functionObj); + void SetReceiveDataForResultCallbackRegister(ani_env *env, ani_object funcObj); + sptr sessionInfo_; sptr uiWindow_; std::weak_ptr context_; ani_ref receiveDataCallback_ = nullptr; bool isRegistered_ = false; - std::shared_ptr receiveDataForResultCallback_; - bool isSyncRegistered = false; + ani_ref receiveDataForResultCallback_ = nullptr; + bool isSyncRegistered_ = false; std::shared_ptr listener_; bool isFirstTriggerBindModal_ = true; }; -} // namespace AbilityRuntime -} // namespace OHOS +} // namespace AbilityRuntime +} // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_ETS_UI_EXTENSION_CONTENT_SESSION_H 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 45268d53655..870753a2f77 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 @@ -20,13 +20,15 @@ #include #include "ani.h" -#include "ui_extension_context.h" +#include "ets_free_install_observer.h" #include "ets_runtime.h" #include "hilog_tag_wrapper.h" #include "hitrace_meter.h" #include "ohos_application.h" #include "ui_extension_context.h" +namespace OHOS { +namespace AbilityRuntime { ani_object CreateEtsUIExtensionContext(ani_env *env, std::shared_ptr context); class EtsUIExtensionContext final { @@ -34,17 +36,28 @@ public: explicit EtsUIExtensionContext(const std::shared_ptr &context) : context_(context) {} virtual ~EtsUIExtensionContext() = default; - + static EtsUIExtensionContext* GetEtsUIExtensionContext(ani_env *env, ani_object obj); static void TerminateSelfSync(ani_env *env, ani_object obj, ani_object callback); - static void TerminateSelfWithResultSync(ani_env *env, ani_object obj, ani_object abilityResult, ani_object callback); + static void TerminateSelfWithResultSync( + ani_env *env, ani_object obj, ani_object abilityResult, ani_object callback); + static void StartAbility(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object call); + static void StartAbilityWithOption( + ani_env *env, ani_object aniObj, ani_object wantObj, ani_object opt, ani_object call); + + static bool BindNativePtrCleaner(ani_env *env); + static void Clean(ani_env *env, ani_object object); - static void EtsCreatExtensionContext(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, - std::shared_ptr context); private: - static void BindExtensionInfo(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, - std::shared_ptr context, std::shared_ptr abilityInfo); + void OnTerminateSelf(ani_env *env, ani_object obj, ani_object callback); + void OnTerminateSelfWithResult(ani_env *env, ani_object obj, ani_object abilityResult, ani_object callback); + void OnStartAbility(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object opt, ani_object call); + void AddFreeInstallObserver( + ani_env *env, const AAFwk::Want &want, ani_object callbackObj, std::shared_ptr context); protected: std::weak_ptr context_; + sptr freeInstallObserver_ = nullptr; }; +} // namespace AbilityRuntime +} // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_ETS_UI_EXTENSION_CONTEXT_H \ No newline at end of file diff --git a/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension.cpp b/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension.cpp index 42d4f040c8d..b3fc24c8898 100644 --- a/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension.cpp +++ b/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension.cpp @@ -188,6 +188,9 @@ void EtsUIExtension::BindContext(ani_env *env, std::shared_ptr want if ((status = env->Object_SetField_Ref(etsObj_->aniObj, contextField, contextRef)) != ANI_OK) { TAG_LOGE(AAFwkTag::ETSRUNTIME, "status: %{public}d", status); } + shellContextRef_ = std::make_shared(); + shellContextRef_->aniObj = contextObj; + shellContextRef_->aniRef = contextRef; } void EtsUIExtension::OnStart(const AAFwk::Want &want, sptr sessionInfo) @@ -294,35 +297,32 @@ void EtsUIExtension::OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> *callba } } -void EtsUIExtension::OnCommandWindow(const AAFwk::Want &want, const sptr &sessionInfo, - AAFwk::WindowCommand winCmd) +bool EtsUIExtension::ForegroundWindowInitInsightIntentExecutorInfo(const AAFwk::Want &want, + const sptr &sessionInfo, InsightIntentExecutorInfo &executorInfo) { - HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - if (sessionInfo == nullptr) { - TAG_LOGE(AAFwkTag::UI_EXT, "sessionInfo null"); - return; + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + return false; } - Extension::OnCommandWindow(want, sessionInfo, winCmd); - if (InsightIntentExecuteParam::IsInsightIntentExecute(want) && winCmd == AAFwk::WIN_CMD_FOREGROUND) { - if (ForegroundWindowWithInsightIntent(want, sessionInfo, false)) { - return; - } + if (sessionInfo == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null sessionInfo"); + return false; } - switch (winCmd) { - case AAFwk::WIN_CMD_FOREGROUND: - ForegroundWindow(want, sessionInfo); - break; - case AAFwk::WIN_CMD_BACKGROUND: - BackgroundWindow(sessionInfo); - break; - case AAFwk::WIN_CMD_DESTROY: - DestroyWindow(sessionInfo); - break; - default: - TAG_LOGD(AAFwkTag::UI_EXT, "unsupported cmd"); - break; + std::shared_ptr abilityInfo = context->GetAbilityInfo(); + if (abilityInfo != nullptr) { + executorInfo.hapPath = abilityInfo->hapPath; + executorInfo.windowMode = abilityInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE; } - OnCommandWindowDone(sessionInfo, winCmd); + executorInfo.token = context->GetToken(); + executorInfo.etsPageLoader = reinterpret_cast(contentSessions_[sessionInfo->uiExtensionComponentId]); + executorInfo.executeParam = std::make_shared(); + InsightIntentExecuteParam::GenerateFromWant(want, *executorInfo.executeParam); + executorInfo.executeParam->executeMode_ = UI_EXTENSION_ABILITY; + executorInfo.srcEntry = want.GetStringParam(INSIGHT_INTENT_SRC_ENTRY); + TAG_LOGD(AAFwkTag::UI_EXT, "executorInfo, insightIntentId: %{public}" PRIu64, + executorInfo.executeParam->insightIntentId_); + return true; } bool EtsUIExtension::ForegroundWindowWithInsightIntent(const AAFwk::Want &want, @@ -342,34 +342,42 @@ bool EtsUIExtension::ForegroundWindowWithInsightIntent(const AAFwk::Want &want, } auto uiExtension = std::static_pointer_cast(shared_from_this()); - executorCallback->Push([uiExtension, sessionInfo, needForeground](AppExecFwk::InsightIntentExecuteResult result) { + executorCallback->Push([uiExtension, sessionInfo, needForeground, want]( + AppExecFwk::InsightIntentExecuteResult result) { if (uiExtension == nullptr) { TAG_LOGE(AAFwkTag::UI_EXT, "UI extension is nullptr"); return; } + InsightIntentExecuteParam executeParam; + InsightIntentExecuteParam::GenerateFromWant(want, executeParam); + if (result.uris.size() > 0) { + uiExtension->ExecuteInsightIntentDone(executeParam.insightIntentId_, result); + } uiExtension->PostInsightIntentExecuted(sessionInfo, result, needForeground); }); - auto context = GetContext(); - if (context == nullptr) { - TAG_LOGE(AAFwkTag::UI_EXT, "context null"); + InsightIntentExecutorInfo executorInfo; + if (!ForegroundWindowInitInsightIntentExecutorInfo(want, sessionInfo, executorInfo)) { return false; } - InsightIntentExecutorInfo executorInfo; - std::shared_ptr abilityInfo = context->GetAbilityInfo(); - if (abilityInfo != nullptr) { - executorInfo.hapPath = abilityInfo->hapPath; - executorInfo.windowMode = abilityInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE; + + int32_t ret = DelayedSingleton::GetInstance()->ExecuteInsightIntent( + etsRuntime_, executorInfo, std::move(executorCallback)); + if (!ret) { + TAG_LOGE(AAFwkTag::UI_EXT, "Execute insight intent failed"); } - executorInfo.token = context->GetToken(); - executorInfo.executeParam = std::make_shared(); - InsightIntentExecuteParam::GenerateFromWant(want, *executorInfo.executeParam); - executorInfo.executeParam->executeMode_ = UI_EXTENSION_ABILITY; - executorInfo.srcEntry = want.GetStringParam(INSIGHT_INTENT_SRC_ENTRY); return true; } +void EtsUIExtension::ExecuteInsightIntentDone(uint64_t intentId, const InsightIntentExecuteResult &result) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "intentId %{public}" PRIu64"", intentId); + auto ret = AAFwk::AbilityManagerClient::GetInstance()->ExecuteInsightIntentDone(token_, intentId, result); + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "notify execute done failed"); + } +} void EtsUIExtension::PostInsightIntentExecuted(const sptr &sessionInfo, const AppExecFwk::InsightIntentExecuteResult &result, bool needForeground) { @@ -399,6 +407,7 @@ void EtsUIExtension::OnForeground(const Want &want, sptr ses TAG_LOGE(AAFwkTag::UI_EXT, "sessionInfo nullptr"); return; } + Extension::OnForeground(want, sessionInfo); if (InsightIntentExecuteParam::IsInsightIntentExecute(want)) { bool finish = ForegroundWindowWithInsightIntent(want, sessionInfo, true); if (finish) { @@ -413,6 +422,7 @@ void EtsUIExtension::OnBackground() { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); CallObjectMethod(false, "onBackground", nullptr); + Extension::OnBackground(); } bool EtsUIExtension::IsEmbeddableStart(int32_t screenMode) @@ -559,6 +569,7 @@ void EtsUIExtension::DestroyWindow(const sptr &sessionInfo) bool EtsUIExtension::CallObjectMethod(bool withResult, const char *name, const char *signature, ...) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name); + TAG_LOGD(AAFwkTag::UI_EXT, "CallObjectMethod %{public}s", name); if (etsObj_ == nullptr) { TAG_LOGE(AAFwkTag::UI_EXT, "etsObj_ nullptr"); return false; diff --git a/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension_content_session.cpp b/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension_content_session.cpp index f7000700459..22761295957 100644 --- a/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension_content_session.cpp +++ b/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension_content_session.cpp @@ -39,39 +39,25 @@ namespace AbilityRuntime { constexpr int32_t ERR_FAILURE = -1; const char* UI_EXTENSION_CONTENT_SESSION_CLASS_NAME = "L@ohos/app/ability/UIExtensionContentSession/UIExtensionContentSession;"; +const char* UI_EXTENSION_CONTENT_SESSION_CLEANER_CLASS_NAME = + "L@ohos/app/ability/UIExtensionContentSession/Cleaner;"; EtsUIExtensionContentSession* EtsUIExtensionContentSession::GetEtsContentSession(ani_env *env, ani_object obj) { if (env == nullptr) { TAG_LOGE(AAFwkTag::UI_EXT, "null env"); - EtsErrorUtil::ThrowInvalidParamError(env, "context null"); return nullptr; } - ani_class cls; ani_status status = ANI_ERROR; - status = env->FindClass(UI_EXTENSION_CONTENT_SESSION_CLASS_NAME, &cls); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); - EtsErrorUtil::ThrowInvalidParamError(env, "findClass fail"); - return nullptr; - } EtsUIExtensionContentSession *etsContentSession = nullptr; - ani_field etsContentSessionField; - status = env->Class_FindField(cls, "nativeContextSession", &etsContentSessionField); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); - EtsErrorUtil::ThrowInvalidParamError(env, "class find field fail"); - return nullptr; - } - status = env->Object_GetField_Long(obj, etsContentSessionField, reinterpret_cast(&etsContentSession)); - if (status != ANI_OK) { + ani_long etsContentSessionLong = 0; + if ((status = env->Object_GetFieldByName_Long(obj, "nativeContextSession", &etsContentSessionLong)) != ANI_OK) { TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); - EtsErrorUtil::ThrowInvalidParamError(env, "object get field Long fail"); return nullptr; } + etsContentSession = reinterpret_cast(etsContentSessionLong); if (etsContentSession == nullptr) { TAG_LOGE(AAFwkTag::UI_EXT, "etsContentSession null"); - EtsErrorUtil::ThrowInvalidParamError(env, "etsContentSession null"); return nullptr; } return etsContentSession; @@ -85,7 +71,16 @@ void EtsUIExtensionContentSession::NativeSetReceiveDataCallback(ani_env* env, an } } -void EtsUIExtensionContentSession::NativeSendData(ani_env *env, ani_object obj, ani_object data) +void EtsUIExtensionContentSession::NativeSetReceiveDataForResultCallback(ani_env *env, + ani_object clsObj, ani_object funcObj) +{ + auto etsContentSession = GetEtsContentSession(env, clsObj); + if (etsContentSession != nullptr) { + etsContentSession->SetReceiveDataForResultCallback(env, funcObj); + } +} + +void EtsUIExtensionContentSession::NativeSendData(ani_env* env, ani_object obj, ani_object data) { auto etsContentSession =EtsUIExtensionContentSession::GetEtsContentSession(env, obj); if (etsContentSession != nullptr) { @@ -194,6 +189,41 @@ EtsUIExtensionContentSession::EtsUIExtensionContentSession(sptrObject_GetFieldByName_Long(object, "nativeContextSession", &ptr)) { + return; + } + + if (ptr != 0) { + delete reinterpret_cast(ptr); + ptr = 0; + } +} + +bool EtsUIExtensionContentSession::BindNativePtrCleaner(ani_env *env) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "nullptr env"); + return false; + } + ani_class cleanerCls; + ani_status status = env->FindClass(UI_EXTENSION_CONTENT_SESSION_CLEANER_CLASS_NAME, &cleanerCls); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::UI_EXT, "Not found Cleaner. status:%{public}d.", status); + return false; + } + std::array methods = { + ani_native_function { "clean", nullptr, reinterpret_cast(EtsUIExtensionContentSession::Clean) }, + }; + if (ANI_OK != env->Class_BindNativeMethods(cleanerCls, methods.data(), methods.size())) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return false; + }; + return true; +} + ani_object EtsUIExtensionContentSession::CreateEtsUIExtensionContentSession(ani_env *env, sptr sessionInfo, sptr uiWindow, std::weak_ptr context, @@ -209,15 +239,15 @@ ani_object EtsUIExtensionContentSession::CreateEtsUIExtensionContentSession(ani_ TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); return nullptr; } - status = env->Class_FindMethod(cls, "", ":V", &method); + ani_long nativeContextSession = reinterpret_cast(contentSessionPtr.get()); + status = env->Class_FindMethod(cls, "", "J:V", &method); if (status != ANI_OK) { return nullptr; } - status = env->Object_New(cls, method, &object); + status = env->Object_New(cls, method, &object, nativeContextSession); if ((status != ANI_OK) || (object == nullptr)) { return nullptr; } - std::array methods = { ani_native_function {"terminateSelfSync", nullptr, reinterpret_cast(EtsUIExtensionContentSession::NativeTerminateSelf)}, @@ -232,21 +262,16 @@ ani_object EtsUIExtensionContentSession::CreateEtsUIExtensionContentSession(ani_ ani_native_function {"getUIExtensionHostWindowProxy", nullptr, reinterpret_cast(EtsUIExtensionContentSession::NativeGetUIExtensionHostWindowProxy)}, ani_native_function {"nativeSetReceiveDataCallback", nullptr, - reinterpret_cast(EtsUIExtensionContentSession::NativeSetReceiveDataCallback)} + reinterpret_cast(EtsUIExtensionContentSession::NativeSetReceiveDataCallback)}, + ani_native_function {"nativeSetReceiveDataForResultCallback", nullptr, + reinterpret_cast(EtsUIExtensionContentSession::NativeSetReceiveDataForResultCallback)} }; status = env->Class_BindNativeMethods(cls, methods.data(), methods.size()); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); return nullptr; } - ani_field nativeField = nullptr; - status = env->Class_FindField(cls, "nativeContextSession", &nativeField); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); - return nullptr; - } - status = env->Object_SetField_Long(object, nativeField, reinterpret_cast(contentSessionPtr.get())); - if (status != ANI_OK) { + if (!EtsUIExtensionContentSession::BindNativePtrCleaner(env)) { TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); return nullptr; } @@ -276,21 +301,22 @@ void EtsUIExtensionContentSession::SendData(ani_env *env, ani_object object, ani void EtsUIExtensionContentSession::LoadContent(ani_env *env, ani_object object, ani_string path, ani_object storage) { - TAG_LOGD(AAFwkTag::UI_EXT, "called"); + TAG_LOGD(AAFwkTag::UI_EXT, "LoadContent called"); std::string contextPath; - ani_size sz {}; - env->String_GetUTF8Size(path, &sz); - contextPath.resize(sz + 1); - env->String_GetUTF8SubString(path, 0, sz, contextPath.data(), contextPath.size(), &sz); - + if (!OHOS::AppExecFwk::GetStdString(env, path, contextPath)) { + TAG_LOGE(AAFwkTag::UI_EXT, "invalid param"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parameter error: Path must be a string."); + return; + } + TAG_LOGD(AAFwkTag::UI_EXT, "contextPath: %{public}s", contextPath.c_str()); if (uiWindow_ == nullptr || sessionInfo_ == nullptr) { TAG_LOGE(AAFwkTag::UI_EXT, "uiWindow_ or sessionInfo_ is nullptr"); EtsErrorUtil::ThrowErrorByNativeErr(env, static_cast(AbilityErrorCode::ERROR_CODE_INNER)); return; } - if (sessionInfo_->isAsyncModalBinding && isFirstTriggerBindModal_) { + TAG_LOGD(AAFwkTag::UI_EXT, "Trigger binding UIExtension modal window"); uiWindow_->TriggerBindModalUIExtension(); isFirstTriggerBindModal_ = false; } @@ -302,6 +328,7 @@ void EtsUIExtensionContentSession::LoadContent(ani_env *env, ani_object object, EtsErrorUtil::ThrowErrorByNativeErr(env, static_cast(AbilityErrorCode::ERROR_CODE_INNER)); } + TAG_LOGD(AAFwkTag::UI_EXT, "LoadContent end"); return; } @@ -321,10 +348,11 @@ void EtsUIExtensionContentSession::SetWindowBackgroundColor(ani_env *env, ani_st { TAG_LOGD(AAFwkTag::UI_EXT, "SetWindowBackgroundColor call"); std::string strColor; - ani_size sz {}; - env->String_GetUTF8Size(color, &sz); - strColor.resize(sz + 1); - env->String_GetUTF8SubString(color, 0, sz, strColor.data(), strColor.size(), &sz); + if (!OHOS::AppExecFwk::GetStdString(env, color, strColor)) { + TAG_LOGE(AAFwkTag::UI_EXT, "invalid param"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parameter error: color must be a string."); + return; + } if (uiWindow_ == nullptr) { TAG_LOGE(AAFwkTag::UI_EXT, "uiWindow_ is nullptr"); EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); @@ -467,6 +495,121 @@ void EtsUIExtensionContentSession::CallReceiveDataCallback(ani_vm* vm, ani_ref c TAG_LOGD(AAFwkTag::UI_EXT, "CallReceiveDataCallback end"); } +void EtsUIExtensionContentSession::SetReceiveDataForResultCallback(ani_env *env, ani_object funcObj) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "SetReceiveDataForResultCallback call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "env null"); + EtsErrorUtil::ThrowErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM)); + return; + } + if (!isSyncRegistered_) { + SetReceiveDataForResultCallbackRegister(env, funcObj); + } else { + if (receiveDataForResultCallback_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null receiveDataForResultCallback_"); + EtsErrorUtil::ThrowErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return; + } + ani_status status = ANI_OK; + if ((status = env->GlobalReference_Delete(receiveDataForResultCallback_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GlobalReference_Delete failed status:%{public}d", status); + EtsErrorUtil::ThrowErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return; + } + receiveDataForResultCallback_ = nullptr; + if ((status = env->GlobalReference_Create(funcObj, &receiveDataForResultCallback_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GlobalReference_Create failed status:%{public}d", status); + EtsErrorUtil::ThrowErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return; + } + } + TAG_LOGD(AAFwkTag::UI_EXT, "SetReceiveDataForResultCallback end"); +} + +void EtsUIExtensionContentSession::SetReceiveDataForResultCallbackRegister(ani_env* env, ani_object funcObj) +{ + if (uiWindow_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null uiWindow_"); + EtsErrorUtil::ThrowErrorByNativeErr( + env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return; + } + if (receiveDataForResultCallback_ == nullptr) { + if (env->GlobalReference_Create(funcObj, &receiveDataForResultCallback_) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GlobalReference_Create receiveDataForResultCallback_ failed"); + EtsErrorUtil::ThrowErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return; + } + } + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "get aniVM failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Get aniVm failed."); + return; + } + auto callbackRef = receiveDataForResultCallback_; + auto handler = std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); + uiWindow_->RegisterTransferComponentDataForResultListener([aniVM, handler, callbackRef] ( + const AAFwk::WantParams& wantParams) -> AAFwk::WantParams { + AAFwk::WantParams retWantParams; + if (handler) { + handler->PostSyncTask([aniVM, callbackRef, wantParams, &retWantParams]() { + EtsUIExtensionContentSession::CallReceiveDataCallbackForResult(aniVM, callbackRef, + wantParams, retWantParams); + }, "StsUIExtensionContentSession:OnSetReceiveDataForResultCallback"); + } + return retWantParams; + }); + isSyncRegistered_ = true; +} + +void EtsUIExtensionContentSession::CallReceiveDataCallbackForResult(ani_vm* vm, ani_ref callbackRef, + const AAFwk::WantParams& wantParams, AAFwk::WantParams& retWantParams) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "CallReceiveDataCallbackForResult call"); + if (vm == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "vm is nullptr"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_OK; + if ((status = vm->GetEnv(ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetEnv failed status: %{public}d", status); + return; + } + if (callbackRef == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "callback is nullptr"); + return; + } + ani_object callbackObj = static_cast(callbackRef); + ani_fn_object callbackFunc = reinterpret_cast(callbackObj); + if (callbackFunc == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "callbackFunc is nullptr"); + return; + } + ani_ref wantObj = AppExecFwk::WrapWantParams(env, wantParams); + if (wantObj == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "wantObj is nullptr"); + return; + } + ani_ref argv[] = {wantObj}; + ani_ref result; + if ((status = env->FunctionalObject_Call(callbackFunc, 1, argv, &result)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "FunctionalObjectCall failed status %{public}d", status); + return; + } + if (!AppExecFwk::UnwrapWantParams(env, result, retWantParams)) { + TAG_LOGE(AAFwkTag::UI_EXT, "UnwrapWantParams failed"); + } + TAG_LOGD(AAFwkTag::UI_EXT, "CallReceiveDataCallbackForResult end"); +} + std::shared_ptr EtsUIExtensionContentSession::GetContext() { return context_.lock(); 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 5affd65c49d..b881c4bdbdd 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 @@ -15,64 +15,110 @@ #include "ets_ui_extension_context.h" #include "ability_manager_client.h" +#include "ani_common_start_options.h" #include "ani_common_want.h" #include "common_fun_ani.h" #include "ets_context_utils.h" #include "ets_error_utils.h" +#include "ets_extension_context.h" #include "ui_extension_context.h" + +namespace OHOS { +namespace AbilityRuntime { const char *INVOKE_METHOD_NAME = "invoke"; const char *UI_EXTENSION_CONTEXT_CLASS_NAME = "Lapplication/UIExtensionContext/UIExtensionContext;"; +const char *UI_EXTENSION_CONTEXT_CLEANER_CLASS_NAME = "Lapplication/UIExtensionContext/Cleaner;"; void EtsUIExtensionContext::TerminateSelfSync(ani_env *env, ani_object obj, ani_object callback) { - TAG_LOGD(AAFwkTag::UI_EXT, "called"); - ani_class cls = nullptr; - ani_long nativeContextLong; - ani_field contextField = nullptr; - ani_status status = ANI_ERROR; - OHOS::ErrCode ret = OHOS::ERR_INVALID_VALUE; - if ((status = env->FindClass(UI_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + TAG_LOGD(AAFwkTag::UI_EXT, "TerminateSelfSync called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); return; } - if ((status = env->Class_FindField(cls, "nativeContext", &contextField)) != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + auto etsUiExtensionContext = GetEtsUIExtensionContext(env, obj); + if (etsUiExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsUiExtensionContext"); return; } - if ((status = env->Object_GetField_Long(obj, contextField, &nativeContextLong)) != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); - return; - } - ret = ((OHOS::AbilityRuntime::UIExtensionContext*)nativeContextLong)->TerminateSelf(); - OHOS::AppExecFwk::AsyncCallback(env, callback, - OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), nullptr); + etsUiExtensionContext->OnTerminateSelf(env, obj, callback); } void EtsUIExtensionContext::TerminateSelfWithResultSync(ani_env *env, ani_object obj, ani_object abilityResult, ani_object callback) { - TAG_LOGD(AAFwkTag::UI_EXT, "called"); - ani_class cls = nullptr; - ani_long nativeContextLong; - ani_field contextField = nullptr; - ani_status status = ANI_ERROR; - OHOS::ErrCode ret = OHOS::ERR_INVALID_VALUE; - if ((status = env->FindClass(UI_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + TAG_LOGD(AAFwkTag::UI_EXT, "TerminateSelfWithResultSync called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); return; } - if ((status = env->Class_FindField(cls, "nativeContext", &contextField)) != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + auto etsUiExtensionContext = GetEtsUIExtensionContext(env, obj); + if (etsUiExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsUiExtensionContext"); return; } - if ((status = env->Object_GetField_Long(obj, contextField, &nativeContextLong)) != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + etsUiExtensionContext->OnTerminateSelfWithResult(env, obj, abilityResult, callback); +} + +void EtsUIExtensionContext::StartAbility(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object call) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "StartAbility"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); return; } - auto context = ((OHOS::AbilityRuntime::UIExtensionContext*)nativeContextLong); - if (!context) { - TAG_LOGE(AAFwkTag::UI_EXT, "context is released"); + auto etsUiExtensionContext = GetEtsUIExtensionContext(env, aniObj); + if (etsUiExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsUiExtensionContext"); + return; + } + etsUiExtensionContext->OnStartAbility(env, aniObj, wantObj, nullptr, call); +} + +void EtsUIExtensionContext::StartAbilityWithOption( + ani_env *env, ani_object aniObj, ani_object wantObj, ani_object opt, ani_object call) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "StartAbilityWithOption"); + 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->OnStartAbility(env, aniObj, wantObj, opt, call); +} + +void EtsUIExtensionContext::OnTerminateSelf(ani_env *env, ani_object obj, ani_object callback) +{ + ani_object aniObject = nullptr; + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "context is nullptr"); + auto errCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = EtsErrorUtil::CreateError(env, static_cast(errCode)); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); + return; + } + context->SetTerminating(true); + auto ret = context->TerminateSelf(); + OHOS::AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), nullptr); +} + +void EtsUIExtensionContext::OnTerminateSelfWithResult(ani_env *env, ani_object obj, + ani_object abilityResult, ani_object callback) +{ + ani_object aniObject = nullptr; + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "context is nullptr"); + auto errCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = EtsErrorUtil::CreateError(env, static_cast(errCode)); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); return; } @@ -96,7 +142,7 @@ void EtsUIExtensionContext::TerminateSelfWithResultSync(ani_env *env, ani_objec return; } #endif // SUPPORT_SCREEN - ret = context->TerminateSelf(); + auto ret = context->TerminateSelf(); if (ret != 0) { TAG_LOGE(AAFwkTag::UI_EXT, "TerminateSelf failed, errorCode is %{public}d", ret); return; @@ -105,44 +151,122 @@ void EtsUIExtensionContext::TerminateSelfWithResultSync(ani_env *env, ani_objec OHOS::AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), nullptr); } -void EtsUIExtensionContext::BindExtensionInfo(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, - std::shared_ptr context, std::shared_ptr abilityInfo) +void EtsUIExtensionContext::OnStartAbility( + ani_env *env, ani_object aniObj, ani_object wantObj, ani_object opt, ani_object callbackObj) { - TAG_LOGD(AAFwkTag::UI_EXT, "called"); - auto hapModuleInfo = context->GetHapModuleInfo(); - ani_status status = ANI_OK; - if (abilityInfo && hapModuleInfo) { - auto isExist = [&abilityInfo](const OHOS::AppExecFwk::ExtensionAbilityInfo& info) { - TAG_LOGD(AAFwkTag::UI_EXT, "%{public}s, %{public}s", info.bundleName.c_str(), info.name.c_str()); - return info.bundleName == abilityInfo->bundleName && info.name == abilityInfo->name; - }; - auto infoIter = std::find_if( - hapModuleInfo->extensionInfos.begin(), hapModuleInfo->extensionInfos.end(), isExist); - if (infoIter == hapModuleInfo->extensionInfos.end()) { - TAG_LOGE(AAFwkTag::UI_EXT, "set extensionAbilityInfo fail"); + ani_object aniObject = nullptr; + AAFwk::Want want; + ErrCode errCode = ERR_OK; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + aniObject = EtsErrorUtil::CreateInvalidParamError(env, "UnwrapWant filed"); + AppExecFwk::AsyncCallback(env, callbackObj, aniObject, nullptr); + return; + } + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "context is nullptr"); + errCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = EtsErrorUtil::CreateError(env, static_cast(errCode)); + AppExecFwk::AsyncCallback(env, callbackObj, aniObject, nullptr); + return; + } + if ((want.GetFlags() & AAFwk::Want::FLAG_INSTALL_ON_DEMAND) == AAFwk::Want::FLAG_INSTALL_ON_DEMAND) { + std::string startTime = std::to_string( + std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) + .count()); + want.SetParam(AAFwk::Want::PARAM_RESV_START_TIME, startTime); + AddFreeInstallObserver(env, want, callbackObj, context); + } + if (opt != nullptr) { + AAFwk::StartOptions startOptions; + if (!AppExecFwk::UnwrapStartOptions(env, opt, startOptions)) { + TAG_LOGE(AAFwkTag::UI_EXT, "UnwrapStartOptions filed"); + aniObject = EtsErrorUtil::CreateInvalidParamError(env, "UnwrapWant filed"); + AppExecFwk::AsyncCallback(env, callbackObj, aniObject, nullptr); return; } - ani_field extensionAbilityInfoField; - status = aniEnv->Class_FindField(contextClass, "extensionAbilityInfo", &extensionAbilityInfoField); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + errCode = context->StartAbility(want, startOptions); + } else { + errCode = context->StartAbility(want); + } + aniObject = EtsErrorUtil::CreateErrorByNativeErr(env, errCode); + if ((want.GetFlags() & AAFwk::Want::FLAG_INSTALL_ON_DEMAND) == AAFwk::Want::FLAG_INSTALL_ON_DEMAND) { + if (errCode != ERR_OK && freeInstallObserver_ != nullptr) { + std::string bundleName = want.GetElement().GetBundleName(); + std::string abilityName = want.GetElement().GetAbilityName(); + std::string startTime = want.GetStringParam(AAFwk::Want::PARAM_RESV_START_TIME); + freeInstallObserver_->OnInstallFinished(bundleName, abilityName, startTime, errCode); + } + } else { + AppExecFwk::AsyncCallback(env, callbackObj, aniObject, nullptr); + } +} + +void EtsUIExtensionContext::AddFreeInstallObserver( + ani_env *env, const AAFwk::Want &want, ani_object callbackObj, std::shared_ptr context) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "called"); + if (!context) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + return; + } + if (!env) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + if (freeInstallObserver_ == nullptr) { + ani_vm *etsVm = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GetVM(&etsVm)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status : %{public}d", status); return; } - ani_object extAbilityInfoObj = OHOS::AppExecFwk::CommonFunAni::ConvertExtensionInfo(aniEnv, *infoIter); - status = aniEnv->Object_SetField_Ref(contextObj, extensionAbilityInfoField, - reinterpret_cast(extAbilityInfoObj)); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + freeInstallObserver_ = new EtsFreeInstallObserver(etsVm); + if (context->AddFreeInstallObserver(freeInstallObserver_)) { + TAG_LOGE(AAFwkTag::UI_EXT, "addFreeInstallObserver error"); return; } } + std::string startTime = want.GetStringParam(AAFwk::Want::PARAM_RESV_START_TIME); + TAG_LOGD(AAFwkTag::UI_EXT, "addEtsObserver"); + std::string bundleName = want.GetElement().GetBundleName(); + std::string abilityName = want.GetElement().GetAbilityName(); + freeInstallObserver_->AddEtsObserverObject(env, bundleName, abilityName, startTime, callbackObj); } -void EtsUIExtensionContext::EtsCreatExtensionContext(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, - std::shared_ptr context) +void EtsUIExtensionContext::Clean(ani_env *env, ani_object object) { - OHOS::AbilityRuntime::ContextUtil::CreateEtsBaseContext(aniEnv, contextClass, contextObj, context); - BindExtensionInfo(aniEnv, contextClass, contextObj, context, context->GetAbilityInfo()); + ani_long ptr = 0; + if (ANI_OK != env->Object_GetFieldByName_Long(object, "nativeExtensionContext", &ptr)) { + return; + } + + if (ptr != 0) { + delete reinterpret_cast(ptr); + ptr = 0; + } +} + +bool EtsUIExtensionContext::BindNativePtrCleaner(ani_env *env) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "nullptr env"); + return false; + } + ani_class cleanerCls; + ani_status status = env->FindClass(UI_EXTENSION_CONTEXT_CLEANER_CLASS_NAME, &cleanerCls); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::UI_EXT, "Not found Cleaner. status:%{public}d.", status); + return false; + } + std::array methods = { + ani_native_function { "clean", nullptr, reinterpret_cast(EtsUIExtensionContext::Clean) }, + }; + if (ANI_OK != env->Class_BindNativeMethods(cleanerCls, methods.data(), methods.size())) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return false; + }; + return true; } ani_object CreateEtsUIExtensionContext(ani_env *env, std::shared_ptr context) @@ -151,39 +275,69 @@ ani_object CreateEtsUIExtensionContext(ani_env *env, std::shared_ptrFindClass(UI_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); return nullptr; } + if ((status = env->Class_FindMethod(cls, "", "J:V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_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::UI_EXT, "status: %{public}d", status); + return nullptr; + } std::array functions = { ani_native_function { "terminateSelfSync", nullptr, reinterpret_cast(EtsUIExtensionContext::TerminateSelfSync) }, ani_native_function { "terminateSelfWithResultSync", nullptr, reinterpret_cast(EtsUIExtensionContext::TerminateSelfWithResultSync) }, + ani_native_function { "nativeStartAbility", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsUIExtensionContext::StartAbility) }, + ani_native_function { "nativeStartAbility", "L@ohos/app/ability/Want/Want;L@ohos/app/ability/" + "StartOptions/StartOptions;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsUIExtensionContext::StartAbilityWithOption) }, }; if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); return nullptr; } - if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + if ((status = env->Object_SetFieldByName_Long(contextObj, "nativeContext", (ani_long)context.get())) != ANI_OK) { TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); return nullptr; } - if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { + if (!EtsUIExtensionContext::BindNativePtrCleaner(env)) { TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); return nullptr; } - if ((status = env->Class_FindField(cls, "nativeContext", &field)) != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + OHOS::AbilityRuntime::ContextUtil::CreateEtsBaseContext(env, cls, contextObj, context); + OHOS::AbilityRuntime::CreateEtsExtensionContext(env, cls, contextObj, context, context->GetAbilityInfo()); + return contextObj; +} + +EtsUIExtensionContext* EtsUIExtensionContext::GetEtsUIExtensionContext(ani_env *env, ani_object obj) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); return nullptr; } - ani_long nativeContextLong = (ani_long)context.get(); - if ((status = env->Object_SetField_Long(contextObj, field, nativeContextLong)) != ANI_OK) { + EtsUIExtensionContext *etsContext = nullptr; + ani_status status = ANI_ERROR; + ani_long etsContextLong = 0; + if ((status = env->Object_GetFieldByName_Long(obj, "nativeExtensionContext", &etsContextLong)) != ANI_OK) { TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); return nullptr; } - EtsUIExtensionContext::EtsCreatExtensionContext(env, cls, contextObj, context); - return contextObj; + etsContext = reinterpret_cast(etsContextLong); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "etsContext null"); + return nullptr; + } + return etsContext; } +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/uri_permission_manager/include/ets_uri_perm_mgr.h b/frameworks/ets/ani/uri_permission_manager/include/ets_uri_perm_mgr.h index 2e7645eb226..7f90db1c7f5 100644 --- a/frameworks/ets/ani/uri_permission_manager/include/ets_uri_perm_mgr.h +++ b/frameworks/ets/ani/uri_permission_manager/include/ets_uri_perm_mgr.h @@ -31,6 +31,6 @@ ani_object WrapBusinessError(ani_env *env, ani_int code); ani_object WrapError(ani_env *env, const std::string &msg); ani_string GetAniString(ani_env *env, const std::string &str); std::string GetErrMsg(int32_t err, const std::string &permission = ""); -} // namespace AbilityRuntime -} // namespace OHOS -#endif // OHOS_ABILITY_RUNTIME_ETS_URI_PERM_MGR_H \ No newline at end of file +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_URI_PERM_MGR_H \ No newline at end of file diff --git a/frameworks/ets/ani/uri_permission_manager/src/ets_uri_perm_mgr.cpp b/frameworks/ets/ani/uri_permission_manager/src/ets_uri_perm_mgr.cpp index 61a8f5c4b6d..0a24a836b02 100644 --- a/frameworks/ets/ani/uri_permission_manager/src/ets_uri_perm_mgr.cpp +++ b/frameworks/ets/ani/uri_permission_manager/src/ets_uri_perm_mgr.cpp @@ -41,7 +41,7 @@ constexpr const int32_t ERR_OK = 0; constexpr const int32_t ERR_FAILURE = -1; constexpr const char* NOT_SYSTEM_APP = "The application is not system-app, can not use system-api."; -ani_object createDouble(ani_env *env, int32_t res) +ani_object CreateDouble(ani_env *env, int32_t res) { if (env == nullptr) { return nullptr; @@ -96,7 +96,7 @@ static void grantUriPermissionCallbackSync([[maybe_unused]]ani_env *env, TAG_LOGE(AAFwkTag::URIPERMMGR, "app not system-app"); etsErrCode = EtsErrorUtil::CreateError(env, static_cast(AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP), NOT_SYSTEM_APP); - AsyncCallback(env, callback, etsErrCode, createDouble(env, ERR_FAILURE)); + AsyncCallback(env, callback, etsErrCode, CreateDouble(env, ERR_FAILURE)); return; } std::string uriStr = GetStdString(env, uri); @@ -114,7 +114,7 @@ static void grantUriPermissionCallbackSync([[maybe_unused]]ani_env *env, etsErrCode = EtsErrorUtil::CreateErrorByNativeErr(env, errCode); } - AsyncCallback(env, callback, etsErrCode, createDouble(env, result)); + AsyncCallback(env, callback, etsErrCode, CreateDouble(env, result)); } static void revokeUriPermissionCallbackSync([[maybe_unused]]ani_env *env, @@ -131,7 +131,7 @@ static void revokeUriPermissionCallbackSync([[maybe_unused]]ani_env *env, TAG_LOGE(AAFwkTag::URIPERMMGR, "app not system-app"); etsErrCode = EtsErrorUtil::CreateError(env, static_cast(AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP), NOT_SYSTEM_APP); - AsyncCallback(env, callback, etsErrCode, createDouble(env, ERR_FAILURE)); + AsyncCallback(env, callback, etsErrCode, CreateDouble(env, ERR_FAILURE)); return; } std::string uriStr = GetStdString(env, uri); @@ -144,7 +144,7 @@ static void revokeUriPermissionCallbackSync([[maybe_unused]]ani_env *env, result = ERR_FAILURE; etsErrCode = EtsErrorUtil::CreateErrorByNativeErr(env, errCode); } - AsyncCallback(env, callback, etsErrCode, createDouble(env, result)); + AsyncCallback(env, callback, etsErrCode, CreateDouble(env, result)); } void EtsUriPermissionManagerInit(ani_env *env) @@ -327,5 +327,5 @@ std::string GetErrMsg(int32_t err, const std::string &permission) return errMsg; } -} // namespace AbilityRuntime -} // namespace OHOS \ No newline at end of file +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/wantagent/BUILD.gn b/frameworks/ets/ani/wantagent/BUILD.gn new file mode 100644 index 00000000000..1bf1b8ec940 --- /dev/null +++ b/frameworks/ets/ani/wantagent/BUILD.gn @@ -0,0 +1,61 @@ +# 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("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("aniwantagent") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime", + ] + + sources = [ "src/ani_want_agent.cpp" ] + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_start_options", + "${ability_runtime_innerkits_path}/error_utils:ability_runtime_error_util", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_innerkits_path}/wantagent:wantagent_innerkits", + "${ability_runtime_native_path}/ability/native:abilitykit_native", + "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_path}/frameworks/ets/ani/ani_wantagent_common:ani_wantagent_common", + ] + + external_deps = [ + "ability_base:want", + "access_token:libtokenid_sdk", + "c_utils:utils", + "hilog:libhilog", + "runtime_core:ani", + ] + + cflags_cc = [] + if (os_dlp_part_enabled) { + cflags_cc += [ "-DWITH_DLP" ] + } + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/wantagent/include/ani_want_agent.h b/frameworks/ets/ani/wantagent/include/ani_want_agent.h new file mode 100644 index 00000000000..bb9d83f6c9f --- /dev/null +++ b/frameworks/ets/ani/wantagent/include/ani_want_agent.h @@ -0,0 +1,101 @@ +/* + * 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_ANI_WANT_AGENT_H +#define OHOS_ABILITY_RUNTIME_ANI_WANT_AGENT_H + +#include "ability.h" +#include "completed_callback.h" +#include "context/application_context.h" +#include "ets_error_utils.h" +#include "ets_runtime.h" +#include "trigger_info.h" +#include "want.h" +#include "want_agent.h" +#include "want_agent_constant.h" +#include "want_params.h" + +namespace OHOS { +using namespace OHOS::AppExecFwk; +using namespace OHOS::AbilityRuntime::WantAgent; + +struct CallbackInfo { + std::shared_ptr wantAgent; + ani_vm *vm = nullptr; + ani_ref call = nullptr; +}; + +struct TriggerReceiveDataWorker { + WantAgent* wantAgent; + AAFwk::Want want; + int resultCode; + std::string resultData; + AAFwk::WantParams resultExtras; + ani_vm *vm = nullptr; + ani_ref call = nullptr; +}; + +struct WantAgentParams { + std::vector> wants = {}; + int32_t operationType = -1; + int32_t requestCode = -1; + std::vector wantAgentFlags = {}; + AAFwk::WantParams extraInfo = {}; +}; + +class EtsWantAgent : public std::enable_shared_from_this { +public: + EtsWantAgent() = default; + ~EtsWantAgent() = default; + static EtsWantAgent& GetInstance(); + static void Equal(ani_env *env, ani_object agent, ani_object otherAgent, ani_object call); + static void GetWant(ani_env *env, ani_object agent, ani_object call); + static void GetOperationType(ani_env *env, ani_object agent, ani_object call); + static void GetBundleName(ani_env *env, ani_object agent, ani_object call); + static void GetUid(ani_env *env, ani_object agent, ani_object call); + static void Cancel(ani_env *env, ani_object agent, ani_object call); + static void Trigger(ani_env *env, ani_object agent, ani_object triggerInfoObj, ani_object call); + static void GetWantAgent(ani_env *env, ani_object info, ani_object call); + static void Clean(ani_env *env, ani_object object); + +private: + void OnEqual(ani_env *env, ani_object agent, ani_object otherAgent, ani_object call); + void OnGetWant(ani_env *env, ani_object agent, ani_object call); + void OnGetOperationType(ani_env *env, ani_object agent, ani_object call); + void OnGetBundleName(ani_env *env, ani_object agent, ani_object call); + void OnGetUid(ani_env *env, ani_object agent, ani_object call); + void OnCancel(ani_env *env, ani_object agent, ani_object call); + void OnTrigger(ani_env *env, ani_object agent, ani_object triggerInfoObj, ani_object call); + void OnGetWantAgent(ani_env *env, ani_object info, ani_object call); + int32_t GetTriggerInfo(ani_env *env, ani_object triggerInfoObj, TriggerInfo &triggerInfo); + int32_t GetWantAgentParam(ani_env *env, ani_object info, WantAgentParams ¶ms); +}; + +class TriggerCompleteCallBack : public CompletedCallback { +public: + TriggerCompleteCallBack(); + virtual ~TriggerCompleteCallBack(); + +public: + void OnSendFinished(const AAFwk::Want &want, int resultCode, const std::string &resultData, + const AAFwk::WantParams &resultExtras) override; + void SetCallbackInfo(ani_vm *vm, ani_ref call); + void SetWantAgentInstance(std::shared_ptr wantAgent); + +private: + CallbackInfo triggerCompleteInfo_; +}; +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANI_WANT_AGENT_H diff --git a/frameworks/ets/ani/wantagent/src/ani_want_agent.cpp b/frameworks/ets/ani/wantagent/src/ani_want_agent.cpp new file mode 100644 index 00000000000..4472b875a0d --- /dev/null +++ b/frameworks/ets/ani/wantagent/src/ani_want_agent.cpp @@ -0,0 +1,698 @@ +/* + * 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 "ani_want_agent.h" + +#include "ability_runtime_error_util.h" +#include "ani_common_start_options.h" +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "ani_common_want_agent.h" +#include "ani_enum_convert.h" +#include "hilog_tag_wrapper.h" +#include "start_options.h" +#include "want_agent_helper.h" +#include "tokenid_kit.h" + +using namespace OHOS::AbilityRuntime; +namespace OHOS { +namespace { +constexpr int32_t ERR_NOT_OK = -1; +constexpr int32_t BUSINESS_ERROR_CODE_OK = 0; +constexpr int32_t PARAMETER_ERROR = -1; +constexpr const char* COMPLETE_DATA_IMPL_CLASS_NAME = "L@ohos/app/ability/wantAgent/wantAgent/CompleteDataImpl;"; +constexpr const char* WANT_AGENT_NAMESPACE = "L@ohos/app/ability/wantAgent/wantAgent;"; +constexpr const char* CLEANER_CLASS = "L@ohos/app/ability/wantAgent/wantAgent/Cleaner;"; + +bool CheckCallerIsSystemApp() +{ + auto selfToken = IPCSkeleton::GetSelfTokenID(); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Non-system app forbidden to call"); + return false; + } + return true; +} +} // namespace + +TriggerCompleteCallBack::TriggerCompleteCallBack() +{} + +TriggerCompleteCallBack::~TriggerCompleteCallBack() +{} + +void TriggerCompleteCallBack::SetCallbackInfo(ani_vm *vm, ani_ref call) +{ + triggerCompleteInfo_.vm = vm; + triggerCompleteInfo_.call = call; +} + +void TriggerCompleteCallBack::SetWantAgentInstance(std::shared_ptr wantAgent) +{ + triggerCompleteInfo_.wantAgent = wantAgent; +} + +void OnSendFinishedCallback(TriggerReceiveDataWorker *dataWorker) +{ + if (dataWorker == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null dataWorker"); + return; + } + ani_vm *etsVm = dataWorker->vm; + if (etsVm == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null etsVm"); + return; + } + ani_env *env = nullptr; + ani_status status = etsVm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetEnv failed status: %{public}d, or null env", status); + return; + } + ani_class cls = nullptr; + if ((status = env->FindClass(COMPLETE_DATA_IMPL_CLASS_NAME, &cls)) != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "FindClass failed status: %{public}d, or null class", status); + return; + } + ani_method method = nullptr; + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK || method == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Class_FindMethod failed status: %{public}d, or null method", status); + return; + } + ani_object object = nullptr; + if ((status = env->Object_New(cls, method, &object)) != ANI_OK || object == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Object_New failed status: %{public}d, or null object", status); + return; + } + env->Object_SetPropertyByName_Ref(object, "info", WrapWantAgent(env, dataWorker->wantAgent)); + env->Object_SetPropertyByName_Ref(object, "want", WrapWant(env, dataWorker->want)); + env->Object_SetPropertyByName_Double(object, "finalCode", static_cast(dataWorker->resultCode)); + env->Object_SetPropertyByName_Ref(object, "finalData", GetAniString(env, dataWorker->resultData)); + env->Object_SetPropertyByName_Ref(object, "extraInfo", WrapWantParams(env, dataWorker->resultExtras)); + + ani_object error = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK); + AsyncCallback(env, reinterpret_cast(dataWorker->call), error, object); + env->GlobalReference_Delete(dataWorker->call); +} + +void TriggerCompleteCallBack::OnSendFinished( + const AAFwk::Want &want, int resultCode, const std::string &resultData, const AAFwk::WantParams &resultExtras) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "OnSendFinished"); + if (triggerCompleteInfo_.call == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null CallBack"); + return; + } + TriggerReceiveDataWorker* dataWorker = new (std::nothrow) TriggerReceiveDataWorker(); + if (dataWorker == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null dataWorker"); + return; + } + dataWorker->want = want; + dataWorker->resultCode = resultCode; + dataWorker->resultData = resultData; + dataWorker->resultExtras = resultExtras; + dataWorker->vm = triggerCompleteInfo_.vm; + dataWorker->call = triggerCompleteInfo_.call; + if (triggerCompleteInfo_.wantAgent != nullptr) { + dataWorker->wantAgent = new (std::nothrow) WantAgent(triggerCompleteInfo_.wantAgent->GetPendingWant()); + } + OnSendFinishedCallback(dataWorker); + if (dataWorker != nullptr) { + delete dataWorker; + dataWorker = nullptr; + } +} + +EtsWantAgent& EtsWantAgent::GetInstance() +{ + static EtsWantAgent instance; + return instance; +} + +void EtsWantAgent::GetBundleName(ani_env *env, ani_object agent, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "GetBundleName called"); + GetInstance().OnGetBundleName(env, agent, call); +}; + +void EtsWantAgent::GetUid(ani_env *env, ani_object agent, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "GetUid called"); + GetInstance().OnGetUid(env, agent, call); +}; + +void EtsWantAgent::Cancel(ani_env *env, ani_object agent, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "Cancel called"); + GetInstance().OnCancel(env, agent, call); +}; + +void EtsWantAgent::Equal(ani_env *env, ani_object agent, ani_object otherAgent, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "Equal called"); + GetInstance().OnEqual(env, agent, otherAgent, call); +}; + +void EtsWantAgent::GetWant(ani_env *env, ani_object agent, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "GetWant called"); + GetInstance().OnGetWant(env, agent, call); +}; + +void EtsWantAgent::GetOperationType(ani_env *env, ani_object agent, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "GetOperationType called"); + GetInstance().OnGetOperationType(env, agent, call); +}; + +void EtsWantAgent::Trigger(ani_env *env, ani_object agent, ani_object triggerInfoObj, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "Trigger called"); + GetInstance().OnTrigger(env, agent, triggerInfoObj, call); +}; + +void EtsWantAgent::GetWantAgent(ani_env *env, ani_object info, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "GetWantAgent called"); + GetInstance().OnGetWantAgent(env, info, call); +} + +void EtsWantAgent::Clean(ani_env *env, ani_object object) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "Clean called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null env"); + return; + } + ani_long ptr = 0; + ani_status status = env->Object_GetFieldByName_Long(object, "ptr", &ptr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "ptr GetField status: %{public}d", status); + return; + } + if (ptr != 0) { + delete reinterpret_cast(ptr); + } +} + +void EtsWantAgent::OnGetBundleName(ani_env *env, ani_object agent, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null env"); + return; + } + WantAgent* pWantAgent = nullptr; + UnwrapWantAgent(env, agent, reinterpret_cast(&pWantAgent)); + if (pWantAgent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Parse pWantAgent failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; + } + std::shared_ptr wantAgent = std::make_shared(*pWantAgent); + std::string bundleName = ""; + ErrCode resultCode = WantAgentHelper::GetBundleName(wantAgent, bundleName); + ani_object error = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK); + if (resultCode != ERR_OK) { + error = EtsErrorUtil::CreateError(env, resultCode, AbilityRuntimeErrorUtil::GetErrMessage(resultCode)); + } + ani_string aniBundleName = GetAniString(env, bundleName); + AsyncCallback(env, call, error, reinterpret_cast(aniBundleName)); +} + +void EtsWantAgent::OnGetUid(ani_env *env, ani_object agent, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null env"); + return; + } + WantAgent* pWantAgent = nullptr; + UnwrapWantAgent(env, agent, reinterpret_cast(&pWantAgent)); + if (pWantAgent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Parse pWantAgent failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; + } + std::shared_ptr wantAgent = std::make_shared(*pWantAgent); + int uid = -1; + ErrCode resultCode = WantAgentHelper::GetUid(wantAgent, uid); + ani_object error = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK); + if (resultCode != ERR_OK) { + error = EtsErrorUtil::CreateError(env, resultCode, AbilityRuntimeErrorUtil::GetErrMessage(resultCode)); + } + AsyncCallback(env, call, error, CreateDouble(env, static_cast(uid))); +} + +void EtsWantAgent::OnCancel(ani_env *env, ani_object agent, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null env"); + return; + } + WantAgent* pWantAgent = nullptr; + UnwrapWantAgent(env, agent, reinterpret_cast(&pWantAgent)); + if (pWantAgent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Parse pWantAgent failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; + } + std::shared_ptr wantAgent = std::make_shared(*pWantAgent); + ErrCode resultCode = WantAgentHelper::Cancel(wantAgent); + ani_object error = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK); + if (resultCode != NO_ERROR) { + error = EtsErrorUtil::CreateError(env, resultCode, AbilityRuntimeErrorUtil::GetErrMessage(resultCode)); + } + AsyncCallback(env, call, error, nullptr); +} + +void EtsWantAgent::OnEqual(ani_env *env, ani_object agent, ani_object otherAgent, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null env"); + return; + } + WantAgent* pWantAgentFirst = nullptr; + WantAgent* pWantAgentSecond = nullptr; + UnwrapWantAgent(env, agent, reinterpret_cast(&pWantAgentFirst)); + UnwrapWantAgent(env, otherAgent, reinterpret_cast(&pWantAgentSecond)); + if (pWantAgentFirst == nullptr || pWantAgentSecond == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null pWantAgentFirst or pWantAgentSecond"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; + } + std::shared_ptr wantAgentFirst = std::make_shared(*pWantAgentFirst); + std::shared_ptr wantAgentSecond = std::make_shared(*pWantAgentSecond); + ErrCode resultCode = WantAgentHelper::IsEquals(wantAgentFirst, wantAgentSecond); + ani_object error = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK); + bool ret = false; + if (resultCode == ERR_NOT_OK) { + ret = false; + } else if (resultCode == ERR_OK) { + ret = true; + } else { + error = EtsErrorUtil::CreateError(env, resultCode, AbilityRuntimeErrorUtil::GetErrMessage(resultCode)); + } + AsyncCallback(env, call, error, CreateBoolean(env, static_cast(ret))); +} + +void EtsWantAgent::OnGetWant(ani_env *env, ani_object agent, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null env"); + return; + } + WantAgent* pWantAgent = nullptr; + if (!CheckCallerIsSystemApp()) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Non-system app"); + EtsErrorUtil::ThrowError(env, ERR_ABILITY_RUNTIME_NOT_SYSTEM_APP); + return; + } + UnwrapWantAgent(env, agent, reinterpret_cast(&pWantAgent)); + if (pWantAgent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Parse pWantAgent failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; + } + std::shared_ptr wantAgent = std::make_shared(*pWantAgent); + std::shared_ptr want = std::make_shared(); + auto retCode = WantAgentHelper::GetWant(wantAgent, want); + ani_object wantAniObj = nullptr; + ani_object error = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK); + if (retCode != NO_ERROR) { + error = EtsErrorUtil::CreateError(env, retCode, AbilityRuntimeErrorUtil::GetErrMessage(retCode)); + wantAniObj = WrapWant(env, AAFwk::Want()); + } else { + wantAniObj = WrapWant(env, *want); + } + AsyncCallback(env, call, error, wantAniObj); +} + +void EtsWantAgent::OnGetOperationType(ani_env *env, ani_object agent, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null env"); + return; + } + WantAgent* pWantAgent = nullptr; + UnwrapWantAgent(env, agent, reinterpret_cast(&pWantAgent)); + if (pWantAgent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Parse pWantAgent failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; + } + std::shared_ptr wantAgent = std::make_shared(*pWantAgent); + int32_t operType = NO_ERROR; + int32_t retCode = NO_ERROR; + retCode = WantAgentHelper::GetType(wantAgent, operType); + ani_object error = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK); + if (retCode != NO_ERROR) { + error = EtsErrorUtil::CreateError(env, retCode, AbilityRuntimeErrorUtil::GetErrMessage(retCode)); + } + AsyncCallback(env, call, error, CreateDouble(env, static_cast(operType))); +} + +int32_t EtsWantAgent::GetWantAgentParam(ani_env *env, ani_object info, WantAgentParams ¶ms) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "GetWantAgentParam called"); + ani_ref wantsRef = nullptr; + ani_status status = env->Object_GetPropertyByName_Ref(info, "wants", &wantsRef); + if (status != ANI_OK || wantsRef == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "wants GetProperty status: %{public}d, or null wantsRef", status); + return PARAMETER_ERROR; + } + ani_array_ref wantsArr = reinterpret_cast(wantsRef); + ani_size length = 0; + if ((status = env->Array_GetLength(wantsArr, &length)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "wants Array_GetLength failed status: %{public}d", status); + return PARAMETER_ERROR; + } + for (size_t i = 0; i < length; i++) { + ani_ref wantRef = nullptr; + if ((status = env->Array_Get_Ref(wantsArr, i, &wantRef)) != ANI_OK || wantRef == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Array_Get_Ref failed status: %{public}d, or null wantRef", status); + return PARAMETER_ERROR; + } + std::shared_ptr want = std::make_shared(); + if (!UnwrapWant(env, reinterpret_cast(wantRef), *want)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "UnwrapWant failed"); + return PARAMETER_ERROR; + } + params.wants.emplace_back(want); + } + + ani_boolean isUndefined = true; + ani_ref actionTypeRef = nullptr; + if (!GetPropertyRef(env, info, "actionType", actionTypeRef, isUndefined) || actionTypeRef == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed, or null actionTypeRef"); + return PARAMETER_ERROR; + } + if (!isUndefined) { + AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative( + env, reinterpret_cast(actionTypeRef), params.operationType); + } + + ani_double dRequestCode = 0.0; + if ((status = env->Object_GetPropertyByName_Double(info, "requestCode", &dRequestCode)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Object_GetPropertyByName_Double failed status: %{public}d", status); + return PARAMETER_ERROR; + } + params.requestCode = dRequestCode; + + ani_ref actionFlagsRef = nullptr; + if (!GetPropertyRef(env, info, "actionFlags", actionFlagsRef, isUndefined) || actionFlagsRef == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed, or null actionFlagsRef"); + return PARAMETER_ERROR; + } + ani_array_ref actionFlagsArr = reinterpret_cast(actionFlagsRef); + if (!isUndefined) { + ani_size actionFlagsLen = 0; + if ((status = env->Array_GetLength(actionFlagsArr, &actionFlagsLen)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Array_GetLength failed status: %{public}d", status); + return PARAMETER_ERROR; + } + for (size_t i = 0; i < actionFlagsLen; i++) { + ani_ref actionFlagRef = nullptr; + if ((status = env->Array_Get_Ref(actionFlagsArr, i, &actionFlagRef)) != ANI_OK || + actionFlagRef == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Array_Get_Ref failed status: %{public}d, or null actionFlagRef", status); + return PARAMETER_ERROR; + } + int32_t actionFlag = 0; + AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative( + env, reinterpret_cast(actionFlagRef), actionFlag); + params.wantAgentFlags.emplace_back(static_cast(actionFlag)); + } + } + + ani_ref extraInfoRef = nullptr; + if (!GetPropertyRef(env, info, "extraInfos", extraInfoRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return PARAMETER_ERROR; + } + if (isUndefined) { + if (!GetPropertyRef(env, info, "extraInfo", extraInfoRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return PARAMETER_ERROR; + } + } + if (!isUndefined) { + if (!UnwrapWantParams(env, extraInfoRef, params.extraInfo)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Convert extraInfo failed"); + return PARAMETER_ERROR; + } + } + return BUSINESS_ERROR_CODE_OK; +} + +void EtsWantAgent::OnTrigger(ani_env *env, ani_object agent, ani_object triggerInfoObj, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null env"); + return; + } + WantAgent* pWantAgent = nullptr; + UnwrapWantAgent(env, agent, reinterpret_cast(&pWantAgent)); + if (pWantAgent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Parse pWantAgent failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; + } + TriggerInfo triggerInfo; + int32_t ret = GetTriggerInfo(env, triggerInfoObj, triggerInfo); + if (ret != BUSINESS_ERROR_CODE_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Get trigger info error"); + EtsErrorUtil::ThrowInvalidParamError(env, "Get trigger info error. TriggerInfo must be a TriggerInfo."); + return; + } + ani_vm *etsVm = nullptr; + ani_status status = env->GetVM(&etsVm); + if (status != ANI_OK || etsVm == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetVM failed status: %{public}d, or null etsVm", status); + return; + } + ani_boolean isUndefined = true; + if ((status = env->Reference_IsUndefined(call, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Reference_IsUndefined failed status: %{public}d", status); + return; + } + ani_ref callbackRef = nullptr; + if (!isUndefined) { + if ((status = env->GlobalReference_Create(call, &callbackRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GlobalReference_Create failed status: %{public}d", status); + return; + } + } + auto triggerObj = std::make_shared(); + triggerObj->SetCallbackInfo(etsVm, callbackRef); + triggerObj->SetWantAgentInstance(std::make_shared(pWantAgent->GetPendingWant())); + std::shared_ptr wantAgent = std::make_shared(*pWantAgent); + sptr completedData; + WantAgentHelper::TriggerWantAgent(wantAgent, triggerObj, triggerInfo, completedData, nullptr); +} + +int32_t EtsWantAgent::GetTriggerInfo(ani_env *env, ani_object triggerInfoObj, TriggerInfo &triggerInfo) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "GetTriggerInfo called"); + ani_double dCode = 0.0; + ani_status status = env->Object_GetPropertyByName_Double(triggerInfoObj, "code", &dCode); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "code GetProperty failed status: %{public}d", status); + return ERR_NOT_OK; + } + const int32_t code = static_cast(dCode); + + ani_ref wantRef = nullptr; + ani_boolean isUndefined = true; + std::shared_ptr want = nullptr; + if (!GetPropertyRef(env, triggerInfoObj, "want", wantRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return ERR_NOT_OK; + } + if (!isUndefined) { + want = std::make_shared(); + if (!UnwrapWant(env, reinterpret_cast(wantRef), *want)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "UnwrapWant failed"); + return ERR_NOT_OK; + } + } + + std::string permission = ""; + ani_ref permissionRef = nullptr; + if (!GetPropertyRef(env, triggerInfoObj, "permission", permissionRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return ERR_NOT_OK; + } + if (!isUndefined && !GetStdString(env, reinterpret_cast(permissionRef), permission)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Failed to get permission string from permissionRef"); + return ERR_NOT_OK; + } + + ani_ref extraInfoRef = nullptr; + if (!GetPropertyRef(env, triggerInfoObj, "extraInfos", extraInfoRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return ERR_NOT_OK; + } + if (isUndefined) { + if (!GetPropertyRef(env, triggerInfoObj, "extraInfo", extraInfoRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return ERR_NOT_OK; + } + } + std::shared_ptr extraInfo = nullptr; + if (!isUndefined) { + extraInfo = std::make_shared(); + if (!UnwrapWantParams(env, extraInfoRef, *extraInfo)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Convert extraInfo failed"); + return ERR_NOT_OK; + } + } + + ani_ref startOptionsRef = nullptr; + if (!GetPropertyRef(env, triggerInfoObj, "startOptions", startOptionsRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return ERR_NOT_OK; + } + std::shared_ptr startOptions = nullptr; + if (!isUndefined) { + if (!CheckCallerIsSystemApp()) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Non-system app"); + EtsErrorUtil::ThrowError(env, ERR_ABILITY_RUNTIME_NOT_SYSTEM_APP); + return ERR_NOT_OK; + } + startOptions = std::make_shared(); + if (!UnwrapStartOptions(env, reinterpret_cast(startOptionsRef), *startOptions)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "UnwrapStartOptions failed"); + return ERR_NOT_OK; + } + } + + TriggerInfo triggerInfoData(permission, extraInfo, want, startOptions, code); + triggerInfo = triggerInfoData; + return BUSINESS_ERROR_CODE_OK; +} + +void EtsWantAgent::OnGetWantAgent(ani_env *env, ani_object info, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null env"); + return; + } + std::shared_ptr parasobj = std::make_shared(); + int32_t ret = GetWantAgentParam(env, info, *parasobj); + if (ret != 0) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Failed to get wantAgent parameter. Agent must be a WantAgent."); + EtsErrorUtil::ThrowInvalidParamError(env, "Failed to get wantAgent parameter. Agent must be a WantAgent."); + return; + } + std::shared_ptr extraInfo = std::make_shared(parasobj->extraInfo); + WantAgentInfo wantAgentInfo(parasobj->requestCode, + static_cast(parasobj->operationType), + parasobj->wantAgentFlags, + parasobj->wants, + extraInfo); + auto context = OHOS::AbilityRuntime::Context::GetApplicationContext(); + std::shared_ptr wantAgent = nullptr; + ErrCode result = WantAgentHelper::GetWantAgent(context, wantAgentInfo, wantAgent); + ani_object error = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK); + ani_object retObj = CreateLong(env, ERR_NOT_OK); + if (result != NO_ERROR) { + error = EtsErrorUtil::CreateError(env, result, AbilityRuntimeErrorUtil::GetErrMessage(result)); + AsyncCallback(env, call, error, retObj); + return; + } + if (wantAgent == nullptr) { + result = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER; + error = EtsErrorUtil::CreateError(env, result, AbilityRuntimeErrorUtil::GetErrMessage(result)); + AsyncCallback(env, call, error, retObj); + return; + } + WantAgent *pWantAgent = new (std::nothrow) WantAgent(wantAgent->GetPendingWant()); + if (pWantAgent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null pWantAgent"); + result = ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER; + error = EtsErrorUtil::CreateError(env, result, AbilityRuntimeErrorUtil::GetErrMessage(result)); + AsyncCallback(env, call, error, retObj); + } else { + retObj = WrapWantAgent(env, pWantAgent); + if (retObj == nullptr) { + delete pWantAgent; + pWantAgent = nullptr; + } + AsyncCallback(env, call, error, retObj); + } +} + +ani_status BindNativeFunctions(ani_env *env) +{ + ani_namespace ns = nullptr; + ani_status status = env->FindNamespace(WANT_AGENT_NAMESPACE, &ns); + if (status != ANI_OK || ns == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "FindNamespace failed status: %{public}d, or null ns", status); + return status; + } + std::array functions = { + ani_native_function { "nativeGetBundleName", nullptr, reinterpret_cast(EtsWantAgent::GetBundleName) }, + ani_native_function { "nativeGetUid", nullptr, reinterpret_cast(EtsWantAgent::GetUid) }, + ani_native_function { + "nativeGetOperationType", nullptr, reinterpret_cast(EtsWantAgent::GetOperationType) }, + ani_native_function { "nativeCancel", nullptr, reinterpret_cast(EtsWantAgent::Cancel) }, + ani_native_function { "nativeEqual", nullptr, reinterpret_cast(EtsWantAgent::Equal) }, + ani_native_function { "nativeTrigger", nullptr, reinterpret_cast(EtsWantAgent::Trigger) }, + ani_native_function { "nativeGetWant", nullptr, reinterpret_cast(EtsWantAgent::GetWant) }, + ani_native_function { "nativeGetWantAgent", nullptr, reinterpret_cast(EtsWantAgent::GetWantAgent) }, + }; + if ((status = env->Namespace_BindNativeFunctions(ns, functions.data(), functions.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Namespace_BindNativeFunctions failed status: %{public}d", status); + return status; + } + + ani_class cleanerCls = nullptr; + if ((status = env->FindClass(CLEANER_CLASS, &cleanerCls)) != ANI_OK || cleanerCls == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Cleaner FindClass failed status: %{public}d, or null cleanerCls", status); + return status; + } + std::array cleanerMethods = { + ani_native_function {"clean", nullptr, reinterpret_cast(EtsWantAgent::Clean) }, + }; + if ((status = env->Class_BindNativeMethods(cleanerCls, cleanerMethods.data(), cleanerMethods.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Class_BindNativeMethods failed status: %{public}d", status); + return status; + } + return ANI_OK; +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "ANI_Constructor"); + ani_env *env = nullptr; + if (vm == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null vm"); + return ANI_NOT_FOUND; + } + ani_status status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetEnv failed status: %{public}d, or null env", status); + return status; + } + if ((status = BindNativeFunctions(env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "BindNativeFunctions failed status: %{public}d", status); + return status; + } + *result = ANI_VERSION_1; + return ANI_OK; +} +} +} // namespace OHOS diff --git a/frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets b/frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets index 4c72a344a57..e2d28887f5c 100644 --- a/frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets +++ b/frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets @@ -19,6 +19,18 @@ namespace AbilityConstant { launchReasonMessage?: string; lastExitReason: LastExitReason; lastExitMessage: string; + lastExitDetailInfo?: LastExitDetailInfo; + } + + export interface LastExitDetailInfo { + pid: number; + processName: string; + uid: number; + exitSubReason: number; + exitMsg: string; + rss: number; + pss: number; + timestamp: number; } export enum LaunchReason { @@ -102,6 +114,18 @@ class LaunchParamImpl implements AbilityConstant.LaunchParam { launchReasonMessage?: string | undefined; lastExitReason: AbilityConstant.LastExitReason = AbilityConstant.LastExitReason.UNKNOWN; lastExitMessage: string = ''; + lastExitDetailInfo?: AbilityConstant.LastExitDetailInfo = undefined; +} + +class LastExitDetailInfoImpl implements AbilityConstant.LastExitDetailInfo { + pid: number = 0; + processName: string = ''; + uid: number = 0; + exitSubReason: number = 0; + exitMsg: string = ''; + rss: number = 0; + pss: number = 0; + timestamp: number = 0; } export default AbilityConstant; diff --git a/frameworks/ets/ets/@ohos.app.ability.InsightIntentContext.ets b/frameworks/ets/ets/@ohos.app.ability.InsightIntentContext.ets new file mode 100644 index 00000000000..40a7569f487 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.InsightIntentContext.ets @@ -0,0 +1,54 @@ +/* + * 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, AsyncCallback } from '@ohos.base'; +import Want from '@ohos.app.ability.Want'; + +export default class InsightIntentContext { + nativeContext: long; + + public native nativeStartAbilitySync(want: Want): BusinessError; + + startAbility(want: Want, callback: AsyncCallback): void { + let p1 = taskpool.execute((): BusinessError => { + return this.nativeStartAbilitySync(want); + }); + p1.then((e: NullishType) => { + let retError = e as BusinessError; + callback(retError, undefined); + }, (err: BusinessError): void => { + callback(err, undefined); + }); + } + + startAbility(want: Want): Promise { + let p = new Promise((resolve: (v: undefined) => void, reject: (error: BusinessError) => void): void => { + let p1 = taskpool.execute((): BusinessError => { + return this.nativeStartAbilitySync(want); + }); + p1.then((e: NullishType) => { + let retError = e as BusinessError; + if (retError.code === 0) { + resolve(undefined); + } else { + reject(retError); + } + }).catch((err: BusinessError): void => { + reject(err); + }); + }); + return p; + } +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.InsightIntentExecutor.ets b/frameworks/ets/ets/@ohos.app.ability.InsightIntentExecutor.ets new file mode 100644 index 00000000000..e1384395f92 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.InsightIntentExecutor.ets @@ -0,0 +1,147 @@ +/* + * 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 window from '@ohos.window'; +import insightIntent from './@ohos.app.ability.insightIntent'; +import InsightIntentContext from '@ohos.app.ability.InsightIntentContext'; +import type UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; + +export default class InsightIntentExecutor { + context: InsightIntentContext = {}; + public nativeExecutor: long = 0; + public isOnExecuteInUIAbilityForegroundModeAsync: boolean = true; + public isOnExecuteInUIAbilityBackgroundModeAsync: boolean = true; + public isOnExecuteInUIExtensionAbilityAsync: boolean = true; + public isOnExecuteInServiceExtensionAbilityAsync: boolean = true; + + public native nativeOnExecuteResult(data: insightIntent.ExecuteResult): void; + + public callOnExecuteInUIAbilityForegroundMode(name: string, param: Record, + pageLoader: window.WindowStage): insightIntent.ExecuteResult { + let p = this.onExecuteInUIAbilityForegroundModeAsync(name, param, pageLoader); + if (this.isOnExecuteInUIAbilityForegroundModeAsync) { + p.then((result: insightIntent.ExecuteResult): void => { + this.nativeOnExecuteResult(result); + }); + let ret: insightIntent.ExecuteResult = {}; + return ret; + } else { + return this.onExecuteInUIAbilityForegroundMode(name, param, pageLoader); + } + } + + public callOnExecuteInUIAbilityBackgroundMode(name: string, param: Record): + insightIntent.ExecuteResult { + let p = this.onExecuteInUIAbilityBackgroundModeAsync(name, param); + if (this.isOnExecuteInUIAbilityBackgroundModeAsync) { + p.then((result: insightIntent.ExecuteResult): void => { + this.nativeOnExecuteResult(result); + }); + let ret: insightIntent.ExecuteResult = {}; + return ret; + } else { + return this.onExecuteInUIAbilityBackgroundMode(name, param); + } + } + + public callOnExecuteInUIExtensionAbility(name: string, param: Record, + pageLoader: UIExtensionContentSession): insightIntent.ExecuteResult { + let p = this.onExecuteInUIExtensionAbilityAsync(name, param, pageLoader); + if (this.isOnExecuteInUIExtensionAbilityAsync) { + p.then((result: insightIntent.ExecuteResult): void => { + this.nativeOnExecuteResult(result); + }); + let ret: insightIntent.ExecuteResult = {}; + return ret; + } else { + return this.onExecuteInUIExtensionAbility(name, param, pageLoader); + } + } + + public callOnExecuteInServiceExtensionAbility(name: string, param: Record): + insightIntent.ExecuteResult { + let p = this.onExecuteInServiceExtensionAbilityAsync(name, param); + if (this.isOnExecuteInServiceExtensionAbilityAsync) { + p.then((result: insightIntent.ExecuteResult): void => { + this.nativeOnExecuteResult(result); + }); + let ret: insightIntent.ExecuteResult = {}; + return ret; + } else { + return this.onExecuteInServiceExtensionAbility(name, param); + } + } + + onExecuteInUIAbilityForegroundMode(name: string, param: Record, pageLoader: window.WindowStage): + insightIntent.ExecuteResult { + let ret: insightIntent.ExecuteResult; + return ret; + } + + onExecuteInUIAbilityForegroundModeAsync(name: string, param: Record, pageLoader: window.WindowStage): + Promise { + this.isOnExecuteInUIAbilityForegroundModeAsync = false; + return new Promise(( + resolve: (a: insightIntent.ExecuteResult) => void, + reject: (err: Error) => void): void => { + }); + } + + onExecuteInUIAbilityBackgroundMode(name: string, param: Record): + insightIntent.ExecuteResult { + let ret: insightIntent.ExecuteResult; + return ret; + } + + onExecuteInUIAbilityBackgroundModeAsync(name: string, param: Record): + Promise { + this.isOnExecuteInUIAbilityBackgroundModeAsync = false; + return new Promise(( + resolve: (a: insightIntent.ExecuteResult) => void, + reject: (err: Error) => void): void => { + }); + } + + onExecuteInUIExtensionAbility(name: string, param: Record, pageLoader: UIExtensionContentSession): + insightIntent.ExecuteResult { + let ret: insightIntent.ExecuteResult; + return ret; + } + + onExecuteInUIExtensionAbilityAsync(name: string, param: Record, + pageLoader: UIExtensionContentSession): + Promise { + this.isOnExecuteInUIExtensionAbilityAsync = false; + return new Promise(( + resolve: (a: insightIntent.ExecuteResult) => void, + reject: (err: Error) => void): void => { + }); + } + + onExecuteInServiceExtensionAbility(name: string, param: Record): + insightIntent.ExecuteResult { + let ret: insightIntent.ExecuteResult; + return ret; + } + + onExecuteInServiceExtensionAbilityAsync(name: string, param: Record): + Promise { + this.isOnExecuteInServiceExtensionAbilityAsync = false; + return new Promise(( + resolve: (a: insightIntent.ExecuteResult) => void, + reject: (err: Error) => void): void => { + }); + } +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.OpenLinkOptions.ets b/frameworks/ets/ets/@ohos.app.ability.OpenLinkOptions.ets new file mode 100644 index 00000000000..bd90238425e --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.OpenLinkOptions.ets @@ -0,0 +1,24 @@ +/* + * 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. + */ + +export default interface OpenLinkOptions { + appLinkingOnly?: boolean; + parameters?: Record; +} + +class OpenLinkOptionsImpl implements OpenLinkOptions { + appLinkingOnly?: boolean|undefined; + parameters?: Record|undefined; +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.ServiceExtensionAbility.ets b/frameworks/ets/ets/@ohos.app.ability.ServiceExtensionAbility.ets index d682398fc09..2227d60a14c 100644 --- a/frameworks/ets/ets/@ohos.app.ability.ServiceExtensionAbility.ets +++ b/frameworks/ets/ets/@ohos.app.ability.ServiceExtensionAbility.ets @@ -100,4 +100,12 @@ export default class ServiceExtensionAbility { onDisconnectAsync(want: Want): Promise { return new Promise((resolve: (a: undefined) => void, reject: (err: Error) => void): void => {}); } + + onConfigurationUpdate(newConfig: Configuration): void { + } + + onDump(params: Array): Array { + let ret:Array; + return ret; + } } \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.StartOptions.ets b/frameworks/ets/ets/@ohos.app.ability.StartOptions.ets index c4a6565f60e..2d25b6e930d 100644 --- a/frameworks/ets/ets/@ohos.app.ability.StartOptions.ets +++ b/frameworks/ets/ets/@ohos.app.ability.StartOptions.ets @@ -13,6 +13,26 @@ * limitations under the License. */ +import contextConstant from '@ohos.app.ability.contextConstant'; +import image from '@ohos.multimedia.image'; +import bundleManager from '@ohos.bundle.bundleManager'; + export default class StartOptions { + windowMode?: number; displayId?: number; -} + withAnimation?: boolean; + windowLeft?: number; + windowTop?: number; + windowWidth?: number; + windowHeight?: number; + windowFocused?: boolean; + processMode?: contextConstant.ProcessMode; + startupVisibility?: contextConstant.StartupVisibility; + startWindowBackgroundColor?: string; + startWindowIcon?: image.PixelMap; + supportWindowModes?: Array; + minWindowWidth?: number; + minWindowHeight?: number; + maxWindowWidth?: number; + maxWindowHeight?: number; +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.UIAbility.ets b/frameworks/ets/ets/@ohos.app.ability.UIAbility.ets index 63fd48d05b8..b3d25a9be05 100644 --- a/frameworks/ets/ets/@ohos.app.ability.UIAbility.ets +++ b/frameworks/ets/ets/@ohos.app.ability.UIAbility.ets @@ -54,9 +54,15 @@ export default class UIAbility { onWindowStageCreate(windowStage: window.WindowStage): void { } + onWindowStageWillDestroy(windowStage: window.WindowStage): void { + } + onWindowStageDestroy(): void { } + onWindowStageRestore(windowStage: window.WindowStage): void { + } + onDestroy(): void { } diff --git a/frameworks/ets/ets/@ohos.app.ability.UIExtensionContentSession.ets b/frameworks/ets/ets/@ohos.app.ability.UIExtensionContentSession.ets index e1e5e6642f5..d48ecfb4593 100644 --- a/frameworks/ets/ets/@ohos.app.ability.UIExtensionContentSession.ets +++ b/frameworks/ets/ets/@ohos.app.ability.UIExtensionContentSession.ets @@ -19,13 +19,42 @@ import { BusinessError } from '@ohos.base'; import uiExtensionHost from '@ohos.uiExtensionHost'; import { LocalStorage } from '@ohos.arkui.stateManagement'; import AsyncCallbackWrapper from './utils/AbilityUtils'; + +class Cleaner { + static callback(cleaner: Cleaner): void { + cleaner.clean() + } + constructor(targetPtr: long) { + this.targetPtr = targetPtr + } + native clean(): void + private targetPtr: long = 0 +} +let destroyRegister = new FinalizationRegistry(Cleaner.callback) +let unregisterToken = new object() + export default class UIExtensionContentSession { nativeContextSession:long = 0; + private cleaner: Cleaner | null = null; + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr) + destroyRegister.register(this, this.cleaner!, unregisterToken); + } + unregisterCleaner(): void { + destroyRegister.unregister(unregisterToken); + } + constructor(contextSession:long) { + if(this.nativeContextSession == 0){ + this.nativeContextSession = contextSession; + } + this.registerCleaner(this.nativeContextSession) + } native nativeSendData(data: Record): void; native loadContent(path: string, storage?: LocalStorage): void; native setWindowBackgroundColor(color: string): void; native getUIExtensionHostWindowProxy(): uiExtensionHost.UIExtensionHostWindowProxy; native nativeSetReceiveDataCallback(callback: (data: Record) => void): void; + native nativeSetReceiveDataForResultCallback(callback: (data: Record) => Record): void; native terminateSelfSync(callback:AsyncCallbackWrapper): void; native terminateSelfWithResultSync(parameter: AbilityResult, callback:AsyncCallbackWrapper): void; @@ -37,6 +66,10 @@ export default class UIExtensionContentSession { this.nativeSetReceiveDataCallback(callback); } + setReceiveDataForResultCallback(callback: (data: Record) => Record): void { + this.nativeSetReceiveDataForResultCallback(callback); + } + terminateSelf(callback:AsyncCallback): void { let myCall = new AsyncCallbackWrapper(callback); taskpool.execute((): void => { diff --git a/frameworks/ets/ets/@ohos.app.ability.abilityDelegatorRegistry.ets b/frameworks/ets/ets/@ohos.app.ability.abilityDelegatorRegistry.ets index 039352f8371..687ae42a14f 100644 --- a/frameworks/ets/ets/@ohos.app.ability.abilityDelegatorRegistry.ets +++ b/frameworks/ets/ets/@ohos.app.ability.abilityDelegatorRegistry.ets @@ -15,6 +15,9 @@ import { AbilityDelegator as _AbilityDelegator } from 'application.AbilityDelegator'; import { AbilityDelegatorArgs as _AbilityDelegatorArgs } from 'application.abilityDelegatorArgs'; +import { AbilityMonitor as _AbilityMonitor } from 'application.AbilityMonitor'; +import { AbilityStageMonitor as _AbilityStageMonitor } from 'application.AbilityStageMonitor'; +import { ShellCmdResult as _ShellCmdResult } from 'application.shellCmdResult'; export default namespace abilityDelegatorRegistry { loadLibrary("ability_delegator_registry_ani_kit.z") @@ -23,6 +26,16 @@ export default namespace abilityDelegatorRegistry { export native function getArguments(): AbilityDelegatorArgs; + export enum AbilityLifecycleState { + UNINITIALIZED, + CREATE, + FOREGROUND, + BACKGROUND, + DESTROY + } export type AbilityDelegator = _AbilityDelegator; export type AbilityDelegatorArgs = _AbilityDelegatorArgs; + export type AbilityMonitor = _AbilityMonitor; + export type ShellCmdResult = _ShellCmdResult; + export type AbilityStageMonitor = _AbilityStageMonitor; } diff --git a/frameworks/ets/ets/@ohos.app.ability.abilityManager.ets b/frameworks/ets/ets/@ohos.app.ability.abilityManager.ets new file mode 100644 index 00000000000..fe887d4662a --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.abilityManager.ets @@ -0,0 +1,72 @@ +/* + * 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 AbilityStateData from 'application.AbilityStateData'; +import { ElementName } from 'bundleManager.ElementName' +import { BusinessError, AsyncCallback } from '@ohos.base'; +import AsyncCallbackWrapper from './utils/AbilityUtils'; + +export default namespace abilityManager { + loadLibrary("ability_manager_ani_kit.z") + + export native function nativeGetForegroundUIAbilities(): Array; + export native function getForegroundUIAbilitiesCallback(callback:AsyncCallbackWrapper>) : void; + export native function nativeGetTopAbility(callback:AsyncCallbackWrapper) : void; + + export function getForegroundUIAbilities():Promise> { + let p = new Promise>((resolve: (data: Array) => void, reject: (error: Error) => void): void => { + let executeFunc = (): Array => { + return nativeGetForegroundUIAbilities(); + }; + let p1 = taskpool.execute(executeFunc); + p1.then((e :NullishType)=>{ + let abilities: Array = e as Array; + resolve(abilities); + }, (err: Error): void => { + reject(err); + }); + }); + return p; + } + + export function getForegroundUIAbilities(callback: AsyncCallback, void>): void { + let myCall = new AsyncCallbackWrapper>(callback); + taskpool.execute((): void => { + abilityManager.getForegroundUIAbilitiesCallback(myCall); + }) + } + export function getTopAbility():Promise { + let p = new Promise((resolve: (data: ElementName)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: ElementName | undefined)=>{ + if (err == null || err.code == 0) { + resolve(data as ElementName); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + abilityManager.nativeGetTopAbility(myCall); + }); + }); + return p; +} + +export function getTopAbility(callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute( (): void => { + abilityManager.nativeGetTopAbility(myCall); + }); +} +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.appManager.ets b/frameworks/ets/ets/@ohos.app.ability.appManager.ets new file mode 100644 index 00000000000..a465ce4d46f --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.appManager.ets @@ -0,0 +1,180 @@ +/* + * 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 { ProcessInformation as _ProcessInformation } from 'application.ProcessInformation'; +import { RunningMultiAppInfo as _RunningMultiAppInfo } from 'application.RunningMultiAppInfo'; +import _AppStateData from 'application.AppStateData'; +import hilog from '@ohos.hilog'; +import { BusinessError, AsyncCallback } from '@ohos.base'; +import AsyncCallbackWrapper from './utils/AbilityUtils'; + +export default namespace appManager { +loadLibrary("app_manager_ani.z") + +export type ProcessInformation = _ProcessInformation; +export type AppStateData = _AppStateData; +export type RunningMultiAppInfo = _RunningMultiAppInfo; + +export enum PreloadMode { + PRESS_DOWN +} + +export enum ApplicationState { + STATE_CREATE, + STATE_FOREGROUND, + STATE_ACTIVE, + STATE_BACKGROUND, + STATE_DESTROY +} + +export enum ProcessState { + STATE_CREATE, + STATE_FOREGROUND, + STATE_ACTIVE, + STATE_BACKGROUND, + STATE_DESTROY +} + +export native function nativePreloadApplication(callback: AsyncCallbackWrapper, bundleName: string, userId: number, + mode: PreloadMode, appIndex?: number): void; +export function preloadApplication(bundleName: string, userId: number, mode: PreloadMode, appIndex?: number): Promise{ + let p:Promise = new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError | null)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null)=>{ + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativePreloadApplication(myCall, bundleName, userId, mode, appIndex); + }); + }); + return p; +} + +export native function nativeGetRunningProcessInformation(callback: AsyncCallbackWrapper>): void; +export function getRunningProcessInformation(callback: AsyncCallback>): void { + let myCall = new AsyncCallbackWrapper>(callback); + taskpool.execute((): void => { + appManager.nativeGetRunningProcessInformation(myCall); + }); +} + +export function getRunningProcessInformation(): Promise> { + let p = new Promise>((resolve:(data:Array)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper>((err: BusinessError | null, data: Array | undefined)=>{ + if (err == null || err.code == 0) { + resolve(data as Array); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeGetRunningProcessInformation(myCall); + }); + }); + return p; +} + +export native function nativeGetForegroundApplications(callback:AsyncCallbackWrapper>): void; +export function getForegroundApplications(callback: AsyncCallback>): void { + let myCall = new AsyncCallbackWrapper>(callback); + taskpool.execute((): void => { + appManager.nativeGetForegroundApplications(myCall); + }); +} + +export function getForegroundApplications(): Promise> { + let p = new Promise>((resolve:(data:Array)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper>((err: BusinessError | null, data: Array | undefined)=>{ + if (err == null || err.code == 0) { + resolve(data as Array); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeGetForegroundApplications(myCall); + }); + }); + return p; +} + +export native function nativeGetRunningMultiAppInfo(bundleName: string, callback: AsyncCallbackWrapper): void; +export function getRunningMultiAppInfo(bundleName: string): Promise { + let p = new Promise((resolve:(data: RunningMultiAppInfo)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: RunningMultiAppInfo | undefined)=>{ + if (err == null || err.code == 0) { + resolve(data as RunningMultiAppInfo); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeGetRunningMultiAppInfo(bundleName, myCall); + }); + }); + return p; +} + +export native function nativeGetRunningProcessInfoByBundleName(bundleName: string, callback:AsyncCallbackWrapper>):void; +export function getRunningProcessInfoByBundleName(bundleName: string, callback: AsyncCallback>): void { + let myCall = new AsyncCallbackWrapper>(callback); + taskpool.execute((): void => { + appManager.nativeGetRunningProcessInfoByBundleName(bundleName, myCall); + }); +} + +export function getRunningProcessInfoByBundleName(bundleName: string): Promise> { + let p = new Promise>((resolve:(data: Array)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper>((err: BusinessError | null, data: Array | undefined)=>{ + if (err == null || err.code == 0) { + resolve(data as Array); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeGetRunningProcessInfoByBundleName(bundleName, myCall); + }); + }); + return p; +} + +export native function nativeGetRunningProcessInfoByBundleNameAndUserId(bundleName: string, + userId: number, callback:AsyncCallbackWrapper>):void; +export function getRunningProcessInfoByBundleName(bundleName: string, userId: number, callback: AsyncCallback>): void { + let myCall = new AsyncCallbackWrapper>(callback); + taskpool.execute((): void => { + appManager.nativeGetRunningProcessInfoByBundleNameAndUserId(bundleName, userId, myCall); + }); +} + +export function getRunningProcessInfoByBundleName(bundleName: string, userId: number): Promise> { + let p = new Promise>((resolve:(data: Array)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper>((err: BusinessError | null, data: Array | undefined)=>{ + if (err == null || err.code == 0) { + resolve(data as Array); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeGetRunningProcessInfoByBundleNameAndUserId(bundleName, userId, myCall); + }); + }); + return p; +} +} // namespace appManager diff --git a/frameworks/ets/ets/@ohos.app.ability.application.ets b/frameworks/ets/ets/@ohos.app.ability.application.ets new file mode 100644 index 00000000000..f5654b6c45f --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.application.ets @@ -0,0 +1,78 @@ +/* + * 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 Context from 'application.Context'; +import { BusinessError, AsyncCallback } from '@ohos.base'; +import AsyncCallbackWrapper from './utils/AbilityUtils'; + +export default namespace application { + loadLibrary("application_ani.z") + export native function nativeCreateModuleContext(context: Context, bundleName: string, moduleName: string, + callback: AsyncCallbackWrapper): void; + + export native function nativeCreateBundleContext(context: Context, bundleName: string, + callback: AsyncCallbackWrapper): void; + + export function createModuleContext(context: Context, moduleName: string): Promise { + let p = + new Promise((resolve: (data: Context) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: Context | undefined) => { + if (err == null || err.code == 0) { + resolve(data as Context); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + application.nativeCreateModuleContext(context, "", moduleName, myCall); + }); + }); + return p; + } + + export function createModuleContext(context: Context, bundleName: string, moduleName: string): Promise { + let p = + new Promise((resolve: (data: Context) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: Context | undefined) => { + if (err == null || err.code == 0) { + resolve(data as Context); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + application.nativeCreateModuleContext(context, bundleName, moduleName, myCall); + }); + }); + return p; + } + + export function createBundleContext(context: Context, bundleName: string): Promise { + let p = + new Promise((resolve: (data: Context) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: Context | undefined) => { + if (err == null || err.code == 0) { + resolve(data as Context); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + application.nativeCreateBundleContext(context, bundleName, myCall); + }); + }); + return p; + } +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.insightIntent.ets b/frameworks/ets/ets/@ohos.app.ability.insightIntent.ets new file mode 100644 index 00000000000..cf3b65fefb5 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.insightIntent.ets @@ -0,0 +1,43 @@ +/* + * 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 Want from '@ohos.app.ability.Want'; +import wantConstant from '@ohos.app.ability.wantConstant'; + +namespace insightIntent { + + export enum ExecuteMode { + UI_ABILITY_FOREGROUND = 0, + UI_ABILITY_BACKGROUND = 1, + UI_EXTENSION_ABILITY = 2, + SERVICE_EXTENSION_ABILITY = 3, + } + + export interface ExecuteResult { + code: number; + result?: Record; + uris?: Array; + flags?: number; + } + + export class ExecuteResultInner implements ExecuteResult{ + code: number; + result?: Record; + uris?: Array; + flags?: number; + } +} + +export default insightIntent; \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.insightIntentDriver.ets b/frameworks/ets/ets/@ohos.app.ability.insightIntentDriver.ets new file mode 100644 index 00000000000..0f9362e7e4a --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.insightIntentDriver.ets @@ -0,0 +1,67 @@ +/* + * 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 Want from '@ohos.app.ability.Want'; +import wantConstant from '@ohos.app.ability.wantConstant'; +import { BusinessError, AsyncCallback } from '@ohos.base'; +import insightIntent from './@ohos.app.ability.insightIntent'; +import AsyncCallbackWrapper from './utils/AbilityUtils'; + +export default namespace insightIntentDriver { + + loadLibrary("insight_intent_driver_ani_kit.z") + + export interface ExecuteParam { + bundleName: string; + moduleName: string; + abilityName: string; + insightIntentName: string; + insightIntentParam: Record; + executeMode: insightIntent.ExecuteMode; + displayId?: number; + uris?: Array; + flags?: number; + } + + export native function nativeExecuteSync(param: ExecuteParam, + callback: AsyncCallbackWrapper, + isCallback: boolean): void; + + export function execute(param: ExecuteParam, callback: AsyncCallback): void { + let pCallback = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + nativeExecuteSync(param, pCallback, true); + }); + } + + export function execute(param: ExecuteParam): Promise { + let pPromise = new Promise(( + resolve: (data: insightIntent.ExecuteResult) => void, + reject: (err: BusinessError) => void) => { + let pCallback = new AsyncCallbackWrapper(( + err: BusinessError | null, data: insightIntent.ExecuteResult | undefined) => { + if (err == null || err.code == 0) { + resolve(data as insightIntent.ExecuteResult); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + nativeExecuteSync(param, pCallback, false); + }); + }); + return pPromise; + } +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.wantAgent.ets b/frameworks/ets/ets/@ohos.app.ability.wantAgent.ets new file mode 100644 index 00000000000..0dd412c9a76 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.wantAgent.ets @@ -0,0 +1,344 @@ +/* + * 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, AsyncCallback } from '@ohos.base'; +import Want from '@ohos.app.ability.Want'; +import { WantAgentInfo as _WantAgentInfo } from 'wantAgent.wantAgentInfo'; +import { TriggerInfo as _TriggerInfo } from 'wantAgent.triggerInfo'; +import AsyncCallbackWrapper from './utils/AbilityUtils'; + +namespace wantAgent { + loadLibrary("aniwantagent.z"); + + class Cleaner { + public ptr: long = 0; + + constructor(ptr: long) { + this.ptr = ptr; + } + + native clean(): void; + } + + export function callback(cleaner: Cleaner): void { + cleaner.clean(); + } + + let destroyRegister = new FinalizationRegistry(callback); + let unregisterToken = new object(); + + class WantAgentCls { + wantAgentPtr: long = 0; + private cleaner: Cleaner | null = null; + + constructor(ptr: long) { + if (this.wantAgentPtr == 0) { + this.wantAgentPtr = ptr; + } + this.registerCleaner(this.wantAgentPtr); + } + + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr); + destroyRegister.register(this, this.cleaner!, unregisterToken); + } + + unregisterCleaner(): void { + destroyRegister.unregister(unregisterToken); + } + } + + native function nativeGetBundleName(agent: WantAgent, callback: AsyncCallbackWrapper): void; + native function nativeGetUid(agent: WantAgent, callback: AsyncCallbackWrapper): void; + native function nativeGetOperationType(agent: WantAgent, callback: AsyncCallbackWrapper): void; + native function nativeCancel(agent: WantAgent, callback: AsyncCallbackWrapper): void; + native function nativeEqual(agent: WantAgent, otherAgent: WantAgent, callback: AsyncCallbackWrapper): void; + native function nativeTrigger(agent: WantAgent, triggerInfo: TriggerInfo, callback?: AsyncCallbackWrapper): void; + native function nativeGetWant(agent: WantAgent, callback: AsyncCallbackWrapper): void; + native function nativeGetWantAgent(agent: WantAgentInfo, callback: AsyncCallbackWrapper): void; + + export function getBundleName(agent: WantAgent, callback: AsyncCallback): void { + let call = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + try { + nativeGetBundleName(agent, call); + } catch (err: BusinessError) { + callback(err, ""); + } + }); + } + + export function getBundleName(agent: WantAgent): Promise { + return new Promise((resolve: (data: string) => void, reject: (err: BusinessError) => void): void => { + let call = new AsyncCallbackWrapper((err: BusinessError | null, data: string | undefined) => { + if (err == null || err.code == 0) { + resolve(data as string); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + try { + nativeGetBundleName(agent, call); + } catch (err: BusinessError) { + reject(err); + } + }); + }); + } + + export function getUid(agent: WantAgent, callback: AsyncCallback): void { + let call = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + try { + nativeGetUid(agent, call); + } catch (err: BusinessError) { + callback(err, -1); + } + }); + } + + export function getUid(agent: WantAgent): Promise { + return new Promise((resolve: (data: number) => void, reject: (err: BusinessError) => void): void => { + let call = new AsyncCallbackWrapper((err: BusinessError | null, data: number | undefined) => { + if (err == null || err.code == 0) { + resolve(data as number); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + try { + nativeGetUid(agent, call); + } catch (err: BusinessError) { + reject(err); + } + }); + }); + } + + export function getWant(agent: WantAgent, callback: AsyncCallback): void { + let call = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + try { + nativeGetWant(agent, call); + } catch (err: BusinessError) { + callback(err, {} as Want); + } + }); + } + + export function getWant(agent: WantAgent): Promise { + return new Promise((resolve: (data: Want) => void, reject: (err: BusinessError) => void): void => { + let call = new AsyncCallbackWrapper((err: BusinessError | null, data: Want | undefined) => { + if (err == null || err.code == 0) { + resolve(data as Want); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + try { + nativeGetWant(agent, call); + } catch (err: BusinessError) { + reject(err); + } + }); + }); + } + + export function cancel(agent: WantAgent, callback: AsyncCallback): void { + let call = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + try { + nativeCancel(agent, call); + } catch (err: BusinessError) { + callback(err, undefined); + } + }); + } + + export function cancel(agent: WantAgent): Promise { + return new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let call = new AsyncCallbackWrapper((err: BusinessError | null) => { + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + try { + nativeCancel(agent, call); + } catch (err: BusinessError) { + reject(err); + } + }); + }); + } + + export function trigger(agent: WantAgent, triggerInfo: TriggerInfo, callback?: AsyncCallback): void { + taskpool.execute((): void => { + if (callback == undefined) { + nativeTrigger(agent, triggerInfo); + } else { + let call = new AsyncCallbackWrapper(callback); + try { + nativeTrigger(agent, triggerInfo, call); + } catch (err: BusinessError) { + callback(err, {} as CompleteData); + } + } + }); + } + + export function equal(agent: WantAgent, otherAgent: WantAgent, callback: AsyncCallback): void { + let call = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + try { + nativeEqual(agent, otherAgent, call); + } catch (err: BusinessError) { + callback(err, false); + } + }); + } + + export function equal(agent: WantAgent, otherAgent: WantAgent): Promise { + return new Promise((resolve: (data: boolean) => void, + reject: (err: BusinessError) => void): void => { + let call = new AsyncCallbackWrapper((err: BusinessError | null, data: boolean | undefined) => { + if (err == null || err.code == 0) { + resolve(data as boolean); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + try { + nativeEqual(agent, otherAgent, call); + } catch (err: BusinessError) { + reject(err); + } + }); + }); + } + + export function getWantAgent(info: WantAgentInfo, callback: AsyncCallback): void { + let call = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + try { + nativeGetWantAgent(info, call); + } catch (err: BusinessError) { + callback(err, {} as WantAgent); + } + }); + } + + export function getWantAgent(info: WantAgentInfo): Promise { + return new Promise((resolve: (data: WantAgent) => void, + reject: (err: BusinessError) => void): void => { + let call = new AsyncCallbackWrapper((err: BusinessError | null, data: WantAgent | undefined) => { + if (err == null || err.code == 0) { + resolve(data as WantAgent); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + try { + nativeGetWantAgent(info, call); + } catch (err: BusinessError) { + reject(err); + } + }); + }); + } + + export function getOperationType(agent: WantAgent, callback: AsyncCallback): void { + let call = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + try { + nativeGetOperationType(agent, call); + } catch (err: BusinessError) { + callback(err, -1); + } + }); + } + + export function getOperationType(agent: WantAgent): Promise { + return new Promise((resolve: (data: number) => void, reject: (err: BusinessError) => void): void => { + let call = new AsyncCallbackWrapper((err: BusinessError | null, data: number | undefined) => { + if (err == null || err.code == 0) { + resolve(data as number); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + try { + nativeGetOperationType(agent, call); + } catch (err: BusinessError) { + reject(err); + } + }); + }); + } + + export enum WantAgentFlags { + ONE_TIME_FLAG = 0, + NO_BUILD_FLAG, + CANCEL_PRESENT_FLAG, + UPDATE_PRESENT_FLAG, + CONSTANT_FLAG, + REPLACE_ELEMENT, + REPLACE_ACTION, + REPLACE_URI, + REPLACE_ENTITIES, + REPLACE_BUNDLE + } + + export enum OperationType { + UNKNOWN_TYPE = 0, + START_ABILITY, + START_ABILITIES, + START_SERVICE, + SEND_COMMON_EVENT, + START_SERVICE_EXTENSION = 6 + } + + export interface CompleteData { + info: WantAgent; + want: Want; + finalCode: number; + finalData: string; + extraInfo?: Record; + } + + class CompleteDataImpl implements CompleteData { + public info: WantAgent; + public want: Want; + public finalCode: number; + public finalData: string; + public extraInfo?: Record; + } + + export type TriggerInfo = _TriggerInfo; + + export type WantAgentInfo = _WantAgentInfo; +} + +export type WantAgent = object; + +export default wantAgent; diff --git a/frameworks/ets/ets/BUILD.gn b/frameworks/ets/ets/BUILD.gn index 07098f4a8b3..ba82da6c3b4 100644 --- a/frameworks/ets/ets/BUILD.gn +++ b/frameworks/ets/ets/BUILD.gn @@ -80,6 +80,42 @@ ohos_prebuilt_etc("ability_runtime_ability_utils_abc_etc") { deps = [ ":ability_runtime_ability_utils_abc" ] } +generate_static_abc("ability_runtime_ability_manager_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.abilityManager.ets" ] + + dst_file = "$target_out_dir/ability_runtime_ability_manager.abc" + out_puts = [ "$target_out_dir/ability_runtime_ability_manager.abc" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_ability_manager.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_manager_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_manager.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_manager_abc" ] +} + +generate_static_abc("ability_runtime_ability_state_data_abc") { + base_url = "./" + files = [ "./application/AbilityStateData.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_ability_state_data_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_state_data_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_state_data_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_state_data_abc" ] +} + generate_static_abc("ability_runtime_ability_constant_abc") { base_url = "./" files = [ "./@ohos.app.ability.AbilityConstant.ets" ] @@ -228,6 +264,120 @@ ohos_prebuilt_etc("service_extension_ability_abc_etc") { part_name = "ability_runtime" deps = [ ":service_extension_ability" ] } +generate_static_abc("ability_runtime_app_state_data_abc") { + base_url = "./" + files = [ "./application/AppStateData.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_app_state_data_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_app_state_data_abc_etc") { + source = "$target_out_dir/ability_runtime_app_state_data_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_app_state_data_abc" ] +} + +generate_static_abc("ability_runtime_process_data_abc") { + base_url = "./" + files = [ "./application/ProcessData.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_process_data_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_process_data_abc_etc") { + source = "$target_out_dir/ability_runtime_process_data_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_process_data_abc" ] +} + +generate_static_abc("ability_runtime_process_information_abc") { + base_url = "./" + files = [ "./application/ProcessInformation.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_process_information_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_process_information_abc_etc") { + source = "$target_out_dir/ability_runtime_process_information_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_process_information_abc" ] +} + +generate_static_abc("ability_runtime_running_app_clone_abc") { + base_url = "./" + files = [ "./application/RunningAppClone.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_running_app_clone_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_running_app_clone_abc_etc") { + source = "$target_out_dir/ability_runtime_running_app_clone_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_running_app_clone_abc" ] +} + +generate_static_abc("ability_runtime_running_multi_appinfo_abc") { + base_url = "./" + files = [ "./application/RunningMultiAppInfo.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_running_multi_appinfo_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_running_multi_appinfo_abc_etc") { + source = "$target_out_dir/ability_runtime_running_multi_appinfo_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_running_multi_appinfo_abc" ] +} + +generate_static_abc("ability_runtime_multi_app_mode_abc") { + base_url = "./" + files = [ "./application/MultiAppMode.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_multi_app_mode_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_multi_app_mode_abc_etc") { + source = "$target_out_dir/ability_runtime_multi_app_mode_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_multi_app_mode_abc" ] +} + +generate_static_abc("ability_runtime_app_manager_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.appManager.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_app_manager_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_app_manager_abc_etc") { + source = "$target_out_dir/ability_runtime_app_manager_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_app_manager_abc" ] +} generate_static_abc("ui_extension_ability_ani_abc") { base_url = "./" @@ -384,13 +534,29 @@ ohos_prebuilt_etc("ability_delegator_ability_monitor_abc_etc") { deps = [ ":ability_delegator_ability_monitor_abc" ] } +generate_static_abc("ability_runtime_ability_stage_monitor_abc") { + base_url = "./" + files = [ "./application/AbilityStageMonitor.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_ability_stage_monitor_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_stage_monitor_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_stage_monitor_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_stage_monitor_abc" ] +} + generate_static_abc("ability_runtime_shell_cmd_result_abc") { base_url = "./" files = [ "./application/shellCmdResult.ets" ] is_boot_abc = "True" - device_dst_file = - "/system/framework/ability_runtime_shell_cmd_result_abc.abc" + device_dst_file = "/system/framework/ability_runtime_shell_cmd_result_abc.abc" } ohos_prebuilt_etc("ability_runtime_shell_cmd_result_abc_etc") { @@ -474,31 +640,198 @@ ohos_prebuilt_etc("uri_permission_manager_abc_etc") { deps = [ ":uri_permission_manager_abc" ] } +generate_static_abc("ability_runtime_want_agent_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.wantAgent.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_want_agent_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_want_agent_abc_etc") { + source = "$target_out_dir/ability_runtime_want_agent_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_want_agent_abc" ] +} + +generate_static_abc("ability_runtime_trigger_info_abc") { + base_url = "./" + files = [ "./wantAgent/triggerInfo.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_trigger_info_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_trigger_info_abc_etc") { + source = "$target_out_dir/ability_runtime_trigger_info_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_trigger_info_abc" ] +} + +generate_static_abc("ability_runtime_want_agent_info_abc") { + base_url = "./" + files = [ "./wantAgent/wantAgentInfo.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_want_agent_info_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_want_agent_info_abc_etc") { + source = "$target_out_dir/ability_runtime_want_agent_info_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_want_agent_info_abc" ] +} + +generate_static_abc("ability_runtime_openLink_options_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.OpenLinkOptions.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_openLink_options_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_openLink_options_abc_etc") { + source = "$target_out_dir/ability_runtime_openLink_options_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_openLink_options_abc" ] +} + +generate_static_abc("ability_application_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.application.ets" ] + + dst_file = "$target_out_dir/ability_application.abc" + out_puts = [ "$target_out_dir/ability_application.abc" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_application.abc" +} + +ohos_prebuilt_etc("ability_application_abc_etc") { + source = "$target_out_dir/ability_application.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_application_abc" ] +} + +generate_static_abc("ability_runtime_insight_intent_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.insightIntent.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_insight_intent_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_insight_intent_abc_etc") { + source = "$target_out_dir/ability_runtime_insight_intent_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_insight_intent_abc" ] +} + +generate_static_abc("ability_runtime_insight_intent_context_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.InsightIntentContext.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_insight_intent_context_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_insight_intent_context_abc_etc") { + source = "$target_out_dir/ability_runtime_insight_intent_context_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_insight_intent_context_abc" ] +} + +generate_static_abc("ability_runtime_insight_intent_driver_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.insightIntentDriver.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_insight_intent_driver_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_insight_intent_driver_abc_etc") { + source = "$target_out_dir/ability_runtime_insight_intent_driver_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_insight_intent_driver_abc" ] +} + +generate_static_abc("ability_runtime_insight_intent_executor_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.InsightIntentExecutor.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_insight_intent_executor_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_insight_intent_executor_abc_etc") { + source = "$target_out_dir/ability_runtime_insight_intent_executor_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_insight_intent_executor_abc" ] +} + group("ets_packages") { deps = [ + ":ability_application_abc_etc", + ":ability_runtime_ability_manager_abc_etc", ":ability_delegator_abc_etc", ":ability_delegator_ability_monitor_abc_etc", ":ability_delegator_application_testRunner_abc_etc", ":ability_delegator_args_abc_etc", ":ability_delegator_registry_abc_etc", - ":ability_runtime_shell_cmd_result_abc_etc", ":ability_runtime_ability_constant_abc_etc", ":ability_runtime_ability_context_constant_abc_etc", ":ability_runtime_ability_result_abc_etc", ":ability_runtime_ability_stage_abc_etc", ":ability_runtime_ability_stage_context_abc_etc", + ":ability_runtime_ability_stage_monitor_abc_etc", + ":ability_runtime_ability_state_data_abc_etc", ":ability_runtime_ability_utils_abc_etc", + ":ability_runtime_app_manager_abc_etc", + ":ability_runtime_app_state_data_abc_etc", ":ability_runtime_application_context_abc_etc", ":ability_runtime_base_context_abc_etc", ":ability_runtime_configuration_abc_etc", ":ability_runtime_configuration_constant_abc_etc", ":ability_runtime_context_abc_etc", ":ability_runtime_extension_context_abc_etc", + ":ability_runtime_insight_intent_abc_etc", + ":ability_runtime_insight_intent_context_abc_etc", + ":ability_runtime_insight_intent_driver_abc_etc", + ":ability_runtime_insight_intent_executor_abc_etc", + ":ability_runtime_openLink_options_abc_etc", + ":ability_runtime_shell_cmd_result_abc_etc", ":ability_runtime_start_options_abc_etc", - ":ability_runtime_want_abc_etc", - ":ability_runtime_want_constant_abc_etc", + ":ability_runtime_trigger_info_abc_etc", ":ability_runtime_ui_ability_abc_etc", ":ability_runtime_ui_ability_context_abc_etc", + ":ability_runtime_multi_app_mode_abc_etc", + ":ability_runtime_process_data_abc_etc", + ":ability_runtime_process_information_abc_etc", + ":ability_runtime_running_app_clone_abc_etc", + ":ability_runtime_running_multi_appinfo_abc_etc", + ":ability_runtime_want_abc_etc", + ":ability_runtime_want_agent_abc_etc", + ":ability_runtime_want_agent_info_abc_etc", + ":ability_runtime_want_constant_abc_etc", + ":form_extension_ability_etc", ":service_extension_ability_abc_etc", ":ui_extension_ability_ani_etc", ":uri_permission_manager_abc_etc", diff --git a/frameworks/ets/ets/application/AbilityDelegator.ets b/frameworks/ets/ets/application/AbilityDelegator.ets index efeab825900..cdc88980dca 100644 --- a/frameworks/ets/ets/application/AbilityDelegator.ets +++ b/frameworks/ets/ets/application/AbilityDelegator.ets @@ -18,7 +18,10 @@ import Want from '@ohos.app.ability.Want'; import Context from 'application.Context'; import { BusinessError, AsyncCallback } from '@ohos.base'; import { ShellCmdResult } from 'application.shellCmdResult'; +import UIAbility from '@ohos.app.ability.UIAbility'; import AsyncCallbackWrapper from '../utils/AbilityUtils'; +import { AbilityStageMonitor } from 'application.AbilityStageMonitor'; +import AbilityStage from '@ohos.app.ability.AbilityStage'; export interface AbilityDelegator { printSync(msg: string): void; @@ -39,12 +42,65 @@ export interface AbilityDelegator { addAbilityMonitor(monitor: AbilityMonitor): Promise; + addAbilityMonitorSync(monitor: AbilityMonitor): void; + + removeAbilityMonitor(monitor: AbilityMonitor, callback: AsyncCallback): void + + removeAbilityMonitor(monitor: AbilityMonitor): Promise; + + removeAbilityMonitorSync(monitor: AbilityMonitor): void; + + waitAbilityMonitor(monitor: AbilityMonitor, callback: AsyncCallback): void; + + waitAbilityMonitor(monitor: AbilityMonitor, timeout: number, callback: AsyncCallback): void; + + waitAbilityMonitor(monitor: AbilityMonitor, timeout?: number): Promise; + + addAbilityStageMonitor(monitor: AbilityStageMonitor, callback: AsyncCallback): void; + + addAbilityStageMonitor(monitor: AbilityStageMonitor): Promise; + + addAbilityStageMonitorSync(monitor: AbilityStageMonitor): void; + + removeAbilityStageMonitor(monitor: AbilityStageMonitor, callback: AsyncCallback): void; + + removeAbilityStageMonitor(monitor: AbilityStageMonitor): Promise; + + removeAbilityStageMonitorSync(monitor: AbilityStageMonitor): void; + + waitAbilityStageMonitor(monitor: AbilityStageMonitor, callback: AsyncCallback): void; + + waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout: number, callback: AsyncCallback): void; + + waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout?: number): Promise; + + doAbilityForeground(ability: UIAbility, callback: AsyncCallback): void; + + doAbilityForeground(ability: UIAbility): Promise; + + doAbilityBackground(ability: UIAbility, callback: AsyncCallback): void; + + doAbilityBackground(ability: UIAbility): Promise; + + print(msg: string, callback: AsyncCallback): void; + + print(msg: string): Promise; + + getAbilityState(ability: UIAbility): number; + + setMockList(mockList: Record): void; + startAbility(want: Want, callback: AsyncCallback): void; startAbility(want: Want): Promise; + + getCurrentTopAbility(callback: AsyncCallback); + + getCurrentTopAbility(): Promise; } class AbilityDelegatorInner implements AbilityDelegator { + public native nativeGetCurrentTopAbility(callback: AsyncCallbackWrapper): UIAbility; public native printSync(msg: string): void; @@ -57,6 +113,37 @@ class AbilityDelegatorInner implements AbilityDelegator { public native nativeAddAbilityMonitor(monitor: AbilityMonitor, callback: AsyncCallbackWrapper): void; + public native addAbilityMonitorSync(monitor: AbilityMonitor): void; + + public native removeAbilityMonitorAsync(monitor: AbilityMonitor, callback: AsyncCallbackWrapper): void; + + public native removeAbilityMonitorSync(monitor: AbilityMonitor): void; + + public native waitAbilityMonitorAsync(monitor: AbilityMonitor, timeout: number, + callback: AsyncCallbackWrapper): void; + + public native addAbilityStageMonitorAsync(monitor: AbilityStageMonitor, callback: AsyncCallbackWrapper): void; + + public native addAbilityStageMonitorSync(monitor: AbilityStageMonitor): void; + + public native removeAbilityStageMonitorAsync(monitor: AbilityStageMonitor, + callback: AsyncCallbackWrapper): void; + + public native removeAbilityStageMonitorSync(monitor: AbilityStageMonitor): void; + + public native waitAbilityStageMonitorAsync(monitor: AbilityStageMonitor, timeout: number, + callback: AsyncCallbackWrapper): void; + + public native doAbilityForegroundAsync(ability: UIAbility, callback: AsyncCallbackWrapper): void; + + public native doAbilityBackgroundAsync(ability: UIAbility, callback: AsyncCallbackWrapper): void; + + public native printAsync(msg: string, callback: AsyncCallbackWrapper): void; + + public native setMockList(mockList: Record): void; + + public native getAbilityState(ability: UIAbility): number; + public native nativeStartAbility(want: Want, callback: AsyncCallbackWrapper): void; finishTest(msg: string, code: number, callback: AsyncCallback): void { @@ -140,6 +227,214 @@ class AbilityDelegatorInner implements AbilityDelegator { return p; } + removeAbilityMonitor(monitor: AbilityMonitor, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.removeAbilityMonitorAsync(monitor, myCall); + }); + } + removeAbilityMonitor(monitor: AbilityMonitor): 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.removeAbilityMonitorAsync(monitor, myCall); + }); + }); + return p; + } + + waitAbilityMonitor(monitor: AbilityMonitor, callback: AsyncCallback): void { + let timeout = -1; + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.waitAbilityMonitorAsync(monitor, timeout, myCall); + }); + } + waitAbilityMonitor(monitor: AbilityMonitor, timeout: number, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.waitAbilityMonitorAsync(monitor, timeout, myCall); + }); + } + waitAbilityMonitor(monitor: AbilityMonitor, timeout?: number): Promise { + let p = new Promise((resolve: (data: UIAbility) => void, + reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: UIAbility | undefined) => { + if (err == null || err.code == 0) { + resolve(data as UIAbility); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + if (timeout == null) { + this.waitAbilityMonitorAsync(monitor, -1, myCall); + } else { + this.waitAbilityMonitorAsync(monitor, timeout as double, myCall); + } + }); + }); + return p; + } + + addAbilityStageMonitor(monitor: AbilityStageMonitor, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.addAbilityStageMonitorAsync(monitor, myCall); + }); + } + addAbilityStageMonitor(monitor: AbilityStageMonitor): 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.addAbilityStageMonitorAsync(monitor, myCall); + }); + }); + return p; + } + + removeAbilityStageMonitor(monitor: AbilityStageMonitor, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.removeAbilityStageMonitorAsync(monitor, myCall); + }); + } + removeAbilityStageMonitor(monitor: AbilityStageMonitor): 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.removeAbilityStageMonitorAsync(monitor, myCall); + }); + }); + return p; + } + + waitAbilityStageMonitor(monitor: AbilityStageMonitor, callback: AsyncCallback): void { + let timeout = -1; + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.waitAbilityStageMonitorAsync(monitor, timeout, myCall); + }); + } + waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout: number, + callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.waitAbilityStageMonitorAsync(monitor, timeout, myCall); + }); + } + waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout?: number): Promise { + let p = new Promise((resolve: (data: AbilityStage) => void, + reject: (err: BusinessError) => void): void => { + let myCall = + new AsyncCallbackWrapper((err: BusinessError | null, data: AbilityStage | undefined) => { + if (err == null || err.code == 0) { + resolve(data as AbilityStage); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + if (timeout == null) { + this.waitAbilityStageMonitorAsync(monitor, -1, myCall); + } else { + this.waitAbilityStageMonitorAsync(monitor, timeout as double, myCall); + } + }); + }); + return p; + } + + doAbilityForeground(ability: UIAbility, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.doAbilityForegroundAsync(ability, myCall); + }); + } + doAbilityForeground(ability: UIAbility): Promise { + let p: Promise = + 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.doAbilityForegroundAsync(ability, myCall); + }); + }); + return p; + } + + doAbilityBackground(ability: UIAbility, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.doAbilityBackgroundAsync(ability, myCall); + }); + } + doAbilityBackground(ability: UIAbility): Promise { + let p: Promise = + 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.doAbilityBackgroundAsync(ability, myCall); + }); + }); + return p; + } + + print(msg: string, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.printAsync(msg, myCall); + }); + } + print(msg: string): Promise { + let p: Promise = + 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.printAsync(msg, myCall); + }); + }); + return p; + } + startAbility(want: Want, callback: AsyncCallback): void { let myCall = new AsyncCallbackWrapper(callback); taskpool.execute((): void => { @@ -163,4 +458,27 @@ class AbilityDelegatorInner implements AbilityDelegator { return p; } + getCurrentTopAbility(callback: AsyncCallback): void { + let getCurrentTopAbilityCall = new AsyncCallbackWrapper(callback); + let p = taskpool.execute((): UIAbility => { + this.nativeGetCurrentTopAbility(getCurrentTopAbilityCall) + }); + console.log("getCurrentTopAbility callback2_04"); + } + getCurrentTopAbility(): Promise { + let p: Promise = new Promise((resolve: (v: UIAbility) => void, reject: (error: Error) => void) => { + console.log("getCurrentTopAbility promise1_01"); + let getCurrentTopAbilityCall = new AsyncCallbackWrapper((err: BusinessError | null, data: UIAbility | undefined) => { + if (err == null || err.code == 0) { + resolve(data as UIAbility); + } else { + reject(err); + } + }); + taskpool.execute((): UIAbility => { + this.nativeGetCurrentTopAbility(getCurrentTopAbilityCall); + }); + }); + return p; + } } diff --git a/frameworks/ets/ets/application/AbilityStageContext.ets b/frameworks/ets/ets/application/AbilityStageContext.ets index b5f1ea1d8aa..bcfc8a9ee14 100644 --- a/frameworks/ets/ets/application/AbilityStageContext.ets +++ b/frameworks/ets/ets/application/AbilityStageContext.ets @@ -15,7 +15,17 @@ import Context from 'application.Context' import { Configuration } from '@ohos.app.ability.Configuration' +import { HapModuleInfo } from 'bundleManager.HapModuleInfo' export default class AbilityStageContext extends Context { - config?: Configuration; + static { + loadLibrary("context_ani"); + } + config?: Configuration; + currentHapModuleInfo: HapModuleInfo; + native constructor(); + constructor(currentHapModuleInfo: HapModuleInfo) { + super(); + this.currentHapModuleInfo = currentHapModuleInfo; + } } \ No newline at end of file diff --git a/frameworks/ets/ets/application/AbilityStageMonitor.ets b/frameworks/ets/ets/application/AbilityStageMonitor.ets new file mode 100644 index 00000000000..62825a9a188 --- /dev/null +++ b/frameworks/ets/ets/application/AbilityStageMonitor.ets @@ -0,0 +1,24 @@ +/* + * 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. + */ + +export default interface AbilityStageMonitor { + moduleName: string; + srcEntrance: string; +} + +class AbilityStageMonitorInner implements AbilityStageMonitor { + public moduleName: string = ''; + public srcEntrance: string = ''; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/AbilityStateData.ets b/frameworks/ets/ets/application/AbilityStateData.ets new file mode 100644 index 00000000000..256b244426b --- /dev/null +++ b/frameworks/ets/ets/application/AbilityStateData.ets @@ -0,0 +1,26 @@ +/* + * 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. + */ + +export default class AbilityStateData { + readonly moduleName: string = ''; + readonly bundleName: string = ''; + readonly abilityName: string = ''; + readonly pid: int; + readonly uid: int; + readonly state: int; + readonly abilityType: int; + readonly isAtomicService: boolean; + readonly appCloneIndex?: int; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/AppStateData.ets b/frameworks/ets/ets/application/AppStateData.ets new file mode 100644 index 00000000000..ca1f7eff420 --- /dev/null +++ b/frameworks/ets/ets/application/AppStateData.ets @@ -0,0 +1,21 @@ +/* + * 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. + */ +export default class AppStateData { + bundleName: string = ''; + uid: number; + state: number; + isSplitScreenMode: boolean; + isFloatingWindowMode: boolean; +} diff --git a/frameworks/ets/ets/application/ApplicationContext.ets b/frameworks/ets/ets/application/ApplicationContext.ets index b572cc28803..c48da89fe52 100644 --- a/frameworks/ets/ets/application/ApplicationContext.ets +++ b/frameworks/ets/ets/application/ApplicationContext.ets @@ -14,11 +14,186 @@ */ import Context from 'application.Context' +import { BusinessError, AsyncCallback } from '@ohos.base' +import AsyncCallbackWrapper from '../utils/AbilityUtils'; +import Want from '@ohos.app.ability.Want'; +import { ProcessInformation } from 'application.ProcessInformation'; +import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant'; + +class Cleaner { + public ptr: long = 0; + + constructor(ptr: long) { + this.ptr = ptr; + } + + native clean(): void; +} + +export function callback(cleaner: Cleaner): void { + cleaner.clean(); +} + +let destroyRegister = new FinalizationRegistry(callback); +let unregisterToken = new object(); export default class ApplicationContext extends Context { + etsApplicationContextPtr: long = 0; + private cleaner: Cleaner | null = null; + + constructor(ptr: long) { + if (this.etsApplicationContextPtr == 0) { + this.etsApplicationContextPtr = ptr; + } + this.registerCleaner(this.etsApplicationContextPtr); + } + + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr); + destroyRegister.register(this, this.cleaner!, unregisterToken); + } + + unregisterCleaner(): void { + destroyRegister.unregister(unregisterToken); + } + public native nativekillAllProcessesSync(clearPageStack: boolean, callback: AsyncCallbackWrapper): void; + public native nativepreloadUIExtensionAbilitySync(want: Want, callback: AsyncCallbackWrapper): void; public native setSupportedProcessCacheSync(isSupported : boolean):void; + public native nativegetRunningProcessInformation(callback: AsyncCallbackWrapper>): void; + public native nativeclearUpApplicationData(callback: AsyncCallbackWrapper): void; + public native nativesetLanguage(language: string): void; + public native nativesetFontSizeScale(fontSizeScale: number): void; + public native nativesetColorMode(colorMode: ConfigurationConstant.ColorMode): void; + public native nativesetFont(font: string): void; + public native nativerestartApp(want: Want): void; setSupportedProcessCache(isSupported : boolean):void { this.setSupportedProcessCacheSync(isSupported); } + preloadUIExtensionAbility(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.nativepreloadUIExtensionAbilitySync(want, myCall); + }); + }); + return p; + } + + killAllProcesses(callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativekillAllProcessesSync(false, myCall); + }); + } + + killAllProcesses(): 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.nativekillAllProcessesSync(false, myCall); + }); + }); + return p; + } + + killAllProcesses(clearPageStack: boolean): 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.nativekillAllProcessesSync(clearPageStack, myCall); + }); + }); + return p; + } + + getRunningProcessInformation(callback: AsyncCallback>): void { + let myCall = new AsyncCallbackWrapper>(callback); + taskpool.execute((): void => { + this.nativegetRunningProcessInformation(myCall); + }); + } + + getRunningProcessInformation(): Promise> { + let p = new Promise>((resolve: (data: Array) => void, + reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper>((err: BusinessError | null, + data: Array | undefined) => { + if (err == null || err.code == 0) { + resolve(data as Array); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativegetRunningProcessInformation(myCall); + }); + }); + return p; + } + + clearUpApplicationData(callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeclearUpApplicationData(myCall); + }); + } + + clearUpApplicationData(): 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.nativeclearUpApplicationData(myCall); + }); + }); + return p; + } + + setLanguage(language: string): void { + this.nativesetLanguage(language); + } + + setFontSizeScale(fontSizeScale: number): void { + this.nativesetFontSizeScale(fontSizeScale); + } + + setColorMode(colorMode: ConfigurationConstant.ColorMode): void { + this.nativesetColorMode(colorMode); + } + + setFont(font: string): void { + this.nativesetFont(font); + } + + restartApp(want: Want): void { + this.nativerestartApp(want); + } } \ No newline at end of file diff --git a/frameworks/ets/ets/application/Context.ets b/frameworks/ets/ets/application/Context.ets index ac4247fe0b6..94092f175c5 100644 --- a/frameworks/ets/ets/application/Context.ets +++ b/frameworks/ets/ets/application/Context.ets @@ -19,10 +19,25 @@ import contextConstant from '@ohos.app.ability.contextConstant' import { ApplicationInfo } from 'bundleManager.ApplicationInfo' import resmgr from '@ohos.resourceManager' +class Cleaner { + public ptr: long = 0; + constructor(ptr: long) { + this.ptr = ptr; + } + native clean(): void; +} +export function callback(cleaner: Cleaner): void { + cleaner.clean(); +} +let destroyRegister = new FinalizationRegistry(callback); +let unregisterToken = new object(); + export class Context extends BaseContext { static { loadLibrary("context_ani"); } + etsContextPtr: long = 0; + private cleaner: Cleaner | null = null; filesDir: string = ""; tempDir: string = ""; preferencesDir: string = ""; @@ -36,7 +51,21 @@ export class Context extends BaseContext { this.applicationInfo = applicationInfo; this.resourceManager = resourceManager; } + private setEtsContextPtr(ptr: long) { + if (this.etsContextPtr == 0) { + this.etsContextPtr = ptr; + } + this.registerCleaner(this.etsContextPtr); + } + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr); + destroyRegister.register(this, this.cleaner!, unregisterToken); + } + unregisterCleaner(): void { + destroyRegister.unregister(unregisterToken); + } public native getApplicationContextSync(): ApplicationContext; + public native createModuleResourceManagerSync(bundleName: string, moduleName: string): resmgr.ResourceManager; private native switchArea(mode: contextConstant.AreaMode): void; private native getArea(): contextConstant.AreaMode; @@ -44,6 +73,10 @@ export class Context extends BaseContext { return this.getApplicationContextSync(); } + createModuleResourceManager(bundleName: string, moduleName: string): resmgr.ResourceManager { + return this.createModuleResourceManagerSync(bundleName, moduleName); + } + set area(mode: contextConstant.AreaMode) { this.switchArea(mode); } diff --git a/frameworks/ets/ets/application/ExtensionContext.ets b/frameworks/ets/ets/application/ExtensionContext.ets index 4b6cbf03130..df825c771b6 100644 --- a/frameworks/ets/ets/application/ExtensionContext.ets +++ b/frameworks/ets/ets/application/ExtensionContext.ets @@ -15,15 +15,21 @@ import Context from 'application.Context' import {ExtensionAbilityInfo} from 'bundleManager.ExtensionAbilityInfo' +import { Configuration } from '@ohos.app.ability.Configuration' +import { HapModuleInfo } from 'bundleManager.HapModuleInfo' export default class ExtensionContext extends Context { static { loadLibrary("context_ani"); } extensionAbilityInfo: ExtensionAbilityInfo; + config: Configuration; + currentHapModuleInfo: HapModuleInfo; native constructor(); - constructor(extensionAbilityInfo: ExtensionAbilityInfo) { + constructor(config: Configuration, extensionAbilityInfo: ExtensionAbilityInfo, currentHapModuleInfo: HapModuleInfo) { super(); + this.config = config; this.extensionAbilityInfo = extensionAbilityInfo; + this.currentHapModuleInfo = currentHapModuleInfo; } } \ No newline at end of file diff --git a/frameworks/ets/ets/application/MultiAppMode.ets b/frameworks/ets/ets/application/MultiAppMode.ets new file mode 100644 index 00000000000..dc7d9e233f7 --- /dev/null +++ b/frameworks/ets/ets/application/MultiAppMode.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024 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. + */ +export enum MultiAppMode { + NOT_SUPPORTED = 0, + MULTI_INSTANCE = 1, + APP_CLONE = 2 +} diff --git a/frameworks/ets/ets/application/ProcessData.ets b/frameworks/ets/ets/application/ProcessData.ets new file mode 100644 index 00000000000..5bec6929cbf --- /dev/null +++ b/frameworks/ets/ets/application/ProcessData.ets @@ -0,0 +1,22 @@ +/* + * 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. + */ +export default class ProcessData { + bundleName: string = ''; + pid: number; + uid: number; + state: number; + isContinuousTask: boolean; + isKeepAlive: boolean; +} diff --git a/frameworks/ets/ets/application/ProcessInformation.ets b/frameworks/ets/ets/application/ProcessInformation.ets new file mode 100644 index 00000000000..3ecd61ca6da --- /dev/null +++ b/frameworks/ets/ets/application/ProcessInformation.ets @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022-2024 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 appManager from '@ohos.app.ability.appManager'; +import bundleManager from '@ohos.bundle.bundleManager'; + +export interface ProcessInformation { + pid: number; + uid: number; + processName: string; + bundleNames: Array; + state: appManager.ProcessState; + bundleType: bundleManager.BundleType; + appCloneIndex?: number; +} + +export default class ProcessInformationInner implements ProcessInformation { + pid: number; + uid: number; + processName: string = ''; + bundleNames: Array = new Array(); + state: appManager.ProcessState = appManager.ProcessState.STATE_CREATE; + bundleType: bundleManager.BundleType = bundleManager.BundleType.APP; + appCloneIndex?: number; +} diff --git a/frameworks/ets/ets/application/RunningAppClone.ets b/frameworks/ets/ets/application/RunningAppClone.ets new file mode 100644 index 00000000000..90334b03447 --- /dev/null +++ b/frameworks/ets/ets/application/RunningAppClone.ets @@ -0,0 +1,25 @@ +/* + * 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. + */ +export interface RunningAppClone { + appCloneIndex: number; + uid: number; + pids: Array; +} + +class RunningAppCloneInner implements RunningAppClone { + appCloneIndex: number; + uid: number; + pids: Array = new Array(); +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/RunningMultiAppInfo.ets b/frameworks/ets/ets/application/RunningMultiAppInfo.ets new file mode 100644 index 00000000000..0fdaf2517ef --- /dev/null +++ b/frameworks/ets/ets/application/RunningMultiAppInfo.ets @@ -0,0 +1,32 @@ +/* + * 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 { MultiAppMode } from 'application.MultiAppMode'; +import { RunningAppClone } from 'application.RunningAppClone'; +import { RunningMultiInstanceInfo } from 'application.RunningMultiInstanceInfo'; + +export interface RunningMultiAppInfo { + bundleName: string; + mode: MultiAppMode; + runningMultiInstances?: Array; + runningAppClones?: Array; +} + +export default class RunningMultiAppInfoInner implements RunningMultiAppInfo { + bundleName: string = ''; + mode: MultiAppMode = MultiAppMode.NOT_SUPPORTED; + runningMultiInstances?: Array; + runningAppClones?: Array; +} diff --git a/frameworks/ets/ets/application/RunningMultiInstanceInfo.ets b/frameworks/ets/ets/application/RunningMultiInstanceInfo.ets new file mode 100644 index 00000000000..10ce3036172 --- /dev/null +++ b/frameworks/ets/ets/application/RunningMultiInstanceInfo.ets @@ -0,0 +1,21 @@ +/* + * 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. + */ +export interface RunningMultiInstanceInfo { + instanceKey: string; +} + +class RunningMultiInstanceInfoInner implements RunningMultiInstanceInfo { + instanceKey: string = ''; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/ServiceExtensionContext.ets b/frameworks/ets/ets/application/ServiceExtensionContext.ets index 8c9fe395ffa..abd9a4dc7ec 100644 --- a/frameworks/ets/ets/application/ServiceExtensionContext.ets +++ b/frameworks/ets/ets/application/ServiceExtensionContext.ets @@ -12,8 +12,153 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import ExtensionContext from 'application.ExtensionContext' + +import { AsyncCallback } from '@ohos.base'; +import AsyncCallbackWrapper from '../utils/AbilityUtils'; +import { BusinessError } from '@ohos.base'; +import ExtensionContext from 'application.ExtensionContext'; +import StartOptions from '@ohos.app.ability.StartOptions'; +import Want from '@ohos.app.ability.Want'; + +class Cleaner { + public ptr: long = 0; + + constructor(ptr: long) { + this.ptr = ptr; + } + + native clean(): void; +} + +export function callback(cleaner: Cleaner): void { + cleaner.clean(); +} + +let destroyRegister = new FinalizationRegistry(callback); +let unregisterToken = new object(); export default class ServiceExtensionContext extends ExtensionContext { + constructor(context: long) { + if (this.nativeEtsContext == 0) { + this.nativeEtsContext = context; + } + this.registerCleaner(this.nativeEtsContext); + } + + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr); + destroyRegister.register(this, this.cleaner!, unregisterToken); + } + + unregisterCleaner(): void { + destroyRegister.unregister(unregisterToken); + } + + nativeEtsContext: long = 0; + private cleaner: Cleaner | null = null; + + native nativeTerminateSelf(callback: AsyncCallbackWrapper): void; + + native nativeStartAbility(want: Want, callback: AsyncCallbackWrapper): void; + + native nativeStartAbility(want: Want, options: StartOptions, callback: AsyncCallbackWrapper): void; + + native nativeStartServiceExtensionAbility(want: Want, callback: AsyncCallbackWrapper): void; + + native nativeStopServiceExtensionAbility(want: Want, callback: AsyncCallbackWrapper): void; + + terminateSelf(callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeTerminateSelf(myCall); + }); + } + + terminateSelf(): Promise { + return 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); + }); + }); + } + + startAbility(want: Want, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartAbility(want, myCall); + }); + } + + startAbility(want: Want, options: StartOptions, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartAbility(want, options, myCall); + }); + } + + startAbility(want: Want, options: StartOptions): Promise { + return 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); + }); + }); + } + + startServiceExtensionAbility(want: Want, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartServiceExtensionAbility(want, myCall); + }); + } + + startServiceExtensionAbility(want: Want): Promise { + return 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); + }); + }); + } + + stopServiceExtensionAbility(want: Want, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStopServiceExtensionAbility(want, myCall); + }); + } -} \ No newline at end of file + stopServiceExtensionAbility(want: Want): Promise { + return 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.nativeStopServiceExtensionAbility(want, myCall); + }); + }); + } +} diff --git a/frameworks/ets/ets/application/UIAbilityContext.ets b/frameworks/ets/ets/application/UIAbilityContext.ets index f332edf4f17..9a916d88efe 100644 --- a/frameworks/ets/ets/application/UIAbilityContext.ets +++ b/frameworks/ets/ets/application/UIAbilityContext.ets @@ -22,23 +22,62 @@ import { Configuration } from '@ohos.app.ability.Configuration'; import Context from 'application.Context'; import window from '@ohos.window'; import AsyncCallbackWrapper from '../utils/AbilityUtils'; +import OpenLinkOptions from '@ohos.app.ability.OpenLinkOptions'; +import { HapModuleInfo } from 'bundleManager.HapModuleInfo'; + +class Cleaner { + public ptr: long = 0; + + constructor(ptr: long) { + this.ptr = ptr; + } + + native clean(): void; +} + +export function callback(cleaner: Cleaner): void { + cleaner.clean(); +} + +let destroyRegister = new FinalizationRegistry(callback); +let unregisterToken = new object(); export default class UIAbilityContext extends Context { static { loadLibrary("context_ani"); } + private cleaner: Cleaner | null = null; + etsAbilityContextPtr: long = 0; config: Configuration; abilityInfo: AbilityInfo; windowStage: window.WindowStage; + currentHapModuleInfo: HapModuleInfo; native constructor(); - constructor(config: Configuration, abilityInfo: AbilityInfo, windowStage: window.WindowStage) { + constructor(config: Configuration, abilityInfo: AbilityInfo, windowStage: window.WindowStage, currentHapModuleInfo: HapModuleInfo) { super(); this.config = config; this.abilityInfo = abilityInfo; this.windowStage = windowStage; + this.currentHapModuleInfo = currentHapModuleInfo; + } + + private setEtsAbilityContextPtr(ptr: long) { + if (this.etsAbilityContextPtr == 0) { + this.etsAbilityContextPtr = ptr; + } + this.registerCleaner(this.etsAbilityContextPtr); + } + + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr); + destroyRegister.register(this, this.cleaner!, unregisterToken); + } + + unregisterCleaner(): void { + destroyRegister.unregister(unregisterToken); } private native nativeStartAbilitySync(want: Want, callback: AsyncCallbackWrapper): void; @@ -56,6 +95,16 @@ export default class UIAbilityContext extends Context { private native nativeReportDrawnCompletedSync(callback: AsyncCallbackWrapper): void; + private native nativeStartServiceExtensionAbility(want: Want, callback: AsyncCallbackWrapper): void; + + private native nativeOpenLink(link: string, myCallback:AsyncCallbackWrapper, options?: OpenLinkOptions, callback?: AsyncCallbackWrapper): void; + + private native nativeIsTerminating(): boolean; + + private native nativeMoveAbilityToBackground(callback: AsyncCallbackWrapper): void; + + private native nativeRequestModalUIExtension(pickerWant: Want, callback: AsyncCallbackWrapper): void; + startAbility(want: Want, callback: AsyncCallback): void { let myCall = new AsyncCallbackWrapper(callback); taskpool.execute((): void => { @@ -206,4 +255,82 @@ export default class UIAbilityContext extends Context { this.nativeReportDrawnCompletedSync(myCall); }); } + + startServiceExtensionAbility(want: Want, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + this.nativeStartServiceExtensionAbility(want, myCall); + } + + startServiceExtensionAbility(want: Want): Promise { + return 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); + } + }); + this.nativeStartServiceExtensionAbility(want, myCall); + }); + } + + openLink(link: string, options?: OpenLinkOptions, callback?: AsyncCallback): Promise { + return 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); + } + }); + let callParam: AsyncCallbackWrapper | undefined = undefined; + if (callback) { + callParam = new AsyncCallbackWrapper(callback); + } + taskpool.execute(() => { + this.nativeOpenLink(link, myCall, options, callParam); + }); + }); + } + + isTerminating(): boolean { + return this.nativeIsTerminating(); + } + + moveAbilityToBackground(): Promise { + return new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let syncCall = new AsyncCallbackWrapper((err: BusinessError | null) => { + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute(() => { + this.nativeMoveAbilityToBackground(syncCall); + }); + }); + } + + requestModalUIExtension(pickerWant: Want, callback: AsyncCallback): void { + let syncCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeRequestModalUIExtension(pickerWant, syncCall); + }); + } + + requestModalUIExtension(pickerWant: Want): Promise { + return new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let syncCall = new AsyncCallbackWrapper((err: BusinessError | null) => { + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute(() => { + this.nativeRequestModalUIExtension(pickerWant, syncCall); + }); + }); + } } diff --git a/frameworks/ets/ets/application/UIExtensionContext.ets b/frameworks/ets/ets/application/UIExtensionContext.ets index f4037cbb75e..7fd231110d3 100644 --- a/frameworks/ets/ets/application/UIExtensionContext.ets +++ b/frameworks/ets/ets/application/UIExtensionContext.ets @@ -18,10 +18,42 @@ import { AsyncCallback } from '@ohos.base'; import { BusinessError } from '@ohos.base'; import AsyncCallbackWrapper from '../utils/AbilityUtils'; import ExtensionContext from 'application.ExtensionContext'; +import StartOptions from '@ohos.app.ability.StartOptions'; +import Want from '@ohos.app.ability.Want'; + +class Cleaner { + static callback(cleaner: Cleaner): void { + cleaner.clean() + } + constructor(targetPtr: long) { + this.targetPtr = targetPtr + } + native clean(): void + private targetPtr: long = 0 +} +let destroyRegister = new FinalizationRegistry(Cleaner.callback) +let unregisterToken = new object() export default class UIExtensionContext extends ExtensionContext { + nativeExtensionContext:long = 0; + private cleaner: Cleaner | null = null; + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr) + destroyRegister.register(this, this.cleaner!, unregisterToken); + } + unregisterCleaner(): void { + destroyRegister.unregister(unregisterToken); + } + constructor(context:long) { + if(this.nativeExtensionContext == 0){ + this.nativeExtensionContext = context; + } + this.registerCleaner(this.nativeExtensionContext) + } native terminateSelfSync(callback:AsyncCallbackWrapper): void; native terminateSelfWithResultSync(parameter: AbilityResult, callback: AsyncCallbackWrapper): void; + native nativeStartAbility(want: Want, callback: AsyncCallbackWrapper): void; + native nativeStartAbility(want: Want, options: StartOptions, callback:AsyncCallbackWrapper): void; terminateSelf(callback:AsyncCallback): void { let myCall = new AsyncCallbackWrapper(callback); @@ -68,4 +100,33 @@ export default class UIExtensionContext extends ExtensionContext { }); return p; } + + startAbility(want: Want, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartAbility(want, myCall); + }); + } + + startAbility(want: Want, options: StartOptions, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartAbility(want, options, myCall); + }); + } + + startAbility(want: Want, options: StartOptions): Promise { + return 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); + }); + }); + } } \ No newline at end of file diff --git a/frameworks/ets/ets/wantAgent/triggerInfo.ets b/frameworks/ets/ets/wantAgent/triggerInfo.ets new file mode 100644 index 00000000000..0653b0f4486 --- /dev/null +++ b/frameworks/ets/ets/wantAgent/triggerInfo.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 Want from '@ohos.app.ability.Want'; +import StartOptions from '@ohos.app.ability.StartOptions'; + +export interface TriggerInfo { + code: number; + want?: Want; + permission?: string; + extraInfo?: Record; + extraInfos?: Record; + startOptions?: StartOptions; +} + +class TriggerInfoImpl implements TriggerInfo { + public code: number; + public want?: Want; + public permission?: string; + public extraInfo?: Record; + public extraInfos?: Record; + public startOptions?: StartOptions; +} diff --git a/frameworks/ets/ets/wantAgent/wantAgentInfo.ets b/frameworks/ets/ets/wantAgent/wantAgentInfo.ets new file mode 100644 index 00000000000..4487de50bf1 --- /dev/null +++ b/frameworks/ets/ets/wantAgent/wantAgentInfo.ets @@ -0,0 +1,44 @@ +/* + * 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 Want from '@ohos.app.ability.Want'; +import wantAgent from '@ohos.app.ability.wantAgent'; +import type abilityWantAgent from '@ohos.app.ability.wantAgent'; + +export interface WantAgentInfo { + wants: Array; + operationType?: wantAgent.OperationType; + actionType?: abilityWantAgent.OperationType; + requestCode: number; + wantAgentFlags?: Array; + actionFlags?: Array; + extraInfo?: Record; + extraInfos?: Record; +} + +class WantAgentInfoImpl implements WantAgentInfo { + public wants: Array; + public operationType?: wantAgent.OperationType; + public actionType?: abilityWantAgent.OperationType; + public requestCode: number; + public wantAgentFlags?: Array; + public actionFlags?: Array; + public extraInfo?: Record; + public extraInfos?: Record; + + constructor(wants: Array) { + this.wants = wants; + } +} diff --git a/frameworks/js/napi/app/ability_delegator/js_ability_delegator.cpp b/frameworks/js/napi/app/ability_delegator/js_ability_delegator.cpp index 34e943e9bd0..9cdb79939a1 100644 --- a/frameworks/js/napi/app/ability_delegator/js_ability_delegator.cpp +++ b/frameworks/js/napi/app/ability_delegator/js_ability_delegator.cpp @@ -583,14 +583,15 @@ napi_value JSAbilityDelegator::OnWaitAbilityStageMonitor(napi_env env, NapiCallb TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); return; } - std::shared_ptr result; + std::shared_ptr result; result = opt.hasTimeoutPara ? delegator->WaitAbilityStageMonitor(monitor, timeout) : delegator->WaitAbilityStageMonitor(monitor); - if (!result || result->object_.expired()) { + auto jsStageProperty = std::static_pointer_cast(result); + if (!jsStageProperty || jsStageProperty->object_.expired()) { TAG_LOGE(AAFwkTag::DELEGATOR, "waitAbilityStageMonitor failed"); return; } - abilityStageObjBox->object_ = result->object_; + abilityStageObjBox->object_ = jsStageProperty->object_; }; NapiAsyncTask::CompleteCallback complete = [abilityStageObjBox](napi_env env, NapiAsyncTask &task, int32_t status) { diff --git a/frameworks/native/ability/native/BUILD.gn b/frameworks/native/ability/native/BUILD.gn index 2776de41c21..08f29ae030b 100644 --- a/frameworks/native/ability/native/BUILD.gn +++ b/frameworks/native/ability/native/BUILD.gn @@ -689,6 +689,7 @@ config("insight_intent_executor_public_config") { ohos_shared_library("insight_intent_executor") { sources = [ + "${ability_runtime_native_path}/ability/native/insight_intent_executor/ets_insight_intent_executor_instance.cpp", "${ability_runtime_native_path}/ability/native/insight_intent_executor/insight_intent_executor.cpp", "${ability_runtime_native_path}/ability/native/insight_intent_executor/insight_intent_executor_mgr.cpp", "${ability_runtime_native_path}/ability/native/insight_intent_executor/js_insight_intent_entry.cpp", @@ -731,6 +732,56 @@ ohos_shared_library("insight_intent_executor") { part_name = "ability_runtime" } +ohos_shared_library("insight_intent_executor_ani") { + + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + sources = [ + "${ability_runtime_native_path}/ability/native/insight_intent_executor/ets_insight_intent_executor.cpp", + "${ability_runtime_path}/frameworks/native/insight_intent/insight_intent_context/ets_insight_intent_context.cpp", + ] + + public_configs = [ ":insight_intent_executor_public_config" ] + + deps = [ + ":insight_intent_executor", + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/ability_manager:ability_start_options", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_napi_path}/inner/napi_common:napi_common", + "${ability_runtime_native_path}/ability/native:ability_business_error", + "${ability_runtime_native_path}/insight_intent/insight_intent_context:insightintentcontext", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_services_path}/common:event_report", + ] + + external_deps = [ + "ability_base:session_info", + "ability_base:want", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "image_framework:image_native", + "ipc:ipc_core", + "ipc:ipc_napi", + "napi:ace_napi", + "runtime_core:ani", + "window_manager:libwm", + ] + + subsystem_name = "ability" + part_name = "ability_runtime" +} + ohos_shared_library("cj_insight_intent_executor") { sanitize = { integer_overflow = true @@ -809,7 +860,6 @@ config("uiability_config") { } ohos_shared_library("ui_ability_ani") { - branch_protector_ret = "pac_ret" sanitize = { @@ -821,17 +871,18 @@ ohos_shared_library("ui_ability_ani") { include_dirs = [ "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", + "${ability_runtime_path}/frameworks/ets/ani/ui_ability/include", "${ability_runtime_path}/interfaces/kits/native/ability/native", "${ability_runtime_path}/interfaces/kits/native/ability/native/ability_runtime", "${ability_runtime_path}/interfaces/kits/native/ability/native/ui_extension_ability", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_delegator", "${ability_runtime_path}/utils/global/time/include", "${ability_runtime_services_path}/common/include", ] sources = [ - "${ability_runtime_native_path}/ability/native/ability_runtime/ets_ability_context.cpp", - "${ability_runtime_native_path}/ability/native/ability_runtime/ets_ui_ability.cpp", - "${ability_runtime_native_path}/ability/native/ets_free_install_observer.cpp", + "${ability_runtime_path}/frameworks/ets/ani/ui_ability/src/ets_ability_context.cpp", + "${ability_runtime_path}/frameworks/ets/ani/ui_ability/src/ets_ui_ability.cpp", ] public_configs = [ ":uiability_config" ] @@ -1414,7 +1465,8 @@ ohos_shared_library("service_extension_ani") { sources = [ "${ability_runtime_path}/frameworks/ets/ani/service_extension_ability/src/ets_service_extension.cpp", - ] + "${ability_runtime_path}/frameworks/ets/ani/service_extension_ability/src/ets_service_extension_context.cpp", + ] deps = [ ":abilitykit_native", @@ -1428,9 +1480,10 @@ ohos_shared_library("service_extension_ani") { "${ability_runtime_native_path}/ability/native:ability_business_error", "${ability_runtime_native_path}/ability/native:insight_intent_executor", "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_native_path}/appkit:app_context_utils", "${ability_runtime_native_path}/insight_intent/insight_intent_context:insightintentcontext", - "${ability_runtime_path}/utils/global/freeze:freeze_util", "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_path}/utils/global/freeze:freeze_util", ] external_deps = [ @@ -1449,6 +1502,7 @@ ohos_shared_library("service_extension_ani") { "runtime_core:ani", "safwk:system_ability_fwk", "samgr:samgr_proxy", + "bundle_framework:bms_ani_common", ] if (ability_runtime_graphics) { @@ -2030,7 +2084,6 @@ ohos_shared_library("ui_extension") { } ohos_shared_library("ui_extension_ani") { - sanitize = { cfi = true cfi_cross_dso = true diff --git a/frameworks/native/ability/native/ability_runtime/js_ui_ability.cpp b/frameworks/native/ability/native/ability_runtime/js_ui_ability.cpp index 10e17da8bb9..ed5aeb34aec 100644 --- a/frameworks/native/ability/native/ability_runtime/js_ui_ability.cpp +++ b/frameworks/native/ability/native/ability_runtime/js_ui_ability.cpp @@ -405,13 +405,7 @@ void JsUIAbility::OnStart(const Want &want, sptr sessionInfo AddLifecycleEventBeforeJSCall(FreezeUtil::TimeoutState::FOREGROUND, methodName); CallObjectMethod("onCreate", argv, ArraySize(argv)); AddLifecycleEventAfterJSCall(FreezeUtil::TimeoutState::FOREGROUND, methodName); - - auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(); - if (delegator) { - TAG_LOGD(AAFwkTag::UIABILITY, "call PostPerformStart"); - delegator->PostPerformStart(CreateADelegatorAbilityProperty()); - } - + HandleAbilityDelegatorStart(); applicationContext = AbilityRuntime::Context::GetApplicationContext(); if (applicationContext != nullptr) { applicationContext->DispatchOnAbilityCreate(jsAbilityObj_); @@ -419,6 +413,17 @@ void JsUIAbility::OnStart(const Want &want, sptr sessionInfo TAG_LOGD(AAFwkTag::UIABILITY, "end"); } +void JsUIAbility::HandleAbilityDelegatorStart() +{ + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(); + auto property = std::make_shared(); + if (delegator && CreateProperty(abilityContext_, property)) { + TAG_LOGD(AAFwkTag::UIABILITY, "call PostPerformStart"); + property->object_ = jsAbilityObj_; + delegator->PostPerformStart(property); + } +} + void JsUIAbility::AddLifecycleEventBeforeJSCall(FreezeUtil::TimeoutState state, const std::string &methodName) const { auto entry = std::string("JsUIAbility::") + methodName + " begin"; @@ -525,9 +530,11 @@ void JsUIAbility::OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> *callbackI void JsUIAbility::OnStopCallback() { auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(); - if (delegator) { + auto property = std::make_shared(); + if (delegator && CreateProperty(abilityContext_, property)) { TAG_LOGD(AAFwkTag::UIABILITY, "call PostPerformStop"); - delegator->PostPerformStop(CreateADelegatorAbilityProperty()); + property->object_ = jsAbilityObj_; + delegator->PostPerformStop(property); } bool ret = ConnectionManager::GetInstance().DisconnectCaller(AbilityContext::token_); @@ -571,9 +578,11 @@ void JsUIAbility::OnSceneCreated() } auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(); - if (delegator) { + auto property = std::make_shared(); + if (delegator && CreateProperty(abilityContext_, property)) { TAG_LOGD(AAFwkTag::UIABILITY, "call PostPerformScenceCreated"); - delegator->PostPerformScenceCreated(CreateADelegatorAbilityProperty()); + property->object_ = jsAbilityObj_; + delegator->PostPerformScenceCreated(property); } applicationContext = AbilityRuntime::Context::GetApplicationContext(); @@ -608,9 +617,11 @@ void JsUIAbility::OnSceneRestored() } auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(); - if (delegator) { + auto property = std::make_shared(); + if (delegator && CreateProperty(abilityContext_, property)) { TAG_LOGD(AAFwkTag::UIABILITY, "call PostPerformScenceRestored"); - delegator->PostPerformScenceRestored(CreateADelegatorAbilityProperty()); + property->object_ = jsAbilityObj_; + delegator->PostPerformScenceRestored(property); } } @@ -652,9 +663,11 @@ void JsUIAbility::onSceneDestroyed() } auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(); - if (delegator) { + auto property = std::make_shared(); + if (delegator && CreateProperty(abilityContext_, property)) { TAG_LOGD(AAFwkTag::UIABILITY, "call PostPerformScenceDestroyed"); - delegator->PostPerformScenceDestroyed(CreateADelegatorAbilityProperty()); + property->object_ = jsAbilityObj_; + delegator->PostPerformScenceDestroyed(property); } applicationContext = AbilityRuntime::Context::GetApplicationContext(); @@ -714,9 +727,11 @@ void JsUIAbility::CallOnForegroundFunc(const Want &want) AddLifecycleEventAfterJSCall(FreezeUtil::TimeoutState::FOREGROUND, methodName); auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(); - if (delegator) { + auto property = std::make_shared(); + if (delegator && CreateProperty(abilityContext_, property)) { TAG_LOGD(AAFwkTag::UIABILITY, "call PostPerformForeground"); - delegator->PostPerformForeground(CreateADelegatorAbilityProperty()); + property->object_ = jsAbilityObj_; + delegator->PostPerformForeground(property); } applicationContext = AbilityRuntime::Context::GetApplicationContext(); @@ -743,9 +758,11 @@ void JsUIAbility::OnBackground() UIAbility::OnBackground(); auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(); - if (delegator) { + auto property = std::make_shared(); + if (delegator && CreateProperty(abilityContext_, property)) { TAG_LOGD(AAFwkTag::UIABILITY, "call PostPerformBackground"); - delegator->PostPerformBackground(CreateADelegatorAbilityProperty()); + property->object_ = jsAbilityObj_; + delegator->PostPerformBackground(property); } applicationContext = AbilityRuntime::Context::GetApplicationContext(); @@ -2017,31 +2034,6 @@ int32_t JsUIAbility::CallSaveStatePromise(napi_value result, CallOnSaveStateInfo return ERR_OK; } -std::shared_ptr JsUIAbility::CreateADelegatorAbilityProperty() -{ - if (abilityContext_ == nullptr) { - TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext_"); - return nullptr; - } - auto property = std::make_shared(); - property->token_ = abilityContext_->GetToken(); - property->name_ = GetAbilityName(); - property->moduleName_ = GetModuleName(); - if (GetApplicationInfo() == nullptr || GetApplicationInfo()->bundleName.empty()) { - property->fullName_ = GetAbilityName(); - } else { - std::string::size_type pos = GetAbilityName().find(GetApplicationInfo()->bundleName); - if (pos == std::string::npos || pos != 0) { - property->fullName_ = GetApplicationInfo()->bundleName + "." + GetAbilityName(); - } else { - property->fullName_ = GetAbilityName(); - } - } - property->lifecycleState_ = GetState(); - property->object_ = jsAbilityObj_; - return property; -} - void JsUIAbility::Dump(const std::vector ¶ms, std::vector &info) { UIAbility::Dump(params, info); diff --git a/frameworks/native/ability/native/insight_intent_executor/ets_insight_intent_executor.cpp b/frameworks/native/ability/native/insight_intent_executor/ets_insight_intent_executor.cpp new file mode 100644 index 00000000000..cdef33bb8b0 --- /dev/null +++ b/frameworks/native/ability/native/insight_intent_executor/ets_insight_intent_executor.cpp @@ -0,0 +1,505 @@ +/* + * 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_insight_intent_executor.h" +#include "hitrace_meter.h" +#include "ability_transaction_callback_info.h" +#include "hilog_tag_wrapper.h" +#include "insight_intent_constant.h" +#include "insight_intent_execute_result.h" +#include "ets_runtime.h" +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "ani_common_execute_result.h" + +#undef STATE_PATTERN_NAIVE_H +#define STATE_PATTERN_NAIVE_STATE state_ +#include "state_pattern_naive.h" + +#define ETS_EXPORT __attribute__((visibility("default"))) + +namespace OHOS { +namespace AbilityRuntime { +using State = EtsInsightIntentExecutor::State; +namespace { +constexpr const char *EXECUTOR_CLASS_NAME = "L@ohos/app/ability/InsightIntentExecutor/InsightIntentExecutor;"; +} +InsightIntentExecutor *EtsInsightIntentExecutor::Create(Runtime &runtime) +{ + return new (std::nothrow) EtsInsightIntentExecutor(static_cast(runtime)); +} + +EtsInsightIntentExecutor::EtsInsightIntentExecutor(ETSRuntime &runtime) : runtime_(runtime) +{ } + +EtsInsightIntentExecutor::~EtsInsightIntentExecutor() +{ + state_ = State::DESTROYED; + TAG_LOGD(AAFwkTag::INTENT, "~EtsInsightIntentExecutor called"); + + ani_env *env = runtime_.GetAniEnv(); + if (env != nullptr) { + if (contextObj_ && contextObj_->aniRef) { + env->GlobalReference_Delete(contextObj_->aniRef); + } + if (etsObj_ && etsObj_->aniRef) { + env->GlobalReference_Delete(etsObj_->aniRef); + } + } +} + +bool EtsInsightIntentExecutor::Init(const InsightIntentExecutorInfo &insightIntentInfo) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::Init called"); + STATE_PATTERN_NAIVE_ACCEPT(State::CREATED, false); + state_ = State::INITIALIZED; + InsightIntentExecutor::Init(insightIntentInfo); + + auto env = runtime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + etsObj_ = EtsInsightIntentExecutor::LoadEtsCode(insightIntentInfo, runtime_); + if (etsObj_ == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null etsObj_"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null Context"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + contextCpp_ = std::make_shared(context); + contextObj_ = CreateEtsInsightIntentContext(env, contextCpp_); + if (contextObj_ == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null contextObj_"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + ani_status status = ANI_ERROR; + if ((status = env->Object_SetFieldByName_Ref(etsObj_->aniObj, "context", contextObj_->aniRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + ani_class executorClass = nullptr; + if ((status = env->FindClass(EXECUTOR_CLASS_NAME, &executorClass)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "find InsightIntentExecutor failed status: %{public}d", status); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + etsObj_->aniCls = executorClass; + + std::array functions = { + ani_native_function {"nativeOnExecuteResult", nullptr, reinterpret_cast(OnExecuteResult)}, + }; + if ((status = env->Class_BindNativeMethods(etsObj_->aniCls, functions.data(), functions.size())) != ANI_OK) { + if (status != ANI_ALREADY_BINDED) { + TAG_LOGE(AAFwkTag::INTENT, "Class_BindNativeMethods failed status: %{public}d", status); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + } + if ((status = env->Object_SetFieldByName_Long(etsObj_->aniObj, "nativeExecutor", + reinterpret_cast(this))) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + return true; +} + +bool EtsInsightIntentExecutor::ExecuteIntentCheckError() +{ + ReplyFailedInner(); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); +} + +bool EtsInsightIntentExecutor::HandleExecuteIntent( + std::shared_ptr executeParam, + void *pageLoader, + std::unique_ptr callback, + bool &isAsync) +{ + TAG_LOGD(AAFwkTag::INTENT, "HandleExecuteIntent called"); + STATE_PATTERN_NAIVE_ACCEPT(State::INITIALIZED, false); + state_ = State::EXECUTING; + + if (callback == nullptr || callback->IsEmpty()) { + TAG_LOGE(AAFwkTag::INTENT, "null callback"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + if (executeParam == nullptr || executeParam->insightIntentParam_ == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "invalid execute param"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + callback_ = std::move(callback); + bool ret = false; + InsightIntentExecuteMode mode = static_cast(executeParam->executeMode_); + auto name = executeParam->insightIntentName_; + auto param = executeParam->insightIntentParam_; + TAG_LOGI(AAFwkTag::INTENT, "call executor, intentName: %{public}s, mode: %{public}d", name.c_str(), mode); + switch (mode) { + case InsightIntentExecuteMode::UIABILITY_FOREGROUND: + if (!EtsInsightIntentExecutor::CheckParametersUIAbilityForeground(reinterpret_cast(pageLoader))) { + TAG_LOGE(AAFwkTag::INTENT, "CheckParametersUIAbilityForeground error"); + return ExecuteIntentCheckError(); + } + ret = ExecuteInsightIntentUIAbilityForeground(name, *param, reinterpret_cast(pageLoader)); + break; + case InsightIntentExecuteMode::UIABILITY_BACKGROUND: + if (!EtsInsightIntentExecutor::CheckParametersUIAbilityBackground()) { + TAG_LOGE(AAFwkTag::INTENT, "CheckParametersUIAbilityBackground error"); + return ExecuteIntentCheckError(); + } + ret = ExecuteInsightIntentUIAbilityBackground(name, *param); + break; + case InsightIntentExecuteMode::UIEXTENSION_ABILITY: + if (!EtsInsightIntentExecutor::CheckParametersUIExtension(reinterpret_cast(pageLoader))) { + TAG_LOGE(AAFwkTag::INTENT, "CheckParametersUIExtension error"); + return ExecuteIntentCheckError(); + } + ret = ExecuteInsightIntentUIExtension(name, *param, reinterpret_cast(pageLoader)); + break; + case InsightIntentExecuteMode::SERVICE_EXTENSION_ABILITY: + if (!EtsInsightIntentExecutor::CheckParametersServiceExtension()) { + TAG_LOGE(AAFwkTag::INTENT, "CheckParametersServiceExtension error"); + return ExecuteIntentCheckError(); + } + ret = ExecuteInsightIntentServiceExtension(name, *param); + break; + default: + TAG_LOGE(AAFwkTag::INTENT, "InsightIntentExecuteMode not supported yet"); + return ExecuteIntentCheckError(); + } + isAsync = isAsync_; + if (!ret) { + ReplyFailedInner(); + } + return ret; +} + +std::unique_ptr EtsInsightIntentExecutor::LoadEtsCode( + const InsightIntentExecutorInfo &info, + ETSRuntime &runtime) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::LoadEtsCode called"); + auto executeParam = info.executeParam; + if (executeParam == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null executeParam"); + return std::unique_ptr(); + } + + std::string moduleName(executeParam->moduleName_); + std::string srcPath(executeParam->moduleName_ + "/" + info.srcEntry); + + auto pos = srcPath.rfind('.'); + if (pos == std::string::npos) { + return std::unique_ptr(); + } + srcPath.erase(pos); + srcPath.append(".abc"); + + std::unique_ptr etsObj = + runtime.LoadModule(moduleName, srcPath, info.hapPath, info.esmodule, false, info.srcEntry); + return etsObj; +} + +void EtsInsightIntentExecutor::ReplyFailed(InsightIntentExecutorAsyncCallback *callback, + InsightIntentInnerErr innerErr) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ReplyFailed called"); + if (callback == nullptr) { + return; + } + AppExecFwk::InsightIntentExecuteResult errorResult{}; + errorResult.innerErr = innerErr; + callback->Call(errorResult); + delete callback; +} + +void EtsInsightIntentExecutor::ReplySucceeded(InsightIntentExecutorAsyncCallback *callback, + std::shared_ptr resultCpp) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ReplySucceeded called"); + if (callback == nullptr) { + return; + } + if (resultCpp == nullptr) { + ReplyFailed(callback); + return; + } + resultCpp->innerErr = InsightIntentInnerErr::INSIGHT_INTENT_ERR_OK; + callback->Call(*resultCpp); + delete callback; +} + +void EtsInsightIntentExecutor::ReplyFailedInner(InsightIntentInnerErr innerErr) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ReplyFailedInner called"); + state_ = EtsInsightIntentExecutor::State::INVALID; + auto* callback = callback_.release(); + EtsInsightIntentExecutor::ReplyFailed(callback, innerErr); +} + +void EtsInsightIntentExecutor::ReplySucceededInner(std::shared_ptr resultCpp) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ReplySucceededInner called"); + state_ = EtsInsightIntentExecutor::State::EXECUTATION_DONE; + auto* callback = callback_.release(); + EtsInsightIntentExecutor::ReplySucceeded(callback, resultCpp); +} + +bool EtsInsightIntentExecutor::HandleResultReturnedFromEtsFunc(ani_env *env, ani_ref result, bool isAsync) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::HandleResultReturnedFromEtsFunc called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + if (result == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null intent result"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + AppExecFwk::InsightIntentExecuteResult resultInner; + ani_object resultObject = static_cast(result); + if (!OHOS::AbilityRuntime::UnwrapExecuteResult(env, resultObject, resultInner)) { + TAG_LOGE(AAFwkTag::INTENT, "UnwrapExecuteResult failed"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + std::shared_ptr resultCpp = + std::make_shared(resultInner); + if (isAsync) { + TAG_LOGI(AAFwkTag::INTENT, "Is promise"); + auto *callback = callback_.release(); + EtsInsightIntentExecutor::ReplySucceeded(callback, resultCpp); + } else { + TAG_LOGI(AAFwkTag::INTENT, "Not promise"); + ReplySucceededInner(resultCpp); + } + return true; +} + +bool EtsInsightIntentExecutor::CheckParametersUIAbilityForeground(ani_ref windowStage) +{ + return windowStage != nullptr; +} + +ani_ref EtsInsightIntentExecutor::CallObjectMethod(bool withResult, const char *name, const char *signature, ...) +{ + ani_status status = ANI_ERROR; + ani_method method = nullptr; + auto env = runtime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return nullptr; + } + if ((status = env->Class_FindMethod(etsObj_->aniCls, name, signature, &method)) != ANI_OK) { + return nullptr; + } + if (method == nullptr) { + return nullptr; + } + ani_ref result = nullptr; + va_list args; + if (withResult) { + va_start(args, signature); + if ((status = env->Object_CallMethod_Ref_V(etsObj_->aniObj, method, &result, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + } + va_end(args); + return result; + } + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(etsObj_->aniObj, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + } + va_end(args); + return nullptr; +} + +bool EtsInsightIntentExecutor::ExecuteInsightIntentUIAbilityForeground( + const std::string &name, + const AAFwk::WantParams ¶m, + ani_ref windowStage) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ExecuteInsightIntentUIAbilityForeground called"); + auto env = runtime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return false; + } + + ani_string aniName = AppExecFwk::GetAniString(env, name); + ani_ref aniWantParams = OHOS::AppExecFwk::WrapWantParams(env, param); + ani_ref result = CallObjectMethod(true, "callOnExecuteInUIAbilityForegroundMode", nullptr, aniName, + aniWantParams, windowStage); + if (result == nullptr) { + return false; + } + + ani_boolean isAsync = false; + if (env->Object_GetFieldByName_Boolean(etsObj_->aniObj, "isOnExecuteInUIAbilityForegroundModeAsync", + &isAsync) != ANI_OK) { + return false; + } + + isAsync_ = static_cast(isAsync); + if (isAsync_) { + return true; + } else { + return HandleResultReturnedFromEtsFunc(env, result, isAsync_); + } +} + +bool EtsInsightIntentExecutor::CheckParametersUIAbilityBackground() +{ + return true; +} + +bool EtsInsightIntentExecutor::ExecuteInsightIntentUIAbilityBackground( + const std::string &name, + const AAFwk::WantParams ¶m) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ExecuteInsightIntentUIAbilityBackground called"); + auto env = runtime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return false; + } + + ani_string aniName = AppExecFwk::GetAniString(env, name); + ani_ref aniWantParams = OHOS::AppExecFwk::WrapWantParams(env, param); + ani_ref result = CallObjectMethod(true, "callOnExecuteInUIAbilityBackgroundMode", nullptr, aniName, + aniWantParams); + if (result == nullptr) { + return false; + } + + ani_boolean isAsync = false; + if (env->Object_GetFieldByName_Boolean(etsObj_->aniObj, "isOnExecuteInUIAbilityBackgroundModeAsync", + &isAsync) != ANI_OK) { + return false; + } + + isAsync_ = static_cast(isAsync); + if (isAsync_) { + return true; + } else { + return HandleResultReturnedFromEtsFunc(env, result, isAsync_); + } +} + +bool EtsInsightIntentExecutor::CheckParametersUIExtension(ani_ref UIExtensionContentSession) +{ + return UIExtensionContentSession != nullptr; +} + +bool EtsInsightIntentExecutor::ExecuteInsightIntentUIExtension( + const std::string &name, + const AAFwk::WantParams ¶m, + ani_ref UIExtensionContentSession) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ExecuteInsightIntentUIExtension called"); + auto env = runtime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return false; + } + + ani_string aniName = AppExecFwk::GetAniString(env, name); + ani_ref aniWantParams = OHOS::AppExecFwk::WrapWantParams(env, param); + ani_ref result = CallObjectMethod(true, "callOnExecuteInUIExtensionAbility", nullptr, aniName, + aniWantParams, UIExtensionContentSession); + if (result == nullptr) { + return false; + } + + ani_boolean isAsync = false; + if (env->Object_GetFieldByName_Boolean(etsObj_->aniObj, "isOnExecuteInUIExtensionAbilityAsync", + &isAsync) != ANI_OK) { + return false; + } + + isAsync_ = static_cast(isAsync); + if (isAsync_) { + return true; + } else { + return HandleResultReturnedFromEtsFunc(env, result, isAsync_); + } +} + +bool EtsInsightIntentExecutor::CheckParametersServiceExtension() +{ + return true; +} + +bool EtsInsightIntentExecutor::ExecuteInsightIntentServiceExtension( + const std::string &name, + const AAFwk::WantParams ¶m) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ExecuteInsightIntentServiceExtension called"); + auto env = runtime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return false; + } + + ani_string aniName = AppExecFwk::GetAniString(env, name); + ani_ref aniWantParams = OHOS::AppExecFwk::WrapWantParams(env, param); + ani_ref result = CallObjectMethod(true, "callOnExecuteInServiceExtensionAbility", nullptr, aniName, + aniWantParams); + if (result == nullptr) { + return false; + } + + ani_boolean isAsync = false; + if (env->Object_GetFieldByName_Boolean(etsObj_->aniObj, "isOnExecuteInServiceExtensionAbilityAsync", + &isAsync) != ANI_OK) { + return false; + } + isAsync_ = static_cast(isAsync); + if (isAsync_) { + return true; + } else { + return HandleResultReturnedFromEtsFunc(env, result, isAsync_); + } +} + +void EtsInsightIntentExecutor::OnExecuteResult(ani_env *env, ani_object aniObj, ani_object result) +{ + if (result == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null result"); + return; + } + + ani_long nativeExecutor = 0; + if (env->Object_GetFieldByName_Long(aniObj, "nativeExecutor", &nativeExecutor) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "nativeExecutor failed"); + return; + } + ((EtsInsightIntentExecutor*)nativeExecutor)->HandleResultReturnedFromEtsFunc(env, result, true); +} +} // namespace AbilityRuntime +} // namespace OHOS + +ETS_EXPORT extern "C" OHOS::AbilityRuntime::InsightIntentExecutor *OHOS_ETS_Insight_Intent_Executor_Create( + OHOS::AbilityRuntime::Runtime &runtime) +{ + return OHOS::AbilityRuntime::EtsInsightIntentExecutor::Create(runtime); +} diff --git a/frameworks/native/ability/native/insight_intent_executor/ets_insight_intent_executor_instance.cpp b/frameworks/native/ability/native/insight_intent_executor/ets_insight_intent_executor_instance.cpp new file mode 100644 index 00000000000..6a5f909a4af --- /dev/null +++ b/frameworks/native/ability/native/insight_intent_executor/ets_insight_intent_executor_instance.cpp @@ -0,0 +1,54 @@ +/* + * 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_insight_intent_executor_instance.h" + +#include +#include + +#include "hilog_tag_wrapper.h" +#include "hitrace_meter.h" +#include "string_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +const char *ETS_ANI_LIBNAME = "libinsight_intent_executor_ani.z.so"; +const char *ETS_ANI_Create_FUNC = "OHOS_ETS_Insight_Intent_Executor_Create"; +using CreateETSInsightIntentExecutorFunc = InsightIntentExecutor*(*)(OHOS::AbilityRuntime::Runtime &); +CreateETSInsightIntentExecutorFunc g_etsCreateFunc = nullptr; +} + +InsightIntentExecutor *CreateETSInsightIntentExecutor(Runtime &runtime) +{ + if (g_etsCreateFunc != nullptr) { + return g_etsCreateFunc(runtime); + } + auto handle = dlopen(ETS_ANI_LIBNAME, RTLD_LAZY); + if (handle == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "dlopen failed %{public}s, %{public}s", ETS_ANI_LIBNAME, dlerror()); + return nullptr; + } + auto symbol = dlsym(handle, ETS_ANI_Create_FUNC); + if (symbol == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "dlsym failed %{public}s, %{public}s", ETS_ANI_Create_FUNC, dlerror()); + dlclose(handle); + return nullptr; + } + g_etsCreateFunc = reinterpret_cast(symbol); + return g_etsCreateFunc(runtime); +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor.cpp b/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor.cpp index 2c04aa1e195..1792aae46be 100644 --- a/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor.cpp +++ b/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor.cpp @@ -14,6 +14,8 @@ */ #include "insight_intent_executor.h" +#include "ets_insight_intent_executor_instance.h" +#include "ets_runtime.h" #include "hilog_tag_wrapper.h" #include "js_insight_intent_entry.h" #include "js_insight_intent_executor.h" @@ -47,6 +49,8 @@ std::shared_ptr InsightIntentExecutor::Create(Runtime& ru return nullptr; } } + case Runtime::Language::ETS: + return std::shared_ptr(CreateETSInsightIntentExecutor(runtime)); default: return nullptr; } diff --git a/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor_mgr.cpp b/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor_mgr.cpp index 9564c243758..bbecb791cfa 100644 --- a/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor_mgr.cpp +++ b/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor_mgr.cpp @@ -75,7 +75,13 @@ bool InsightIntentExecutorMgr::ExecuteInsightIntent(Runtime& runtime, const Insi TAG_LOGI(AAFwkTag::INTENT, "execute insight intent, type: %{public}hhu", type); bool isAsync = false; - auto ret = intentExecutor->HandleExecuteIntent(executeParam, executeInfo.pageLoader, std::move(callback), isAsync); + bool ret = false; + if (runtime.GetLanguage() == AbilityRuntime::Runtime::Language::ETS) { + ret = intentExecutor->HandleExecuteIntent(executeParam, executeInfo.etsPageLoader, + std::move(callback), isAsync); + } else { + ret = intentExecutor->HandleExecuteIntent(executeParam, executeInfo.pageLoader, std::move(callback), isAsync); + } if (!ret) { TAG_LOGE(AAFwkTag::INTENT, "Handle Execute intent failed"); // callback has removed, if execute insight intent failed, call in sub function. diff --git a/frameworks/native/ability/native/js_service_extension.cpp b/frameworks/native/ability/native/js_service_extension.cpp index 95038f4a179..a02c8f513f4 100644 --- a/frameworks/native/ability/native/js_service_extension.cpp +++ b/frameworks/native/ability/native/js_service_extension.cpp @@ -542,48 +542,6 @@ bool JsServiceExtension::HandleInsightIntent(const AAFwk::Want &want) return true; } -bool JsServiceExtension::GetInsightIntentExecutorInfo(const Want &want, - const std::shared_ptr &executeParam, - InsightIntentExecutorInfo &executorInfo) -{ - TAG_LOGD(AAFwkTag::SERVICE_EXT, "called"); - auto context = GetContext(); - if (executeParam == nullptr || context == nullptr || abilityInfo_ == nullptr) { - TAG_LOGE(AAFwkTag::SERVICE_EXT, "Param invalid"); - return false; - } - - const WantParams &wantParams = want.GetParams(); - executorInfo.srcEntry = wantParams.GetStringParam(AppExecFwk::INSIGHT_INTENT_SRC_ENTRY); - executorInfo.hapPath = abilityInfo_->hapPath; - executorInfo.esmodule = abilityInfo_->compileMode == AppExecFwk::CompileMode::ES_MODULE; - executorInfo.token = context->GetToken(); - executorInfo.executeParam = executeParam; - return true; -} - -bool JsServiceExtension::OnInsightIntentExecuteDone(uint64_t intentId, - const AppExecFwk::InsightIntentExecuteResult &result) -{ - TAG_LOGI(AAFwkTag::SERVICE_EXT, "Notify execute done, intentId %{public}" PRIu64"", intentId); - auto context = GetContext(); - if (context == nullptr) { - TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); - return false; - } - auto token = context->GetToken(); - if (token == nullptr) { - TAG_LOGE(AAFwkTag::SERVICE_EXT, "null token"); - return false; - } - auto ret = AAFwk::AbilityManagerClient::GetInstance()->ExecuteInsightIntentDone(token, intentId, result); - if (ret != ERR_OK) { - TAG_LOGE(AAFwkTag::SERVICE_EXT, "Notify execute done failed"); - return false; - } - return true; -} - napi_value JsServiceExtension::CallObjectMethod(const char* name, napi_value const* argv, size_t argc) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name); @@ -769,22 +727,6 @@ void JsServiceExtension::OnConfigurationUpdated(const AppExecFwk::Configuration& HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); ServiceExtension::OnConfigurationUpdated(configuration); TAG_LOGD(AAFwkTag::SERVICE_EXT, "call"); - auto context = GetContext(); - if (context == nullptr) { - TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); - return; - } - - auto contextConfig = context->GetConfiguration(); - if (contextConfig != nullptr) { - TAG_LOGD(AAFwkTag::SERVICE_EXT, "Config dump: %{public}s", contextConfig->GetName().c_str()); - std::vector changeKeyV; - contextConfig->CompareDifferent(changeKeyV, configuration); - if (!changeKeyV.empty()) { - contextConfig->Merge(changeKeyV, configuration); - } - TAG_LOGD(AAFwkTag::SERVICE_EXT, "Config dump after merge: %{public}s", contextConfig->GetName().c_str()); - } ConfigurationUpdated(); } diff --git a/frameworks/native/ability/native/service_extension.cpp b/frameworks/native/ability/native/service_extension.cpp index 06cf600af4f..21c37d5b478 100644 --- a/frameworks/native/ability/native/service_extension.cpp +++ b/frameworks/native/ability/native/service_extension.cpp @@ -15,6 +15,7 @@ #include "service_extension.h" +#include "ability_manager_client.h" #include "configuration_utils.h" #include "connection_manager.h" #include "hilog_tag_wrapper.h" @@ -90,6 +91,58 @@ void ServiceExtension::OnConfigurationUpdated(const AppExecFwk::Configuration &c auto configUtils = std::make_shared(); configUtils->UpdateGlobalConfig(configuration, context->GetResourceManager()); + auto contextConfig = context->GetConfiguration(); + if (contextConfig != nullptr) { + TAG_LOGD(AAFwkTag::SERVICE_EXT, "Config dump: %{public}s", contextConfig->GetName().c_str()); + std::vector changeKeyV; + contextConfig->CompareDifferent(changeKeyV, configuration); + if (!changeKeyV.empty()) { + contextConfig->Merge(changeKeyV, configuration); + } + TAG_LOGD(AAFwkTag::SERVICE_EXT, "Config dump after merge: %{public}s", contextConfig->GetName().c_str()); + } +} + +bool ServiceExtension::GetInsightIntentExecutorInfo(const Want &want, + const std::shared_ptr &executeParam, + InsightIntentExecutorInfo &executorInfo) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "GetInsightIntentExecutorInfo called"); + auto context = GetContext(); + if (executeParam == nullptr || context == nullptr || abilityInfo_ == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Param invalid"); + return false; + } + + const WantParams &wantParams = want.GetParams(); + executorInfo.srcEntry = wantParams.GetStringParam(AppExecFwk::INSIGHT_INTENT_SRC_ENTRY); + executorInfo.hapPath = abilityInfo_->hapPath; + executorInfo.esmodule = abilityInfo_->compileMode == AppExecFwk::CompileMode::ES_MODULE; + executorInfo.token = context->GetToken(); + executorInfo.executeParam = executeParam; + return true; +} + +bool ServiceExtension::OnInsightIntentExecuteDone(uint64_t intentId, + const AppExecFwk::InsightIntentExecuteResult &result) +{ + TAG_LOGI(AAFwkTag::SERVICE_EXT, "Notify execute done, intentId %{public}" PRIu64"", intentId); + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); + return false; + } + auto token = context->GetToken(); + if (token == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null token"); + return false; + } + auto ret = AAFwk::AbilityManagerClient::GetInstance()->ExecuteInsightIntentDone(token, intentId, result); + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Notify execute done failed"); + return false; + } + return true; } } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/native/ability/native/ui_ability.cpp b/frameworks/native/ability/native/ui_ability.cpp index 928869f1622..2567ac4df58 100644 --- a/frameworks/native/ability/native/ui_ability.cpp +++ b/frameworks/native/ability/native/ui_ability.cpp @@ -306,6 +306,30 @@ void UIAbility::DestroyInstance() TAG_LOGD(AAFwkTag::UIABILITY, "called"); } +bool UIAbility::CreateProperty(std::shared_ptr abilityContext, + std::shared_ptr delegatorAbilityProperty) +{ + if (abilityContext == nullptr || delegatorAbilityProperty == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext or delegatorAbilityProperty"); + return false; + } + delegatorAbilityProperty->token_ = abilityContext->GetToken(); + delegatorAbilityProperty->name_ = GetAbilityName(); + delegatorAbilityProperty->moduleName_ = GetModuleName(); + if (GetApplicationInfo() == nullptr || GetApplicationInfo()->bundleName.empty()) { + delegatorAbilityProperty->fullName_ = GetAbilityName(); + } else { + std::string::size_type pos = GetAbilityName().find(GetApplicationInfo()->bundleName); + if (pos == std::string::npos || pos != 0) { + delegatorAbilityProperty->fullName_ = GetApplicationInfo()->bundleName + "." + GetAbilityName(); + } else { + delegatorAbilityProperty->fullName_ = GetAbilityName(); + } + } + delegatorAbilityProperty->lifecycleState_ = GetState(); + return true; +} + bool UIAbility::IsRestoredInContinuation() const { if (abilityContext_ == nullptr) { diff --git a/frameworks/native/appkit/BUILD.gn b/frameworks/native/appkit/BUILD.gn index e8ffa3b4521..4972a335829 100644 --- a/frameworks/native/appkit/BUILD.gn +++ b/frameworks/native/appkit/BUILD.gn @@ -397,6 +397,7 @@ ohos_shared_library("ability_stage_ani") { "ability_base:base", "ability_base:string_utils", "ability_base:want", + "bundle_framework:bms_ani_common", "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", "c_utils:utils", diff --git a/frameworks/native/appkit/ability_delegator/ability_delegator.cpp b/frameworks/native/appkit/ability_delegator/ability_delegator.cpp index 0c9ef8125c7..d7d3c4e6497 100644 --- a/frameworks/native/appkit/ability_delegator/ability_delegator.cpp +++ b/frameworks/native/appkit/ability_delegator/ability_delegator.cpp @@ -134,7 +134,7 @@ std::shared_ptr AbilityDelegator::WaitAbilityMonit return obtainedAbility; } -std::shared_ptr AbilityDelegator::WaitAbilityStageMonitor( +std::shared_ptr AbilityDelegator::WaitAbilityStageMonitor( const std::shared_ptr &monitor) { if (!monitor) { @@ -170,7 +170,7 @@ std::shared_ptr AbilityDelegator::WaitAbilityMonit return obtainedAbility; } -std::shared_ptr AbilityDelegator::WaitAbilityStageMonitor( +std::shared_ptr AbilityDelegator::WaitAbilityStageMonitor( const std::shared_ptr &monitor, const int64_t timeoutMs) { if (!monitor) { @@ -394,7 +394,7 @@ void AbilityDelegator::PostPerformStart(const std::shared_ptr &abilityStage) +void AbilityDelegator::PostPerformStageStart(const std::shared_ptr &abilityStage) { TAG_LOGI(AAFwkTag::DELEGATOR, "called"); if (!abilityStage) { diff --git a/frameworks/native/appkit/ability_delegator/iability_stage_monitor.cpp b/frameworks/native/appkit/ability_delegator/iability_stage_monitor.cpp index 0a62b35ba87..5d14d38a3ac 100644 --- a/frameworks/native/appkit/ability_delegator/iability_stage_monitor.cpp +++ b/frameworks/native/appkit/ability_delegator/iability_stage_monitor.cpp @@ -21,7 +21,7 @@ IAbilityStageMonitor::IAbilityStageMonitor(const std::string &moduleName, const : moduleName_(moduleName), srcEntrance_(srcEntrance) {} -bool IAbilityStageMonitor::Match(const std::shared_ptr &abilityStage, bool isNotify) +bool IAbilityStageMonitor::Match(const std::shared_ptr &abilityStage, bool isNotify) { if (!abilityStage) { TAG_LOGE(AAFwkTag::DELEGATOR, "null abilityStage"); @@ -46,12 +46,12 @@ bool IAbilityStageMonitor::Match(const std::shared_ptr IAbilityStageMonitor::WaitForAbilityStage() +std::shared_ptr IAbilityStageMonitor::WaitForAbilityStage() { return WaitForAbilityStage(MAX_TIME_OUT); } -std::shared_ptr IAbilityStageMonitor::WaitForAbilityStage(const int64_t timeoutMs) +std::shared_ptr IAbilityStageMonitor::WaitForAbilityStage(const int64_t timeoutMs) { auto realTime = timeoutMs; if (timeoutMs <= 0) { diff --git a/frameworks/native/appkit/ability_runtime/app/ets_ability_stage.cpp b/frameworks/native/appkit/ability_runtime/app/ets_ability_stage.cpp index a6b0158e27d..e5c81ec0682 100644 --- a/frameworks/native/appkit/ability_runtime/app/ets_ability_stage.cpp +++ b/frameworks/native/appkit/ability_runtime/app/ets_ability_stage.cpp @@ -187,9 +187,9 @@ bool ETSAbilityStage::CallObjectMethod(bool withResult, const char *name, const return false; } -std::shared_ptr ETSAbilityStage::CreateStageProperty() const +std::shared_ptr ETSAbilityStage::CreateStageProperty() const { - auto property = std::make_shared(); + auto property = std::make_shared(); property->moduleName_ = GetHapModuleProp("name"); property->srcEntrance_ = GetHapModuleProp("srcEntrance"); return property; diff --git a/frameworks/native/appkit/ability_runtime/app/ets_ability_stage_context.cpp b/frameworks/native/appkit/ability_runtime/app/ets_ability_stage_context.cpp index 29d027aeb71..3ad856a706c 100644 --- a/frameworks/native/appkit/ability_runtime/app/ets_ability_stage_context.cpp +++ b/frameworks/native/appkit/ability_runtime/app/ets_ability_stage_context.cpp @@ -76,7 +76,6 @@ ani_object ETSAbilityStageContext::CreateEtsAbilityStageContext(ani_env *env, st } ContextUtil::CreateEtsBaseContext(env, abilityStageCtxCls, obj, context); - // set Config class SetConfiguration(env, abilityStageCtxCls, obj, context); return obj; } diff --git a/frameworks/native/insight_intent/insight_intent_context/ets_insight_intent_context.cpp b/frameworks/native/insight_intent/insight_intent_context/ets_insight_intent_context.cpp new file mode 100644 index 00000000000..62a7cb80c95 --- /dev/null +++ b/frameworks/native/insight_intent/insight_intent_context/ets_insight_intent_context.cpp @@ -0,0 +1,168 @@ +/* + * 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_insight_intent_context.h" + +#include "ability_window_configuration.h" +#include "hilog_tag_wrapper.h" +#include "hitrace_meter.h" +#include "ani_common_want.h" +#include "ets_error_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char *CONTEXT_CLASS_NAME = "L@ohos/app/ability/InsightIntentContext/InsightIntentContext;"; +} +void EtsInsightIntentContext::Finalizer(ani_env *env, void *data, void *hint) +{ + TAG_LOGI(AAFwkTag::INTENT, "EtsInsightIntentContext::Finalizer called"); + std::unique_ptr(static_cast(data)); +} + +ani_object EtsInsightIntentContext::StartAbiitySync(ani_env *env, ani_object aniObj, ani_object wantObj) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + auto context = GetContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "get context failed."); + return EtsErrorUtil::CreateInvalidParamError(env, "context null"); + } + + AAFwk::Want want; + if (!OHOS::AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::INTENT, "parse wantParam failed"); + return EtsErrorUtil::CreateInvalidParamError(env, "Parse param want failed, want must be Want."); + } + + return context->StartAbilityInner(env, want); +} + +EtsInsightIntentContext *EtsInsightIntentContext::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::INTENT, "null env"); + return nullptr; + } + + if ((status = env->FindClass(CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + + if ((status = env->Class_FindField(cls, "nativeContext", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_GetField_Long(aniObj, contextField, &nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + return reinterpret_cast(nativeContextLong); +} + +ani_object EtsInsightIntentContext::StartAbilityInner(ani_env *env, AAFwk::Want &want) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentContext::StartAbilityInner called"); + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null context"); + return EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INNER); + } + + // verify if bundleName is empty or invalid + auto bundleNameFromWant = want.GetElement().GetBundleName(); + if (bundleNameFromWant.empty() || bundleNameFromWant != context->GetBundleName()) { + TAG_LOGE(AAFwkTag::INTENT, "bundleName empty or invalid"); + return EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_OPERATION_NOT_SUPPORTED); + } + // modify windowmode setting + auto windowMode = context->GetCurrentWindowMode(); + if (windowMode == AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY || + windowMode == AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY) { + want.SetParam(AAFwk::Want::PARAM_RESV_WINDOW_MODE, windowMode); + } + + auto innerErrCode = context->StartAbilityByInsightIntent(want); + if (innerErrCode == ERR_OK) { + return EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK); + } else { + return EtsErrorUtil::CreateErrorByNativeErr(env, innerErrCode); + } +} + +std::unique_ptr CreateEtsInsightIntentContext(ani_env *env, + const std::shared_ptr &context) +{ + TAG_LOGD(AAFwkTag::INTENT, "CreateEtsInsightIntentContext called"); + ani_long nativeContextLong = (ani_long)context.get(); + ani_class cls {}; + ani_status status = ANI_ERROR; + ani_object contextObj = nullptr; + ani_method method {}; + ani_field field = nullptr; + ani_ref contextObjtRef = nullptr; + if (context == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null context"); + return std::unique_ptr(); + } + if ((status = env->FindClass(CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return std::unique_ptr(); + } + std::array functions = { + ani_native_function { "nativeStartAbilitySync", nullptr, + reinterpret_cast(EtsInsightIntentContext::StartAbiitySync) }, + }; + if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { + if (status != ANI_ALREADY_BINDED) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return std::unique_ptr(); + } + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return std::unique_ptr(); + } + if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return std::unique_ptr(); + } + if ((status = env->Class_FindField(cls, "nativeContext", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return std::unique_ptr(); + } + if ((status = env->Object_SetField_Long(contextObj, field, nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return std::unique_ptr(); + } + if ((status = env->GlobalReference_Create(contextObj, &contextObjtRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return std::unique_ptr(); + } + auto nativeReference = std::make_unique(); + nativeReference->aniCls = cls; + nativeReference->aniObj = contextObj; + nativeReference->aniRef = contextObjtRef; + return nativeReference; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/interfaces/inner_api/ani_base_context/src/ani_base_context.cpp b/interfaces/inner_api/ani_base_context/src/ani_base_context.cpp index 1d6b39755c5..84970846a2b 100644 --- a/interfaces/inner_api/ani_base_context/src/ani_base_context.cpp +++ b/interfaces/inner_api/ani_base_context/src/ani_base_context.cpp @@ -19,15 +19,8 @@ namespace OHOS { namespace AbilityRuntime { ani_status IsStageContext(ani_env* env, ani_object object, ani_boolean& stageMode) { - if (env == nullptr) { - TAG_LOGE(AAFwkTag::APPMGR, "env is nullptr"); - return ANI_ERROR; - } - ani_status status = env->Object_GetFieldByName_Boolean(object, "stageMode", &stageMode); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::APPMGR, "GetField failed, status: %{public}d", status); - return ANI_ERROR; - } + // arkTS 1.2 only supported stage mode + stageMode = true; return ANI_OK; } diff --git a/interfaces/inner_api/insight_intent/insight_intent_context/ets_insight_intent_context.h b/interfaces/inner_api/insight_intent/insight_intent_context/ets_insight_intent_context.h new file mode 100644 index 00000000000..ee211cc4cb4 --- /dev/null +++ b/interfaces/inner_api/insight_intent/insight_intent_context/ets_insight_intent_context.h @@ -0,0 +1,57 @@ +/* + * 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_INSIGHT_INTENT_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_CONTEXT_H + +#include "ani.h" +#include "ets_native_reference.h" +#include "insight_intent_context.h" +namespace OHOS { +namespace AbilityRuntime { +/** + * @class EtsInsightIntentContext + * EtsInsightIntentContext provides a context for insightintent to execute certain tasks. + */ +class EtsInsightIntentContext final { +public: + + explicit EtsInsightIntentContext(const std::shared_ptr &context) : context_(context) {} + ~EtsInsightIntentContext() = default; + + static void Finalizer(ani_env *env, void *data, void *hint); + + /** + * Starts a new ability. Only such ability in the same application with the + * caller can be started. + * + * @param env, the ani environment. + * @param info, the params passed from ets caller. + * + * @return result of StartAbility. + */ + static ani_object StartAbiitySync(ani_env *env, ani_object aniObj, ani_object wantObj); + static EtsInsightIntentContext *GetContext(ani_env *env, ani_object aniObj); + +private: + ani_object StartAbilityInner(ani_env *env, AAFwk::Want &want); + std::weak_ptr context_; +}; + +std::unique_ptr CreateEtsInsightIntentContext(ani_env *env, + const std::shared_ptr &context); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_CONTEXT_H diff --git a/interfaces/kits/native/ability/native/ability_runtime/js_ui_ability.h b/interfaces/kits/native/ability/native/ability_runtime/js_ui_ability.h index 26121ff0013..29f5194959e 100644 --- a/interfaces/kits/native/ability/native/ability_runtime/js_ui_ability.h +++ b/interfaces/kits/native/ability/native/ability_runtime/js_ui_ability.h @@ -410,7 +410,6 @@ private: bool CallPromise(napi_value result, AppExecFwk::AbilityTransactionCallbackInfo *callbackInfo); int32_t CallSaveStatePromise(napi_value result, CallOnSaveStateInfo info); std::unique_ptr CreateAppWindowStage(); - std::shared_ptr CreateADelegatorAbilityProperty(); sptr SetNewRuleFlagToCallee(napi_env env, napi_value remoteJsObj); void SetAbilityContext(std::shared_ptr abilityInfo, std::shared_ptr want, const std::string &moduleName, const std::string &srcPath); @@ -427,6 +426,7 @@ private: void ReleaseOnContinueAsset(const napi_env env, napi_value &promise, napi_ref &jsWantParamsRef, AppExecFwk::AbilityTransactionCallbackInfo *callbackInfo); void RemoveShareRouterByBundleType(const Want &want); + void HandleAbilityDelegatorStart(); JsRuntime &jsRuntime_; std::shared_ptr shellContextRef_; diff --git a/interfaces/kits/native/ability/native/insight_intent_executor/ets_insight_intent_executor.h b/interfaces/kits/native/ability/native/insight_intent_executor/ets_insight_intent_executor.h new file mode 100644 index 00000000000..e96e4e37a38 --- /dev/null +++ b/interfaces/kits/native/ability/native/insight_intent_executor/ets_insight_intent_executor.h @@ -0,0 +1,120 @@ +/* + * 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_INSIGHT_INTENT_EXECUTOR_H +#define OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_EXECUTOR_H + +#include "insight_intent_executor.h" +#include "ets_insight_intent_context.h" +#include "ets_native_reference.h" +#include "ets_runtime.h" + +namespace OHOS { +namespace AppExecFwk { +struct InsightIntentExecuteResult; +} // namespace AAFwk +namespace AbilityRuntime { + +class EtsInsightIntentExecutor final : public InsightIntentExecutor { +public: + static InsightIntentExecutor *Create(Runtime &runtime); + enum class State { + INVALID, + CREATED, + INITIALIZED, + EXECUTING, + EXECUTATION_DONE, + DESTROYED + }; + + explicit EtsInsightIntentExecutor(ETSRuntime &runtime); +public: + EtsInsightIntentExecutor(const EtsInsightIntentExecutor&) = delete; + EtsInsightIntentExecutor(const EtsInsightIntentExecutor&&) = delete; + EtsInsightIntentExecutor &operator=(const EtsInsightIntentExecutor&) = delete; + EtsInsightIntentExecutor &operator=(const EtsInsightIntentExecutor&&) = delete; + ~EtsInsightIntentExecutor() override; + + bool Init(const InsightIntentExecutorInfo &insightIntentInfo) override; + + bool HandleExecuteIntent( + std::shared_ptr executeParam, + const std::shared_ptr &pageLoader, + std::unique_ptr callback, + bool &isAsync) override { return false; }; + + bool HandleExecuteIntent( + std::shared_ptr executeParam, + void *pageLoader, + std::unique_ptr callback, + bool &isAsync) override; + + inline State GetState() const + { + return state_; + } + +private: + static std::unique_ptr LoadEtsCode( + const InsightIntentExecutorInfo &insightIntentInfo, + ETSRuntime &runtime); + + ani_ref CallObjectMethod(bool withResult, const char *name, const char *ignature, ...); + + static void ReplyFailed(InsightIntentExecutorAsyncCallback *callback, + InsightIntentInnerErr innerErr = InsightIntentInnerErr::INSIGHT_INTENT_EXECUTE_REPLY_FAILED); + static void ReplySucceeded(InsightIntentExecutorAsyncCallback *callback, + std::shared_ptr resultCpp); + void ReplyFailedInner(InsightIntentInnerErr innerErr = InsightIntentInnerErr::INSIGHT_INTENT_EXECUTE_REPLY_FAILED); + void ReplySucceededInner(std::shared_ptr resultCpp); + bool ExecuteIntentCheckError(); + + bool HandleResultReturnedFromEtsFunc(ani_env *env, ani_ref result, bool isAsync); + + static bool CheckParametersUIAbilityForeground(ani_ref windowStage); + bool ExecuteInsightIntentUIAbilityForeground( + const std::string &name, + const AAFwk::WantParams ¶m, + ani_ref windowStage); + + static bool CheckParametersUIAbilityBackground(); + bool ExecuteInsightIntentUIAbilityBackground( + const std::string &name, + const AAFwk::WantParams ¶m); + + static bool CheckParametersUIExtension(ani_ref UIExtensionContentSession); + bool ExecuteInsightIntentUIExtension( + const std::string &name, + const AAFwk::WantParams ¶m, + ani_ref UIExtensionContentSession); + + static bool CheckParametersServiceExtension(); + bool ExecuteInsightIntentServiceExtension( + const std::string &name, + const AAFwk::WantParams ¶m); + + static void OnExecuteResult(ani_env *env, ani_object aniObj, ani_object result); + + ETSRuntime &runtime_; + State state_ = State::CREATED; + std::unique_ptr etsObj_ = nullptr; + std::unique_ptr contextObj_ = nullptr; + std::shared_ptr contextCpp_ = nullptr; + std::unique_ptr callback_; + bool isAsync_ = false; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_EXECUTOR_H diff --git a/interfaces/kits/native/ability/native/insight_intent_executor/ets_insight_intent_executor_instance.h b/interfaces/kits/native/ability/native/insight_intent_executor/ets_insight_intent_executor_instance.h new file mode 100644 index 00000000000..038210b258c --- /dev/null +++ b/interfaces/kits/native/ability/native/insight_intent_executor/ets_insight_intent_executor_instance.h @@ -0,0 +1,29 @@ +/* + * 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_INSIGHT_INTENT_EXECUTOR_INSTANCE_H +#define OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_EXECUTOR_INSTANCE_H + +#include "insight_intent_executor.h" + +namespace OHOS { +namespace AbilityRuntime { +class InsightIntentExecutor; +class Runtime; + +InsightIntentExecutor *CreateETSInsightIntentExecutor(Runtime &runtime); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_EXECUTOR_INSTANCE_H \ No newline at end of file diff --git a/interfaces/kits/native/ability/native/insight_intent_executor/insight_intent_executor.h b/interfaces/kits/native/ability/native/insight_intent_executor/insight_intent_executor.h index 0d87fe15afe..d489b07658f 100644 --- a/interfaces/kits/native/ability/native/insight_intent_executor/insight_intent_executor.h +++ b/interfaces/kits/native/ability/native/insight_intent_executor/insight_intent_executor.h @@ -66,6 +66,12 @@ public: std::unique_ptr callback, bool& isAsync) = 0; + virtual bool HandleExecuteIntent( + std::shared_ptr executeParam, + void *pageLoader, + std::unique_ptr callback, + bool& isAsync) { return false; }; + /** * @brief Get current insight intent context. * diff --git a/interfaces/kits/native/ability/native/insight_intent_executor/insight_intent_executor_info.h b/interfaces/kits/native/ability/native/insight_intent_executor/insight_intent_executor_info.h index 69f210a8868..cb0b482ea5e 100644 --- a/interfaces/kits/native/ability/native/insight_intent_executor/insight_intent_executor_info.h +++ b/interfaces/kits/native/ability/native/insight_intent_executor/insight_intent_executor_info.h @@ -32,6 +32,7 @@ struct InsightIntentExecutorInfo { int32_t windowMode = 0; sptr token = nullptr; std::shared_ptr pageLoader = nullptr; + void *etsPageLoader = nullptr; std::shared_ptr executeParam = nullptr; }; } // namespace OHOS::AbilityRuntime diff --git a/interfaces/kits/native/ability/native/js_service_extension.h b/interfaces/kits/native/ability/native/js_service_extension.h index 05902518d25..07d53e3a72b 100644 --- a/interfaces/kits/native/ability/native/js_service_extension.h +++ b/interfaces/kits/native/ability/native/js_service_extension.h @@ -180,12 +180,6 @@ private: void ListenWMS(); - bool GetInsightIntentExecutorInfo(const Want &want, - const std::shared_ptr &executeParam, - InsightIntentExecutorInfo &executorInfo); - - bool OnInsightIntentExecuteDone(uint64_t intentId, const AppExecFwk::InsightIntentExecuteResult &result) override; - void AddLifecycleEventForJSCall(const std::string &eventStr); JsRuntime& jsRuntime_; diff --git a/interfaces/kits/native/ability/native/service_extension.h b/interfaces/kits/native/ability/native/service_extension.h index 81d50fababc..f0e992f389a 100644 --- a/interfaces/kits/native/ability/native/service_extension.h +++ b/interfaces/kits/native/ability/native/service_extension.h @@ -19,11 +19,16 @@ #include "extension_base.h" namespace OHOS { +namespace AppExecFwk { +class InsightIntentExecuteParam; +struct InsightIntentExecuteResult; +} namespace AbilityRuntime { class ServiceExtensionContext; class Runtime; class ServiceExtension; using CreatorFunc = std::function& runtime)>; +struct InsightIntentExecutorInfo; /** * @brief Basic service components. */ @@ -82,6 +87,27 @@ public: */ void OnConfigurationUpdated(const AppExecFwk::Configuration &configuration) override; + /** + * @brief Get the executor info. + * + * @param want The want. + * @param executeParam The execute param. + * @param executorInfo The executor info. + * @return True if success, otherwise false. + */ + virtual bool GetInsightIntentExecutorInfo(const Want &want, + const std::shared_ptr &executeParam, + InsightIntentExecutorInfo &executorInfo); + + /** + * @brief On execute done. + * + * @param intentId The intent id. + * @param result The execute result. + * @return True if success, otherwise false. + */ + bool OnInsightIntentExecuteDone(uint64_t intentId, + const AppExecFwk::InsightIntentExecuteResult &result) override; private: static CreatorFunc creator_; }; diff --git a/interfaces/kits/native/ability/native/ui_ability.h b/interfaces/kits/native/ability/native/ui_ability.h index 539f3bdd87d..6af9cf48ba1 100644 --- a/interfaces/kits/native/ability/native/ui_ability.h +++ b/interfaces/kits/native/ability/native/ui_ability.h @@ -46,6 +46,7 @@ class LifeCycle; class ContinuationHandlerStage; class ContinuationManagerStage; class InsightIntentExecuteParam; +struct BaseDelegatorAbilityProperty; struct InsightIntentExecuteResult; using InsightIntentExecutorAsyncCallback = AbilityTransactionCallbackInfo; } // namespace AppExecFwk @@ -335,6 +336,9 @@ public: void SetIsSilentForeground(bool isSilentForeground); + bool CreateProperty(std::shared_ptr abilityContext, + std::shared_ptr delegatorAbilityProperty); + protected: const AAFwk::LaunchParam &GetLaunchParam() const; bool IsRestoredInContinuation() const; diff --git a/interfaces/kits/native/appkit/ability_delegator/ability_delegator.h b/interfaces/kits/native/appkit/ability_delegator/ability_delegator.h index 217952afe26..1a894f9c02f 100644 --- a/interfaces/kits/native/appkit/ability_delegator/ability_delegator.h +++ b/interfaces/kits/native/appkit/ability_delegator/ability_delegator.h @@ -151,7 +151,7 @@ public: * @param monitor, Indicates the specified stage monitor object. * @return the obtained abilityStage. */ - std::shared_ptr WaitAbilityStageMonitor( + std::shared_ptr WaitAbilityStageMonitor( const std::shared_ptr &monitor); /** @@ -171,7 +171,7 @@ public: * @param timeoutMs, Indicates the specified time out time, in milliseconds. * @return the obtained abilityStage. */ - std::shared_ptr WaitAbilityStageMonitor( + std::shared_ptr WaitAbilityStageMonitor( const std::shared_ptr &monitor, const int64_t timeoutMs); /** @@ -266,7 +266,7 @@ public: * * @param abilityStage , Indicates the abilityStage properties. */ - void PostPerformStageStart(const std::shared_ptr &abilityStage); + void PostPerformStageStart(const std::shared_ptr &abilityStage); /** * Saves ability properties when scence is created and notify monitors of state changes. diff --git a/interfaces/kits/native/appkit/ability_delegator/ability_delegator_infos.h b/interfaces/kits/native/appkit/ability_delegator/ability_delegator_infos.h index 4bdff9e6de2..8d123da8311 100644 --- a/interfaces/kits/native/appkit/ability_delegator/ability_delegator_infos.h +++ b/interfaces/kits/native/appkit/ability_delegator/ability_delegator_infos.h @@ -41,15 +41,22 @@ struct ADelegatorAbilityProperty : public BaseDelegatorAbilityProperty { std::weak_ptr object_; }; -struct ETSDelegatorAbilityProperty : public BaseDelegatorAbilityProperty { +struct EtsDelegatorAbilityProperty : public BaseDelegatorAbilityProperty { std::weak_ptr object_; }; -struct DelegatorAbilityStageProperty { +struct BaseDelegatorAbilityStageProperty { std::string moduleName_; std::string srcEntrance_; +}; + +struct DelegatorAbilityStageProperty : public BaseDelegatorAbilityStageProperty { std::weak_ptr object_; }; + +struct EtsDelegatorAbilityStageProperty : public BaseDelegatorAbilityStageProperty { + std::weak_ptr object_; +}; } // namespace AppExecFwk } // namespace OHOS diff --git a/interfaces/kits/native/appkit/ability_delegator/iability_stage_monitor.h b/interfaces/kits/native/appkit/ability_delegator/iability_stage_monitor.h index c1cd1251539..59d2afa7562 100644 --- a/interfaces/kits/native/appkit/ability_delegator/iability_stage_monitor.h +++ b/interfaces/kits/native/appkit/ability_delegator/iability_stage_monitor.h @@ -53,7 +53,7 @@ public: * @param isNotify Indicates whether to notify the matched abilityStage to the object who waited. * @return true if match is successful; returns false otherwise. */ - virtual bool Match(const std::shared_ptr &abilityStage, bool isNotify = false); + virtual bool Match(const std::shared_ptr &abilityStage, bool isNotify = false); /** * Waits for and returns the started AbilityStage object that matches the conditions specified in this monitor @@ -65,7 +65,7 @@ public: * @return the AbilityStage object if any object has started is matched within the specified time; * returns null otherwise. */ - virtual std::shared_ptr WaitForAbilityStage(const int64_t timeoutMs); + virtual std::shared_ptr WaitForAbilityStage(const int64_t timeoutMs); /** * Waits for and returns the started AbilityStage object that matches the conditions specified in this monitor @@ -74,12 +74,12 @@ public: * * @return the AbilityStage object if any object has started is matched within 5 seconds; returns null otherwise. */ - virtual std::shared_ptr WaitForAbilityStage(); + virtual std::shared_ptr WaitForAbilityStage(); private: std::string moduleName_; std::string srcEntrance_; - std::shared_ptr matchedAbilityStage_; + std::shared_ptr matchedAbilityStage_; std::condition_variable cvMatch_; std::mutex mtxMatch_; diff --git a/interfaces/kits/native/appkit/ability_runtime/app/ets_ability_stage.h b/interfaces/kits/native/appkit/ability_runtime/app/ets_ability_stage.h index 55eca830a9d..f293b5eba25 100644 --- a/interfaces/kits/native/appkit/ability_runtime/app/ets_ability_stage.h +++ b/interfaces/kits/native/appkit/ability_runtime/app/ets_ability_stage.h @@ -49,7 +49,7 @@ public: private: bool CallObjectMethod(bool withResult, const char *name, const char *signature, ...) const; - std::shared_ptr CreateStageProperty() const; + std::shared_ptr CreateStageProperty() const; std::string GetHapModuleProp(const std::string &propName) const; diff --git a/interfaces/kits/native/appkit/ability_runtime/app/ets_ability_stage_context.h b/interfaces/kits/native/appkit/ability_runtime/app/ets_ability_stage_context.h index 670131675e9..4431bdd6acb 100644 --- a/interfaces/kits/native/appkit/ability_runtime/app/ets_ability_stage_context.h +++ b/interfaces/kits/native/appkit/ability_runtime/app/ets_ability_stage_context.h @@ -45,6 +45,7 @@ public: private: static void SetConfiguration(ani_env *env, ani_class stageCls, ani_object stageCtxObj, std::shared_ptr &context); + static ani_object CreateHapModuleInfo(ani_env* env, const std::shared_ptr &context); private: std::weak_ptr context_; static ani_ref etsAbilityStageContextObj_; diff --git a/test/unittest/frameworks_kits_ability_native_test/BUILD.gn b/test/unittest/frameworks_kits_ability_native_test/BUILD.gn index 1796dc93a13..e399d87b77e 100644 --- a/test/unittest/frameworks_kits_ability_native_test/BUILD.gn +++ b/test/unittest/frameworks_kits_ability_native_test/BUILD.gn @@ -29,19 +29,20 @@ config("module_private_config") { include_dirs = [ "${ability_runtime_innerkits_path}/ability_manager/include", "${ability_runtime_innerkits_path}/app_manager/include/appmgr", + "${ability_runtime_path}/interfaces/kits/native/ability/ability_runtime", "${ability_runtime_path}/interfaces/kits/native/ability/native", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_bundle_manager_helper", - "${ability_runtime_test_path}/mock/frameworks_kits_ability_native_test/include", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_delegator", "${ability_runtime_path}/interfaces/kits/native/appkit/app", "${ability_runtime_path}/interfaces/kits/native/appkit/app_startup", "${ability_runtime_path}/interfaces/kits/native/appkit/app/task", - "${ability_runtime_test_path}/mock/services_abilitymgr_test/libs/aakit/include", - "${ability_runtime_test_path}/mock/frameworks_kits_appkit_native_test/include", "${ability_runtime_services_path}/abilitymgr/include/utils", "${ability_runtime_services_path}/abilitymgr/include", "${ability_runtime_services_path}/common/include", + "${ability_runtime_test_path}/mock/frameworks_kits_ability_native_test/include", + "${ability_runtime_test_path}/mock/frameworks_kits_appkit_native_test/include", + "${ability_runtime_test_path}/mock/services_abilitymgr_test/libs/aakit/include", "${ability_runtime_test_path}/mock/services_appmgr_test/include", - "${ability_runtime_path}/interfaces/kits/native/ability/ability_runtime", ] cflags = [] if (target_cpu == "arm") { diff --git a/test/unittest/frameworks_kits_ability_native_test/ui_ability_test.cpp b/test/unittest/frameworks_kits_ability_native_test/ui_ability_test.cpp index ed83c44ed03..d29f840e5b5 100644 --- a/test/unittest/frameworks_kits_ability_native_test/ui_ability_test.cpp +++ b/test/unittest/frameworks_kits_ability_native_test/ui_ability_test.cpp @@ -21,6 +21,7 @@ #undef protected #undef private #include "ability_context_impl.h" +#include "ability_delegator_infos.h" #include "ability_handler.h" #include "ability_recovery.h" #include "fa_ability_thread.h" @@ -1776,5 +1777,71 @@ HWTEST_F(UIAbilityBaseTest, UIAbility_IsStartByScb_0300, TestSize.Level1) EXPECT_FALSE(result); TAG_LOGI(AAFwkTag::TEST, "%{public}s end.", __func__); } + +/** + * @tc.name: UIAbility_CreateProperty_0100 + * @tc.desc: CreateProperty test + * @tc.desc: Verify function CreateProperty. + */ +HWTEST_F(UIAbilityBaseTest, UIAbility_CreateProperty_0100, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "%{public}s start.", __func__); + std::shared_ptr uiAbility = std::make_shared(); + ASSERT_NE(uiAbility, nullptr); + bool result = uiAbility->CreateProperty(nullptr, nullptr); + EXPECT_FALSE(result); + TAG_LOGI(AAFwkTag::TEST, "%{public}s end.", __func__); +} + +/** + * @tc.name: UIAbility_CreateProperty_0200 + * @tc.desc: CreateProperty test + * @tc.desc: Verify function CreateProperty. + */ +HWTEST_F(UIAbilityBaseTest, UIAbility_CreateProperty_0200, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "%{public}s start.", __func__); + std::shared_ptr uiAbility = std::make_shared(); + ASSERT_NE(uiAbility, nullptr); + auto abilityContext = uiAbility->GetAbilityContext(); + ASSERT_NE(abilityContext, nullptr); + bool result = uiAbility->CreateProperty(abilityContext, nullptr); + EXPECT_FALSE(result); + TAG_LOGI(AAFwkTag::TEST, "%{public}s end.", __func__); +} + +/** + * @tc.name: UIAbility_CreateProperty_0300 + * @tc.desc: CreateProperty test + * @tc.desc: Verify function CreateProperty. + */ +HWTEST_F(UIAbilityBaseTest, UIAbility_CreateProperty_0300, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "%{public}s start.", __func__); + std::shared_ptr uiAbility = std::make_shared(); + ASSERT_NE(uiAbility, nullptr); + auto property = std::make_shared(); + bool result = uiAbility->CreateProperty(nullptr, property); + EXPECT_FALSE(result); + TAG_LOGI(AAFwkTag::TEST, "%{public}s end.", __func__); +} + +/** + * @tc.name: UIAbility_CreateProperty_0400 + * @tc.desc: CreateProperty test + * @tc.desc: Verify function CreateProperty. + */ +HWTEST_F(UIAbilityBaseTest, UIAbility_CreateProperty_0400, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "%{public}s start.", __func__); + std::shared_ptr uiAbility = std::make_shared(); + ASSERT_NE(uiAbility, nullptr); + auto abilityContext = uiAbility->GetAbilityContext(); + ASSERT_NE(abilityContext, nullptr); + auto property = std::make_shared(); + bool result = uiAbility->CreateProperty(abilityContext, property); + EXPECT_TRUE(result); + TAG_LOGI(AAFwkTag::TEST, "%{public}s end.", __func__); +} } // namespace AppExecFwk } // namespace OHOS -- Gitee