From 8ecf6f6754626db1f1187022d7333ec2907be0b5 Mon Sep 17 00:00:00 2001 From: zhangzezhong Date: Wed, 3 Sep 2025 13:39:39 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90AMS=E3=80=910702=20merge=20master=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhangzezhong --- .../ets_environment/src/ets_environment.cpp | 4 + frameworks/ets/ani/BUILD.gn | 3 + .../include/ets_ability_delegator.h | 8 +- .../src/ets_ability_delegator.cpp | 24 +- .../src/ets_ability_delegator_registry.cpp | 14 +- .../src/ets_ability_delegator_utils.cpp | 34 +- frameworks/ets/ani/ability_manager/BUILD.gn | 11 +- .../ets_ability_foreground_state_observer.h | 58 + .../include/ets_ability_manager_utils.h | 40 + .../ets_ability_foreground_state_observer.cpp | 233 ++++ .../src/ets_ability_manager.cpp | 206 +++- .../src/ets_ability_manager_utils.cpp | 379 ++++++ frameworks/ets/ani/ani_common/BUILD.gn | 6 + .../ani_common/include/ani_common_remote.h | 31 + .../include/ani_common_start_options.h | 3 + .../ani/ani_common/include/ani_common_util.h | 16 +- .../ani/ani_common/include/ani_common_want.h | 2 + .../ets/ani/ani_common/include/ani_task.h | 35 + .../include/ets_application_context_utils.h | 25 +- .../ets_application_state_change_callback.h | 55 + .../ani_common/include/ets_context_utils.h | 7 + .../include/ets_enviroment_callback.h | 43 + .../ani/ani_common/include/ets_error_utils.h | 1 + .../include/ets_extension_context.h | 9 + .../src/ani_common_ability_result.cpp | 3 +- .../src/ani_common_ability_state_data.cpp | 21 +- .../src/ani_common_configuration.cpp | 2 +- .../src/ani_common_execute_param.cpp | 10 +- .../src/ani_common_execute_result.cpp | 18 +- .../ani/ani_common/src/ani_common_remote.cpp | 43 + .../src/ani_common_start_options.cpp | 82 +- .../ani/ani_common/src/ani_common_util.cpp | 245 +++- .../ani/ani_common/src/ani_common_want.cpp | 74 +- .../ets/ani/ani_common/src/ani_task.cpp | 51 + .../src/ets_application_context_utils.cpp | 294 ++++- .../ets_application_state_change_callback.cpp | 176 +++ .../ani/ani_common/src/ets_context_utils.cpp | 276 ++++- .../src/ets_data_struct_converter.cpp | 17 +- .../src/ets_enviroment_callback.cpp | 215 ++++ .../ani/ani_common/src/ets_error_utils.cpp | 17 +- .../ani_common/src/ets_extension_context.cpp | 18 + .../ets/ani/ani_mission_manager/BUILD.gn | 60 + .../include/ets_mission_info_utils.h | 30 + .../include/ets_mission_manager.h | 26 + .../src/ets_mission_info_utils.cpp | 127 ++ .../src/ets_mission_manager.cpp | 187 +++ frameworks/ets/ani/app_manager/BUILD.gn | 3 + .../ets_ability_first_frame_state_observer.h | 77 ++ .../ets_app_foreground_state_observer.h | 54 + .../include/ets_app_manager_utils.h | 31 +- .../include/ets_app_state_observer.h | 67 + ...ets_ability_first_frame_state_observer.cpp | 242 ++++ .../src/ets_app_foreground_state_observer.cpp | 225 ++++ .../ani/app_manager/src/ets_app_manager.cpp | 1083 ++++++++++++++++- .../app_manager/src/ets_app_manager_utils.cpp | 345 +++++- .../src/ets_app_state_observer.cpp | 490 ++++++++ .../ani/application/include/ets_application.h | 1 + .../ani/application/src/ets_application.cpp | 31 + frameworks/ets/ani/featureAbility/BUILD.gn | 45 + .../include/ani_data_ability_helper.h | 27 + .../src/ani_data_ability_helper.cpp | 148 +++ .../include/ets_service_extension_context.h | 39 + .../src/ets_service_extension.cpp | 5 +- .../src/ets_service_extension_context.cpp | 301 +++++ .../ui_ability/include/ets_ability_context.h | 59 + .../ani/ui_ability/include/ets_ui_ability.h | 48 + .../ui_ability/src/ets_ability_context.cpp | 617 +++++++++- .../ets/ani/ui_ability/src/ets_ui_ability.cpp | 145 ++- .../include/ets_extension_common.h | 74 ++ .../include/ets_ui_extension.h | 18 +- .../ets_ui_extension_content_session.h | 9 + .../include/ets_ui_extension_context.h | 52 + .../src/ets_extension_common.cpp | 111 ++ .../src/ets_ui_extension.cpp | 121 +- .../src/ets_ui_extension_content_session.cpp | 116 +- .../src/ets_ui_extension_context.cpp | 502 +++++++- .../ets/ani/ui_extension_callback/BUILD.gn | 65 + .../include/ets_ui_extension_callback.h | 42 + .../src/ets_ui_extension_callback.cpp | 181 +++ .../include/ets_uri_perm_mgr.h | 4 +- .../src/ets_uri_perm_mgr.cpp | 11 +- .../ets/ani/wantagent/src/ani_want_agent.cpp | 6 +- .../ets/ets/@ohos.ability.errorCode.ets | 21 + .../ets/ets/@ohos.app.ability.Ability.ets | 25 + .../ets/@ohos.app.ability.AbilityConstant.ets | 24 +- ...ability.ApplicationStateChangeCallback.ets | 29 + ...@ohos.app.ability.AtomicServiceOptions.ets | 21 + .../ets/@ohos.app.ability.Configuration.ets | 12 +- .../@ohos.app.ability.EnvironmentCallback.ets | 31 + .../@ohos.app.ability.ExtensionAbility.ets | 19 + ...os.app.ability.ServiceExtensionAbility.ets | 26 +- ...ohos.app.ability.ShareExtensionAbility.ets | 19 + .../ets/@ohos.app.ability.StartOptions.ets | 20 +- .../ets/ets/@ohos.app.ability.UIAbility.ets | 19 +- .../@ohos.app.ability.UIExtensionAbility.ets | 25 +- ....app.ability.UIExtensionContentSession.ets | 39 + frameworks/ets/ets/@ohos.app.ability.Want.ets | 5 +- .../ets/@ohos.app.ability.abilityManager.ets | 85 +- .../ets/ets/@ohos.app.ability.appManager.ets | 408 ++++++- .../ets/ets/@ohos.app.ability.application.ets | 7 + .../ets/@ohos.app.ability.dataUriUtils.ets | 94 ++ .../ets/@ohos.app.ability.insightIntent.ets | 8 +- .../@ohos.app.ability.insightIntentDriver.ets | 4 +- .../ets/@ohos.app.ability.missionManager.ets | 74 ++ .../ets/ets/@ohos.app.ability.wantAgent.ets | 32 +- ...@ohos.application.uriPermissionManager.ets | 8 +- frameworks/ets/ets/BUILD.gn | 377 ++++++ frameworks/ets/ets/ability/abilityResult.ets | 4 +- frameworks/ets/ets/ability/connectOptions.ets | 35 + .../ets/ets/ability/dataAbilityHelper.ets | 16 + .../ets/ets/application/AbilityDelegator.ets | 38 +- .../AbilityFirstFrameStateData.ets | 30 + .../AbilityFirstFrameStateObserver.ets | 24 + .../AbilityForegroundStateObserver.ets | 23 + .../ets/application/AbilityRunningInfo.ets | 35 + .../ets/application/AbilityStartCallback.ets | 24 + .../AppForegroundStateObserver.ets | 24 + .../ets/application/ApplicationContext.ets | 79 +- .../application/ApplicationStateObserver.ets | 52 + frameworks/ets/ets/application/Context.ets | 46 + frameworks/ets/ets/application/CustomData.ets | 22 + .../ets/application/ExtensionRunningInfo.ets | 37 + .../ets/ets/application/MissionInfo.ets | 41 + .../ets/ets/application/ProcessData.ets | 6 +- .../ets/application/ProcessInformation.ets | 12 +- .../ets/ets/application/RunningAppClone.ets | 12 +- .../application/RunningMultiInstanceInfo.ets | 6 +- .../application/ServiceExtensionContext.ets | 66 +- .../ets/ets/application/UIAbilityContext.ets | 225 +++- .../ets/application/UIExtensionContext.ets | 90 +- .../ets/ets/application/shellCmdResult.ets | 4 +- frameworks/native/ability/BUILD.gn | 1 + .../ability_runtime/ability_context_impl.cpp | 30 +- frameworks/native/ability/native/BUILD.gn | 46 + .../ability_runtime/js_ability_context.cpp | 1 + .../ets_auto_fill_extension_util.cpp | 68 ++ .../native/js_ui_extension_callback.cpp | 32 +- .../ui_extension_ability/js_ui_extension.cpp | 109 +- .../ui_extension_ability/ui_extension.cpp | 111 +- .../js_ui_extension_content_session.cpp | 3 +- .../ui_extension_context.cpp | 6 +- .../ability/native/ui_extension_callback.cpp | 63 + .../js_ui_service_extension_context.cpp | 3 +- .../ability_runtime/app/ets_ability_stage.cpp | 20 + .../ui_service_extension_context.cpp | 32 +- frameworks/native/runtime/ets_runtime.cpp | 2 +- .../ability/ability_runtime/ability_context.h | 4 +- .../ability_runtime/ability_context_impl.h | 4 +- .../ets_auto_fill_extension_util.h | 34 + .../ability/native/js_ui_extension_callback.h | 22 +- .../ui_extension_ability/js_ui_extension.h | 15 +- .../ui_extension_ability/ui_extension.h | 10 +- .../ability/native/ui_extension_callback.h | 46 + .../ui_service_extension_context.h | 6 +- .../ability_runtime/app/ets_ability_stage.h | 7 +- .../ability_context_impl_test.cpp | 1 + .../ability_context_test.cpp | 2 +- .../BUILD.gn | 1 + .../ui_service_extension_test.cpp | 1 + 159 files changed, 10988 insertions(+), 709 deletions(-) create mode 100644 frameworks/ets/ani/ability_manager/include/ets_ability_foreground_state_observer.h create mode 100644 frameworks/ets/ani/ability_manager/include/ets_ability_manager_utils.h create mode 100644 frameworks/ets/ani/ability_manager/src/ets_ability_foreground_state_observer.cpp create mode 100644 frameworks/ets/ani/ability_manager/src/ets_ability_manager_utils.cpp create mode 100644 frameworks/ets/ani/ani_common/include/ani_common_remote.h create mode 100644 frameworks/ets/ani/ani_common/include/ani_task.h create mode 100644 frameworks/ets/ani/ani_common/include/ets_application_state_change_callback.h create mode 100644 frameworks/ets/ani/ani_common/include/ets_enviroment_callback.h create mode 100644 frameworks/ets/ani/ani_common/src/ani_common_remote.cpp create mode 100644 frameworks/ets/ani/ani_common/src/ani_task.cpp create mode 100644 frameworks/ets/ani/ani_common/src/ets_application_state_change_callback.cpp create mode 100644 frameworks/ets/ani/ani_common/src/ets_enviroment_callback.cpp create mode 100644 frameworks/ets/ani/ani_mission_manager/BUILD.gn create mode 100644 frameworks/ets/ani/ani_mission_manager/include/ets_mission_info_utils.h create mode 100644 frameworks/ets/ani/ani_mission_manager/include/ets_mission_manager.h create mode 100644 frameworks/ets/ani/ani_mission_manager/src/ets_mission_info_utils.cpp create mode 100644 frameworks/ets/ani/ani_mission_manager/src/ets_mission_manager.cpp create mode 100644 frameworks/ets/ani/app_manager/include/ets_ability_first_frame_state_observer.h create mode 100644 frameworks/ets/ani/app_manager/include/ets_app_foreground_state_observer.h create mode 100644 frameworks/ets/ani/app_manager/include/ets_app_state_observer.h create mode 100644 frameworks/ets/ani/app_manager/src/ets_ability_first_frame_state_observer.cpp create mode 100644 frameworks/ets/ani/app_manager/src/ets_app_foreground_state_observer.cpp create mode 100644 frameworks/ets/ani/app_manager/src/ets_app_state_observer.cpp create mode 100644 frameworks/ets/ani/featureAbility/BUILD.gn create mode 100644 frameworks/ets/ani/featureAbility/include/ani_data_ability_helper.h create mode 100644 frameworks/ets/ani/featureAbility/src/ani_data_ability_helper.cpp create mode 100644 frameworks/ets/ani/ui_extension_ability/include/ets_extension_common.h create mode 100644 frameworks/ets/ani/ui_extension_ability/src/ets_extension_common.cpp create mode 100644 frameworks/ets/ani/ui_extension_callback/BUILD.gn create mode 100644 frameworks/ets/ani/ui_extension_callback/include/ets_ui_extension_callback.h create mode 100644 frameworks/ets/ani/ui_extension_callback/src/ets_ui_extension_callback.cpp create mode 100644 frameworks/ets/ets/@ohos.ability.errorCode.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.Ability.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.ApplicationStateChangeCallback.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.AtomicServiceOptions.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.EnvironmentCallback.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.ExtensionAbility.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.ShareExtensionAbility.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.dataUriUtils.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.missionManager.ets create mode 100644 frameworks/ets/ets/ability/connectOptions.ets create mode 100644 frameworks/ets/ets/ability/dataAbilityHelper.ets create mode 100644 frameworks/ets/ets/application/AbilityFirstFrameStateData.ets create mode 100644 frameworks/ets/ets/application/AbilityFirstFrameStateObserver.ets create mode 100644 frameworks/ets/ets/application/AbilityForegroundStateObserver.ets create mode 100644 frameworks/ets/ets/application/AbilityRunningInfo.ets create mode 100644 frameworks/ets/ets/application/AbilityStartCallback.ets create mode 100644 frameworks/ets/ets/application/AppForegroundStateObserver.ets create mode 100644 frameworks/ets/ets/application/ApplicationStateObserver.ets create mode 100644 frameworks/ets/ets/application/CustomData.ets create mode 100644 frameworks/ets/ets/application/ExtensionRunningInfo.ets create mode 100644 frameworks/ets/ets/application/MissionInfo.ets create mode 100644 frameworks/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.cpp create mode 100644 frameworks/native/ability/native/ui_extension_callback.cpp create mode 100644 interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.h create mode 100644 interfaces/kits/native/ability/native/ui_extension_callback.h diff --git a/ets_environment/frameworks/ets_environment/src/ets_environment.cpp b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp index ee3ed919acd..c87debfe7b2 100644 --- a/ets_environment/frameworks/ets_environment/src/ets_environment.cpp +++ b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp @@ -351,6 +351,10 @@ std::string ETSEnvironment::GetErrorProperty(ani_error aniError, const char *pro { TAG_LOGD(AAFwkTag::ETSRUNTIME, "GetErrorProperty called"); auto aniEnv = GetAniEnv(); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env"); + return ""; + } std::string propertyValue; ani_status status = ANI_ERROR; ani_type errorType = nullptr; diff --git a/frameworks/ets/ani/BUILD.gn b/frameworks/ets/ani/BUILD.gn index 359adf59688..ebc4e686f90 100644 --- a/frameworks/ets/ani/BUILD.gn +++ b/frameworks/ets/ani/BUILD.gn @@ -19,11 +19,14 @@ group("ani_packages") { "${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_mission_manager:missionmanager_ani", "${ability_runtime_path}/frameworks/ets/ani/ani_wantagent_common:ani_wantagent_common", "${ability_runtime_path}/frameworks/ets/ani/app_manager:app_manager_ani", "${ability_runtime_path}/frameworks/ets/ani/application:application_ani", + "${ability_runtime_path}/frameworks/ets/ani/featureAbility:featureability_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/ui_extension_callback:ani_ui_extension_callback", "${ability_runtime_path}/frameworks/ets/ani/uri_permission_manager:uri_permission_manager_ani_kit", "${ability_runtime_path}/frameworks/ets/ani/vertical_panel_manager:vertical_panel_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 8fed5dee018..85e249b5f66 100644 --- a/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator.h +++ b/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator.h @@ -36,7 +36,7 @@ public: 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); + ani_string msg, ani_long code, ani_object callback); static ani_object SetAppContext(ani_env *env, const std::shared_ptr &context); @@ -55,7 +55,7 @@ public: static void RemoveAbilityMonitorSync(ani_env *env, [[maybe_unused]]ani_class aniClass, ani_object monitorObj); static void WaitAbilityMonitor(ani_env *env, [[maybe_unused]]ani_class aniClass, - ani_object monitorOb0, ani_double timeout, ani_object callback); + ani_object monitorObj, ani_long timeout, ani_object callback); static void AddAbilityStageMonitor(ani_env *env, [[maybe_unused]]ani_class aniClass, ani_object stageMonitorObj, ani_object callback); @@ -70,7 +70,7 @@ public: ani_object stageMonitorObj); static void WaitAbilityStageMonitor(ani_env *env, [[maybe_unused]]ani_class aniClass, - ani_object stageMonitorObj, ani_double timeout, ani_object callback); + ani_object stageMonitorObj, ani_long timeout, ani_object callback); static void DoAbilityForeground(ani_env *env, [[maybe_unused]]ani_object object, ani_object abilityObj, ani_object callback); @@ -80,7 +80,7 @@ public: static void Print(ani_env *env, [[maybe_unused]]ani_object object, ani_string msg, ani_object callback); - static ani_double GetAbilityState(ani_env *env, [[maybe_unused]]ani_object object, ani_object abilityObj); + static ani_int GetAbilityState(ani_env *env, [[maybe_unused]]ani_object object, ani_object abilityObj); static void StartAbility(ani_env *env, [[maybe_unused]]ani_object object, ani_object wantObj, ani_object callback); 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 53f1cf4f337..f57dd6dd05e 100644 --- a/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator.cpp +++ b/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator.cpp @@ -117,25 +117,25 @@ ani_object EtsAbilityDelegator::WrapShellCmdResult(ani_env *env, std::unique_ptr TAG_LOGD(AAFwkTag::DELEGATOR, "WrapShellCmdResult called"); if (result == nullptr || env == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "result or env is null"); - return {}; + return nullptr; } ani_class cls = nullptr; ani_status status = ANI_ERROR; status = env->FindClass(SHELL_CMD_RESULT_CLASS_NAME, &cls); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "find AbilityDelegator failed status: %{public}d", status); - return {}; + return nullptr; } 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); - return {}; + return nullptr; } ani_object object = nullptr; if (env->Object_New(cls, method, &object) != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Object_New failed status: %{public}d", status); - return {}; + return nullptr; } TAG_LOGD(AAFwkTag::DELEGATOR, "Object_New success"); ani_field filed = nullptr; @@ -154,7 +154,7 @@ ani_object EtsAbilityDelegator::WrapShellCmdResult(ani_env *env, std::unique_ptr TAG_LOGE(AAFwkTag::DELEGATOR, "set strResult failed status: %{public}d", status); } int32_t exitCode = result->GetExitCode(); - status = env->Object_SetPropertyByName_Double(object, "exitCode", exitCode); + status = env->Object_SetPropertyByName_Int(object, "exitCode", exitCode); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "set exitCode failed status: %{public}d", status); } @@ -166,7 +166,7 @@ ani_object EtsAbilityDelegator::GetAppContext(ani_env *env, [[maybe_unused]]ani_ TAG_LOGD(AAFwkTag::DELEGATOR, "GetAppContext call"); if (env == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); - return {}; + return nullptr; } ani_class cls = nullptr; ani_object nullobj = nullptr; @@ -229,7 +229,7 @@ void EtsAbilityDelegator::ExecuteShellCommand(ani_env *env, [[maybe_unused]]ani_ } void EtsAbilityDelegator::FinishTest(ani_env *env, [[maybe_unused]]ani_object object, - ani_string msg, ani_double code, ani_object callback) + ani_string msg, ani_long code, ani_object callback) { TAG_LOGD(AAFwkTag::DELEGATOR, "called"); if (env == nullptr) { @@ -273,13 +273,11 @@ void EtsAbilityDelegator::PrintSync(ani_env *env, [[maybe_unused]]ani_class aniC "Parse msg failed, msg must be string."); return; } - auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); if (delegator == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); return; } - delegator->Print(strMsg); return; } @@ -477,7 +475,7 @@ void EtsAbilityDelegator::RemoveAbilityMonitorSync(ani_env *env, [[maybe_unused] } void EtsAbilityDelegator::WaitAbilityMonitor(ani_env *env, [[maybe_unused]]ani_class aniClass, - ani_object monitorObj, ani_double timeout, ani_object callback) + ani_object monitorObj, ani_long timeout, ani_object callback) { TAG_LOGD(AAFwkTag::DELEGATOR, "WaitAbilityMonitor called"); if (env == nullptr) { @@ -656,7 +654,7 @@ void EtsAbilityDelegator::RemoveAbilityStageMonitorSync(ani_env *env, [[maybe_un } void EtsAbilityDelegator::WaitAbilityStageMonitor(ani_env *env, [[maybe_unused]]ani_class aniClass, - ani_object stageMonitorObj, ani_double timeout, ani_object callback) + ani_object stageMonitorObj, ani_long timeout, ani_object callback) { TAG_LOGI(AAFwkTag::DELEGATOR, "WaitAbilityStageMonitor called"); if (env == nullptr) { @@ -794,7 +792,7 @@ void EtsAbilityDelegator::Print(ani_env *env, [[maybe_unused]]ani_object object, return; } -ani_double EtsAbilityDelegator::GetAbilityState(ani_env *env, [[maybe_unused]]ani_object object, ani_object abilityObj) +ani_int EtsAbilityDelegator::GetAbilityState(ani_env *env, [[maybe_unused]]ani_object object, ani_object abilityObj) { TAG_LOGD(AAFwkTag::DELEGATOR, "GetAbilityState called"); if (env == nullptr) { @@ -818,7 +816,7 @@ ani_double EtsAbilityDelegator::GetAbilityState(ani_env *env, [[maybe_unused]]an AbilityDelegator::AbilityState lifeState = delegator->GetAbilityState(remoteObject); AbilityLifecycleState abilityLifeState = AbilityLifecycleState::UNINITIALIZED; AbilityLifecycleStateToEts(lifeState, abilityLifeState); - return static_cast(abilityLifeState); + return static_cast(abilityLifeState); } void EtsAbilityDelegator::AbilityLifecycleStateToEts( 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 76673d5ff46..a58a7806a44 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 @@ -39,34 +39,34 @@ static ani_object GetAbilityDelegator(ani_env *env) { if (env == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "null env"); - return {}; + return nullptr; } std::lock_guard lock(etsReferenceMutex); auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::ETS); if (delegator == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); - return {}; + return nullptr; } if (etsReference == nullptr) { ani_object value = CreateEtsAbilityDelegator(env); if (value == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "value is nullptr"); - return {}; + return nullptr; } ani_boolean isValue = false; env->Reference_IsNullishValue(value, &isValue); if (isValue) { TAG_LOGE(AAFwkTag::DELEGATOR, "Reference_IsNullishValue"); - return {}; + return nullptr; } etsReference = std::make_unique(); 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); - return {}; + return nullptr; } etsReference->aniObj = static_cast(result); return etsReference->aniObj; @@ -79,13 +79,13 @@ static ani_object GetArguments(ani_env *env) { if (env == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "null env"); - return {}; + return nullptr; } auto abilityDelegatorArgs = AppExecFwk::AbilityDelegatorRegistry::GetArguments(); if (abilityDelegatorArgs == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "get argument failed"); - return {}; + return nullptr; } return CreateEtsAbilityDelegatorArguments(env, abilityDelegatorArgs); 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 35e335416d1..e72d7a93f6e 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 @@ -25,7 +25,7 @@ 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_NUMBER_ASYNCCALLBACK = "Lstd/core/String;JLutils/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"; @@ -34,19 +34,23 @@ 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"; + "Lapplication/AbilityMonitor/AbilityMonitor;JLutils/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"; + "Lapplication/AbilityStageMonitor/AbilityStageMonitor;JLutils/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_UIABILITY_NUMBER = "L@ohos/app/ability/UIAbility/UIAbility;:I"; constexpr const char* STRING_CALLBACK_UIABILITY = "Lutils/AbilityUtils/AsyncCallbackWrapper;:L@ohos/app/ability/UIAbility/UIAbility;"; +constexpr const char* RECORD_GET_NAME = + "X{C{std.core.BaseEnum}C{std.core.Numeric}C{std.core.String}}:C{std.core.Object}"; +constexpr const char* RECORD_SET_NAME = + "X{C{std.core.BaseEnum}C{std.core.Numeric}C{std.core.String}}C{std.core.Object}:"; } bool BindFunctions(ani_env *aniEnv, ani_class abilityDelegator) @@ -108,34 +112,34 @@ ani_object CreateEtsAbilityDelegator(ani_env *aniEnv) TAG_LOGD(AAFwkTag::DELEGATOR, "CreateEtsAbilityDelegator"); if (aniEnv == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv"); - return {}; + return nullptr; } ani_class abilityDelegator = nullptr; ani_status status = ANI_ERROR; status = aniEnv->FindClass(ABILITY_DELEGATOR_CLASS_NAME, &abilityDelegator); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "find AbilityDelegatorInner failed status: %{public}d", status); - return {}; + return nullptr; } TAG_LOGD(AAFwkTag::DELEGATOR, "find AbilityDelegator success"); if (!BindFunctions(aniEnv, abilityDelegator)) { TAG_LOGE(AAFwkTag::DELEGATOR, "BindFunctions failed"); - return {}; + return nullptr; } ani_method method = nullptr; status = aniEnv->Class_FindMethod(abilityDelegator, "", ":V", &method); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod ctor failed status: %{public}d", status); - return {}; + return nullptr; } TAG_LOGD(AAFwkTag::DELEGATOR, "Class_FindMethod ctor success"); ani_object object = nullptr; if (aniEnv->Object_New(abilityDelegator, method, &object) != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Object_New failed status: %{public}d", status); - return {}; + return nullptr; } TAG_LOGD(AAFwkTag::DELEGATOR, "CreateEtsAbilityDelegator success"); @@ -192,13 +196,13 @@ void SetParameters(ani_env *aniEnv, ani_class arguments, ani_object argumentObje return; } ani_method recordGetMethod = nullptr; - status = aniEnv->Class_FindMethod(recordCls, "$_get", "Lstd/core/Object;:Lstd/core/Object;", &recordGetMethod); + status = aniEnv->Class_FindMethod(recordCls, "$_get", RECORD_GET_NAME, &recordGetMethod); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status); return; } ani_method recordSetMethod = nullptr; - status = aniEnv->Class_FindMethod(recordCls, "$_set", "Lstd/core/Object;Lstd/core/Object;:V", &recordSetMethod); + status = aniEnv->Class_FindMethod(recordCls, "$_set", RECORD_SET_NAME, &recordSetMethod); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status); return; @@ -308,14 +312,14 @@ ani_object CreateEtsAbilityDelegatorArguments( TAG_LOGD(AAFwkTag::DELEGATOR, "CreateEtsAbilityDelegatorArguments"); if (aniEnv == nullptr || abilityDelegatorArgs == nullptr) { TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv or abilityDelegatorArgs"); - return {}; + return nullptr; } ani_class arguments = nullptr; ani_status status = ANI_ERROR; status = aniEnv->FindClass(ARGS_ABILITY_DELEGATOR_CLASS_NAME, &arguments); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "find abilityDelegatorArgs failed status: %{public}d", status); - return {}; + return nullptr; } TAG_LOGD(AAFwkTag::DELEGATOR, "find AbilityDelegatorArgs success"); @@ -323,7 +327,7 @@ ani_object CreateEtsAbilityDelegatorArguments( status = aniEnv->Class_FindMethod(arguments, "", ":V", &method); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod ctor failed status: %{public}d", status); - return {}; + return nullptr; } TAG_LOGD(AAFwkTag::DELEGATOR, "Class_FindMethod ctor success"); @@ -331,7 +335,7 @@ ani_object CreateEtsAbilityDelegatorArguments( status = aniEnv->Object_New(arguments, method, &argumentObject); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::DELEGATOR, "Object_New failed status: %{public}d", status); - return {}; + return nullptr; } TAG_LOGD(AAFwkTag::DELEGATOR, "Object_New success"); diff --git a/frameworks/ets/ani/ability_manager/BUILD.gn b/frameworks/ets/ani/ability_manager/BUILD.gn index a80f282124b..1b341d09719 100644 --- a/frameworks/ets/ani/ability_manager/BUILD.gn +++ b/frameworks/ets/ani/ability_manager/BUILD.gn @@ -27,16 +27,22 @@ ohos_shared_library("ability_manager_ani_kit") { include_dirs = [ "./include", "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/interfaces/kits/native/ability/ability_runtime", "${ability_runtime_path}/interfaces/kits/native/ability/native", "${ability_runtime_path}/interfaces/inner_api/runtime/include", "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", ] configs = [] public_configs = [] - sources = [ "./src/ets_ability_manager.cpp" ] + sources = [ + "./src/ets_ability_manager.cpp", + "./src/ets_ability_foreground_state_observer.cpp", + "./src/ets_ability_manager_utils.cpp", + ] cflags = [] if (target_cpu == "arm") { @@ -45,7 +51,10 @@ ohos_shared_library("ability_manager_ani_kit") { deps = [ "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/ani_base_context:ani_base_context", + "${ability_runtime_innerkits_path}/app_manager:app_manager", "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_native_path}/ability:ability_context_native", "${ability_runtime_native_path}/ability/native:ability_business_error", "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", ] diff --git a/frameworks/ets/ani/ability_manager/include/ets_ability_foreground_state_observer.h b/frameworks/ets/ani/ability_manager/include/ets_ability_foreground_state_observer.h new file mode 100644 index 00000000000..1c9be14824b --- /dev/null +++ b/frameworks/ets/ani/ability_manager/include/ets_ability_foreground_state_observer.h @@ -0,0 +1,58 @@ +/* + * 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_FOREGROUND_STATE_OBSERVER_H +#define OHOS_ABILITY_RUNTIME_ETS_ABILITY_FOREGROUND_STATE_OBSERVER_H + +#include + +#include "ability_foreground_state_observer_stub.h" +#include "ability_state_data.h" +#include "ani_common_util.h" +#include "ets_runtime.h" +#include "event_handler.h" + +namespace OHOS { +namespace AbilityRuntime { +using AppExecFwk::AbilityForegroundStateObserverStub; +using AppExecFwk::AbilityStateData; +class ETSAbilityForegroundStateObserver : public AbilityForegroundStateObserverStub { +public: + explicit ETSAbilityForegroundStateObserver(ani_vm *etsVm); + virtual ~ETSAbilityForegroundStateObserver(); + + void OnAbilityStateChanged(const AbilityStateData &abilityStateData); + void HandleOnAbilityStateChanged(const AbilityStateData &abilityStateData); + void AddEtsObserverObject(ani_env *env, ani_object etsObserverObject); + bool RemoveEtsObserverObject(const ani_object &observerObj); + ani_ref GetObserverObject(const ani_object &observerObject); + void RemoveAllEtsObserverObject(); + bool IsEmpty(); + void SetValid(bool valid); + void CallEtsFunction(ani_env* env, ani_object etsObserverObject, + const char *methodName, const char *signature, ...); + inline size_t GetEtsObserverMapSize() { return etsObserverObjects_.size(); } +private: + void ReleaseObjectReference(ani_ref etsObjRef); + bool IsStrictEquals(ani_ref observerRef, const ani_object &etsObserverObject); + + ani_vm *etsVm_; + volatile bool valid_ = true; + std::mutex mutexlock_; + std::vector etsObserverObjects_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_FOREGROUND_STATE_OBSERVER_H diff --git a/frameworks/ets/ani/ability_manager/include/ets_ability_manager_utils.h b/frameworks/ets/ani/ability_manager/include/ets_ability_manager_utils.h new file mode 100644 index 00000000000..a0247314122 --- /dev/null +++ b/frameworks/ets/ani/ability_manager/include/ets_ability_manager_utils.h @@ -0,0 +1,40 @@ +/* + * 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_UTILS_H +#define OHOS_ABILITY_RUNTIME_ETS_ABILITY_MANAGER_UTILS_H + +#include "ability_running_info.h" +#include "ability_state_data.h" +#include "ani.h" +#include "extension_running_info.h" + +namespace OHOS { +namespace AbilityManagerEts { +using OHOS::AppExecFwk::AbilityStateData; +ani_object WrapAbilityStateData(ani_env *env, const AbilityStateData &abilityStateData); +bool SetAbilityStateData(ani_env *env, ani_object object, const AbilityStateData &abilityStateData); +bool WrapAbilityRunningInfo(ani_env *env, ani_object &infoObj, const AAFwk::AbilityRunningInfo &info); +bool WrapAbilityRunningInfoArray( + ani_env *env, ani_object &arrayObj, const std::vector &infos); +bool WrapAbilityRunningInfoInner( + ani_env *env, ani_object &infoObj, const AAFwk::AbilityRunningInfo &info, ani_class cls); +bool WrapExtensionRunningInfo(ani_env *env, ani_object &infoObj, const AAFwk::ExtensionRunningInfo &info); +bool WrapExtensionRunningInfoInner( + ani_env *env, ani_object &infoObj, const AAFwk::ExtensionRunningInfo &info, ani_class cls); +bool WrapArrayString(ani_env *env, ani_object &arrayObj, const std::vector &values); +} // namespace AbilityManagerEts +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_MANAGER_UTILS_H diff --git a/frameworks/ets/ani/ability_manager/src/ets_ability_foreground_state_observer.cpp b/frameworks/ets/ani/ability_manager/src/ets_ability_foreground_state_observer.cpp new file mode 100644 index 00000000000..41581812da7 --- /dev/null +++ b/frameworks/ets/ani/ability_manager/src/ets_ability_foreground_state_observer.cpp @@ -0,0 +1,233 @@ +/* + * 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_foreground_state_observer.h" + +#include "ani_common_util.h" +#include "ani_task.h" +#include "ets_ability_manager_utils.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* ABILITY_FOREGROUND_STATE_OBSERVER_CLASS_NAME = + "Lapplication/AbilityForegroundStateObserver/AbilityForegroundStateObserver;"; +constexpr const char *SIGNATURE_ABILITY_STATE_DATA = "Lapplication/AbilityStateData/AbilityStateData;:V"; +} + +ETSAbilityForegroundStateObserver::ETSAbilityForegroundStateObserver(ani_vm *etsVm) : etsVm_(etsVm) {} + +ETSAbilityForegroundStateObserver::~ETSAbilityForegroundStateObserver() +{ + RemoveAllEtsObserverObject(); +} + +void ETSAbilityForegroundStateObserver::OnAbilityStateChanged(const AbilityStateData &abilityStateData) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "OnAbilityStateChanged called"); + if (!valid_) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid appms"); + return; + } + wptr weakPtr = this; + auto task = [abilityStateData, weakPtr] () { + auto abilityForegroundStateObserver = weakPtr.promote(); + if (abilityForegroundStateObserver == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null observerPtr"); + return; + } + abilityForegroundStateObserver->HandleOnAbilityStateChanged(abilityStateData); + }; + if (AniTask::AniSendEvent(task) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Failed to aniSendEvent"); + } + TAG_LOGD(AAFwkTag::ABILITYMGR, "OnAbilityStateChanged end"); +} + +void ETSAbilityForegroundStateObserver::CallEtsFunction(ani_env* env, ani_object etsObserverObject, + const char *methodName, const char *signature, ...) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "call method:%{public}s", methodName); + ani_class cls; + ani_method method = nullptr; + ani_status status = ANI_OK; + if ((status = env->FindClass(ABILITY_FOREGROUND_STATE_OBSERVER_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "find observer failed status : %{public}d", status); + return; + } + if ((status = env->Class_FindMethod(cls, methodName, signature, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "status: %{public}d", status); + return; + } + env->ResetError(); + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(etsObserverObject, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "status: %{public}d", status); + return; + } + va_end(args); + TAG_LOGD(AAFwkTag::ABILITYMGR, "end"); + return; +} + +void ETSAbilityForegroundStateObserver::HandleOnAbilityStateChanged(const AbilityStateData &abilityStateData) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "HandleOnAbilityStateChanged called"); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "etsVm_ nullptr"); + return; + } + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return; + } + auto abilityStateDataObj = AbilityManagerEts::WrapAbilityStateData(env, abilityStateData); + if (abilityStateDataObj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "WrapAbilityStateData failed"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + std::lock_guard lock(mutexlock_); + for (auto &item : etsObserverObjects_) { + if (item != nullptr) { + CallEtsFunction(env, reinterpret_cast(item), + "onAbilityStateChanged", SIGNATURE_ABILITY_STATE_DATA, abilityStateDataObj); + } + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + TAG_LOGD(AAFwkTag::ABILITYMGR, "HandleOnAbilityStateChanged end"); +} + +void ETSAbilityForegroundStateObserver::AddEtsObserverObject(ani_env *env, ani_object etsObserverObject) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "AddEtsObserverObject called"); + if (etsObserverObject == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer"); + return; + } + if (GetObserverObject(etsObserverObject) != nullptr) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "observer exist"); + return; + } + ani_ref global = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GlobalReference_Create(etsObserverObject, &global)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "status : %{public}d", status); + return; + } + std::lock_guard lock(mutexlock_); + etsObserverObjects_.emplace_back(global); + TAG_LOGD(AAFwkTag::ABILITYMGR, "AddEtsObserverObject end"); +} + +ani_ref ETSAbilityForegroundStateObserver::GetObserverObject(const ani_object &observerObject) +{ + if (observerObject == nullptr) { + return nullptr; + } + std::lock_guard lock(mutexlock_); + for (const auto& observer : etsObserverObjects_) { + if (IsStrictEquals(observer, observerObject)) { + return observer; + } + } + return nullptr; +} + +void ETSAbilityForegroundStateObserver::ReleaseObjectReference(ani_ref etsObjRef) +{ + if (etsObjRef == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null etsObj"); + return; + } + ani_status status = ANI_ERROR; + ani_env *env = nullptr; + status = etsVm_->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "GetEnv failed"); + return; + } + if ((status = env->GlobalReference_Delete(etsObjRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "GlobalReference_Delete status: %{public}d", status); + } +} + +bool ETSAbilityForegroundStateObserver::RemoveEtsObserverObject(const ani_object &observerObj) +{ + if (observerObj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer"); + return false; + } + std::lock_guard lock(mutexlock_); + wptr weakPtr = this; + auto it = std::find_if(etsObserverObjects_.begin(), etsObserverObjects_.end(), + [weakPtr, &observerObj](ani_ref item) { + auto abilityForegroundStateObserver = weakPtr.promote(); + if (abilityForegroundStateObserver == nullptr) { + return false; + } + return abilityForegroundStateObserver->IsStrictEquals(item, observerObj); + }); + if (it != etsObserverObjects_.end() && *it != nullptr) { + ReleaseObjectReference(*it); + etsObserverObjects_.erase(it); + } + return true; +} + +void ETSAbilityForegroundStateObserver::RemoveAllEtsObserverObject() +{ + std::lock_guard lock(mutexlock_); + for (auto &item : etsObserverObjects_) { + ReleaseObjectReference(item); + } + etsObserverObjects_.clear(); +} + +void ETSAbilityForegroundStateObserver::SetValid(const bool valid) +{ + valid_ = valid; +} + +bool ETSAbilityForegroundStateObserver::IsEmpty() +{ + return etsObserverObjects_.empty(); +} + +bool ETSAbilityForegroundStateObserver::IsStrictEquals(ani_ref observerRef, const ani_object &etsObserverObject) +{ + if (observerRef == nullptr || etsObserverObject == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "etsObserverObject or observerRef null"); + return false; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed status: %{public}d", status); + return false; + } + ani_boolean isEquals = ANI_FALSE; + if ((status = env->Reference_StrictEquals(observerRef, etsObserverObject, &isEquals)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Reference_StrictEquals failed status: %{public}d", status); + return false; + } + return isEquals == ANI_TRUE; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/ability_manager/src/ets_ability_manager.cpp b/frameworks/ets/ani/ability_manager/src/ets_ability_manager.cpp index fb6b18d7cf2..e00129e225f 100644 --- a/frameworks/ets/ani/ability_manager/src/ets_ability_manager.cpp +++ b/frameworks/ets/ani/ability_manager/src/ets_ability_manager.cpp @@ -16,11 +16,16 @@ #include "ets_ability_manager.h" #include "ability_business_error.h" +#include "ability_context.h" #include "ability_manager_client.h" #include "ability_manager_errors.h" #include "ability_manager_interface.h" +#include "ani_base_context.h" #include "ani_common_ability_state_data.h" #include "ani_common_want.h" +#include "app_mgr_interface.h" +#include "ets_ability_foreground_state_observer.h" +#include "ets_ability_manager_utils.h" #include "ets_error_utils.h" #include "hilog_tag_wrapper.h" #include "if_system_ability_manager.h" @@ -36,18 +41,45 @@ constexpr const char* ETS_ABILITY_MANAGER_NAMESPACE = "L@ohos/app/ability/abilit constexpr const char* ETS_ABILITY_MANAGER_SIGNATURE_ARRAY = ":Lescompat/Array;"; constexpr const char* ETS_ABILITY_MANAGER_SIGNATURE_CALLBACK = "Lutils/AbilityUtils/AsyncCallbackWrapper;:V"; constexpr const char* ETS_ABILITY_MANAGER_SIGNATURE_VOID = ":V"; +constexpr const char *ON_OFF_TYPE_ABILITY_FOREGROUND_STATE = "abilityForegroundState"; constexpr int32_t ERR_FAILURE = -1; } -sptr GetAbilityManagerInstance() +class EtsAbilityManager final { +public: + static ani_object GetForegroundUIAbilities(ani_env *env); + static void GetForegroundUIAbilitiesCallBack(ani_env *env, ani_object callbackObj); + static void GetTopAbility(ani_env *env, ani_object callback); + static void CheckSystemApp(ani_env *env); + static void GetAbilityRunningInfos(ani_env *env, ani_object callback); + static void IsEmbeddedOpenAllowed(ani_env *env, ani_object contextObj, ani_string aniAppId, ani_object callbackObj); + static void NativeOn(ani_env *env, ani_string aniType, ani_object aniObserver); + static void NativeOff(ani_env *env, ani_string aniType, ani_object aniObserver); +private: + static sptr GetAbilityManagerInstance(); + static sptr GetAppManagerInstance(); + static sptr observerForeground_; +}; + +sptr EtsAbilityManager::observerForeground_ = nullptr; + +sptr EtsAbilityManager::GetAbilityManagerInstance() { sptr systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); - sptr abilityManagerObj = - systemAbilityManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abilityManagerObj = systemAbilityManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID); return iface_cast(abilityManagerObj); } -static ani_object GetForegroundUIAbilities(ani_env *env) + +sptr EtsAbilityManager::GetAppManagerInstance() +{ + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + sptr appObject = systemAbilityManager->GetSystemAbility(APP_MGR_SERVICE_ID); + return iface_cast(appObject); +} + +ani_object EtsAbilityManager::GetForegroundUIAbilities(ani_env *env) { TAG_LOGD(AAFwkTag::ABILITYMGR, "call GetForegroundUIAbilities"); @@ -80,7 +112,7 @@ static ani_object GetForegroundUIAbilities(ani_env *env) return aniArray; } -void GetForegroundUIAbilitiesCallBack(ani_env *env, ani_object callbackObj) +void EtsAbilityManager::GetForegroundUIAbilitiesCallBack(ani_env *env, ani_object callbackObj) { TAG_LOGD(AAFwkTag::ABILITYMGR, "call GetForegroundUIAbilitiesCallBack"); if (env == nullptr) { @@ -114,7 +146,21 @@ void GetForegroundUIAbilitiesCallBack(ani_env *env, ani_object callbackObj) AppExecFwk::AsyncCallback(env, callbackObj, EtsErrorUtil::CreateErrorByNativeErr(env, ERR_OK), aniArray); } -static void GetTopAbility(ani_env *env, ani_object callback) +void EtsAbilityManager::CheckSystemApp(ani_env *env) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return; + } + auto selfToken = IPCSkeleton::GetSelfTokenID(); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "not system app"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); + return; + } +} + +void EtsAbilityManager::GetTopAbility(ani_env *env, ani_object callback) { TAG_LOGD(AAFwkTag::ABILITYMGR, "call GetTopAbility"); if (env == nullptr) { @@ -139,18 +185,141 @@ static void GetTopAbility(ani_env *env, ani_object callback) return; } -static void CheckSystemApp(ani_env *env) +void EtsAbilityManager::GetAbilityRunningInfos(ani_env *env, ani_object callback) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "GetAbilityRunningInfos"); if (env == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); return; } - auto selfToken = IPCSkeleton::GetSelfTokenID(); - if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "not system app"); - EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); + std::vector infos; + auto errcode = AAFwk::AbilityManagerClient::GetInstance()->GetAbilityRunningInfos(infos); + ani_object retObject = nullptr; + AbilityManagerEts::WrapAbilityRunningInfoArray(env, retObject, infos); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateErrorByNativeErr(env, errcode), retObject); +} + +void EtsAbilityManager::IsEmbeddedOpenAllowed(ani_env *env, ani_object contextObj, + ani_string aniAppId, ani_object callbackObj) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "IsEmbeddedOpenAllowed"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return; + } + auto context = OHOS::AbilityRuntime::GetStageModeContext(env, contextObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null context"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param context failed, must not be nullptr."); + return; + } + auto uiAbilityContext = OHOS::AbilityRuntime::Context::ConvertTo(context); + if (uiAbilityContext == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null UIAbilityContext"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param context failed, must be UIAbilityContext."); + return; + } + std::string appId; + if (!AppExecFwk::GetStdString(env, aniAppId, appId)) { + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param appId failed, must be a string."); + return; + } + auto token = uiAbilityContext->GetToken(); + ani_boolean ret = AAFwk::AbilityManagerClient::GetInstance()->IsEmbeddedOpenAllowed(token, appId); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK), AppExecFwk::CreateBoolean(env, ret)); +} + +void EtsAbilityManager::NativeOn(ani_env *env, ani_string aniType, ani_object aniObserver) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "nativeOn called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "env null ptr"); + return; + } + std::string strType; + if (!AppExecFwk::GetStdString(env, aniType, strType) || strType != ON_OFF_TYPE_ABILITY_FOREGROUND_STATE) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "GetStdString failed"); + EtsErrorUtil::ThrowInvalidParamError(env, + "Parse param observer failed, must be a AbilityForegroundStateObserver."); + return; + } + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "get aniVM failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Get aniVm failed."); return; } + if (observerForeground_ == nullptr) { + observerForeground_ = sptr::MakeSptr(aniVM); + if (observerForeground_ == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null observerForeground_"); + EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + } + if (observerForeground_->IsEmpty()) { + auto appManager = GetAppManagerInstance(); + if (appManager == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "appManager null ptr"); + EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + int32_t ret = appManager->RegisterAbilityForegroundStateObserver(observerForeground_); + TAG_LOGD(AAFwkTag::ABILITYMGR, "ret: %{public}d", ret); + if (ret != NO_ERROR) { + EtsErrorUtil::ThrowErrorByNativeErr(env, static_cast(ret)); + return; + } + } + observerForeground_->AddEtsObserverObject(env, aniObserver); + TAG_LOGD(AAFwkTag::ABILITYMGR, "nativeOn end"); +} + +void EtsAbilityManager::NativeOff(ani_env *env, ani_string aniType, ani_object aniObserver) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "nativeOff called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "env null ptr"); + return; + } + std::string strType; + if (!AppExecFwk::GetStdString(env, aniType, strType)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "GetStdString failed"); + EtsErrorUtil::ThrowInvalidParamError(env, + "Parse param observer failed, must be a AbilityForegroundStateObserver."); + return; + } + if (observerForeground_ == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null observer"); + EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + ani_status status = ANI_OK; + ani_boolean isUndefined = false; + if ((status = env->Reference_IsUndefined(aniObserver, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Failed to check undefined status : %{public}d", status); + return; + } + if (!isUndefined) { + observerForeground_->RemoveEtsObserverObject(aniObserver); + } else { + observerForeground_->RemoveAllEtsObserverObject(); + } + if (observerForeground_->IsEmpty()) { + auto appManager = GetAppManagerInstance(); + if (appManager == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "appManager null ptr"); + EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + int32_t ret = appManager->UnregisterAbilityForegroundStateObserver(observerForeground_); + TAG_LOGD(AAFwkTag::ABILITYMGR, "ret: %{public}d", ret); + if (ret != NO_ERROR) { + EtsErrorUtil::ThrowErrorByNativeErr(env, static_cast(ret)); + } + } + TAG_LOGD(AAFwkTag::ABILITYMGR, "nativeOff end"); } void EtsAbilityManagerRegistryInit(ani_env *env) @@ -173,16 +342,23 @@ void EtsAbilityManagerRegistryInit(ani_env *env) std::array methods = { ani_native_function { "nativeGetForegroundUIAbilities", ETS_ABILITY_MANAGER_SIGNATURE_ARRAY, - reinterpret_cast(GetForegroundUIAbilities) + reinterpret_cast(EtsAbilityManager::GetForegroundUIAbilities) }, ani_native_function { "getForegroundUIAbilitiesCallback", "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", - reinterpret_cast(GetForegroundUIAbilitiesCallBack) + reinterpret_cast(EtsAbilityManager::GetForegroundUIAbilitiesCallBack) }, ani_native_function {"nativeGetTopAbility", ETS_ABILITY_MANAGER_SIGNATURE_CALLBACK, - reinterpret_cast(GetTopAbility)}, + reinterpret_cast(EtsAbilityManager::GetTopAbility)}, ani_native_function {"nativeCheckSystemApp", ETS_ABILITY_MANAGER_SIGNATURE_VOID, - reinterpret_cast(CheckSystemApp)}, + reinterpret_cast(EtsAbilityManager::CheckSystemApp)}, + ani_native_function { "nativeGetAbilityRunningInfos", "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAbilityManager::GetAbilityRunningInfos) }, + ani_native_function { "nativeIsEmbeddedOpenAllowed", + "Lapplication/Context/Context;Lstd/core/String;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAbilityManager::IsEmbeddedOpenAllowed) }, + ani_native_function { "nativeOn", nullptr, reinterpret_cast(EtsAbilityManager::NativeOn) }, + ani_native_function { "nativeOff", nullptr, reinterpret_cast(EtsAbilityManager::NativeOff) } }; status = env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()); if (status != ANI_OK) { diff --git a/frameworks/ets/ani/ability_manager/src/ets_ability_manager_utils.cpp b/frameworks/ets/ani/ability_manager/src/ets_ability_manager_utils.cpp new file mode 100644 index 00000000000..8d585f896d7 --- /dev/null +++ b/frameworks/ets/ani/ability_manager/src/ets_ability_manager_utils.cpp @@ -0,0 +1,379 @@ +/* + * 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_utils.h" + +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "ani_enum_convert.h" + +namespace OHOS { +namespace AbilityManagerEts { +constexpr const char *CLASSNAME_ARRAY = "Lescompat/Array;"; +constexpr const char *SET_OBJECT_VOID_SIGNATURE = "ILstd/core/Object;:V"; +constexpr const char *CLASSNAME_ABILITY_RRUNNINGINFO = "Lapplication/AbilityRunningInfo/AbilityRunningInfoImpl;"; +constexpr const char *ABILITY_STATE_ENUM_NAME = "L@ohos/app/ability/abilityManager/abilityManager/AbilityState;"; +constexpr const char *CLASSNAME_EXTENSION_RUNNINGINFO = "Lapplication/ExtensionRunningInfo/ExtensionRunningInfoInner;"; +constexpr const char *EXTENSION_ABILITY_TYPE_ENUM_NAME + = "L@ohos/app/ability/abilityManager/abilityManager/ExtensionAbilityType;"; + +bool WrapAbilityRunningInfoArray( + ani_env *env, ani_object &arrayObj, const std::vector &infos) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "WrapAbilityRunningInfoArray"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return false; + } + ani_class arrayCls = nullptr; + ani_method arrayCtor = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(CLASSNAME_ARRAY, &arrayCls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "status : %{public}d", status); + return false; + } + if (arrayCls == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null arrayCls"); + return false; + } + if ((status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "status : %{public}d", status); + return false; + } + if (arrayCtor == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null arrayCtor"); + return false; + } + if ((status = env->Object_New(arrayCls, arrayCtor, &arrayObj, infos.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "status : %{public}d", status); + return false; + } + if (arrayObj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null arrayObjs"); + return false; + } + for (size_t i = 0; i < infos.size(); i++) { + ani_object infoObj = nullptr; + if (!WrapAbilityRunningInfo(env, infoObj, infos[i])) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "WrapAbilityRunningInfo failed"); + return false; + } + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", SET_OBJECT_VOID_SIGNATURE, i, infoObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "status : %{public}d", status); + return false; + } + } + return true; +} + +bool WrapAbilityRunningInfo(ani_env *env, ani_object &infoObj, const AAFwk::AbilityRunningInfo &info) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "WrapAbilityRunningInfo"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return false; + } + ani_object elementNameObj = WrapElementName(env, info.ability); + if (elementNameObj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "WrapElementName failed"); + return false; + } + ani_class cls; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(CLASSNAME_ABILITY_RRUNNINGINFO, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "findClass failed, status: %{public}d", status); + return false; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null cls"); + return false; + } + ani_method method = nullptr; + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "findMethod failed, status: %{public}d", status); + return false; + } + if (method == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null method"); + return false; + } + if ((status = env->Object_New(cls, method, &infoObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Object_New failed, status: %{public}d", status); + return false; + } + if (infoObj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null infoObj"); + return false; + } + if ((status = env->Object_SetPropertyByName_Ref(infoObj, "ability", elementNameObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set ability failed, status: %{public}d", status); + return false; + } + return WrapAbilityRunningInfoInner(env, infoObj, info, cls); +} + +bool WrapAbilityRunningInfoInner( + ani_env *env, ani_object &infoObj, const AAFwk::AbilityRunningInfo &info, ani_class cls) +{ + ani_status status = ANI_ERROR; + if ((status = env->Object_SetPropertyByName_Int(infoObj, "pid", info.pid)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set pid failed, status: %{public}d", status); + return false; + } + if ((status = env->Object_SetPropertyByName_Int(infoObj, "uid", info.uid)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set uid failed, status: %{public}d", status); + return false; + } + if (!AppExecFwk::SetFieldStringByName(env, cls, infoObj, "processName", info.processName)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set processName failed"); + return false; + } + if ((status = env->Object_SetPropertyByName_Long(infoObj, "startTime", info.startTime)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set processName failed, status: %{public}d", status); + return false; + } + ani_enum_item abilityStateItem {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts( + env, ABILITY_STATE_ENUM_NAME, info.abilityState, abilityStateItem); + if ((status = env->Object_SetPropertyByName_Ref(infoObj, "abilityState", abilityStateItem)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set abilityState failed, status: %{public}d", status); + return false; + } + return true; +} + +bool WrapArrayString(ani_env *env, ani_object &arrayObj, const std::vector &values) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "WrapArrayString"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return false; + } + ani_class arrayCls = nullptr; + ani_method arrayCtor = nullptr; + ani_string aniStr = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(CLASSNAME_ARRAY, &arrayCls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "findClass failed, status : %{public}d", status); + return false; + } + if (arrayCls == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null arrayCls"); + return false; + } + if ((status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "findMethod failed, status : %{public}d", status); + return false; + } + if (arrayCtor == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null arrayCtor"); + return false; + } + if ((status = env->Object_New(arrayCls, arrayCtor, &arrayObj, values.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Object_New failed, status : %{public}d", status); + return false; + } + if (arrayObj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null arrayObj"); + return false; + } + for (size_t i = 0; i < values.size(); i++) { + status = env->String_NewUTF8(values[i].c_str(), values[i].size(), &aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "String_NewUTF8 failed, status : %{public}d", status); + return false; + } + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", i, aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Object_CallMethodByName_Void failed, status : %{public}d", status); + return false; + } + } + return true; +} + +bool WrapExtensionRunningInfo(ani_env *env, ani_object &infoObj, const AAFwk::ExtensionRunningInfo &info) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "WrapExtensionRunningInfo"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return false; + } + ani_object elementNameObj = WrapElementName(env, info.extension); + if (elementNameObj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "WrapElementName failed"); + return false; + } + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(CLASSNAME_EXTENSION_RUNNINGINFO, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "findClass failed, status: %{public}d", status); + return false; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null cls"); + return false; + } + ani_method method = nullptr; + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "findMethod failed, status: %{public}d", status); + return false; + } + if (method == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null method"); + return false; + } + if ((status = env->Object_New(cls, method, &infoObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Object_New failed, status: %{public}d", status); + return false; + } + if (infoObj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null infoObj"); + return false; + } + if ((status = env->Object_SetPropertyByName_Ref(infoObj, "extension", elementNameObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set extension failed, status: %{public}d", status); + return false; + } + return WrapExtensionRunningInfoInner(env, infoObj, info, cls); +} + +bool WrapExtensionRunningInfoInner( + ani_env *env, ani_object &infoObj, const AAFwk::ExtensionRunningInfo &info, ani_class cls) +{ + ani_status status = ANI_ERROR; + if ((status = env->Object_SetPropertyByName_Int(infoObj, "pid", info.pid)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set pid failed, status: %{public}d", status); + return false; + } + if ((status = env->Object_SetPropertyByName_Int(infoObj, "uid", info.uid)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set uid failed, status: %{public}d", status); + return false; + } + if (!AppExecFwk::SetFieldStringByName(env, cls, infoObj, "processName", info.processName)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set processName failed"); + return false; + } + if ((status = env->Object_SetPropertyByName_Long(infoObj, "startTime", info.startTime)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set startTimee failed, status: %{public}d", status); + return false; + } + bool result = WrapArrayString(env, infoObj, info.clientPackage); + if (((status = env->Object_SetFieldByName_Boolean(infoObj, "clientPackage", result)) != ANI_OK)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set clientPackage failed, status: %{public}d", status); + return false; + } + ani_enum_item typeItem = nullptr; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts( + env, EXTENSION_ABILITY_TYPE_ENUM_NAME, info.type, typeItem); + if ((status = env->Object_SetPropertyByName_Ref(infoObj, "type", typeItem)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set type failed, status: %{public}d", status); + return false; + } + return true; +} + +bool SetAbilityStateData(ani_env *env, ani_object object, const AbilityStateData &abilityStateData) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return false; + } + ani_status status = ANI_OK; + if ((status = env->Object_SetFieldByName_Ref(object, "moduleName", + OHOS::AppExecFwk::GetAniString(env, abilityStateData.moduleName))) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "moduleName failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Ref(object, "bundleName", + OHOS::AppExecFwk::GetAniString(env, abilityStateData.bundleName))) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "bundleName failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Ref(object, "abilityName", + OHOS::AppExecFwk::GetAniString(env, abilityStateData.abilityName))) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityName failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Int(object, "pid", static_cast(abilityStateData.pid))) + != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "pid failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Int(object, "uid", abilityStateData.uid)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "uid failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Int(object, "state", abilityStateData.abilityState)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "state failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Int(object, "abilityType", abilityStateData.abilityType)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityType failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Boolean(object, "isAtomicService", + abilityStateData.isAtomicService)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "isAtomicService failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetFieldByName_Ref(object, "appCloneIndex", + OHOS::AppExecFwk::CreateInt(env, abilityStateData.appCloneIndex))) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "appCloneIndex failed status:%{public}d", status); + return false; + } + return true; +} + +ani_object WrapAbilityStateData(ani_env *env, const AbilityStateData &abilityStateData) +{ + ani_class cls {}; + ani_status status = ANI_ERROR; + ani_method method {}; + ani_object object = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return nullptr; + } + if ((status = env->FindClass("Lapplication/AbilityStateData/AbilityStateData;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "find class failed status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "find ctor failed status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Object_New AppStateData failed status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null object"); + return nullptr; + } + if (!SetAbilityStateData(env, object, abilityStateData)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "SetAppStateData failed"); + return nullptr; + } + return object; +} + +} // namespace AbilityManagerEts +} // namespace OHOS diff --git a/frameworks/ets/ani/ani_common/BUILD.gn b/frameworks/ets/ani/ani_common/BUILD.gn index 12fe1f08f4f..eafcb2277cf 100644 --- a/frameworks/ets/ani/ani_common/BUILD.gn +++ b/frameworks/ets/ani/ani_common/BUILD.gn @@ -50,12 +50,16 @@ ohos_shared_library("ani_common") { "src/ani_common_util.cpp", "src/ani_common_want.cpp", "src/context_transfer.cpp", + "src/ani_task.cpp", "src/ets_application_context_utils.cpp", + "src/ets_application_state_change_callback.cpp", "src/ets_context_utils.cpp", "src/ets_data_struct_converter.cpp", + "src/ets_enviroment_callback.cpp", "src/ets_error_utils.cpp", "src/ets_extension_context.cpp", "src/ets_free_install_observer.cpp", + "src/ani_common_remote.cpp", ] cflags = [] @@ -69,6 +73,7 @@ ohos_shared_library("ani_common") { "${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}/error_utils:ability_runtime_error_util", "${ability_runtime_innerkits_path}/runtime:runtime", "${ability_runtime_native_path}/ability/native:ability_business_error", "${ability_runtime_native_path}/ability/native:abilitykit_native", @@ -91,6 +96,7 @@ ohos_shared_library("ani_common") { "image_framework:image_ani", "ipc:ipc_core", "ipc:ipc_napi", + "ipc:rpc_ani", "json:nlohmann_json_static", "napi:ace_napi", "resource_management:global_resmgr", diff --git a/frameworks/ets/ani/ani_common/include/ani_common_remote.h b/frameworks/ets/ani/ani_common/include/ani_common_remote.h new file mode 100644 index 00000000000..a8fe380d9d7 --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_remote.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_RUNTIME_ANI_REMOTE_H +#define OHOS_ABILITY_RUNTIME_ANI_REMOTE_H + +#include "ani.h" +#include "ani_remote_object.h" + +namespace OHOS { +namespace AbilityRuntime { + +class AniRemote { +public: + static ani_object CreateAniRemoteObject(ani_env *env, const sptr target); +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANI_REMOTE_H \ No newline at end of file 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 de202218897..0f729b3dd2f 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,6 +18,7 @@ #include "start_options.h" #include "ani_common_util.h" +#include "ani_common_want.h" #ifdef START_WINDOW_OPTIONS_WITH_PIXELMAP #include "pixel_map_ani.h" #include "image_ani_utils.h" @@ -36,6 +37,8 @@ bool UnwrapPixelMapFromAni(ani_env *env, ani_object param, std::shared_ptr &startWindowOption); +bool UnwrapAtomicServiceOptions(ani_env *env, ani_object optionsObj, AAFwk::Want &want, + AAFwk::StartOptions &startOptions); } // 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 7475d48f30a..30c52026461 100644 --- a/frameworks/ets/ani/ani_common/include/ani_common_util.h +++ b/frameworks/ets/ani/ani_common/include/ani_common_util.h @@ -26,6 +26,9 @@ 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); +bool GetFieldLongByName(ani_env *env, ani_object object, const char *name, int64_t &value); +bool SetFieldLongByName(ani_env *env, ani_class cls, ani_object object, const char *name, int64_t value); + bool GetFieldBoolByName(ani_env *env, ani_object object, const char *name, bool &value); bool SetFieldBoolByName(ani_env *env, ani_class cls, ani_object object, const char *name, bool value); @@ -33,8 +36,8 @@ bool GetFieldStringByName(ani_env *env, ani_object object, const char *name, std bool SetFieldStringByName(ani_env *env, ani_class cls, ani_object object, const char *name, const std::string &value); -bool GetFieldIntByName(ani_env *env, ani_object object, const char *name, int &value); -bool SetFieldIntByName(ani_env *env, ani_class cls, ani_object object, const char *name, int value); +bool GetFieldIntByName(ani_env *env, ani_object object, const char *name, int32_t &value); +bool SetFieldIntByName(ani_env *env, ani_class cls, ani_object object, const char *name, int32_t value); bool GetFieldStringArrayByName(ani_env *env, ani_object object, const char *name, std::vector &value); bool SetFieldArrayStringByName(ani_env *env, ani_class cls, ani_object object, const char *name, @@ -67,15 +70,24 @@ 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 GetIntPropertyObject(ani_env *env, ani_object param, const char *name, ani_int &value); +bool GetLongPropertyObject(ani_env *env, ani_object param, const char *name, ani_long &value); bool GetDoublePropertyValue(ani_env *env, ani_object param, const char *name, double &value); +bool GetIntPropertyValue(ani_env *env, ani_object param, const char *name, int32_t &value); bool GetRefProperty(ani_env *env, ani_object param, const char *name, ani_ref &value); +bool GetBooleanPropertyObject(ani_env *env, ani_object param, const char *name, bool &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 SetIntPropertyObject(ani_env *env, ani_object param, const char *name, int32_t value); +bool SetIntPropertyValue(ani_env *env, ani_object param, const char *name, int32_t 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); bool GetStaticFieldString(ani_env *env, ani_class classObj, const char *fieldName, std::string &value); + +ani_env *AttachAniEnv(ani_vm * etsVm, bool &isAttachThread); +void DetachAniEnv(ani_vm * etsVm, bool &isAttachThread); } // 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 4a77835fb82..a34527f839a 100644 --- a/frameworks/ets/ani/ani_common/include/ani_common_want.h +++ b/frameworks/ets/ani/ani_common/include/ani_common_want.h @@ -32,6 +32,8 @@ bool UnwrapWant(ani_env *env, ani_object param, AAFwk::Want &want); ani_ref WrapWantParams(ani_env *env, const AAFwk::WantParams &wantParams); bool UnwrapWantParams(ani_env *env, ani_ref param, AAFwk::WantParams &wantParams); +ani_ref WrapWantParamsFD(ani_env *env, const 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); diff --git a/frameworks/ets/ani/ani_common/include/ani_task.h b/frameworks/ets/ani/ani_common/include/ani_task.h new file mode 100644 index 00000000000..ad2d7249ca8 --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_task.h @@ -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. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_TASK_H +#define OHOS_ABILITY_RUNTIME_ETS_TASK_H + +#include "ability_business_error.h" +#include "ani.h" +#include "event_handler.h" + +namespace OHOS { +namespace AbilityRuntime { + +class AniTask { +public: + static ani_status AniSendEvent(const std::function task); + +private: + static std::shared_ptr mainHandler_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_TASK_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 39bf4846e2d..6930f95da05 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 @@ -21,8 +21,9 @@ #include "ani_common_util.h" #include "ani_common_want.h" #include "application_context.h" +#include "ets_application_state_change_callback.h" #include "ets_context_utils.h" -#include "ets_error_utils.h" +#include "ets_enviroment_callback.h" namespace OHOS { namespace AbilityRuntime { @@ -45,11 +46,18 @@ public: 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, + static ani_object SetApplicationContext(ani_env *aniEnv, const std::shared_ptr &applicationContext); - static ani_object CreateEtsApplicationContext(ani_env* aniEnv, + static ani_object CreateEtsApplicationContext(ani_env *aniEnv, const std::shared_ptr &applicationContext); - static void BindApplicationContextFunc(ani_env* aniEnv); + static void BindApplicationContextFunc(ani_env *aniEnv); + static ani_int GetCurrentAppCloneIndex(ani_env *env, ani_object aniObj); + static ani_string GetCurrentInstanceKey(ani_env *env, ani_object aniObj); + static void GetAllRunningInstanceKeys(ani_env *env, ani_object aniObj, ani_object callback); + static void NativeOffApplicationStateChangeSync(ani_env *env, ani_object aniObj, ani_object callback); + static void NativeOnApplicationStateChangeSync(ani_env *env, ani_object aniObj, ani_object callback); + static void NativeOffEnvironmentSync(ani_env *env, ani_object aniObj, ani_int callbackId, ani_object callback); + static ani_int NativeOnEnvironmentSync(ani_env *env, ani_object aniObj, ani_object envCallback); protected: std::weak_ptr applicationContext_; private: @@ -63,6 +71,15 @@ private: 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); + ani_int OnGetCurrentAppCloneIndex(ani_env *env, ani_object aniObj); + ani_string OnGetCurrentInstanceKey(ani_env *env, ani_object aniObj); + void OnGetAllRunningInstanceKeys(ani_env *env, ani_object aniObj, ani_object callback); + void OnNativeOffApplicationStateChangeSync(ani_env *env, ani_object aniObj, ani_object callback); + void OnNativeOnApplicationStateChangeSync(ani_env *env, ani_object aniObj, ani_object callback); + void OnNativeOffEnvironmentSync(ani_env *env, ani_object aniObj, ani_int callbackId, ani_object callback); + ani_int OnNativeOnEnvironmentSync(ani_env *env, ani_object aniObj, ani_object envCallback); + std::shared_ptr etsEnviromentCallback_; + std::shared_ptr applicationStateCallback_; }; } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/ets/ani/ani_common/include/ets_application_state_change_callback.h b/frameworks/ets/ani/ani_common/include/ets_application_state_change_callback.h new file mode 100644 index 00000000000..8d035160d2a --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ets_application_state_change_callback.h @@ -0,0 +1,55 @@ +/* + * 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_STATE_CHANGE_CALLBACK_H +#define OHOS_ABILITY_RUNTIME_ETS_APPLICATION_STATE_CHANGE_CALLBACK_H + +#include +#include +#include +#include + +#include "application_state_change_callback.h" +#include "ani.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsApplicationStateChangeCallback : public ApplicationStateChangeCallback, + public std::enable_shared_from_this { +public: + explicit EtsApplicationStateChangeCallback(ani_vm *etsVm); + ~EtsApplicationStateChangeCallback() override; + void NotifyApplicationForeground() override; + void NotifyApplicationBackground() override; + void Register(ani_object aniCallback); + + /** + * @brief Unregister application state change callback. + * @param aniCallback, if anicallback is nullptr, delete all register anicallback. + * or if anicallback is specified, delete prescribed anicallback. + * @return Returns true on unregister success, others return false. + */ + bool UnRegister(ani_object aniCallback = nullptr); + bool IsEmpty() const; +private: + void CallEtsMethod(const std::string &methodName); + ani_vm *etsVm_ = nullptr; + std::set callbacks_; + mutable std::mutex mutex_; + std::atomic isAttachThread_ = false; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_APPLICATION_STATE_CHANGE_CALLBACK_H 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 a67924090f8..884acc37138 100644 --- a/frameworks/ets/ani/ani_common/include/ets_context_utils.h +++ b/frameworks/ets/ani/ani_common/include/ets_context_utils.h @@ -36,6 +36,13 @@ 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); +void NativeGetGroupDir([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_string dataGroupIdObj, ani_object callBackObj); +ani_object NativeCreateDisplayContext(ani_env *env, ani_object aniObj, ani_long displayId); +ani_object NativeCreateAreaModeContext(ani_env *env, ani_object aniObj, ani_object areaModeObj); +ani_object NativeCreateSystemHspModuleResourceManager(ani_env *env, ani_object aniObj, + ani_string bundleNameObj, ani_string moduleNameObj); +ani_object CreateContextObject(ani_env* env, ani_class contextClass, std::shared_ptr nativeContext); } } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/ets/ani/ani_common/include/ets_enviroment_callback.h b/frameworks/ets/ani/ani_common/include/ets_enviroment_callback.h new file mode 100644 index 00000000000..a6942bce3b8 --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ets_enviroment_callback.h @@ -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. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_ENVIRONMENT_CALLBACK_H +#define OHOS_ABILITY_RUNTIME_ETS_ENVIRONMENT_CALLBACK_H + +#include "environment_callback.h" + +#include "ani.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsEnviromentCallback : public EnvironmentCallback, + public std::enable_shared_from_this { +public: + explicit EtsEnviromentCallback(ani_vm *etsVm); + ~EtsEnviromentCallback() override; + void OnConfigurationUpdated(const AppExecFwk::Configuration &config) override; + void OnMemoryLevel(const int level) override; + int32_t Register(ani_object aniCallback); + bool UnRegister(int32_t callbackId); +private: + ani_vm *etsVm_ = nullptr; + std::map enviromentAniCallbacks_; + int32_t serialNumber_ = 0; + std::mutex mutex_; + std::atomic isAttachThread_ = false; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_ENVIRONMENT_CALLBACK_H \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/include/ets_error_utils.h b/frameworks/ets/ani/ani_common/include/ets_error_utils.h index 97ebfc0bf48..015e88e7feb 100644 --- a/frameworks/ets/ani/ani_common/include/ets_error_utils.h +++ b/frameworks/ets/ani/ani_common/include/ets_error_utils.h @@ -35,6 +35,7 @@ public: static void ThrowErrorByNativeErr(ani_env *env, int32_t err); static void ThrowNotSystemAppError(ani_env *env); static void ThrowEtsTransferClassError(ani_env *env); + static void ThrowRuntimeError(ani_env *env, int32_t errCode, const std::string &errMessage = ""); static ani_object CreateError(ani_env *env, const AbilityErrorCode &err); static ani_object CreateError(ani_env *env, ani_int code, const std::string &msg); diff --git a/frameworks/ets/ani/ani_common/include/ets_extension_context.h b/frameworks/ets/ani/ani_common/include/ets_extension_context.h index 1a2d6155dd0..359c6bd95cf 100644 --- a/frameworks/ets/ani/ani_common/include/ets_extension_context.h +++ b/frameworks/ets/ani/ani_common/include/ets_extension_context.h @@ -20,7 +20,16 @@ #include "extension_context.h" namespace OHOS { +namespace AppExecFwk { +struct ETSNativeReference; +} namespace AbilityRuntime { +class EtsExtensionContext final { +public: + static void ConfigurationUpdated(ani_env *env, const std::shared_ptr &EtsContext, + const std::shared_ptr &config); +}; + void CreateEtsExtensionContext(ani_env *aniEnv, ani_class contextClass, ani_object &contextObj, std::shared_ptr context, std::shared_ptr abilityInfo); } // namespace AbilityRuntime diff --git a/frameworks/ets/ani/ani_common/src/ani_common_ability_result.cpp b/frameworks/ets/ani/ani_common/src/ani_common_ability_result.cpp index 105588c8557..6a9fd755dfe 100644 --- a/frameworks/ets/ani/ani_common/src/ani_common_ability_result.cpp +++ b/frameworks/ets/ani/ani_common/src/ani_common_ability_result.cpp @@ -55,8 +55,7 @@ ani_object WrapAbilityResult(ani_env *env, int32_t resultCode, const AAFwk::Want return nullptr; } - ani_double dResultCode {resultCode}; - if ((status = env->Object_CallMethod_Void(resultObj, resultCodeSetter, dResultCode)) != ANI_OK) { + if ((status = env->Object_CallMethod_Void(resultObj, resultCodeSetter, resultCode)) != ANI_OK) { TAG_LOGE(AAFwkTag::ANI, "Object_CallMethod_Void status: %{public}d", status); return nullptr; } 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 index 29abfa3e4e4..ff24c46cfdd 100644 --- 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 @@ -42,23 +42,22 @@ ani_object WrapAbilityStateDataInner(ani_env *env, ani_class cls, ani_object obj return nullptr; } - if (!SetFieldIntByName(env, cls, object, "pid", data.pid)) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "set pid failed"); + ani_status status = ANI_ERROR; + if ((status = env->Object_SetFieldByName_Int(object, "pid", data.pid)) + != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "pid failed status:%{public}d", status); return nullptr; } - - if (!SetFieldIntByName(env, cls, object, "uid", data.uid)) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "set uid failed"); + if ((status = env->Object_SetFieldByName_Int(object, "uid", data.uid)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "uid failed status:%{public}d", status); return nullptr; } - - if (!SetFieldIntByName(env, cls, object, "state", data.abilityState)) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "set state failed"); + if ((status = env->Object_SetFieldByName_Int(object, "state", data.abilityState)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "state failed status:%{public}d", status); return nullptr; } - - if (!SetFieldIntByName(env, cls, object, "abilityType", data.abilityType)) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "set type failed"); + if ((status = env->Object_SetFieldByName_Int(object, "abilityType", data.abilityType)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityType failed status:%{public}d", status); return nullptr; } diff --git a/frameworks/ets/ani/ani_common/src/ani_common_configuration.cpp b/frameworks/ets/ani/ani_common/src/ani_common_configuration.cpp index 345288acdf8..d6a3901d1b5 100644 --- a/frameworks/ets/ani/ani_common/src/ani_common_configuration.cpp +++ b/frameworks/ets/ani/ani_common/src/ani_common_configuration.cpp @@ -50,7 +50,7 @@ void SetBasicConfiguration(ani_env *env, ani_object object, const AppExecFwk::Co env->Object_SetPropertyByName_Ref(object, "colorMode", colorModeItem); int32_t displayId = ConvertDisplayId(configuration.GetItem(ConfigurationInner::APPLICATION_DISPLAYID)); - env->Object_SetPropertyByName_Ref(object, "displayId", CreateDouble(env, static_cast(displayId))); + env->Object_SetPropertyByName_Ref(object, "displayId", CreateLong(env, static_cast(displayId))); std::string direction = configuration.GetItem(displayId, ConfigurationInner::APPLICATION_DIRECTION); ani_enum_item directionItem = nullptr; 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 index 2c624320c1e..31bb5a39576 100644 --- a/frameworks/ets/ani/ani_common/src/ani_common_execute_param.cpp +++ b/frameworks/ets/ani/ani_common/src/ani_common_execute_param.cpp @@ -85,11 +85,11 @@ bool UnwrapExecuteParam(ani_env *env, ani_object param, AppExecFwk::InsightInten static_cast(executeModeRef), executeMode); executeParam.executeMode_ = executeMode; - double displayIdD = 0.0; + ani_long displayIdD = 0; int32_t displayId = INVALID_DISPLAY_ID; if (executeMode == ExecuteMode::UI_ABILITY_FOREGROUND && IsExistsProperty(env, param, "displayId")) { - if (GetDoublePropertyObject(env, param, "displayId", displayIdD)) { + if (GetLongPropertyObject(env, param, "displayId", displayIdD)) { displayId = static_cast(displayIdD); if (displayId < 0) { TAG_LOGE(AAFwkTag::INTENT, "invalid displayId"); @@ -108,12 +108,12 @@ bool UnwrapExecuteParam(ani_env *env, ani_object param, AppExecFwk::InsightInten executeParam.uris_ = uris; } if (IsExistsProperty(env, param, "flags")) { - double flags = 0.0; - if (!GetDoublePropertyObject(env, param, "flags", flags)) { + ani_int flags = 0; + if (!GetIntPropertyObject(env, param, "flags", flags)) { TAG_LOGE(AAFwkTag::INTENT, "Wrong argument flags fail"); return false; } - executeParam.flags_ = static_cast(flags); + executeParam.flags_ = flags; } return true; 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 index 875c6fac091..b1efbe74342 100644 --- a/frameworks/ets/ani/ani_common/src/ani_common_execute_result.cpp +++ b/frameworks/ets/ani/ani_common/src/ani_common_execute_result.cpp @@ -65,12 +65,12 @@ bool UnwrapExecuteResult(ani_env *env, ani_object ¶m, InsightIntentExecuteRe return false; } - ani_double code = 0; - if (!GetDoublePropertyValue(env, param, "code", code)) { + int32_t code = 0; + if (!GetIntPropertyValue(env, param, "code", code)) { TAG_LOGE(AAFwkTag::INTENT, "parse code fail"); return false; } - executeResult.code = static_cast(code); + executeResult.code = code; if (IsExistsProperty(env, param, "result")) { if (!UnwrapResultOfExecuteResult(env, param, executeResult)) { @@ -89,12 +89,12 @@ bool UnwrapExecuteResult(ani_env *env, ani_object ¶m, InsightIntentExecuteRe } if (IsExistsProperty(env, param, "flags")) { - double flags = 0.0; - if (!GetDoublePropertyObject(env, param, "flags", flags)) { + int32_t flags = 0; + if (!GetIntPropertyObject(env, param, "flags", flags)) { TAG_LOGE(AAFwkTag::INTENT, "unwrap flags is null"); return false; } - executeResult.flags = static_cast(flags); + executeResult.flags = flags; } return true; @@ -128,8 +128,8 @@ ani_object WrapExecuteResult(ani_env *env, const AppExecFwk::InsightIntentExecut return nullptr; } - if (!SetDoublePropertyValue(env, objValue, "code", static_cast(executeResult.code))) { - TAG_LOGE(AAFwkTag::INTENT, "SetDoubleProperty failded"); + if (!SetIntPropertyValue(env, objValue, "code", executeResult.code)) { + TAG_LOGE(AAFwkTag::INTENT, "SetIntPropertyValue failded"); return nullptr; } if (executeResult.result != nullptr) { @@ -138,7 +138,7 @@ ani_object WrapExecuteResult(ani_env *env, const AppExecFwk::InsightIntentExecut if (executeResult.uris.size() > 0) { SetStringArrayProperty(env, objValue, "uris", executeResult.uris); } - SetDoublePropertyObject(env, objValue, "flags", static_cast(executeResult.flags)); + SetIntPropertyObject(env, objValue, "flags", executeResult.flags); return objValue; } diff --git a/frameworks/ets/ani/ani_common/src/ani_common_remote.cpp b/frameworks/ets/ani/ani_common/src/ani_common_remote.cpp new file mode 100644 index 00000000000..f74600380b2 --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_remote.cpp @@ -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. + */ + +#include "ani_common_remote.h" + +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +ani_object AniRemote::CreateAniRemoteObject(ani_env *env, const sptr target) +{ + ani_status status = ANI_ERROR; + ani_class cls {}; + ani_method method = nullptr; + if ((status = env->FindClass("L@ohos/rpc/rpc/RemoteProxy;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "FindClass RemoteProxy: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", "l:", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "RemoteProxy ctor: %{public}d", status); + return nullptr; + } + ani_object remoteObj = nullptr; + if ((status = env->Object_New(cls, method, &remoteObj, (ani_long)(target.GetRefPtr()))) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "RemoteProxy create: %{public}d", status); + return nullptr; + } + return remoteObj; +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file 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 f7138f6996c..6df004f26b8 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 @@ -49,58 +49,58 @@ bool UnwrapStartOptionsWithProcessOption(ani_env* env, ani_object param, AAFwk:: 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); + ani_int windowLeft = 0; + if (GetFieldIntByName(env, param, "windowLeft", windowLeft)) { + TAG_LOGD(AAFwkTag::ANI, "windowLeft:%{public}d", 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); + ani_int windowTop = 0; + if (GetFieldIntByName(env, param, "windowTop", windowTop)) { + TAG_LOGD(AAFwkTag::ANI, "windowTop:%{public}d", 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); + ani_int windowWidth = 0; + if (GetFieldIntByName(env, param, "windowWidth", windowWidth)) { + TAG_LOGD(AAFwkTag::ANI, "windowWidth:%{public}d", 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); + ani_int windowHeight = 0; + if (GetFieldIntByName(env, param, "windowHeight", windowHeight)) { + TAG_LOGD(AAFwkTag::ANI, "windowHeight:%{public}d", 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); + ani_int minWindowWidth = 0; + if (GetFieldIntByName(env, param, "minWindowWidth", minWindowWidth)) { + TAG_LOGD(AAFwkTag::ANI, "minWindowWidth:%{public}d", 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); + ani_int minWindowHeight = 0; + if (GetFieldIntByName(env, param, "minWindowHeight", minWindowHeight)) { + TAG_LOGD(AAFwkTag::ANI, "minWindowHeight:%{public}d", 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); + ani_int maxWindowWidth = 0; + if (GetFieldIntByName(env, param, "maxWindowWidth", maxWindowWidth)) { + TAG_LOGD(AAFwkTag::ANI, "maxWindowWidth:%{public}d", 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); + ani_int maxWindowHeight = 0; + if (GetFieldIntByName(env, param, "maxWindowHeight", maxWindowHeight)) { + TAG_LOGD(AAFwkTag::ANI, "maxWindowHeight:%{public}d", maxWindowHeight); startOptions.SetMaxWindowHeight(maxWindowHeight); startOptions.maxWindowHeightUsed_ = true; } @@ -143,14 +143,14 @@ bool UnwrapStartOptions(ani_env *env, ani_object param, AAFwk::StartOptions &sta return false; } - ani_double windowMode = 0.0; - if (GetFieldDoubleByName(env, param, "windowMode", windowMode)) { - TAG_LOGD(AAFwkTag::ANI, "windowMode:%{public}f", windowMode); + ani_int windowMode = 0; + if (GetFieldIntByName(env, param, "windowMode", windowMode)) { + TAG_LOGD(AAFwkTag::ANI, "windowMode:%{public}d", windowMode); startOptions.SetWindowMode(windowMode); } - ani_double displayId = 0.0; - if (GetFieldDoubleByName(env, param, "displayId", displayId)) { + ani_long displayId = 0; + if (GetFieldLongByName(env, param, "displayId", displayId)) { startOptions.SetDisplayID(static_cast(displayId)); } @@ -291,5 +291,29 @@ bool UnwrapStartWindowOption(ani_env *env, ani_object param, startWindowOption = option; return true; } + +bool UnwrapAtomicServiceOptions(ani_env *env, ani_object optionsObj, AAFwk::Want &want, + AAFwk::StartOptions &startOptions) +{ + if (!UnwrapStartOptionsWithProcessOption(env, optionsObj, startOptions)) { + TAG_LOGE(AAFwkTag::ANI, "UnwrapStartOptions filed"); + return false; + } + ani_status status = ANI_ERROR; + ani_ref paramRef = nullptr; + if ((status = env->Object_GetPropertyByName_Ref(optionsObj, "parameters", ¶mRef)) == ANI_OK) { + AAFwk::WantParams wantParam; + if (UnwrapWantParams(env, paramRef, wantParam)) { + want.SetParams(wantParam); + } else { + TAG_LOGE(AAFwkTag::ANI, "UnwrapWantParams failed"); + } + } + int32_t flags = 0; + if (GetIntPropertyObject(env, optionsObj, "flags", flags)) { + want.SetFlags(flags); + } + return true; +} } // 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 f24a6c079c5..be44c24463a 100644 --- a/frameworks/ets/ani/ani_common/src/ani_common_util.cpp +++ b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp @@ -194,15 +194,30 @@ bool SetFieldStringByName(ani_env *env, ani_class cls, ani_object object, const return true; } -bool GetFieldIntByName(ani_env *env, ani_object object, const char *name, int &value) +bool GetFieldIntByName(ani_env *env, ani_object object, const char *name, int32_t &value) { if (env == nullptr) { TAG_LOGE(AAFwkTag::ANI, "null env"); return false; } ani_status status = ANI_ERROR; + ani_ref field = nullptr; + if ((status = env->Object_GetFieldByName_Ref(object, name, &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + ani_boolean isUndefined = ANI_TRUE; + if ((status = env->Reference_IsUndefined(field, &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; + } ani_int aniInt = 0; - if ((status = env->Object_GetFieldByName_Int(object, name, &aniInt)) != ANI_OK) { + if ((status = env->Object_CallMethodByName_Int( + reinterpret_cast(field), "intValue", nullptr, &aniInt)) != ANI_OK) { TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); return false; } @@ -210,7 +225,7 @@ bool GetFieldIntByName(ani_env *env, ani_object object, const char *name, int &v return true; } -bool SetFieldIntByName(ani_env *env, ani_class cls, ani_object object, const char *name, int value) +bool SetFieldIntByName(ani_env *env, ani_class cls, ani_object object, const char *name, int32_t value) { if (env == nullptr) { TAG_LOGE(AAFwkTag::ANI, "null env"); @@ -222,7 +237,67 @@ bool SetFieldIntByName(ani_env *env, ani_class cls, ani_object object, const cha TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); return false; } - if ((status = env->Object_SetField_Int(object, field, value)) != ANI_OK) { + ani_object obj = CreateInt(env, value); + if (obj == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "CreateInt failed"); + return false; + } + if ((status = env->Object_SetField_Ref(object, field, reinterpret_cast(obj))) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + return true; +} + +bool GetFieldLongByName(ani_env *env, ani_object object, const char *name, int64_t &value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + ani_status status = ANI_ERROR; + ani_ref field = nullptr; + if ((status = env->Object_GetFieldByName_Ref(object, name, &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + ani_boolean isUndefined = ANI_TRUE; + if ((status = env->Reference_IsUndefined(field, &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; + } + ani_long aniLong = 0; + if ((status = env->Object_CallMethodByName_Long( + reinterpret_cast(field), "longValue", nullptr, &aniLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + value = static_cast(aniLong); + return true; +} + +bool SetFieldLongByName(ani_env *env, ani_class cls, ani_object object, const char *name, int64_t value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + ani_status status = ANI_ERROR; + ani_field field = nullptr; + if ((status = env->Class_FindField(cls, name, &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + ani_object obj = CreateLong(env, value); + if (obj == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "CreateLong failed"); + return false; + } + if ((status = env->Object_SetField_Ref(object, field, reinterpret_cast(obj))) != ANI_OK) { TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); return false; } @@ -745,11 +820,11 @@ bool SetProcessInformation(ani_env *env, ani_object object, const AppExecFwk::Ru return false; } ani_status status = ANI_OK; - if ((status = env->Object_SetPropertyByName_Double(object, "pid", processInfo.pid_)) != ANI_OK) { + if ((status = env->Object_SetPropertyByName_Int(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) { + if ((status = env->Object_SetPropertyByName_Int(object, "uid", processInfo.uid_)) != ANI_OK) { TAG_LOGE(AAFwkTag::ANI, "uid failed status:%{public}d", status); return false; } @@ -781,9 +856,9 @@ bool SetProcessInformation(ani_env *env, ani_object object, const AppExecFwk::Ru 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) { + if (processInfo.appCloneIndex != -1 && + (status = env->Object_SetPropertyByName_Ref( + object, "appCloneIndex", CreateInt(env, processInfo.appCloneIndex))) != ANI_OK) { TAG_LOGE(AAFwkTag::ANI, "appCloneIndex failed status:%{public}d", status); return false; } @@ -1027,6 +1102,49 @@ bool GetDoublePropertyObject(ani_env *env, ani_object param, const char *name, d } return true; } + +bool GetLongPropertyObject(ani_env *env, ani_object param, const char *name, ani_long &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_Long( + reinterpret_cast(obj), "longValue", nullptr, &value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + return true; +} + +bool GetIntPropertyObject(ani_env *env, ani_object param, const char *name, ani_int &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_Int( + reinterpret_cast(obj), "intValue", 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) { @@ -1044,6 +1162,23 @@ bool GetDoublePropertyValue(ani_env *env, ani_object param, const char *name, do return true; } +bool GetIntPropertyValue(ani_env *env, ani_object param, const char *name, int32_t &value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + + ani_status status = ANI_ERROR; + ani_int res = 0; + if ((status = env->Object_GetPropertyByName_Int(param, name, &res)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + value = res; + return true; +} + bool GetRefProperty(ani_env *env, ani_object param, const char *name, ani_ref &value) { if (env == nullptr) { @@ -1065,6 +1200,29 @@ bool GetRefProperty(ani_env *env, ani_object param, const char *name, ani_ref &v return !isUndefined; } +bool GetBooleanPropertyObject(ani_env *env, ani_object param, const char *name, bool &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; + } + ani_boolean aniValue = ANI_FALSE; + if ((status = env->Object_CallMethodByName_Boolean( + reinterpret_cast(obj), "unboxed", nullptr, &aniValue)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + value = aniValue; + return true; +} + bool SetDoublePropertyObject(ani_env *env, ani_object param, const char *name, double value) { if (env == nullptr) { @@ -1101,6 +1259,42 @@ bool SetDoublePropertyValue(ani_env *env, ani_object param, const char *name, do return true; } +bool SetIntPropertyObject(ani_env *env, ani_object param, const char *name, int32_t value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + + ani_object obj = CreateInt(env, 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 SetIntPropertyValue(ani_env *env, ani_object param, const char *name, int32_t value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return false; + } + + ani_status status = ANI_ERROR; + if ((status = env->Object_SetPropertyByName_Int(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) { @@ -1205,5 +1399,38 @@ bool GetStaticFieldString(ani_env *env, ani_class classObj, const char *fieldNam } return true; } + +ani_env *AttachAniEnv(ani_vm * etsVm, bool &isAttachThread) +{ + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if (etsVm == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "etsVm is null"); + return nullptr; + } + if ((status = etsVm->GetEnv(ANI_VERSION_1, &env)) == ANI_OK) { + return env; + } + ani_option interopEnabled { "--interop=disable", nullptr }; + ani_options aniArgs { 1, &interopEnabled }; + if ((status = etsVm->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + return nullptr; + } + isAttachThread = true; + return env; +} + +void DetachAniEnv(ani_vm * etsVm, bool &isAttachThread) +{ + if (isAttachThread) { + if (etsVm == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "etsVm is null"); + return; + } + etsVm->DetachCurrentThread(); + isAttachThread = false; + } +} } // 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 d0bb2b35e68..382c38a59cd 100644 --- a/frameworks/ets/ani/ani_common/src/ani_common_want.cpp +++ b/frameworks/ets/ani/ani_common/src/ani_common_want.cpp @@ -41,6 +41,7 @@ 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/ElementNameInner/ElementNameInner;"; +const int PROPERTIES_SIZE = 2; bool InnerWrapWantParams(ani_env* env, ani_class wantCls, ani_object wantObject, const AAFwk::WantParams& wantParams) { @@ -52,6 +53,16 @@ bool InnerWrapWantParams(ani_env* env, ani_class wantCls, ani_object wantObject, return SetFieldRefByName(env, wantCls, wantObject, "parameters", wantParamRef); } +bool InnerWrapWantParamsFD(ani_env *env, ani_class wantCls, ani_object wantObject, const AAFwk::WantParams &wantParams) +{ + ani_ref wantParamFDRef = WrapWantParamsFD(env, wantParams); + if (wantParamFDRef == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "failed to WrapWantParamsFD"); + return false; + } + return SetFieldRefByName(env, wantCls, wantObject, "fds", wantParamFDRef); +} + bool InnerUnwrapWantParams(ani_env* env, ani_object wantObject, AAFwk::WantParams& wantParams) { ani_ref wantParamRef = nullptr; @@ -102,14 +113,61 @@ ani_object WrapWant(ani_env *env, const AAFwk::Want &want) SetFieldStringByName(env, cls, object, "moduleName", elementName.GetModuleName()); SetFieldStringByName(env, cls, object, "uri", want.GetUriString()); SetFieldStringByName(env, cls, object, "type", want.GetType()); - SetFieldDoubleByName(env, cls, object, "flags", want.GetFlags()); + SetFieldIntByName(env, cls, object, "flags", want.GetFlags()); SetFieldStringByName(env, cls, object, "action", want.GetAction()); InnerWrapWantParams(env, cls, object, want.GetParams()); + InnerWrapWantParamsFD(env, cls, object, want.GetParams()); SetFieldArrayStringByName(env, cls, object, "entities", want.GetEntities()); return object; } +ani_ref WrapWantParamsFD(ani_env *env, const AAFwk::WantParams &wantParams) +{ + auto paramList = wantParams.GetParams(); + AAFwk::WantParams fds; + for (auto it = paramList.begin(); it != paramList.end(); it++) { + if (AAFwk::IWantParams::Query(it->second) == nullptr) { + TAG_LOGW(AAFwkTag::ANI, "not wantParam"); + continue; + } + auto value = wantParams.GetParam(it->first); + AAFwk::IWantParams *o = AAFwk::IWantParams::Query(value); + if (o == nullptr) { + return nullptr; + } + AAFwk::WantParams wp = AAFwk::WantParamWrapper::Unbox(o); + auto valueMap = wp.GetParams(); + if (valueMap.size() != PROPERTIES_SIZE) { + TAG_LOGD(AAFwkTag::ANI, "not fd"); + return nullptr; + } + auto typeIt = valueMap.find(AAFwk::TYPE_PROPERTY); + if (typeIt == valueMap.end()) { + return nullptr; + } + AAFwk::IString *strValue = AAFwk::IString::Query(typeIt->second); + if (strValue == nullptr) { + return nullptr; + } + std::string typeString = AAFwk::String::Unbox(strValue); + if (typeString != AAFwk::FD) { + TAG_LOGD(AAFwkTag::ANI, "not fd"); + return nullptr; + } + auto valueIt = valueMap.find(AAFwk::VALUE_PROPERTY); + if (valueIt == valueMap.end()) { + return nullptr; + } + AAFwk::IInteger *intValue = AAFwk::IInteger::Query(valueIt->second); + if (intValue == nullptr) { + return nullptr; + } + fds.SetParam(it->first, intValue); + } + return WrapWantParams(env, fds); +} + ani_ref WrapWantParams(ani_env *env, const AAFwk::WantParams &wantParams) { if (env == nullptr) { @@ -210,10 +268,10 @@ bool UnwrapWant(ani_env *env, ani_object param, AAFwk::Want &want) want.SetUri(uri); } - double flags = 0.0; - if (GetFieldDoubleByName(env, param, "flags", flags)) { - TAG_LOGD(AAFwkTag::ANI, "flags %{public}f", flags); - want.SetFlags(static_cast(flags)); + int32_t flags = 0; + if (GetFieldIntByName(env, param, "flags", flags)) { + TAG_LOGD(AAFwkTag::ANI, "flags %{public}d", flags); + want.SetFlags(flags); } std::string type = ""; @@ -309,13 +367,13 @@ bool GetResultCode(ani_env *env, ani_object param, ani_class cls, int &resultCod TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); return false; } - ani_double dResultCode = 0.0; - status = env->Object_CallMethod_Double(param, method, &dResultCode); + ani_int iResultCode = 0; + status = env->Object_CallMethod_Int(param, method, &iResultCode); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); return false; } - resultCode = static_cast(dResultCode); + resultCode = static_cast(iResultCode); return true; } diff --git a/frameworks/ets/ani/ani_common/src/ani_task.cpp b/frameworks/ets/ani/ani_common/src/ani_task.cpp new file mode 100644 index 00000000000..2a047bfc98e --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_task.cpp @@ -0,0 +1,51 @@ +/* + * 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_task.h" + +#include +#include + +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +std::shared_ptr AniTask::mainHandler_ = nullptr; + +ani_status AniTask::AniSendEvent(const std::function task) +{ + TAG_LOGD(AAFwkTag::ANI, "AniSendEvent"); + if (task == nullptr) { + TAG_LOGD(AAFwkTag::ANI, "null task"); + return ani_status::ANI_INVALID_ARGS; + } + + if (!mainHandler_) { + std::shared_ptr runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner(); + if (!runner) { + TAG_LOGD(AAFwkTag::ANI, "null EventRunner"); + return ani_status::ANI_NOT_FOUND; + } + mainHandler_ = std::make_shared(runner); + } + if (mainHandler_ == nullptr) { + TAG_LOGD(AAFwkTag::ANI, "null mainHandler"); + return ani_status::ANI_NOT_FOUND; + } + mainHandler_->PostTask(std::move(task)); + return ani_status::ANI_OK; +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file 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 f2a0b9ddf19..06e10ce8755 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 @@ -28,6 +28,7 @@ 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; +constexpr int32_t ERROR_ID = -1; } void EtsApplicationContextUtils::Clean(ani_env *env, ani_object object) { @@ -47,6 +48,196 @@ void EtsApplicationContextUtils::Clean(ani_env *env, ani_object object) } } +ani_int EtsApplicationContextUtils::OnNativeOnEnvironmentSync(ani_env *env, ani_object aniObj, + ani_object envCallback) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "env is nullptr"); + return ERROR_ID; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "nativeContext is null"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return ERROR_ID; + } + if (etsEnviromentCallback_ != nullptr) { + return etsEnviromentCallback_->Register(envCallback); + } + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "get aniVM failed"); + return ERROR_ID; + } + etsEnviromentCallback_ = std::make_shared(aniVM); + int32_t callbackId = etsEnviromentCallback_->Register(envCallback); + applicationContext->RegisterEnvironmentCallback(etsEnviromentCallback_); + + return callbackId; +} + +void EtsApplicationContextUtils::OnNativeOffEnvironmentSync(ani_env *env, ani_object aniObj, + ani_int callbackId, ani_object callback) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "env is nullptr"); + return; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "nativeContext is null"); + AppExecFwk::AsyncCallback(env, callback, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM), nullptr); + return; + } + + if (etsEnviromentCallback_ == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "etsEnviromentCallback is null"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, + (ani_int)AbilityErrorCode::ERROR_CODE_INVALID_PARAM, "env_callback is nullptr"), nullptr); + return; + } + + if (!etsEnviromentCallback_->UnRegister(callbackId)) { + TAG_LOGE(AAFwkTag::APPKIT, "call UnRegister failed"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, + (ani_int)AbilityErrorCode::ERROR_CODE_INVALID_PARAM, "call UnRegister failed!"), nullptr); + return; + } + + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK), nullptr); +} + +void EtsApplicationContextUtils::OnNativeOnApplicationStateChangeSync(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"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return; + } + if (applicationStateCallback_ != nullptr) { + applicationStateCallback_->Register(callback); + return; + } + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "get aniVM failed"); + return; + } + applicationStateCallback_ = std::make_shared(aniVM); + applicationStateCallback_->Register(callback); + applicationContext->RegisterApplicationStateChangeCallback(applicationStateCallback_); +} + +void EtsApplicationContextUtils::OnNativeOffApplicationStateChangeSync(ani_env *env, ani_object aniObj, + ani_object callback) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + if (applicationStateCallback_ == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationStateCallback_"); + EtsErrorUtil::ThrowInvalidParamError( + env, "Parse applicationStateCallback failed, applicationStateCallback must be function."); + return; + } + ani_boolean isUndefined = true; + env->Reference_IsUndefined(callback, &isUndefined); + if (isUndefined) { + applicationStateCallback_->UnRegister(); + } else if (!applicationStateCallback_->UnRegister(callback)) { + TAG_LOGE(AAFwkTag::APPKIT, "call UnRegister failed"); + EtsErrorUtil::ThrowInvalidParamError(env, + "Parse param call UnRegister failed, call UnRegister must be function."); + return; + } + if (applicationStateCallback_->IsEmpty()) { + applicationStateCallback_.reset(); + } +} + +ani_int EtsApplicationContextUtils::OnGetCurrentAppCloneIndex(ani_env *env, ani_object aniObj) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return ANI_ERROR; + } + auto context = applicationContext_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return ANI_ERROR; + } + if (context->GetCurrentAppMode() != static_cast(AppExecFwk::MultiAppModeType::APP_CLONE)) { + TAG_LOGE(AAFwkTag::APPKIT, "not clone"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_NOT_APP_CLONE); + return ANI_ERROR; + } + int32_t appIndex = context->GetCurrentAppCloneIndex(); + return appIndex; +} + +ani_string EtsApplicationContextUtils::OnGetCurrentInstanceKey(ani_env *env, ani_object aniObj) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return nullptr; + } + auto context = applicationContext_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return nullptr; + } + if (context->GetCurrentAppMode() != static_cast(AppExecFwk::MultiAppModeType::MULTI_INSTANCE)) { + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_MULTI_INSTANCE_NOT_SUPPORTED); + TAG_LOGE(AAFwkTag::APPKIT, "not support"); + return nullptr; + } + std::string instanceKey = context->GetCurrentInstanceKey(); + return AppExecFwk::GetAniString(env, instanceKey); +} + +void EtsApplicationContextUtils::OnGetAllRunningInstanceKeys(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); + std::vector instanceKeys; + auto applicationContext = applicationContext_.lock(); + if (!applicationContext) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, + AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT), emptyArray); + return; + } + if (applicationContext->GetCurrentAppMode() != static_cast(AppExecFwk::MultiAppModeType::MULTI_INSTANCE)) { + TAG_LOGE(AAFwkTag::APPKIT, "not supported"); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateErrorByNativeErr(env, + AAFwk::ERR_MULTI_INSTANCE_NOT_SUPPORTED), emptyArray); + return; + } + ErrCode innerErrCode = applicationContext->GetAllRunningInstanceKeys(instanceKeys); + if (innerErrCode != ERR_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "innerErrCode=%{public}d", innerErrCode); + AppExecFwk::AsyncCallback(env, callback, + EtsErrorUtil::CreateErrorByNativeErr(env, (int32_t)innerErrCode), emptyArray); + return; + } + ani_object stringArray; + AppExecFwk::WrapArrayString(env, stringArray, instanceKeys); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK), stringArray); +} + void EtsApplicationContextUtils::OnRestartApp(ani_env *env, ani_object aniObj, ani_object wantObj) { if (env == nullptr) { @@ -408,6 +599,86 @@ void EtsApplicationContextUtils::SetSupportedProcessCacheSync(ani_env *env, ani_ etsContext->OnSetSupportedProcessCacheSync(env, aniObj, value); } +ani_int EtsApplicationContextUtils::NativeOnEnvironmentSync(ani_env *env, ani_object aniObj, ani_object envCallback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "NativeOnEnvironmentSync Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return ANI_ERROR; + } + return etsContext->OnNativeOnEnvironmentSync(env, aniObj, envCallback); +} + +void EtsApplicationContextUtils::NativeOffEnvironmentSync(ani_env *env, ani_object aniObj, + ani_int callbackId, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "NativeOffEnvironmentSync Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return; + } + etsContext->OnNativeOffEnvironmentSync(env, aniObj, callbackId, callback); +} + +void EtsApplicationContextUtils::NativeOnApplicationStateChangeSync(ani_env *env, ani_object aniObj, + ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "NativeOnApplicationStateChangeSync Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return; + } + etsContext->OnNativeOnApplicationStateChangeSync(env, aniObj, callback); +} + +void EtsApplicationContextUtils::NativeOffApplicationStateChangeSync(ani_env *env, ani_object aniObj, + ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "NativeOffApplicationStateChangeSync Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return; + } + etsContext->OnNativeOffApplicationStateChangeSync(env, aniObj, callback); +} + +void EtsApplicationContextUtils::GetAllRunningInstanceKeys(ani_env *env, ani_object aniObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "GetAllRunningInstanceKeys Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return; + } + etsContext->OnGetAllRunningInstanceKeys(env, aniObj, callback); +} + +ani_string EtsApplicationContextUtils::GetCurrentInstanceKey(ani_env *env, ani_object aniObj) +{ + TAG_LOGD(AAFwkTag::APPKIT, "GetCurrentInstanceKey Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return nullptr; + } + return etsContext->OnGetCurrentInstanceKey(env, aniObj); +} + +ani_int EtsApplicationContextUtils::GetCurrentAppCloneIndex(ani_env *env, ani_object aniObj) +{ + TAG_LOGD(AAFwkTag::APPKIT, "GetCurrentAppCloneIndex Call"); + auto etsContext = GeApplicationContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null etsContext"); + return ANI_ERROR; + } + return etsContext->OnGetCurrentAppCloneIndex(env, aniObj); +} + EtsApplicationContextUtils* EtsApplicationContextUtils::GeApplicationContext(ani_env *env, ani_object aniObj) { if (env == nullptr || aniObj == nullptr) { @@ -424,7 +695,7 @@ EtsApplicationContextUtils* EtsApplicationContextUtils::GeApplicationContext(ani return etsContext; } -ani_object EtsApplicationContextUtils::SetApplicationContext(ani_env* aniEnv, +ani_object EtsApplicationContextUtils::SetApplicationContext(ani_env *aniEnv, const std::shared_ptr &applicationContext) { TAG_LOGD(AAFwkTag::APPKIT, "SetApplicationContext Call"); @@ -474,7 +745,7 @@ ani_object EtsApplicationContextUtils::SetApplicationContext(ani_env* aniEnv, return contextObj; } -void EtsApplicationContextUtils::BindApplicationContextFunc(ani_env* aniEnv) +void EtsApplicationContextUtils::BindApplicationContextFunc(ani_env *aniEnv) { if (aniEnv == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null aniEnv"); @@ -512,6 +783,23 @@ void EtsApplicationContextUtils::BindApplicationContextFunc(ani_env* aniEnv) reinterpret_cast(EtsApplicationContextUtils::SetFont)}, ani_native_function {"nativerestartApp", "L@ohos/app/ability/Want/Want;:V", reinterpret_cast(EtsApplicationContextUtils::RestartApp)}, + ani_native_function {"nativeOnEnvironmentSync", + "L@ohos/app/ability/EnvironmentCallback/EnvironmentCallback;:I", + reinterpret_cast(EtsApplicationContextUtils::NativeOnEnvironmentSync)}, + ani_native_function {"nativeOffEnvironmentSync", "ILutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplicationContextUtils::NativeOffEnvironmentSync)}, + ani_native_function {"nativeOnApplicationStateChangeSync", + "L@ohos/app/ability/ApplicationStateChangeCallback/ApplicationStateChangeCallback;:V", + reinterpret_cast(EtsApplicationContextUtils::NativeOnApplicationStateChangeSync)}, + ani_native_function {"nativeOffApplicationStateChangeSync", + "L@ohos/app/ability/ApplicationStateChangeCallback/ApplicationStateChangeCallback;:V", + reinterpret_cast(EtsApplicationContextUtils::NativeOffApplicationStateChangeSync)}, + ani_native_function {"nativeGetAllRunningInstanceKeys", "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplicationContextUtils::GetAllRunningInstanceKeys)}, + ani_native_function{"nativegetCurrentInstanceKey", ":Lstd/core/String;", + reinterpret_cast(EtsApplicationContextUtils::GetCurrentInstanceKey)}, + ani_native_function {"nativegetCurrentAppCloneIndex", ":I", + reinterpret_cast(EtsApplicationContextUtils::GetCurrentAppCloneIndex)}, }; if ((status = aniEnv->Class_BindNativeMethods(contextClass, applicationContextFunctions.data(), applicationContextFunctions.size())) != ANI_OK) { @@ -534,7 +822,7 @@ void EtsApplicationContextUtils::BindApplicationContextFunc(ani_env* aniEnv) }); } -ani_object EtsApplicationContextUtils::CreateEtsApplicationContext(ani_env* aniEnv, +ani_object EtsApplicationContextUtils::CreateEtsApplicationContext(ani_env *aniEnv, const std::shared_ptr &applicationContext) { TAG_LOGD(AAFwkTag::APPKIT, "CreateEtsApplicationContext Call"); diff --git a/frameworks/ets/ani/ani_common/src/ets_application_state_change_callback.cpp b/frameworks/ets/ani/ani_common/src/ets_application_state_change_callback.cpp new file mode 100644 index 00000000000..00d80618555 --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ets_application_state_change_callback.cpp @@ -0,0 +1,176 @@ +/* + * 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_state_change_callback.h" + +#include "ani_common_util.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* APPLICATION_STATE_CHANGE_CALLBACK = + "L@ohos/app/ability/ApplicationStateChangeCallback/ApplicationStateChangeCallbackInner;"; +} + +EtsApplicationStateChangeCallback::EtsApplicationStateChangeCallback(ani_vm *etsVm) : etsVm_(etsVm) {} + +EtsApplicationStateChangeCallback::~EtsApplicationStateChangeCallback() +{ + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed"); + return; + } + ani_status status = ANI_ERROR; + { + std::lock_guard lock(mutex_); + for (auto &callback : callbacks_) { + if (!callback) { + TAG_LOGE(AAFwkTag::APPKIT, "Invalid aniCallback"); + continue; + } + if ((status = env->GlobalReference_Delete(callback)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "GlobalReference_Delete status: %{public}d", status); + } + } + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +}; + +void EtsApplicationStateChangeCallback::CallEtsMethod(const std::string &methodName) +{ + TAG_LOGD(AAFwkTag::APPKIT, "MethodName = %{public}s", methodName.c_str()); + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed"); + return; + } + ani_class cls {}; + ani_status status = ANI_ERROR; + status = env->FindClass(APPLICATION_STATE_CHANGE_CALLBACK, &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "FindClass status: %{public}d", status); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_method method {}; + if ((status = env->Class_FindMethod(cls, methodName.c_str(), nullptr, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_FindMethod status: %{public}d", status); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + { + std::lock_guard lock(mutex_); + for (auto &callback : callbacks_) { + if ((status = env->Object_CallMethod_Void(reinterpret_cast(callback), method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_CallMethod_Void status: %{public}d", status); + } + } + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +void EtsApplicationStateChangeCallback::NotifyApplicationForeground() +{ + CallEtsMethod("onApplicationForeground"); +} + +void EtsApplicationStateChangeCallback::NotifyApplicationBackground() +{ + CallEtsMethod("onApplicationBackground"); +} + +void EtsApplicationStateChangeCallback::Register(ani_object aniCallback) +{ + if (aniCallback == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env or aniCallback"); + return; + } + ani_ref aniCallbackRef = nullptr; + ani_status status = ANI_ERROR; + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed"); + return; + } + if ((status = env->GlobalReference_Create(aniCallback, &aniCallbackRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "GlobalReference_Create status : %{public}d", status); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + { + std::lock_guard lock(mutex_); + callbacks_.emplace(aniCallbackRef); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +bool EtsApplicationStateChangeCallback::UnRegister(ani_object aniCallback) +{ + ani_status status = ANI_ERROR; + std::lock_guard lock(mutex_); + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed"); + return false; + } + if (aniCallback == nullptr) { + TAG_LOGI(AAFwkTag::APPKIT, "null aniCallback"); + for (auto &callback : callbacks_) { + if (!callback) { + TAG_LOGE(AAFwkTag::APPKIT, "Invalid aniCallback"); + continue; + } + if ((status = env->GlobalReference_Delete(callback)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "GlobalReference_Delete status: %{public}d", status); + } + } + callbacks_.clear(); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return true; + } + for (auto &callback : callbacks_) { + if (!callback) { + TAG_LOGE(AAFwkTag::APPKIT, "Invalid aniCallback"); + continue; + } + ani_boolean isEqual = false; + env->Reference_StrictEquals(aniCallback, callback, &isEqual); + if (isEqual) { + if ((status = env->GlobalReference_Delete(callback)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "GlobalReference_Delete status: %{public}d", status); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return false; + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return callbacks_.erase(callback) == 1; + } + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return false; +} + +bool EtsApplicationStateChangeCallback::IsEmpty() const +{ + std::lock_guard lock(mutex_); + return callbacks_.empty(); +} +} // namespace AbilityRuntime +} // namespace OHOS 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 695ae6fa468..67cd9211672 100644 --- a/frameworks/ets/ani/ani_common/src/ets_context_utils.cpp +++ b/frameworks/ets/ani/ani_common/src/ets_context_utils.cpp @@ -17,6 +17,7 @@ #include "ani_common_util.h" #include "ani_enum_convert.h" +#include "ability_runtime_error_util.h" #include "application_context.h" #include "application_context_manager.h" #include "common_fun_ani.h" @@ -37,6 +38,44 @@ 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 BindContextDirInner(ani_env *aniEnv, ani_object contextObj, std::shared_ptr context) +{ + ani_status status = ANI_ERROR; + auto cloudFileDir = context->GetCloudFileDir(); + ani_string cloudFileDirString = nullptr; + aniEnv->String_NewUTF8(cloudFileDir.c_str(), cloudFileDir.size(), &cloudFileDirString); + if ((status = aniEnv->Object_SetFieldByName_Ref(contextObj, "cloudFileDir", cloudFileDirString)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "cloudFileDir SetField status: %{public}d", status); + return; + } + + auto distributedFilesDir = context->GetDistributedFilesDir(); + ani_string distributedFilesDirString = nullptr; + aniEnv->String_NewUTF8(distributedFilesDir.c_str(), distributedFilesDir.size(), &distributedFilesDirString); + if ((status = aniEnv->Object_SetFieldByName_Ref(contextObj, "distributedFilesDir", + distributedFilesDirString)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "distributedFilesDir SetField status: %{public}d", status); + return; + } + + auto bundleCodeDir = context->GetBundleCodeDir(); + ani_string bundleCodeDirString = nullptr; + aniEnv->String_NewUTF8(bundleCodeDir.c_str(), bundleCodeDir.size(), &bundleCodeDirString); + if ((status = aniEnv->Object_SetFieldByName_Ref(contextObj, "bundleCodeDir", bundleCodeDirString)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "bundleCodeDir SetField status: %{public}d", status); + return; + } + + auto resourceDir = context->GetResourceDir(); + ani_string resourceDirString = nullptr; + aniEnv->String_NewUTF8(resourceDir.c_str(), resourceDir.size(), &resourceDirString); + if ((status = aniEnv->Object_SetFieldByName_Ref(contextObj, "resourceDir", resourceDirString)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "resourceDir SetField status: %{public}d", status); + return; + } +} + void BindContextDir(ani_env *aniEnv, ani_object contextObj, std::shared_ptr context) { if (aniEnv == nullptr || context == nullptr) { @@ -83,6 +122,7 @@ void BindContextDir(ani_env *aniEnv, ani_object contextObj, std::shared_ptrClass_FindField(contextClass, "processName", &processNameField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "find processName failed status: %{public}d", status); + return; + } + auto processName = context->GetProcessName(); + ani_string processNameString = nullptr; + aniEnv->String_NewUTF8(processName.c_str(), processName.size(), &processNameString); + if ((status = aniEnv->Object_SetField_Ref(contextObj, processNameField, + reinterpret_cast(processNameString))) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_SetField_Ref failed, status: %{public}d", status); + return; + } } void BindNativeFunction(ani_env *aniEnv) @@ -209,14 +263,24 @@ void BindNativeFunction(ani_env *aniEnv) std::call_once(g_bindNativeMethodsFlag, [&status, aniEnv, contextCls]() { std::array contextFunctions = { ani_native_function {"getApplicationContextSync", ":Lapplication/ApplicationContext/ApplicationContext;", - reinterpret_cast(AbilityRuntime::ContextUtil::GetApplicationContextSync)}, + reinterpret_cast(ContextUtil::GetApplicationContextSync)}, ani_native_function {"switchArea", nullptr, - reinterpret_cast(AbilityRuntime::ContextUtil::SwitchArea)}, + reinterpret_cast(ContextUtil::SwitchArea)}, ani_native_function {"getArea", nullptr, - reinterpret_cast(AbilityRuntime::ContextUtil::GetArea)}, + reinterpret_cast(ContextUtil::GetArea)}, ani_native_function {"createModuleResourceManagerSync", "Lstd/core/String;Lstd/core/String;" ":L@ohos/resourceManager/resourceManager/ResourceManager;", - reinterpret_cast(AbilityRuntime::ContextUtil::CreateModuleResourceManagerSync)}, + reinterpret_cast(ContextUtil::CreateModuleResourceManagerSync)}, + ani_native_function {"nativeGetGroupDir", nullptr, + reinterpret_cast(ContextUtil::NativeGetGroupDir)}, + ani_native_function {"nativeCreateDisplayContext", "J:Lapplication/Context/Context;", + reinterpret_cast(ContextUtil::NativeCreateDisplayContext)}, + ani_native_function {"nativeCreateAreaModeContext", + "L@ohos/app/ability/contextConstant/contextConstant/AreaMode;:Lapplication/Context/Context;", + reinterpret_cast(ContextUtil::NativeCreateAreaModeContext)}, + ani_native_function {"nativeCreateSystemHspModuleResourceManager", "Lstd/core/String;Lstd/core/String;" + ":L@ohos/resourceManager/resourceManager/ResourceManager;", + reinterpret_cast(ContextUtil::NativeCreateSystemHspModuleResourceManager)}, }; status = aniEnv->Class_BindNativeMethods(contextCls, contextFunctions.data(), contextFunctions.size()); @@ -343,6 +407,210 @@ ani_object CreateModuleResourceManagerSync(ani_env *env, ani_object aniObj, return Global::Resource::ResMgrAddon::CreateResMgr(env, "", resourceManager, context); } +void NativeGetGroupDir([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_string dataGroupIdObj, ani_object callBackObj) +{ + TAG_LOGD(AAFwkTag::APPKIT, "NativeGetGroupDir"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "env is nullptr"); + return; + } + std::string dataGroupId = ""; + if (!AppExecFwk::GetStdString(env, dataGroupIdObj, dataGroupId)) { + TAG_LOGE(AAFwkTag::APPKIT, "Parse groupId failed"); + AppExecFwk::AsyncCallback(env, callBackObj, EtsErrorUtil::CreateError(env, + AbilityErrorCode::ERROR_CODE_INVALID_PARAM), nullptr); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param groupId failed, groupId must be string."); + return; + } + auto context = GetBaseContext(env, aniObj); + if (!context) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + AppExecFwk::AsyncCallback(env, callBackObj, EtsErrorUtil::CreateError(env, + AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT), nullptr); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return; + } + ErrCode ret = ERR_OK; + std::string path = context->GetGroupDir(dataGroupId); + ani_object errorObject = EtsErrorUtil::CreateError(env, static_cast(ret)); + ani_string aniPath = AppExecFwk::GetAniString(env, path); + AppExecFwk::AsyncCallback(env, callBackObj, errorObject, aniPath); +} + +ani_object NativeCreateDisplayContext(ani_env *env, ani_object aniObj, ani_long displayId) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "NativeCreateDisplayContext"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return nullptr; + } + ani_ref undefRef = nullptr; + ani_status status = env->GetUndefined(&undefRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "GetUndefined failed %{public}d", status); + return nullptr; + } +#ifdef SUPPORT_GRAPHICS + auto context = GetBaseContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + EtsErrorUtil::ThrowRuntimeError(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER); + return reinterpret_cast(undefRef); + } + if (displayId < 0) { + TAG_LOGE(AAFwkTag::APPKIT, "displayId is invalid, less than 0"); + EtsErrorUtil::ThrowRuntimeError(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER); + return reinterpret_cast(undefRef); + } + uint64_t validDisplayId = static_cast(displayId); + auto displayContext = context->CreateDisplayContext(validDisplayId); + if (displayContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "Failed to create displayContext"); + return reinterpret_cast(undefRef); + } + ani_class contextClass = nullptr; + status = env->FindClass(CONTEXT_CLASS_NAME, &contextClass); + if (status != ANI_OK || contextClass == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "FindClass Context failed, status: %{public}d", status); + EtsErrorUtil::ThrowInvalidParamError(env, "FindClass failed"); + return reinterpret_cast(undefRef); + } + ani_object displayContextObj = CreateContextObject(env, contextClass, displayContext); + if (displayContextObj == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null contextObj"); + return reinterpret_cast(undefRef); + } + return displayContextObj; +#else + return reinterpret_cast(undefRef); +#endif +} + +ani_object NativeCreateAreaModeContext(ani_env *env, ani_object aniObj, ani_object areaModeObj) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "NativeCreateAreaModeContext"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return nullptr; + } + ani_ref undefRef = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GetUndefined(&undefRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "GetUndefined failed %{public}d", status); + return nullptr; + } + auto context = GetBaseContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return reinterpret_cast(undefRef); + } + int areaMode = 0; + if (!AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative(env, areaModeObj, areaMode)) { + TAG_LOGE(AAFwkTag::APPMGR, "param areaMode err"); + EtsErrorUtil::ThrowInvalidNumParametersError(env); + return reinterpret_cast(undefRef); + } + auto areaContext = context->CreateAreaModeContext(areaMode); + if (areaContext == nullptr) { + EtsErrorUtil::ThrowError(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER); + TAG_LOGE(AAFwkTag::APPKIT, "Failed to create areaContext"); + return reinterpret_cast(undefRef); + } + ani_class contextClass = nullptr; + if ((status = env->FindClass(CONTEXT_CLASS_NAME, &contextClass)) != ANI_OK || contextClass == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "FindClass Context failed status: %{public}d", status); + EtsErrorUtil::ThrowInvalidParamError(env, "FindClass failed"); + return reinterpret_cast(undefRef); + } + ani_object areaContextObj = CreateContextObject(env, contextClass, areaContext); + if (areaContextObj == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null areaContextObj"); + return reinterpret_cast(undefRef); + } + return areaContextObj; +} + +ani_object NativeCreateSystemHspModuleResourceManager(ani_env *env, ani_object aniObj, + ani_string bundleNameObj, ani_string moduleNameObj) +{ + TAG_LOGE(AAFwkTag::UIABILITY, "NativeCreateSystemHspModuleResourceManager"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "env is nullptr"); + return nullptr; + } + ani_ref undefRef = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GetUndefined(&undefRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "GetUndefined failed %{public}d", status); + return nullptr; + } + auto context = GetBaseContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return reinterpret_cast(undefRef); + } + std::string bundleName = ""; + if (!AppExecFwk::GetStdString(env, bundleNameObj, bundleName)) { + TAG_LOGE(AAFwkTag::APPKIT, "Parse bundleName failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param bundleName failed, bundleName must be string."); + return reinterpret_cast(undefRef); + } + std::string moduleName = ""; + if (!AppExecFwk::GetStdString(env, moduleNameObj, moduleName)) { + TAG_LOGE(AAFwkTag::APPKIT, "Parse moduleName failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param moduleName failed, moduleName must be string."); + return reinterpret_cast(undefRef); + } + std::shared_ptr resourceManager = nullptr; + int32_t retCode = context->CreateSystemHspModuleResourceManager(bundleName, moduleName, resourceManager); + if (resourceManager == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null resourceManager, errorCode:%{public}d", retCode); + EtsErrorUtil::ThrowError(env, retCode); + return reinterpret_cast(undefRef); + } + return Global::Resource::ResMgrAddon::CreateResMgr(env, "", resourceManager, context); +} + +ani_object CreateContextObject(ani_env* env, ani_class contextClass, std::shared_ptr nativeContext) +{ + ani_object contextObj = nullptr; + ani_method ctorMethod = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->Class_FindMethod(contextClass, "", ":V", &ctorMethod)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Find ctor method failed, status: %{public}d", status); + return nullptr; + } + if (ctorMethod == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null ctorMethod"); + return nullptr; + } + if ((status = env->Object_New(contextClass, ctorMethod, &contextObj)) != ANI_OK || contextObj == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_New failed, status: %{public}d", status); + return nullptr; + } + CreateEtsBaseContext(env, contextClass, contextObj, nativeContext); + ani_field contextField; + if ((status = env->Class_FindField(contextClass, "nativeContext", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "call Class_FindField nativeContext failed"); + return nullptr; + } + auto workContext = new (std::nothrow) std::weak_ptr(nativeContext); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "workContext nullptr"); + return nullptr; + } + ani_long nativeContextLong = (ani_long)workContext; + if ((status = env->Object_SetField_Long(contextObj, contextField, nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "call Object_SetField_Long contextField failed"); + delete workContext; + return nullptr; + } + return contextObj; +} + ani_object GetApplicationContext(ani_env *env, const std::shared_ptr applicationContext) { if (env == nullptr) { 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 2cb892fa9ac..9f273c9c825 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 @@ -71,14 +71,14 @@ ani_object CreateEtsLastExitDetailInfo(ani_env* env, const AAFwk::LastExitDetail TAG_LOGE(AAFwkTag::ETSRUNTIME, "null object"); return nullptr; } - env->Object_SetPropertyByName_Double(object, "pid", lastExitDetailInfo.pid); + env->Object_SetPropertyByName_Int(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_Int(object, "uid", lastExitDetailInfo.uid); + env->Object_SetPropertyByName_Int(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); + env->Object_SetPropertyByName_Int(object, "rss", lastExitDetailInfo.rss); + env->Object_SetPropertyByName_Int(object, "pss", lastExitDetailInfo.pss); + env->Object_SetPropertyByName_Long(object, "timestamp", lastExitDetailInfo.timestamp); return object; } @@ -148,6 +148,11 @@ bool WrapLaunchParam(ani_env *env, const AAFwk::LaunchParam &launchParam, ani_ob TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to set lastExitMessage"); return false; } + if ((status = env->Object_SetPropertyByName_Ref( + object, "launchReasonMessage", GetAniString(env, launchParam.launchReasonMessage))) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to set launchReasonMessage"); + return false; + } return WrapLaunchParamInner(env, launchParam, object); } } // namespace AbilityRuntime diff --git a/frameworks/ets/ani/ani_common/src/ets_enviroment_callback.cpp b/frameworks/ets/ani/ani_common/src/ets_enviroment_callback.cpp new file mode 100644 index 00000000000..902a196ad7b --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ets_enviroment_callback.cpp @@ -0,0 +1,215 @@ +/* + * 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_enviroment_callback.h" + +#include "ani_common_configuration.h" +#include "hilog_tag_wrapper.h" +#include "ani_enum_convert.h" +#include "app_mem_info.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* APPLICATION_ENVIROMENT_CALLBACK = + "L@ohos/app/ability/EnvironmentCallback/EnvironmentCallbackInner;"; +constexpr const char* APPLICATION_MEMORYLEVEL = + "L@ohos/app/ability/AbilityConstant/AbilityConstant/MemoryLevel;:V"; +constexpr const char* APPLICATION_MEMORYLEVEL_ENUM = + "L@ohos/app/ability/AbilityConstant/AbilityConstant/MemoryLevel;"; +constexpr const char* APPLICATION_CONFIGURATION = + "L@ohos/app/ability/Configuration/Configuration;:V"; +} +EtsEnviromentCallback::EtsEnviromentCallback(ani_vm *etsVm) : etsVm_(etsVm) {} + +EtsEnviromentCallback::~EtsEnviromentCallback() +{ + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed"); + return; + } + ani_status status = ANI_ERROR; + { + std::lock_guard lock(mutex_); + for (auto it = enviromentAniCallbacks_.begin(); it != enviromentAniCallbacks_.end();) { + if ((status = env->GlobalReference_Delete(it->second)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "GlobalReference_Delete status: %{public}d", status); + } + it++; + } + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +}; + +int32_t EtsEnviromentCallback::Register(ani_object aniCallback) +{ + int32_t callbackId = serialNumber_; + if (serialNumber_ < INT32_MAX) { + serialNumber_++; + } else { + serialNumber_ = 0; + } + ani_ref aniCallbackRef = nullptr; + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed"); + return -1; + } + ani_status status = ANI_ERROR; + if ((status = env->GlobalReference_Create(aniCallback, &aniCallbackRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "GlobalReference_Create status: %{public}d", status); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return -1; + } + { + std::lock_guard lock(mutex_); + enviromentAniCallbacks_.emplace(callbackId, aniCallbackRef); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return callbackId; +} + +bool EtsEnviromentCallback::UnRegister(int32_t callbackId) +{ + std::lock_guard lock(mutex_); + auto it = enviromentAniCallbacks_.find(callbackId); + if (it == enviromentAniCallbacks_.end()) { + TAG_LOGE(AAFwkTag::APPKIT, "callbackId: %{public}d not in callbacks_", callbackId); + return false; + } + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed"); + return false; + } + TAG_LOGD(AAFwkTag::APPKIT, "callbacks_.callbackId: %{public}d", it->first); + ani_status status = ANI_ERROR; + if ((status = env->GlobalReference_Delete(it->second)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "GlobalReference_Delete status: %{public}d", status); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return false; + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return enviromentAniCallbacks_.erase(callbackId) == 1; +} + +void EtsEnviromentCallback::OnMemoryLevel(const int level) +{ + TAG_LOGD(AAFwkTag::APPKIT, "OnMemoryLevel Call"); + if (enviromentAniCallbacks_.empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "null enviromentAniCallbacks_"); + return; + } + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed"); + return; + } + ani_class cls {}; + ani_status status = env->FindClass(APPLICATION_ENVIROMENT_CALLBACK, &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "FindClass status: %{public}d", status); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_method method {}; + if ((status = env->Class_FindMethod(cls, "onMemoryLevel", APPLICATION_MEMORYLEVEL, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_FindMethod status: %{public}d", status); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_enum_item memoryLevel {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts(env, + APPLICATION_MEMORYLEVEL_ENUM, (AppExecFwk::MemoryLevel)level, memoryLevel); + if (memoryLevel == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "create memoryLevel failed"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + { + std::lock_guard lock(mutex_); + for (auto &callback : enviromentAniCallbacks_) { + ani_status status = ANI_ERROR; + if (!callback.second) { + TAG_LOGE(AAFwkTag::APPKIT, "callback object is null"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_object envCallback = reinterpret_cast(callback.second); + if ((status = env->Object_CallMethod_Void(envCallback, method, memoryLevel)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_CallMethod_Void status: %{public}d", status); + } + } + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +void EtsEnviromentCallback::OnConfigurationUpdated(const AppExecFwk::Configuration &config) +{ + TAG_LOGD(AAFwkTag::APPKIT, "OnConfigurationUpdated Call"); + if (enviromentAniCallbacks_.empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "null enviromentAniCallbacks_"); + return; + } + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed"); + return; + } + ani_class cls {}; + ani_status status = env->FindClass(APPLICATION_ENVIROMENT_CALLBACK, &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "FindClass status: %{public}d", status); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_method method {}; + if ((status = env->Class_FindMethod(cls, "onConfigurationUpdated", + APPLICATION_CONFIGURATION, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_FindMethod status: %{public}d", status); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_object configObj = OHOS::AppExecFwk::WrapConfiguration(env, config); + if (configObj == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "create configObj failed"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + { + std::lock_guard lock(mutex_); + for (auto &callback : enviromentAniCallbacks_) { + ani_status status = ANI_ERROR; + if (!callback.second) { + TAG_LOGE(AAFwkTag::APPKIT, "callback object is null"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_object envCallback = reinterpret_cast(callback.second); + if ((status = env->Object_CallMethod_Void(envCallback, method, configObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_CallMethod_Void status: %{public}d", status); + } + } + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file 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 bd7b64b251c..5485f911511 100644 --- a/frameworks/ets/ani/ani_common/src/ets_error_utils.cpp +++ b/frameworks/ets/ani/ani_common/src/ets_error_utils.cpp @@ -15,6 +15,7 @@ #include "ets_error_utils.h" +#include "ability_runtime_error_util.h" #include "hilog_tag_wrapper.h" namespace OHOS { @@ -57,6 +58,19 @@ void EtsErrorUtil::ThrowError(ani_env *env, const AbilityErrorCode &err) EtsErrorUtil::ThrowError(env, EtsErrorUtil::CreateError(env, static_cast(err), GetErrorMsg(err))); } +void EtsErrorUtil::ThrowRuntimeError(ani_env *env, int32_t errCode, const std::string &errMessage) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return; + } + std::string eMes = errMessage; + if (eMes.empty()) { + eMes = AbilityRuntimeErrorUtil::GetErrMessage(errCode); + } + EtsErrorUtil::ThrowError(env, EtsErrorUtil::CreateError(env, errCode, eMes)); +} + void EtsErrorUtil::ThrowInvalidCallerError(ani_env *env) { if (env == nullptr) { @@ -232,8 +246,7 @@ ani_object EtsErrorUtil::CreateError(ani_env *env, ani_int code, const std::stri return nullptr; } ani_object obj = nullptr; - ani_double dCode(code); - if ((status = env->Object_New(cls, method, &obj, dCode, error)) != ANI_OK) { + if ((status = env->Object_New(cls, method, &obj, (ani_double)code, error)) != ANI_OK) { TAG_LOGE(AAFwkTag::ANI, "Object_New failed %{public}d", status); return nullptr; } diff --git a/frameworks/ets/ani/ani_common/src/ets_extension_context.cpp b/frameworks/ets/ani/ani_common/src/ets_extension_context.cpp index 3cdb9f65397..62a803ab6d1 100644 --- a/frameworks/ets/ani/ani_common/src/ets_extension_context.cpp +++ b/frameworks/ets/ani/ani_common/src/ets_extension_context.cpp @@ -17,6 +17,8 @@ #include "ani_common_configuration.h" #include "common_fun_ani.h" +#include "ets_native_reference.h" +#include "ets_runtime.h" #include "hilog_tag_wrapper.h" namespace OHOS { @@ -106,5 +108,21 @@ void CreateEtsExtensionContext(ani_env *aniEnv, ani_class contextClass, ani_obje return; } } + +void EtsExtensionContext::ConfigurationUpdated(ani_env *env, + const std::shared_ptr &EtsContext, + const std::shared_ptr &config) +{ + if (env == nullptr || EtsContext == nullptr || config == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "env or EtsContext or config is null"); + return; + } + ani_ref configurationRef = AppExecFwk::WrapConfiguration(env, *config); + ani_status status = env->Object_SetFieldByName_Ref(EtsContext->aniObj, "config", configurationRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "Object_SetFieldByName_Ref status: %{public}d", status); + return; + } +} } // namespace AbilityRuntime } // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ani_mission_manager/BUILD.gn b/frameworks/ets/ani/ani_mission_manager/BUILD.gn new file mode 100644 index 00000000000..dc538fee9a2 --- /dev/null +++ b/frameworks/ets/ani/ani_mission_manager/BUILD.gn @@ -0,0 +1,60 @@ +# 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("missionmanager_ani") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + sources = [ + "./src/ets_mission_info_utils.cpp", + "./src/ets_mission_manager.cpp", + ] + + include_dirs = [ + "./include", + "${ability_runtime_path}/interfaces/inner_api/ability_manager/include", + "${ability_runtime_services_path}/common/include", + ] + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/ability_manager:ability_start_options", + "${ability_runtime_innerkits_path}/ability_manager:mission_info", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_native_path}/ability/native:ability_business_error", + "${ability_runtime_native_path}/ability/native:abilitykit_native", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "ipc:ipc_napi", + "runtime_core:ani", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/ani_mission_manager/include/ets_mission_info_utils.h b/frameworks/ets/ani/ani_mission_manager/include/ets_mission_info_utils.h new file mode 100644 index 00000000000..fe58d7980bd --- /dev/null +++ b/frameworks/ets/ani/ani_mission_manager/include/ets_mission_info_utils.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_ETS_MISSION_INFO_UTILS_H +#define OHOS_ABILITY_RUNTIME_ETS_MISSION_INFO_UTILS_H + +typedef struct __ani_env ani_env; +typedef class __ani_object *ani_object; + +namespace OHOS { +namespace AAFwk { +struct MissionInfo; +} +namespace AbilityRuntime { +ani_object CreateEtsMissionInfo(ani_env *env, const AAFwk::MissionInfo &missionInfo); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_MISSION_INFO_UTILS_H diff --git a/frameworks/ets/ani/ani_mission_manager/include/ets_mission_manager.h b/frameworks/ets/ani/ani_mission_manager/include/ets_mission_manager.h new file mode 100644 index 00000000000..bca041f0481 --- /dev/null +++ b/frameworks/ets/ani/ani_mission_manager/include/ets_mission_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_MISSION_MANAGER_H +#define OHOS_ABILITY_RUNTIME_ETS_MISSION_MANAGER_H + +typedef struct __ani_env ani_env; + +namespace OHOS { +namespace AbilityRuntime { +void EtsMissionManagerInit(ani_env* env); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_MISSION_MANAGER_H \ No newline at end of file diff --git a/frameworks/ets/ani/ani_mission_manager/src/ets_mission_info_utils.cpp b/frameworks/ets/ani/ani_mission_manager/src/ets_mission_info_utils.cpp new file mode 100644 index 00000000000..e26bd01cfe8 --- /dev/null +++ b/frameworks/ets/ani/ani_mission_manager/src/ets_mission_info_utils.cpp @@ -0,0 +1,127 @@ +/* + * 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_mission_info_utils.h" + +#include "ani.h" +#include "ani_common_want.h" +#include "ani_common_util.h" +#include "hilog_tag_wrapper.h" +#include "mission_info.h" +#include "want.h" + +namespace OHOS { +namespace AbilityRuntime { + +namespace { +constexpr const char* ETS_MISSION_INFO_NAME = "Lapplication/MissionInfo/MissionInfoInner;"; +constexpr const char* KEY_MISSION_ID = "missionId"; +constexpr const char* KEY_RUNNING_STATE = "runningState"; +constexpr const char* KEY_LOCKED_STATE = "lockedState"; +constexpr const char* KEY_TIMESTAMP = "timestamp"; +constexpr const char* KEY_LABEL = "label"; +constexpr const char* KEY_ICON_PATH = "iconPath"; +constexpr const char* KEY_CONTINUABLE = "continuable"; +constexpr const char* KEY_ABILITY_STATE = "abilityState"; +constexpr const char* KEY_UNCLEARABLE = "unclearable"; +constexpr const char* KEY_WANT = "want"; +} + +bool WrapWantInner(ani_env *env, ani_class cls, ani_object object, const AAFwk::Want &want) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "env is null"); + return false; + } + ani_object wantObj = AppExecFwk::WrapWant(env, want); + if (wantObj == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "wrap want failed"); + return false; + } + ani_status status = ANI_ERROR; + ani_field wantField = nullptr; + status = env->Class_FindField(cls, KEY_WANT, &wantField); + if (status != ANI_OK || wantField == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "find want field failed status: %{public}d, or wantField is nullptr", status); + return false; + } + status = env->Object_SetField_Ref(object, wantField, reinterpret_cast(wantObj)); + if (status != ANI_OK || wantObj == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "Object_SetField_Ref failed status: %{public}d, or wantObj is unllptr", status); + return false; + } + return true; +} + +bool WrapMissionInfo(ani_env *env, ani_class cls, ani_object object, const AAFwk::MissionInfo &missionInfo) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "result or env is null"); + return false; + } + if (!AppExecFwk::SetIntPropertyValue(env, object, KEY_MISSION_ID, missionInfo.id) || + !AppExecFwk::SetIntPropertyValue(env, object, KEY_RUNNING_STATE, missionInfo.runningState) || + !AppExecFwk::SetFieldBoolByName(env, cls, object, KEY_LOCKED_STATE, missionInfo.lockedState) || + !AppExecFwk::SetFieldStringByName(env, cls, object, KEY_TIMESTAMP, missionInfo.time) || + !AppExecFwk::SetFieldStringByName(env, cls, object, KEY_LABEL, missionInfo.label) || + !AppExecFwk::SetFieldStringByName(env, cls, object, KEY_ICON_PATH, missionInfo.iconPath) || + !AppExecFwk::SetFieldBoolByName(env, cls, object, KEY_CONTINUABLE, missionInfo.continuable) || + !AppExecFwk::SetIntPropertyValue(env, object, KEY_ABILITY_STATE, missionInfo.abilityState) || + !AppExecFwk::SetFieldBoolByName(env, cls, object, KEY_UNCLEARABLE, missionInfo.unclearable)) { + TAG_LOGE(AAFwkTag::MISSION, "set mission info failed"); + return false; + } + + if (!WrapWantInner(env, cls, object, missionInfo.want)) { + TAG_LOGE(AAFwkTag::MISSION, "wrap want failed"); + return false; + } + return true; +} + +ani_object CreateEtsMissionInfo(ani_env *env, const AAFwk::MissionInfo &missionInfo) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "result or env is null"); + return nullptr; + } + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + status = env->FindClass(ETS_MISSION_INFO_NAME, &cls); + if (status != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "find MissionInfo failed status: %{public}d, or cls is nullptr", status); + return nullptr; + } + ani_method method = nullptr; + status = env->Class_FindMethod(cls, "", ":V", &method); + if (status != ANI_OK || method == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "Class_FindMethod ctor failed status: %{public}d, method cls is nullptr", status); + return nullptr; + } + ani_object object = nullptr; + status = env->Object_New(cls, method, &object); + if (status != ANI_OK || object == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "Object_New failed status: %{public}d, or object is nullptr", status); + return nullptr; + } + + if (!WrapMissionInfo(env, cls, object, missionInfo)) { + TAG_LOGE(AAFwkTag::MISSION, "WrapMissionInfo failed"); + return nullptr; + } + return object; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/ani_mission_manager/src/ets_mission_manager.cpp b/frameworks/ets/ani/ani_mission_manager/src/ets_mission_manager.cpp new file mode 100644 index 00000000000..d5ca898b99d --- /dev/null +++ b/frameworks/ets/ani/ani_mission_manager/src/ets_mission_manager.cpp @@ -0,0 +1,187 @@ +/* + * 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_mission_manager.h" + +#include "ability_manager_client.h" +#include "ani.h" +#include "ani_common_util.h" +#include "ets_error_utils.h" +#include "ets_mission_info_utils.h" +#include "hilog_tag_wrapper.h" +#include "permission_constants.h" + +namespace OHOS { +namespace AbilityRuntime { +using namespace OHOS::AppExecFwk; +using AbilityManagerClient = AAFwk::AbilityManagerClient; +namespace { +constexpr const char* ETS_MISSION_INFO_NAME = "Lapplication/MissionInfo/MissionInfoInner;"; +constexpr const char* ETS_MISSION_MANAGER_NAME = "L@ohos/app/ability/missionManager/missionManager;"; +} +class EtsMissionManager { +public: + EtsMissionManager(const EtsMissionManager&) = delete; + EtsMissionManager& operator=(const EtsMissionManager&) = delete; + + static EtsMissionManager& GetInstance() + { + return instance; + } + + static void ClearAllMissions(ani_env* env, ani_object callback) + { + instance.OnClearAllMissions(env, callback); + } + + static void GetMissionInfo(ani_env* env, ani_string deviceId, ani_int missionId, ani_object callback) + { + instance.OnGetMissionInfo(env, deviceId, missionId, callback); + } +private: + EtsMissionManager() = default; + ~EtsMissionManager() = default; + + static EtsMissionManager instance; + + void OnClearAllMissions(ani_env* env, ani_object callback) + { + TAG_LOGD(AAFwkTag::MISSION, "OnClearAllMissions Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "null env"); + return; + } + auto ret = AbilityManagerClient::GetInstance()->CleanAllMissions(); + if (ret != 0) { + TAG_LOGE(AAFwkTag::MISSION, "OnClearAllMissions is failed. ret = %{public}d.", ret); + AsyncCallback(env, callback, EtsErrorUtil::CreateErrorByNativeErr(env, + ret, PermissionConstants::PERMISSION_MANAGE_MISSION), nullptr); + return; + } + AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK), nullptr); + } + + void OnGetMissionInfo(ani_env* env, ani_string deviceId, ani_int missionId, ani_object callback) + { + TAG_LOGD(AAFwkTag::MISSION, "OnGetMissionInfo Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "null env"); + return; + } + auto emptyObject = GetEmptyMissionInfo(env); + std::string stdDeviceId = ""; + if (!GetStdString(env, deviceId, stdDeviceId) || stdDeviceId.empty()) { + TAG_LOGE(AAFwkTag::MISSION, "GetStdString failed"); + AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env, + "Parse param deviceId failed, must be a string."), emptyObject); + return; + } + AAFwk::MissionInfo missionInfo; + auto ret = AbilityManagerClient::GetInstance()->GetMissionInfo(stdDeviceId, + missionId, missionInfo); + if (ret != 0) { + TAG_LOGE(AAFwkTag::MISSION, "GetMissionInfo is failed. ret = %{public}d.", ret); + AsyncCallback(env, callback, EtsErrorUtil::CreateErrorByNativeErr(env, + ret, PermissionConstants::PERMISSION_MANAGE_MISSION), emptyObject); + return; + } + auto aniMissionInfo = CreateEtsMissionInfo(env, missionInfo); + AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK), aniMissionInfo); + } + + ani_object GetEmptyMissionInfo(ani_env* env) + { + if (env == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "null env"); + return nullptr; + } + ani_class cls = nullptr; + ani_status status = env->FindClass(ETS_MISSION_INFO_NAME, &cls); + if (status != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "find Context failed status: %{public}d", status); + return nullptr; + } + ani_method method = nullptr; + status = env->Class_FindMethod(cls, "", ":V", &method); + if (status != ANI_OK || method == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "Class_FindMethod ctor failed status: %{public}d", status); + return nullptr; + } + ani_object objValue = nullptr; + status = env->Object_New(cls, method, &objValue); + if (status != ANI_OK || objValue == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "Object_New failed status: %{public}d", status); + return nullptr; + } + return objValue; + } +}; + +EtsMissionManager EtsMissionManager::instance; + +void EtsMissionManagerInit(ani_env* env) +{ + TAG_LOGD(AAFwkTag::MISSION, "EtsMissionManagerInit Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "null env"); + return; + } + ani_status status = ANI_ERROR; + ani_namespace ns; + status = env->FindNamespace(ETS_MISSION_MANAGER_NAME, &ns); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::MISSION, "FindNamespace application failed status: %{public}d", status); + return; + } + std::array methods = { + ani_native_function { + "nativeClearAllMissions", "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsMissionManager::ClearAllMissions) + }, + ani_native_function { + "nativeGetMissionInfo", + "Lstd/core/String;ILutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsMissionManager::GetMissionInfo) + }, + }; + status = env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::MISSION, "Namespace_BindNativeFunctions failed status: %{public}d", status); + } +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::MISSION, "in MissionManagerETS.ANI_Constructor"); + if (vm == nullptr || result == nullptr) { + TAG_LOGE(AAFwkTag::MISSION, "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::MISSION, "GetEnv failed, status: %{public}d", status); + return ANI_NOT_FOUND; + } + EtsMissionManagerInit(env); + *result = ANI_VERSION_1; + TAG_LOGD(AAFwkTag::MISSION, "MissionManagerETS.ANI_Constructor finished"); + return ANI_OK; +} +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/app_manager/BUILD.gn b/frameworks/ets/ani/app_manager/BUILD.gn index af3ae03d123..4aeb3a81238 100644 --- a/frameworks/ets/ani/app_manager/BUILD.gn +++ b/frameworks/ets/ani/app_manager/BUILD.gn @@ -39,8 +39,11 @@ ohos_shared_library("app_manager_ani") { public_configs = [] sources = [ + "./src/ets_ability_first_frame_state_observer.cpp", + "./src/ets_app_foreground_state_observer.cpp", "./src/ets_app_manager.cpp", "./src/ets_app_manager_utils.cpp", + "./src/ets_app_state_observer.cpp", ] cflags = [] diff --git a/frameworks/ets/ani/app_manager/include/ets_ability_first_frame_state_observer.h b/frameworks/ets/ani/app_manager/include/ets_ability_first_frame_state_observer.h new file mode 100644 index 00000000000..bffac8de1f7 --- /dev/null +++ b/frameworks/ets/ani/app_manager/include/ets_ability_first_frame_state_observer.h @@ -0,0 +1,77 @@ +/* + * 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_FIRST_FRAME_STATE_OBSERVER_H +#define OHOS_ABILITY_RUNTIME_ETS_ABILITY_FIRST_FRAME_STATE_OBSERVER_H + +#ifdef SUPPORT_GRAPHICS +#include +#include + +#include "ability_first_frame_state_data.h" +#include "ability_first_frame_state_observer_stub.h" +#include "ability_manager_interface.h" +#include "ani.h" +#include "ani_common_util.h" +#include "event_handler.h" +#include "singleton.h" + +namespace OHOS { +namespace AbilityRuntime { +using AppExecFwk::AbilityFirstFrameStateObserverStub; +using AppExecFwk::AbilityFirstFrameStateData; +class ETSAbilityFirstFrameStateObserver : public AbilityFirstFrameStateObserverStub { +public: + explicit ETSAbilityFirstFrameStateObserver(ani_vm *vm); + virtual ~ETSAbilityFirstFrameStateObserver() = default; + void OnAbilityFirstFrameState(const AbilityFirstFrameStateData &abilityFirstFrameStateData) override; + void HandleOnAbilityFirstFrameState(const AbilityFirstFrameStateData &abilityFirstFrameStateData); + void CallEtsFunction( + ani_env *env, ani_object etsObserverObject, const char *methodName, const char *signature, ...); + void SetEtsObserverObject(const ani_object &etsObserverObject); + void ResetEtsObserverObject(); + bool IsStrictEquals(const ani_object &etsObserverObject); + ani_ref GetAniObserver() { return etsObserverObject_; } +private: + ani_vm *etsVm_ = nullptr; + ani_ref etsObserverObject_ = nullptr; +}; + +class ETSAbilityFirstFrameStateObserverManager { +public: + static ETSAbilityFirstFrameStateObserverManager *GetInstance() + { + static ETSAbilityFirstFrameStateObserverManager instance; + return &instance; + } + ~ETSAbilityFirstFrameStateObserverManager() = default; + void AddEtsAbilityFirstFrameStateObserver(const sptr observer); + bool IsObserverObjectExist(const ani_object &esObserverObject); + void RemoveAllEtsObserverObjects(sptr &abilityManager); + void RemoveEtsObserverObject(sptr &abilityManager, + const ani_object &etsObserverObject); +private: + ETSAbilityFirstFrameStateObserverManager() = default; + DISALLOW_COPY_AND_MOVE(ETSAbilityFirstFrameStateObserverManager); + ani_ref GetObserverObject(const ani_object &etsObserverObject); + +private: + std::mutex observerListLock_; + std::list> etsAbilityFirstFrameStateObserverList_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // SUPPORT_GRAPHICS +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_FIRST_FRAME_STATE_OBSERVER_H diff --git a/frameworks/ets/ani/app_manager/include/ets_app_foreground_state_observer.h b/frameworks/ets/ani/app_manager/include/ets_app_foreground_state_observer.h new file mode 100644 index 00000000000..b755254f5fe --- /dev/null +++ b/frameworks/ets/ani/app_manager/include/ets_app_foreground_state_observer.h @@ -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. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_APP_FOREGROUND_STATE_OBSERVER_H +#define OHOS_ABILITY_RUNTIME_ETS_APP_FOREGROUND_STATE_OBSERVER_H + +#include +#include + +#include "ani.h" +#include "ani_common_util.h" +#include "app_foreground_state_observer_stub.h" +#include "event_handler.h" + +namespace OHOS { +namespace AbilityRuntime { +using AppExecFwk::AppForegroundStateObserverStub; +using AppExecFwk::AppStateData; +class ETSAppForegroundStateObserver : public AppForegroundStateObserverStub { +public: +virtual ~ETSAppForegroundStateObserver(); +explicit ETSAppForegroundStateObserver(ani_vm *etsVm); + void OnAppStateChanged(const AppStateData &appStateData); + void HandleOnAppStateChanged(const AppStateData &appStateData); + void AddEtsObserverObject(const ani_object &observerObj); + void RemoveEtsObserverObject(const ani_object &observerObj); + void RemoveAllEtsObserverObjects(); + ani_ref GetObserverObject(const ani_object &observerObject); + void CallEtsFunction(ani_env* env, ani_object etsObserverObject, + const char *methodName, const char *signature, ...); + bool IsEmpty(); + void SetValid(bool valid); +private: + bool IsStrictEquals(ani_ref observerRef, const ani_object &etsObserverObject); + ani_vm *etsVm_ = nullptr; + volatile bool valid_ = true; + std::vector etsObserverObjects_; + std::mutex etsObserverObjectSetLock_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_APP_FOREGROUND_STATE_OBSERVER_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 index 0f86067097c..5eeec26358f 100644 --- a/frameworks/ets/ani/app_manager/include/ets_app_manager_utils.h +++ b/frameworks/ets/ani/app_manager/include/ets_app_manager_utils.h @@ -17,12 +17,17 @@ #include +#include "ability_state_data.h" #include "ani.h" #include "app_state_data.h" #include "ets_runtime.h" +#include "keep_alive_info.h" #include "process_data.h" #include "running_multi_info.h" #include "running_process_info.h" +#ifdef SUPPORT_GRAPHICS +#include "ability_first_frame_state_data.h" +#endif namespace OHOS { namespace AppManagerEts { @@ -33,20 +38,34 @@ ani_object CreateAppStateDataArray(ani_env *env, const std::vector &infos); ani_object CreateRunningAppCloneArray(ani_env *env, const std::vector &infos); -bool SetRunningMultiAppInfo( - ani_env *env, ani_object object, const AppExecFwk::RunningMultiAppInfo &runningMultiAppInfo); +bool 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); -bool SetRunningMultiInstanceInfo( - ani_env *env, ani_object object, const AppExecFwk::RunningMultiInstanceInfo &instanceInfo); +bool SetRunningMultiInstanceInfo(ani_env *env, ani_object object, + const AppExecFwk::RunningMultiInstanceInfo &instanceInfo); ani_object WrapRunningAppClone(ani_env *env, const AppExecFwk::RunningAppClone &runningAppClone); bool SetRunningAppClone(ani_env *env, ani_object object, const AppExecFwk::RunningAppClone &runningAppClone); ani_object WrapProcessData(ani_env *env, const AppExecFwk::ProcessData &processData); -bool SetProcessData(ani_env *env, ani_object object, const AppExecFwk::ProcessData &processData); +bool 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); +ani_object CreateIntAniArray(ani_env *env, const std::vector &dataArry); +bool UnWrapArrayInt(ani_env *env, ani_object arrayObj, std::vector &list); +ani_object CreateKeepAliveInfoArray(ani_env *env, const std::vector &infos); +ani_object WrapKeepAliveInfo(ani_env *env, const AbilityRuntime::KeepAliveInfo &keepAliveInfo); +bool SetKeepAliveInfo(ani_env *env, ani_object object, const AbilityRuntime::KeepAliveInfo &keepInfo); +#ifdef SUPPORT_GRAPHICS +ani_object WrapAbilityFirstFrameStateData(ani_env *env, + const AppExecFwk::AbilityFirstFrameStateData &abilityFirstFrameStateData); +bool SetAbilityFirstFrameStateData(ani_env *env, ani_object object, + const AppExecFwk::AbilityFirstFrameStateData &abilityFirstFrameStateData); +#endif +bool AttachAniEnv(ani_vm *etsVm, ani_env *&env); +void DetachAniEnv(ani_vm *etsVm); +void ReleaseObjectReference(ani_vm *etsVm, ani_ref etsObjRef); + } // namespace AppManagerEts } // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_ETS_APP_MANAGER_UTILS_H diff --git a/frameworks/ets/ani/app_manager/include/ets_app_state_observer.h b/frameworks/ets/ani/app_manager/include/ets_app_state_observer.h new file mode 100644 index 00000000000..ebf589a5aaf --- /dev/null +++ b/frameworks/ets/ani/app_manager/include/ets_app_state_observer.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_APP_STATE_OBSERVER_H +#define OHOS_ABILITY_RUNTIME_ETS_APP_STATE_OBSERVER_H + +#include "ani_common_util.h" +#include "application_state_observer_stub.h" +#include "event_handler.h" +#include "ets_runtime.h" + +namespace OHOS { +namespace AbilityRuntime { +using OHOS::AppExecFwk::ApplicationStateObserverStub; +using OHOS::AppExecFwk::AppStateData; +using OHOS::AppExecFwk::AbilityStateData; +using OHOS::AppExecFwk::ProcessData; +class EtsAppStateObserver : public ApplicationStateObserverStub { +public: + explicit EtsAppStateObserver(ani_vm *etsVm); + ~EtsAppStateObserver() override; + void OnForegroundApplicationChanged(const AppStateData &appStateData) override; + void OnAbilityStateChanged(const AbilityStateData &abilityStateData) override; + void OnExtensionStateChanged(const AbilityStateData &abilityStateData) override; + void OnProcessCreated(const ProcessData &processData) override; + void OnProcessStateChanged(const ProcessData &processData) override; + void OnProcessDied(const ProcessData &processData) override; + void HandleOnForegroundApplicationChanged(const AppStateData &appStateData); + void HandleOnAbilityStateChanged(const AbilityStateData &abilityStateData); + void HandleOnExtensionStateChanged(const AbilityStateData &abilityStateData); + void HandleOnProcessCreated(const ProcessData &processData); + void HandleOnProcessStateChanged(const ProcessData &processData); + void HandleOnProcessDied(const ProcessData &processData); + void CallEtsFunction(ani_env* env, ani_object EtsObserverObject, + const char *methodName, const char *signature, ...); + void AddEtsObserverObject(ani_env *env, const int32_t observerId, ani_object EtsObserverObject); + bool RemoveEtsObserverObject(const int32_t observerId); + bool FindObserverByObserverId(const int32_t observerId); + size_t GetEtsObserverMapSize(); + void SetValid(const bool valid); + void OnAppStarted(const AppStateData &appStateData) override; + void OnAppStopped(const AppStateData &appStateData) override; + void HandleOnAppStarted(const AppStateData &appStateData); + void HandleOnAppStopped(const AppStateData &appStateData); + std::map GetEtsObserverObjectMap(); + +private: + ani_vm *etsVm_; + volatile bool valid_ = true; + std::map etsObserverObjectMap_; + std::mutex etsObserverObjectMapLock_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_APP_STATE_OBSERVER_H \ No newline at end of file diff --git a/frameworks/ets/ani/app_manager/src/ets_ability_first_frame_state_observer.cpp b/frameworks/ets/ani/app_manager/src/ets_ability_first_frame_state_observer.cpp new file mode 100644 index 00000000000..488a825ef53 --- /dev/null +++ b/frameworks/ets/ani/app_manager/src/ets_ability_first_frame_state_observer.cpp @@ -0,0 +1,242 @@ +/* + * 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. + */ + +#ifdef SUPPORT_GRAPHICS +#include "ets_ability_first_frame_state_observer.h" + +#include "ani_task.h" +#include "ets_app_manager_utils.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* ABILITY_FIRST_FRAME_STATE_OBSERVER_CLASS_NAME = + "Lapplication/AbilityFirstFrameStateObserver/AbilityFirstFrameStateObserver;"; +} +ETSAbilityFirstFrameStateObserver::ETSAbilityFirstFrameStateObserver(ani_vm *vm) : etsVm_(vm) {} + +void ETSAbilityFirstFrameStateObserver::OnAbilityFirstFrameState( + const AbilityFirstFrameStateData &abilityFirstFrameStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "OnAbilityFirstFrameState called"); + wptr weakPtr = this; + auto task = [abilityFirstFrameStateData, weakPtr] () { + auto abilityFirstFrameStateObserver = weakPtr.promote(); + if (abilityFirstFrameStateObserver == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observerPtr"); + return; + } + abilityFirstFrameStateObserver->HandleOnAbilityFirstFrameState(abilityFirstFrameStateData); + }; + if (AniTask::AniSendEvent(task) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to aniSendEvent"); + } + TAG_LOGD(AAFwkTag::APPMGR, "OnAbilityFirstFrameState end"); +} + +void ETSAbilityFirstFrameStateObserver::HandleOnAbilityFirstFrameState( + const AbilityFirstFrameStateData &abilityFirstFrameStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "HandleOnAbilityFirstFrameState called"); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "etsVm_ nullptr"); + return; + } + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed"); + return; + } + auto paramObj = AppManagerEts::WrapAbilityFirstFrameStateData(env, abilityFirstFrameStateData); + if (paramObj != nullptr && etsObserverObject_ != nullptr) { + CallEtsFunction(env, reinterpret_cast(etsObserverObject_), "onAbilityFirstFrameDrawn", + nullptr, paramObj); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +void ETSAbilityFirstFrameStateObserver::CallEtsFunction(ani_env* env, ani_object etsObserverObject, + const char *methodName, const char *signature, ...) +{ + TAG_LOGD(AAFwkTag::APPMGR, "call method:%{public}s", methodName); + ani_class cls; + ani_method method = nullptr; + ani_status status = ANI_OK; + if ((status = env->FindClass(ABILITY_FIRST_FRAME_STATE_OBSERVER_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "find observer failed status : %{public}d", status); + return; + } + if ((status = env->Class_FindMethod(cls, methodName, signature, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status: %{public}d", status); + return; + } + env->ResetError(); + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(etsObserverObject, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status: %{public}d", status); + return; + } + va_end(args); + TAG_LOGD(AAFwkTag::APPMGR, "end"); + return; +} + +void ETSAbilityFirstFrameStateObserver::SetEtsObserverObject(const ani_object &etsObserverObject) +{ + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null etsVm_"); + return; + } + if (etsObserverObject == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed status: %{public}d", status); + return; + } + ani_ref observerRef = nullptr; + if ((status = env->GlobalReference_Create(etsObserverObject, &observerRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status : %{public}d", status); + return; + } + etsObserverObject_ = observerRef; +} + +void ETSAbilityFirstFrameStateObserver::ResetEtsObserverObject() +{ + if (etsObserverObject_) { + AppManagerEts::ReleaseObjectReference(etsVm_, etsObserverObject_); + } +} + +void ETSAbilityFirstFrameStateObserverManager::AddEtsAbilityFirstFrameStateObserver( + const sptr observer) +{ + if (observer == nullptr || observer->GetAniObserver() == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + return; + } + std::lock_guard lock(observerListLock_); + etsAbilityFirstFrameStateObserverList_.emplace_back(observer); +} + +bool ETSAbilityFirstFrameStateObserverManager::IsObserverObjectExist(const ani_object &esObserverObject) +{ + if (GetObserverObject(esObserverObject) == nullptr) { + TAG_LOGD(AAFwkTag::APPMGR, "observer not exist"); + return false; + } + TAG_LOGD(AAFwkTag::APPMGR, "observer exist"); + return true; +} + +void ETSAbilityFirstFrameStateObserverManager::RemoveAllEtsObserverObjects( + sptr &abilityManager) +{ + TAG_LOGD(AAFwkTag::APPMGR, "RemoveAllEtsObserverObject called"); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null abilityMgr"); + return; + } + std::lock_guard lock(observerListLock_); + for (auto &observer : etsAbilityFirstFrameStateObserverList_) { + if (observer == nullptr) { + continue; + } + abilityManager->UnregisterAbilityFirstFrameStateObserver(observer); + observer->ResetEtsObserverObject(); + } + etsAbilityFirstFrameStateObserverList_.clear(); +} + +bool ETSAbilityFirstFrameStateObserver::IsStrictEquals(const ani_object &etsObserverObject) +{ + if (etsObserverObject == nullptr) { + return false; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed status: %{public}d", status); + return false; + } + ani_boolean isEquals = ANI_FALSE; + if ((status = env->Reference_StrictEquals(etsObserverObject_, etsObserverObject, &isEquals)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Reference_StrictEquals failed status: %{public}d", status); + return false; + } + return isEquals == ANI_TRUE; +} + +void ETSAbilityFirstFrameStateObserverManager::RemoveEtsObserverObject( + sptr &abilityManager, const ani_object &etsObserverObject) +{ + TAG_LOGD(AAFwkTag::APPMGR, "RemoveEtsObserverObject called"); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null abilityMgr"); + return; + } + if (etsObserverObject == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + return; + } + std::lock_guard lock(observerListLock_); + auto it = etsAbilityFirstFrameStateObserverList_.begin(); + for (; it != etsAbilityFirstFrameStateObserverList_.end(); ++it) { + if (*it == nullptr) { + continue; + } + if ((*it)->GetAniObserver() == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null value"); + continue; + } + if ((*it)->IsStrictEquals(etsObserverObject)) { + abilityManager->UnregisterAbilityFirstFrameStateObserver(*it); + (*it)->ResetEtsObserverObject(); + etsAbilityFirstFrameStateObserverList_.erase(it); + return; + } + } +} + +ani_ref ETSAbilityFirstFrameStateObserverManager::GetObserverObject(const ani_object &etsObserverObject) +{ + if (etsObserverObject == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + return nullptr; + } + std::lock_guard lock(observerListLock_); + auto it = find_if(etsAbilityFirstFrameStateObserverList_.begin(), + etsAbilityFirstFrameStateObserverList_.end(), + [&etsObserverObject](const sptr &observer) { + if (observer == nullptr || observer->GetAniObserver() == nullptr) { + return false; + } + return observer->IsStrictEquals(etsObserverObject); + }); + if (it != etsAbilityFirstFrameStateObserverList_.end() && *it != nullptr) { + return (*it)->GetAniObserver(); + } + return nullptr; +} +} // namespace AbilityRuntime +} // namespace OHOS +#endif // SUPPORT_GRAPHICS \ No newline at end of file diff --git a/frameworks/ets/ani/app_manager/src/ets_app_foreground_state_observer.cpp b/frameworks/ets/ani/app_manager/src/ets_app_foreground_state_observer.cpp new file mode 100644 index 00000000000..2ca01a4b214 --- /dev/null +++ b/frameworks/ets/ani/app_manager/src/ets_app_foreground_state_observer.cpp @@ -0,0 +1,225 @@ +/* + * 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_foreground_state_observer.h" + +#include "ani_task.h" +#include "ets_app_manager_utils.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* APP_FOREGROUND_STATE_OBSERVER_CLASS_NAME = + "Lapplication/AppForegroundStateObserver/AppForegroundStateObserver;"; +} +ETSAppForegroundStateObserver::ETSAppForegroundStateObserver(ani_vm *etsVm) : etsVm_(etsVm) {} + +ETSAppForegroundStateObserver::~ETSAppForegroundStateObserver() +{ + RemoveAllEtsObserverObjects(); +} + +void ETSAppForegroundStateObserver::OnAppStateChanged(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "OnAppStateChanged called"); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "invalid appMgr"); + return; + } + wptr weakPtr = this; + auto task = [appStateData, weakPtr] () { + auto appForegroundStateObserver = weakPtr.promote(); + if (appForegroundStateObserver == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observerPtr"); + return; + } + appForegroundStateObserver->HandleOnAppStateChanged(appStateData); + }; + if (AniTask::AniSendEvent(task) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to aniSendEvent"); + } + TAG_LOGD(AAFwkTag::APPMGR, "OnAppStateChanged end"); +} + +void ETSAppForegroundStateObserver::HandleOnAppStateChanged(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "HandleOnAppStateChanged called"); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "etsVm_ nullptr"); + return; + } + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed"); + return; + } + auto appStateDataObj = AppManagerEts::WrapAppStateData(env, appStateData); + if (appStateDataObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "WrapAppStateData failed"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + std::lock_guard lock(etsObserverObjectSetLock_); + for (auto &item : etsObserverObjects_) { + if (item != nullptr) { + CallEtsFunction(env, reinterpret_cast(item), "onAppStateChanged", nullptr, appStateDataObj); + } + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +void ETSAppForegroundStateObserver::CallEtsFunction(ani_env* env, ani_object etsObserverObject, + const char *methodName, const char *signature, ...) +{ + TAG_LOGD(AAFwkTag::APPMGR, "call method:%{public}s", methodName); + ani_class cls; + ani_method method = nullptr; + ani_status status = ANI_OK; + if ((status = env->FindClass(APP_FOREGROUND_STATE_OBSERVER_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "find observer failed status : %{public}d", status); + return; + } + if ((status = env->Class_FindMethod(cls, methodName, signature, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "status: %{public}d", status); + return; + } + env->ResetError(); + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(etsObserverObject, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "status: %{public}d", status); + return; + } + va_end(args); + TAG_LOGD(AAFwkTag::APPMGR, "end"); + return; +} + +void ETSAppForegroundStateObserver::AddEtsObserverObject(const ani_object &observerObj) +{ + if (observerObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + return; + } + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null etsVm_"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed status: %{public}d", status); + return; + } + if (GetObserverObject(observerObj) == nullptr) { + std::lock_guard lock(etsObserverObjectSetLock_); + ani_ref global = nullptr; + if ((status = env->GlobalReference_Create(observerObj, &global)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status : %{public}d", status); + return; + } + etsObserverObjects_.emplace_back(global); + } else { + TAG_LOGD(AAFwkTag::APPMGR, "observer exist"); + } +} + +void ETSAppForegroundStateObserver::RemoveAllEtsObserverObjects() +{ + std::lock_guard lock(etsObserverObjectSetLock_); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null etsVm_"); + return; + } + for (const auto &item : etsObserverObjects_) { + if (item == nullptr) { + continue; + } + AppManagerEts::ReleaseObjectReference(etsVm_, item); + } + etsObserverObjects_.clear(); +} + +void ETSAppForegroundStateObserver::RemoveEtsObserverObject(const ani_object &observerObj) +{ + if (observerObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + return; + } + wptr weakPtr = this; + auto it = find_if(etsObserverObjects_.begin(), + etsObserverObjects_.end(), + [weakPtr, &observerObj](ani_ref item) { + auto appForegroundStateObserver = weakPtr.promote(); + if (appForegroundStateObserver == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null appForegroundStateObserver"); + return false; + } + return appForegroundStateObserver->IsStrictEquals(item, observerObj); + }); + if (it != etsObserverObjects_.end()) { + std::lock_guard lock(etsObserverObjectSetLock_); + AppManagerEts::ReleaseObjectReference(etsVm_, *it); + etsObserverObjects_.erase(it); + } +} + +ani_ref ETSAppForegroundStateObserver::GetObserverObject(const ani_object &observerObject) +{ + if (observerObject == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + return nullptr; + } + for (auto& item : etsObserverObjects_) { + if (IsStrictEquals(item, observerObject)) { + return item; + } + } + return nullptr; +} + +void ETSAppForegroundStateObserver::SetValid(bool valid) +{ + valid_ = valid; +} + +bool ETSAppForegroundStateObserver::IsEmpty() +{ + std::lock_guard lock(etsObserverObjectSetLock_); + return etsObserverObjects_.empty(); +} + +bool ETSAppForegroundStateObserver::IsStrictEquals(ani_ref observerRef, const ani_object &etsObserverObject) +{ + if (etsVm_ == nullptr || observerRef == nullptr || etsObserverObject == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "etsVm_ or etsObserverObject or observerRef null"); + return false; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed status: %{public}d", status); + return false; + } + ani_boolean isEquals = ANI_FALSE; + if ((status = env->Reference_StrictEquals(observerRef, etsObserverObject, &isEquals)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Reference_StrictEquals failed status: %{public}d", status); + return false; + } + return isEquals == ANI_TRUE; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/app_manager/src/ets_app_manager.cpp b/frameworks/ets/ani/app_manager/src/ets_app_manager.cpp index ae0b8dcab19..27c947fef34 100644 --- a/frameworks/ets/ani/app_manager/src/ets_app_manager.cpp +++ b/frameworks/ets/ani/app_manager/src/ets_app_manager.cpp @@ -21,7 +21,10 @@ #include "ani_enum_convert.h" #include "app_mgr_constants.h" #include "app_mgr_interface.h" +#include "ets_ability_first_frame_state_observer.h" +#include "ets_app_foreground_state_observer.h" #include "ets_app_manager_utils.h" +#include "ets_app_state_observer.h" #include "ets_error_utils.h" #include "hilog_tag_wrapper.h" #include "if_system_ability_manager.h" @@ -37,36 +40,112 @@ namespace OHOS { namespace AppManagerEts { namespace { +constexpr int32_t ERR_FAILURE = -1; constexpr const char* APP_MANAGER_SPACE_NAME = "L@ohos/app/ability/appManager/appManager;"; -} +constexpr const char* ON_OFF_TYPE = "applicationState"; +constexpr const char* ON_OFF_TYPE_ABILITY_FIRST_FRAME_STATE = "abilityFirstFrameState"; +constexpr const char* ON_OFF_TYPE_APP_FOREGROUND_STATE = "appForegroundState"; + +constexpr const char *APPLICATION_STATE_WITH_BUNDLELIST_ON_SIGNATURE = + "Lstd/core/String;Lapplication/ApplicationStateObserver/ApplicationStateObserver;Lescompat/Array;:I"; +constexpr const char *APPLICATION_STATE_ON_SIGNATURE = + "Lstd/core/String;Lapplication/ApplicationStateObserver/ApplicationStateObserver;:I"; +constexpr const char *APPLICATION_STATE_OFF_SIGNATURE = "Lstd/core/String;ILutils/AbilityUtils/AsyncCallbackWrapper;:V"; +static const char* ON_SIGNATURE_ABILITY_FIRST_FRAME_STATE + = "Lstd/core/String;Lapplication/AbilityFirstFrameStateObserver/AbilityFirstFrameStateObserver;Lstd/core/String;:V"; +static const char* ON_SIGNATURE_APP_FOREGROUND_STATE + = "Lstd/core/String;Lapplication/AppForegroundStateObserver/AppForegroundStateObserver;:V"; +static const char *OFF_SIGNATURE_ABILITY_FIRST_FRAME_STATE + = "Lstd/core/String;Lapplication/AbilityFirstFrameStateObserver/AbilityFirstFrameStateObserver;:V"; +static const char *OFF_SIGNATURE_APP_FOREGROUND_STATE + = "Lstd/core/String;Lapplication/AppForegroundStateObserver/AppForegroundStateObserver;:V"; +} // namespace class EtsAppManager final { public: - static void PreloadApplication(ani_env *env, ani_object callback, ani_string aniBundleName, ani_double aniUserId, + static void PreloadApplication(ani_env *env, ani_object callback, ani_string aniBundleName, ani_int 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); + ani_int aniUserId, ani_object callback); static void GetRunningProcessInfoByBundleName(ani_env *env, ani_string aniBundleName, ani_object callback); + static void GetAppMemorySize(ani_env *env, ani_object callback); + static void IsRamConstrainedDevice(ani_env *env, ani_object callback); + static void IsRunningInStabilityTest(ani_env *env, ani_object callback); + static void NativeKillProcessesByBundleNameSync(ani_env *env, ani_string bundleName, ani_object callback); + static void NativeKillProcessesByBundleName( + ani_env *env, ani_object callback, ani_string bundleName, ani_boolean clearPageStack, ani_object stsAppIndex); + static void NativeKillProcessWithAccountSync(ani_env *env, ani_string aniBundleName, ani_int aniAccountId, + ani_object callback); + static void NativeKillProcessWithAccount(ani_env *env, ani_object callback, ani_string aniBundleName, + ani_int aniAccountId, ani_boolean clearPageStack, ani_object aniAppIndex); + static void NativeGetProcessMemoryByPid(ani_env *env, ani_int aniPid, ani_object callback); + static void GetRunningProcessInformationByBundleType( + ani_env *env, ani_enum_item aniBundleType, ani_object callback); + static void NativeIsSharedBundleRunning(ani_env *env, ani_string aniBundleName, + ani_long aniVersionCode, ani_object callback); + static void NativeGetSupportedProcessCachePids(ani_env *env, ani_string aniBundleName, ani_object callback); + static void NativeKillProcessesInBatch(ani_env *env, ani_object pids, ani_object callback); + static void NativeIsAppRunning( + ani_env *env, ani_object callback, ani_string aniBundleName, ani_object aniAppCloneIndex); + static void NativeSetKeepAliveForBundle( + ani_env *env, ani_string aniBundleName, ani_int aniUserId, ani_boolean enable, ani_object callback); + static void NativeGetKeepAliveBundles(ani_env *env, ani_object callback, ani_enum_item aniType, + ani_object aniUserId); + static ani_int OnOnApplicationStateWithBundleList(ani_env *env, ani_string type, + ani_object observer, ani_object etsBundleNameList); + static ani_int OnOnApplicationState(ani_env *env, ani_string type, ani_object observer); + static void OnOff(ani_env *env, ani_string type, ani_int etsObserverId, ani_object callback); + static void OnOnAppForegroundState(ani_env *env, ani_string type, ani_object observer); + static void OnOffAppForegroundState(ani_env *env, ani_string type, ani_object observer); + static void OnOnAbilityFirstFrameState( + ani_env *env, ani_string type, ani_object aniObserver, ani_object aniBundleName); + static void OnOffAbilityFirstFrameState(ani_env *env, ani_string type, ani_object aniObserver); + private: static sptr GetAppManagerInstance(); + static sptr GetAbilityManagerInstance(); #ifdef SUPPORT_SCREEN static bool CheckCallerIsSystemApp(); #endif - static ani_double OnOnApplicationStateInner( + static bool CheckOnOnApplicationStateInnerParam(ani_env *env, ani_string type, ani_object observer, + ani_object etsBundleNameList, std::vector &bundleNameList); + static ani_int OnOnApplicationStateInner( ani_env *env, ani_string type, ani_object observer, ani_object aniBundleNameList); + static void KillProcessesByBundleNameInner(ani_env *env, ani_object callback, ani_string etsBundleName, + ani_boolean clearPageStack, ani_object etsAppIndex); + static void KillProcessWithAccountInner(ani_env *env, ani_object callback, ani_string aniBundleName, + ani_int aniAccountId, ani_boolean clearPageStack, ani_object aniAppIndex); + static void OnOnAbilityFirstFrameStateInner(ani_env *env, ani_object aniObserver, const std::string &strBundleName); + static int32_t GetObserverId(); + static int32_t serialNumber_; + static sptr appStateObserver_; + static sptr observerForeground_; }; +int32_t EtsAppManager::serialNumber_ = 0; +sptr EtsAppManager::appStateObserver_ = nullptr; +sptr EtsAppManager::observerForeground_ = nullptr; + sptr EtsAppManager::GetAppManagerInstance() { sptr systemAbilityManager = - OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); sptr appObject = systemAbilityManager->GetSystemAbility(APP_MGR_SERVICE_ID); return iface_cast(appObject); } +sptr EtsAppManager::GetAbilityManagerInstance() +{ + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + sptr abilityObject = + systemAbilityManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + return iface_cast(abilityObject); +} + #ifdef SUPPORT_SCREEN bool EtsAppManager::CheckCallerIsSystemApp() { @@ -76,7 +155,7 @@ bool EtsAppManager::CheckCallerIsSystemApp() #endif void EtsAppManager::PreloadApplication(ani_env *env, ani_object callback, ani_string aniBundleName, - ani_double aniUserId, ani_enum_item aniMode, ani_object aniAppIndex) + ani_int aniUserId, ani_enum_item aniMode, ani_object aniAppIndex) { TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication"); if (env == nullptr) { @@ -91,9 +170,8 @@ void EtsAppManager::PreloadApplication(ani_env *env, ani_object callback, ani_st env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM)), nullptr); return; } - TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication userId:%{public}f, bundleName %{public}s", + TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication userId:%{public}d, 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)) { @@ -111,18 +189,16 @@ void EtsAppManager::PreloadApplication(ani_env *env, ani_object callback, ani_st 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); + if ((status = env->Object_CallMethodByName_Int(aniAppIndex, "intValue", nullptr, &appIndex)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_CallMethodByName_Int status : %{public}d", status); return; } - TAG_LOGD(AAFwkTag::APPMGR, "aniAppIndex: %{public}f", dval); - appIndex = static_cast(dval); + TAG_LOGD(AAFwkTag::APPMGR, "aniAppIndex: %{public}d", appIndex); } TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication userId:%{public}d, mode:%{public}d, appIndex:%{public}d", - userId, mode, appIndex); - sptr appMgr = GetAppManagerInstance(); + aniUserId, mode, appIndex); + sptr appMgr = GetAppManagerInstance(); if (appMgr == nullptr) { TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); AppExecFwk::AsyncCallback(env, callback, @@ -130,7 +206,7 @@ void EtsAppManager::PreloadApplication(ani_env *env, ani_object callback, ani_st env, static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), nullptr); return; } - auto ret = appMgr->PreloadApplication(bundleName, userId, static_cast(mode), appIndex); + auto ret = appMgr->PreloadApplication(bundleName, aniUserId, static_cast(mode), appIndex); TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication ret %{public}d", ret); AppExecFwk::AsyncCallback(env, callback, @@ -267,7 +343,7 @@ void EtsAppManager::GetRunningMultiAppInfo(ani_env *env, ani_string aniBundleNam } void EtsAppManager::GetRunningProcessInfoByBundleNameAndUserId( - ani_env *env, ani_string aniBundleName, ani_double aniUserId, ani_object callback) + ani_env *env, ani_string aniBundleName, ani_int aniUserId, ani_object callback) { TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInfoByBundleNameAndUserId called"); if (env == nullptr) { @@ -290,8 +366,7 @@ void EtsAppManager::GetRunningProcessInfoByBundleNameAndUserId( 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); + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInfoByBundleNameAndUserId userid:%{public}d", aniUserId); auto appManager = GetAppManagerInstance(); if (appManager == nullptr) { TAG_LOGE(AAFwkTag::APPMGR, "appManager nullptr"); @@ -301,7 +376,7 @@ void EtsAppManager::GetRunningProcessInfoByBundleNameAndUserId( return; } std::vector infos; - int32_t ret = appManager->GetRunningProcessInformation(bundleName, userId, infos); + int32_t ret = appManager->GetRunningProcessInformation(bundleName, aniUserId, infos); TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInformation ret: %{public}d, size:%{public}zu", ret, infos.size()); if (ret != ERR_OK) { AppExecFwk::AsyncCallback(env, callback, @@ -323,7 +398,914 @@ void EtsAppManager::GetRunningProcessInfoByBundleNameAndUserId( 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); + GetRunningProcessInfoByBundleNameAndUserId(env, aniBundleName, userId, callback); +} + +int32_t EtsAppManager::GetObserverId() +{ + int32_t observerId = serialNumber_; + if (serialNumber_ < INT32_MAX) { + serialNumber_++; + } else { + serialNumber_ = 0; + } + return observerId; +} + +bool EtsAppManager::CheckOnOnApplicationStateInnerParam(ani_env *env, ani_string type, ani_object observer, + ani_object etsBundleNameList, std::vector &bundleNameList) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return false; + } + std::string strType; + if (!AppExecFwk::GetStdString(env, type, strType) || strType != ON_OFF_TYPE) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString failed"); + AbilityRuntime::EtsErrorUtil::ThrowInvalidParamError( + env, "Parse param type failed, must be a string, value must be applicationState."); + return false; + } + ani_boolean isUndefined = false; + ani_status status = ANI_OK; + if ((status = env->Reference_IsUndefined(etsBundleNameList, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to check undefined status : %{public}d", status); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return false; + } + if (!isUndefined && !UnWrapArrayString(env, etsBundleNameList, bundleNameList)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString failed"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return false; + } + return true; +} + +ani_int EtsAppManager::OnOnApplicationStateInner(ani_env *env, ani_string type, ani_object observer, + ani_object etsBundleNameList) +{ + TAG_LOGD(AAFwkTag::APPMGR, "OnOnApplicationStateInner called"); + std::vector bundleNameList; + if (!CheckOnOnApplicationStateInnerParam(env, type, observer, etsBundleNameList, bundleNameList)) { + return ANI_ERROR; + } + auto appManager = GetAppManagerInstance(); + if (appManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null appManager"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return ANI_ERROR; + } + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "get aniVM failed"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return ANI_ERROR; + } + if (appStateObserver_ == nullptr) { + appStateObserver_ = new (std::nothrow) AbilityRuntime::EtsAppStateObserver(aniVM); + } + int32_t ret = appManager->RegisterApplicationStateObserver(appStateObserver_, bundleNameList); + TAG_LOGD(AAFwkTag::APPMGR, "err:%{public}d", ret); + if (ret == ERR_OK) { + int32_t observerId = GetObserverId(); + appStateObserver_->AddEtsObserverObject(env, observerId, observer); + TAG_LOGD(AAFwkTag::APPMGR, "OnOnApplicationStateInner end"); + return observerId; + } + AbilityRuntime::EtsErrorUtil::ThrowErrorByNativeErr(env, static_cast(ret)); + return ANI_ERROR; +} + +ani_int EtsAppManager::OnOnApplicationStateWithBundleList(ani_env *env, ani_string type, + ani_object observer, ani_object etsBundleNameList) +{ + return OnOnApplicationStateInner(env, type, observer, etsBundleNameList); +} + +ani_int EtsAppManager::OnOnApplicationState(ani_env *env, ani_string type, ani_object observer) +{ + ani_ref undefined = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return ANI_ERROR; + } + env->GetUndefined(&undefined); + return OnOnApplicationStateInner(env, type, observer, static_cast(undefined)); +} + +void EtsAppManager::OnOff(ani_env *env, ani_string type, ani_int etsObserverId, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPMGR, "OnOff called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + std::string strType; + if (!AppExecFwk::GetStdString(env, type, strType) || strType != ON_OFF_TYPE) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString failed"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateInvalidParamError( + env, "Parse param type failed, must be a string, value must be applicationState."), nullptr); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "observerId:%{public}d", etsObserverId); + int64_t observerId = static_cast(etsObserverId); + + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), + nullptr); + return; + } + if (appStateObserver_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateInvalidParamError( + env, "observer is nullptr, please register first."), nullptr); + return; + } + if (!appStateObserver_->FindObserverByObserverId(observerId)) { + TAG_LOGE(AAFwkTag::APPMGR, "not find observer:%{public}d", static_cast(observerId)); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateInvalidParamError( + env, "not find observerId."), nullptr); + return; + } + int32_t ret = appMgr->UnregisterApplicationStateObserver(appStateObserver_); + if (ret == 0 && appStateObserver_->RemoveEtsObserverObject(observerId)) { + TAG_LOGD(AAFwkTag::APPMGR, "OnOff success"); + } else { + TAG_LOGE(AAFwkTag::APPMGR, "OnOff err:%{public}d", ret); + } + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), nullptr); + TAG_LOGD(AAFwkTag::APPMGR, "OnOff end"); +} + +void EtsAppManager::GetAppMemorySize(ani_env *env, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPMGR, "GetAppMemorySize called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + auto abilityManager = GetAbilityManagerInstance(); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "abilityManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), + AppExecFwk::CreateInt(env, ERR_FAILURE)); + return; + } + int32_t memorySize = abilityManager->GetAppMemorySize(); + TAG_LOGD(AAFwkTag::APPMGR, "memorySize:%{public}d", memorySize); + + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ERR_OK)), + AppExecFwk::CreateInt(env, memorySize)); + TAG_LOGD(AAFwkTag::APPMGR, "GetAppMemorySize end"); +} + +void EtsAppManager::IsRamConstrainedDevice(ani_env *env, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPMGR, "IsRamConstrainedDevice called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + auto abilityManager = GetAbilityManagerInstance(); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "abilityManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), + AppExecFwk::CreateBoolean(env, false)); + return; + } + bool ret = abilityManager->IsRamConstrainedDevice(); + TAG_LOGD(AAFwkTag::APPMGR, "IsRamConstrainedDevice:%{public}d", ret); + + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ERR_OK)), + AppExecFwk::CreateBoolean(env, static_cast(ret))); + TAG_LOGD(AAFwkTag::APPMGR, "IsRamConstrainedDevice end"); +} + +void EtsAppManager::IsRunningInStabilityTest(ani_env *env, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPMGR, "IsRunningInStabilityTest called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + auto abilityManager = GetAbilityManagerInstance(); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "abilityManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), + AppExecFwk::CreateBoolean(env, false)); + return; + } + bool ret = abilityManager->IsRunningInStabilityTest(); + TAG_LOGD(AAFwkTag::APPMGR, "IsRunningInStabilityTest:%{public}d", ret); + + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ERR_OK)), + AppExecFwk::CreateBoolean(env, static_cast(ret))); + TAG_LOGD(AAFwkTag::APPMGR, "IsRunningInStabilityTest end"); +} + +void EtsAppManager::NativeKillProcessesByBundleNameSync(ani_env *env, ani_string bundleName, ani_object callback) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_ref undefined = nullptr; + env->GetUndefined(&undefined); + KillProcessesByBundleNameInner(env, callback, bundleName, false, static_cast(undefined)); +} + +void EtsAppManager::NativeKillProcessesByBundleName(ani_env *env, ani_object callback, ani_string bundleName, + ani_boolean clearPageStack, ani_object etsAppIndex) +{ + KillProcessesByBundleNameInner(env, callback, bundleName, clearPageStack, etsAppIndex); +} + +void EtsAppManager::KillProcessesByBundleNameInner(ani_env *env, ani_object callback, ani_string etsBundleName, + ani_boolean clearPageStack, ani_object etsAppIndex) +{ + TAG_LOGD(AAFwkTag::APPMGR, "KillProcessesByBundleNameInner called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + auto abilityManager = GetAbilityManagerInstance(); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "abilityManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), nullptr); + return; + } + ani_status status = ANI_OK; + std::string bundleName; + if (!AppExecFwk::GetStdString(env, etsBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateInvalidParamError( + env, "Parse param bundleName failed, must be a string."), nullptr); + return; + } + int32_t appIndex = 0; + ani_boolean isUndefined = false; + if ((status = env->Reference_IsUndefined(etsAppIndex, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to check undefined status : %{public}d", status); + return; + } + if (!isUndefined) { + if ((status = env->Object_CallMethodByName_Int(etsAppIndex, + "toInt", nullptr, &appIndex)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_CallMethodByName_Int status : %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "etsAppIndex: %{public}d", appIndex); + } + auto ret = abilityManager->KillProcess(bundleName, clearPageStack, appIndex); + TAG_LOGD(AAFwkTag::APPMGR, "KillProcess ret: %{public}d", ret); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), nullptr); + TAG_LOGD(AAFwkTag::APPMGR, "KillProcessesByBundleNameInner end"); +} + +void EtsAppManager::NativeKillProcessWithAccountSync(ani_env *env, ani_string aniBundleName, ani_int aniAccountId, + ani_object callback) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_ref undefined = nullptr; + env->GetUndefined(&undefined); + KillProcessWithAccountInner(env, callback, aniBundleName, aniAccountId, + false, static_cast(undefined)); +} + +void EtsAppManager::NativeKillProcessWithAccount(ani_env *env, ani_object callback, ani_string aniBundleName, + ani_int aniAccountId, ani_boolean clearPageStack, ani_object aniAppIndex) +{ + KillProcessWithAccountInner(env, callback, aniBundleName, aniAccountId, + clearPageStack, aniAppIndex); +} + +void EtsAppManager::KillProcessWithAccountInner(ani_env *env, ani_object callback, ani_string aniBundleName, + ani_int aniAccountId, ani_boolean clearPageStack, ani_object aniAppIndex) +{ + TAG_LOGD(AAFwkTag::APPMGR, "KillProcessWithAccountInner called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr || appMgr->GetAmsMgr() == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), nullptr); + return; + } + std::string bundleName; + if (!AppExecFwk::GetStdString(env, aniBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateInvalidParamError( + env, "Parse param bundleName failed, must be a string."), nullptr); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "KillProcessWithAccount accountId:%{public}d", aniAccountId); + int32_t appIndex = 0; + ani_status status = ANI_OK; + 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; + } + if (!isUndefined) { + if ((status = env->Object_CallMethodByName_Int(aniAppIndex, + "toInt", nullptr, &appIndex)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_CallMethodByName_Int status : %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "stsAppIndex: %{public}d", appIndex); + } + auto ret = appMgr->GetAmsMgr()->KillProcessWithAccount(bundleName, aniAccountId, clearPageStack, appIndex); + TAG_LOGD(AAFwkTag::APPMGR, "KillProcessWithAccount ret: %{public}d", ret); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), nullptr); + TAG_LOGD(AAFwkTag::APPMGR, "KillProcessWithAccount end"); +} + +void EtsAppManager::NativeGetProcessMemoryByPid(ani_env *env, ani_int aniPid, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPMGR, "NativeGetProcessMemoryByPid called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "NativeGetProcessMemoryByPid pid:%{public}d", aniPid); + + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), + AppExecFwk::CreateInt(env, ERR_FAILURE)); + return; + } + int32_t memSize = 0; + int32_t ret = appMgr->GetProcessMemoryByPid(aniPid, memSize); + TAG_LOGD(AAFwkTag::APPMGR, "NativeGetProcessMemoryByPid memSize: %{public}d, ret:%{public}d", memSize, ret); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), + AppExecFwk::CreateInt(env, memSize)); + TAG_LOGD(AAFwkTag::APPMGR, "NativeGetProcessMemoryByPid end"); +} + +void EtsAppManager::GetRunningProcessInformationByBundleType( + ani_env *env, ani_enum_item aniBundleType, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInformationByBundleType 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, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + return; + } + ani_int bundleType; + if (!AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative(env, aniBundleType, bundleType)) { + TAG_LOGE(AAFwkTag::APPMGR, "param aniBundleType err"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateInvalidParamError( + env, "Parse param bundleType failed, must be a BundleType."), emptyArray); + return; + } + std::vector infos; + auto ret = appMgr->GetRunningProcessesByBundleType(static_cast(bundleType), infos); + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInformationByBundleType ret:%{public}d, size:%{public}zu", + ret, infos.size()); + if (ret != ERR_OK) { + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), emptyArray); + return; + } + ani_object aniInfosRef = CreateRunningProcessInfoArray(env, infos); + if (aniInfosRef == nullptr) { + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + } else { + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), aniInfosRef); + } + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInformationByBundleType end"); +} + +void EtsAppManager::NativeIsSharedBundleRunning(ani_env *env, ani_string aniBundleName, + ani_long aniVersionCode, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPMGR, "NativeIsSharedBundleRunning called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), + AppExecFwk::CreateBoolean(env, false)); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "NativeGetProcessMemoryByPid pid:%{public}lld", aniVersionCode); + uint32_t versionCode = static_cast(aniVersionCode); + + std::string bundleName; + if (!AppExecFwk::GetStdString(env, aniBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateInvalidParamError( + env, "Parse param bundleName failed, must be a string."), AppExecFwk::CreateBoolean(env, false)); + return; + } + bool ret = appMgr->IsSharedBundleRunning(bundleName, versionCode); + TAG_LOGD(AAFwkTag::APPMGR, "NativeIsSharedBundleRunning ret :%{public}d", ret); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ERR_OK)), + AppExecFwk::CreateBoolean(env, static_cast(ret))); + TAG_LOGD(AAFwkTag::APPMGR, "NativeIsSharedBundleRunning end"); +} + +void EtsAppManager::NativeGetSupportedProcessCachePids(ani_env *env, ani_string aniBundleName, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPMGR, "NativeGetSupportedProcessCachePids 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, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + return; + } + std::string bundleName; + if (!AppExecFwk::GetStdString(env, aniBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateInvalidParamError( + env, "Parse param bundleName failed, must be a string."), emptyArray); + return; + } + std::vector list; + int32_t ret = appMgr->GetSupportedProcessCachePids(bundleName, list); + TAG_LOGD(AAFwkTag::APPMGR, "GetSupportedProcessCachePids ret:%{public}d, size:%{public}zu", ret, list.size()); + if (ret != ERR_OK) { + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), emptyArray); + return; + } + ani_object arrayObj = CreateIntAniArray(env, list); + if (arrayObj == nullptr) { + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + } else { + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)), arrayObj); + } + TAG_LOGD(AAFwkTag::APPMGR, "NativeGetSupportedProcessCachePids end"); +} + +void EtsAppManager::NativeKillProcessesInBatch(ani_env *env, ani_object pids, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPMGR, "NativeKillProcessesInBatch called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr || appMgr->GetAmsMgr() == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), nullptr); + return; + } + std::vector pidList; + if (!UnWrapArrayInt(env, pids, pidList)) { + TAG_LOGE(AAFwkTag::APPMGR, "Parse pids failed"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateInvalidParamError( + env, "Parse param pids failed, must be array of numbers."), nullptr); + return; + } + int32_t innerErrorCode = appMgr->GetAmsMgr()->KillProcessesInBatch(pidList); + TAG_LOGD(AAFwkTag::APPMGR, "NativeKillProcessesInBatch ret:%{public}d", innerErrorCode); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(innerErrorCode)), nullptr); + TAG_LOGD(AAFwkTag::APPMGR, "NativeKillProcessesInBatch end"); +} + +void EtsAppManager::NativeIsAppRunning(ani_env *env, ani_object callback, ani_string aniBundleName, + ani_object aniAppCloneIndex) +{ + TAG_LOGD(AAFwkTag::APPMGR, "NativeIsAppRunning called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), + AppExecFwk::CreateBoolean(env, false)); + return; + } + std::string bundleName; + if (!AppExecFwk::GetStdString(env, aniBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateInvalidParamError( + env, "Parse param bundleName failed, must be a string."), AppExecFwk::CreateBoolean(env, false)); + return; + } + ani_status status = ANI_OK; + int32_t appCloneIndex = 0; + ani_boolean isUndefined = false; + if ((status = env->Reference_IsUndefined(aniAppCloneIndex, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to check undefined status : %{public}d", status); + return; + } + if (!isUndefined) { + if ((status = env->Object_CallMethodByName_Int(aniAppCloneIndex, + "toInt", nullptr, &appCloneIndex)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_CallMethodByName_Int status : %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "aniAppCloneIndex: %{public}d", appCloneIndex); + } + bool isRunnig = false; + int32_t innerErrorCode = appMgr->IsAppRunning(bundleName, appCloneIndex, isRunnig); + TAG_LOGD(AAFwkTag::APPMGR, "innerErrorCode:%{public}d, isRunning:%{public}d", innerErrorCode, isRunnig); + if (innerErrorCode == ERR_OK) { + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(innerErrorCode)), + AppExecFwk::CreateBoolean(env, isRunnig)); + } else { + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(innerErrorCode)), + AppExecFwk::CreateBoolean(env, false)); + } + TAG_LOGD(AAFwkTag::APPMGR, "NativeIsAppRunning end"); +} + +void EtsAppManager::NativeSetKeepAliveForBundle(ani_env *env, ani_string aniBundleName, + ani_int aniUserId, ani_boolean enable, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPMGR, "NativeSetKeepAliveForBundle called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + auto abilityManager = GetAbilityManagerInstance(); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "abilityManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateError( + env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER), nullptr); + return; + } + std::string bundleName; + if (!AppExecFwk::GetStdString(env, aniBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateInvalidParamError( + env, "Parse param bundleName failed, must be a string."), nullptr); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "KillProcessWithAccount aniUserId:%{public}d", aniUserId); + int32_t innerErrCode = abilityManager->SetApplicationKeepAlive(bundleName, aniUserId, enable); + TAG_LOGD(AAFwkTag::APPMGR, "innerErrCode:%{public}d", innerErrCode); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(innerErrCode)), nullptr); + TAG_LOGD(AAFwkTag::APPMGR, "NativeSetKeepAliveForBundle end"); +} + +void EtsAppManager::NativeGetKeepAliveBundles(ani_env *env, ani_object callback, ani_enum_item aniType, + ani_object aniUserId) +{ + TAG_LOGD(AAFwkTag::APPMGR, "NativeGetKeepAliveBundles called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_object emptyArray = CreateEmptyAniArray(env); + auto abilityManager = GetAbilityManagerInstance(); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "abilityManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateError( + env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER), nullptr); + return; + } + ani_int appType = 0; + if (!AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative(env, aniType, appType)) { + TAG_LOGE(AAFwkTag::APPMGR, "param mode err"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateInvalidParamError( + env, "Parse param appType failed, must be a number."), nullptr); + return; + } + ani_status status = ANI_OK; + int32_t userId = -1; + ani_boolean isUndefined = false; + if ((status = env->Reference_IsUndefined(aniUserId, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to check undefined status : %{public}d", status); + return; + } + if (!isUndefined) { + if ((status = env->Object_CallMethodByName_Int(aniUserId, + "toInt", nullptr, &userId)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_CallMethodByName_Int status : %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "stsAppIndex: %{public}d", userId); + } + std::vector infoList; + int32_t innerErrCode = abilityManager->QueryKeepAliveApplications(appType, userId, infoList); + TAG_LOGD(AAFwkTag::APPMGR, "GetSupportedProcessCachePids innerErrCode:%{public}d, size:%{public}zu", + innerErrCode, infoList.size()); + if (innerErrCode != ERR_OK) { + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(innerErrCode)), emptyArray); + return; + } + ani_object arrayObj = CreateKeepAliveInfoArray(env, infoList); + if (arrayObj == nullptr) { + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + } else { + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(innerErrCode)), arrayObj); + } + TAG_LOGD(AAFwkTag::APPMGR, "NativeGetKeepAliveBundles end"); +} + +void EtsAppManager::OnOnAbilityFirstFrameStateInner( + ani_env *env, ani_object aniObserver, const std::string &strBundleName) +{ +#ifdef SUPPORT_SCREEN + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "get aniVM failed"); + AbilityRuntime::EtsErrorUtil::ThrowInvalidParamError(env, "Get aniVm failed."); + return; + } + auto abilityManager = GetAbilityManagerInstance(); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "abilityManager null ptr"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + sptr observer = + new (std::nothrow) AbilityRuntime::ETSAbilityFirstFrameStateObserver(aniVM); + if (observer == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null abilityMgr_ or observer"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + if (AbilityRuntime::ETSAbilityFirstFrameStateObserverManager::GetInstance()->IsObserverObjectExist(aniObserver)) { + TAG_LOGE(AAFwkTag::APPMGR, "observer exist"); + return; + } + int32_t ret = abilityManager->RegisterAbilityFirstFrameStateObserver(observer, strBundleName); + TAG_LOGD(AAFwkTag::APPMGR, "ret: %{public}d", ret); + if (ret != NO_ERROR) { + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + observer->SetEtsObserverObject(aniObserver); + AbilityRuntime::ETSAbilityFirstFrameStateObserverManager::GetInstance()->AddEtsAbilityFirstFrameStateObserver( + observer); +#endif +} + +void EtsAppManager::OnOnAbilityFirstFrameState( + ani_env *env, ani_string type, ani_object aniObserver, ani_object aniBundleName) +{ +#ifdef SUPPORT_SCREEN + TAG_LOGD(AAFwkTag::APPMGR, "OnOnAbilityFirstFrameState called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + if (!CheckCallerIsSystemApp()) { + TAG_LOGE(AAFwkTag::APPMGR, "Non-system app"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); + return; + } + std::string strType; + if (!OHOS::AppExecFwk::GetStdString(env, type, strType) + && strType != ON_OFF_TYPE_ABILITY_FIRST_FRAME_STATE) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString failed"); + AbilityRuntime::EtsErrorUtil::ThrowInvalidParamError(env, + "Parse param observer failed, must be a AbilityFirstFrameStateObserver."); + return; + } + ani_status status = ANI_OK; + std::string strBundleName; + ani_boolean isUndefined; + if ((status = env->Reference_IsUndefined(aniBundleName, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to check undefined status : %{public}d", status); + return; + } + if (!isUndefined && !OHOS::AppExecFwk::GetStdString(env, + reinterpret_cast(aniBundleName), strBundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString failed"); + AbilityRuntime::EtsErrorUtil::ThrowInvalidParamError(env, "Parse param bundleName failed, must be a string."); + return; + } + OnOnAbilityFirstFrameStateInner(env, aniObserver, strBundleName); + TAG_LOGD(AAFwkTag::APPMGR, "OnOnAbilityFirstFrameState end"); +#endif +} + +void EtsAppManager::OnOnAppForegroundState(ani_env *env, ani_string type, ani_object observer) +{ + TAG_LOGD(AAFwkTag::APPMGR, "OnOnAppForegroundState called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "get aniVM failed"); + AbilityRuntime::EtsErrorUtil::ThrowInvalidParamError(env, "Get aniVm failed."); + return; + } + std::string strType; + if (!OHOS::AppExecFwk::GetStdString(env, type, strType) + && strType != ON_OFF_TYPE_APP_FOREGROUND_STATE) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString failed"); + AbilityRuntime::EtsErrorUtil::ThrowInvalidParamError(env, + "Parse param observer failed, must be a AppForegroundStateObserver."); + return; + } + + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + //Create Observer + if (observerForeground_ == nullptr) { + observerForeground_ = new (std::nothrow) AbilityRuntime::ETSAppForegroundStateObserver(aniVM); + } + if (observerForeground_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null appMgr or observer"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + if (observerForeground_->IsEmpty()) { + int32_t ret = appMgr->RegisterAppForegroundStateObserver(observerForeground_); + TAG_LOGD(AAFwkTag::APPMGR, "RegisterAppForegroundStateObserver ret: %{public}d", ret); + if (ret != NO_ERROR) { + AbilityRuntime::EtsErrorUtil::ThrowErrorByNativeErr(env, static_cast(ret)); + return; + } + } + observerForeground_->AddEtsObserverObject(observer); + TAG_LOGD(AAFwkTag::APPMGR, "OnOnAppForegroundState end"); +} + +void EtsAppManager::OnOffAbilityFirstFrameState(ani_env *env, ani_string type, ani_object aniObserver) +{ +#ifdef SUPPORT_SCREEN + TAG_LOGD(AAFwkTag::APPMGR, "OnOffAbilityFirstFrameState called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + if (!CheckCallerIsSystemApp()) { + TAG_LOGE(AAFwkTag::APPMGR, "Non-system app"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); + return; + } + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "get aniVM failed"); + AbilityRuntime::EtsErrorUtil::ThrowInvalidParamError(env, "Get aniVm failed."); + return; + } + std::string strType; + if (!OHOS::AppExecFwk::GetStdString(env, type, strType) + && strType != ON_OFF_TYPE_ABILITY_FIRST_FRAME_STATE) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString failed"); + AbilityRuntime::EtsErrorUtil::ThrowInvalidParamError(env, + "Parse param observer failed, must be a AbilityFirstFrameStateObserver."); + return; + } + ani_status status = ANI_OK; + ani_boolean isUndefined = false; + if ((status = env->Reference_IsUndefined(aniObserver, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to check undefined status : %{public}d", status); + return; + } + auto abilityManager = GetAbilityManagerInstance(); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "abilityManager null ptr"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + if (isUndefined) { + AbilityRuntime::ETSAbilityFirstFrameStateObserverManager::GetInstance()->RemoveAllEtsObserverObjects( + abilityManager); + } else { + AbilityRuntime::ETSAbilityFirstFrameStateObserverManager::GetInstance()->RemoveEtsObserverObject( + abilityManager, aniObserver); + } + TAG_LOGD(AAFwkTag::APPMGR, "OnOffAbilityFirstFrameState end"); +#endif +} + +void EtsAppManager::OnOffAppForegroundState(ani_env *env, ani_string type, ani_object observer) +{ + TAG_LOGD(AAFwkTag::APPMGR, "OnOffAppForegroundState called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + std::string strType; + if (!OHOS::AppExecFwk::GetStdString(env, type, strType) + && strType != ON_OFF_TYPE_APP_FOREGROUND_STATE) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString failed"); + AbilityRuntime::EtsErrorUtil::ThrowInvalidParamError(env, + "Parse param observer failed, must be a AppForegroundStateObserver."); + return; + } + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + if (observerForeground_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null observer or appMgr"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + ani_status status = ANI_OK; + ani_boolean isUndefined = false; + if ((status = env->Reference_IsUndefined(observer, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to check undefined status : %{public}d", status); + return; + } + if (isUndefined) { + observerForeground_->RemoveAllEtsObserverObjects(); + } else { + observerForeground_->RemoveEtsObserverObject(observer); + } + if (observerForeground_->IsEmpty()) { + int32_t ret = appMgr->UnregisterAppForegroundStateObserver(observerForeground_); + TAG_LOGD(AAFwkTag::APPMGR, "ret: %{public}d.", ret); + if (ret != NO_ERROR) { + AbilityRuntime::EtsErrorUtil::ThrowErrorByNativeErr(env, static_cast(ret)); + } + } + TAG_LOGD(AAFwkTag::APPMGR, "OnOffAppForegroundState end"); } void EtsAppManagerRegistryInit(ani_env *env) @@ -346,20 +1328,61 @@ void EtsAppManagerRegistryInit(ani_env *env) std::array kitFunctions = { ani_native_function{ "nativePreloadApplication", nullptr, reinterpret_cast(EtsAppManager::PreloadApplication)}, - ani_native_function{"nativeGetRunningProcessInformation", - nullptr, + ani_native_function{"nativeGetRunningProcessInformation", nullptr, reinterpret_cast(EtsAppManager::GetRunningProcessInformation)}, - ani_native_function{"nativeGetForegroundApplications", - nullptr, + ani_native_function{"nativeGetForegroundApplications", nullptr, reinterpret_cast(EtsAppManager::GetForegroundApplications)}, ani_native_function{ "nativeGetRunningMultiAppInfo", nullptr, reinterpret_cast(EtsAppManager::GetRunningMultiAppInfo)}, - ani_native_function{"nativeGetRunningProcessInfoByBundleName", - nullptr, + ani_native_function{"nativeGetRunningProcessInfoByBundleName", nullptr, reinterpret_cast(EtsAppManager::GetRunningProcessInfoByBundleName)}, - ani_native_function{"nativeGetRunningProcessInfoByBundleNameAndUserId", - nullptr, - reinterpret_cast(EtsAppManager::GetRunningProcessInfoByBundleNameAndUserId)}}; + ani_native_function{"nativeGetRunningProcessInfoByBundleNameAndUserId", nullptr, + reinterpret_cast(EtsAppManager::GetRunningProcessInfoByBundleNameAndUserId)}, + ani_native_function {"nativeOn", APPLICATION_STATE_WITH_BUNDLELIST_ON_SIGNATURE, + reinterpret_cast(EtsAppManager::OnOnApplicationStateWithBundleList)}, + ani_native_function {"nativeOn", APPLICATION_STATE_ON_SIGNATURE, + reinterpret_cast(EtsAppManager::OnOnApplicationState)}, + ani_native_function {"nativeOff", APPLICATION_STATE_OFF_SIGNATURE, + reinterpret_cast(EtsAppManager::OnOff)}, + ani_native_function {"nativeGetAppMemorySize", nullptr, + reinterpret_cast(EtsAppManager::GetAppMemorySize)}, + ani_native_function {"nativeIsRamConstrainedDevice", nullptr, + reinterpret_cast(EtsAppManager::IsRamConstrainedDevice)}, + ani_native_function {"nativeIsRunningInStabilityTest", nullptr, + reinterpret_cast(EtsAppManager::IsRunningInStabilityTest)}, + ani_native_function {"nativeKillProcessesByBundleNameSync", nullptr, + reinterpret_cast(EtsAppManager::NativeKillProcessesByBundleNameSync)}, + ani_native_function {"nativeKillProcessesByBundleName", nullptr, + reinterpret_cast(EtsAppManager::NativeKillProcessesByBundleName)}, + ani_native_function {"nativeKillProcessWithAccountSync", nullptr, + reinterpret_cast(EtsAppManager::NativeKillProcessWithAccountSync)}, + ani_native_function {"nativeKillProcessWithAccount", nullptr, + reinterpret_cast(EtsAppManager::NativeKillProcessWithAccount)}, + ani_native_function {"nativeGetProcessMemoryByPid", nullptr, + reinterpret_cast(EtsAppManager::NativeGetProcessMemoryByPid)}, + ani_native_function {"nativeGetRunningProcessInformationByBundleType", nullptr, + reinterpret_cast(EtsAppManager::GetRunningProcessInformationByBundleType)}, + ani_native_function {"nativeIsSharedBundleRunning", nullptr, + reinterpret_cast(EtsAppManager::NativeIsSharedBundleRunning)}, + ani_native_function {"nativeGetSupportedProcessCachePids", nullptr, + reinterpret_cast(EtsAppManager::NativeGetSupportedProcessCachePids)}, + ani_native_function {"nativeKillProcessesInBatch", nullptr, + reinterpret_cast(EtsAppManager::NativeKillProcessesInBatch)}, + ani_native_function {"nativeIsAppRunning", nullptr, + reinterpret_cast(EtsAppManager::NativeIsAppRunning)}, + ani_native_function {"nativeSetKeepAliveForBundle", nullptr, + reinterpret_cast(EtsAppManager::NativeSetKeepAliveForBundle)}, + ani_native_function {"nativeGetKeepAliveBundles", nullptr, + reinterpret_cast(EtsAppManager::NativeGetKeepAliveBundles)}, + ani_native_function {"nativeOnAppForeGroundState", ON_SIGNATURE_APP_FOREGROUND_STATE, + reinterpret_cast(EtsAppManager::OnOnAppForegroundState)}, + ani_native_function {"nativeOffAppForeGroundState", OFF_SIGNATURE_APP_FOREGROUND_STATE, + reinterpret_cast(EtsAppManager::OnOffAppForegroundState)}, + ani_native_function {"nativeOnAbilityFirstFrameState", ON_SIGNATURE_ABILITY_FIRST_FRAME_STATE, + reinterpret_cast(EtsAppManager::OnOnAbilityFirstFrameState)}, + ani_native_function {"nativeOffAbilityFirstFrameState", OFF_SIGNATURE_ABILITY_FIRST_FRAME_STATE, + reinterpret_cast(EtsAppManager::OnOffAbilityFirstFrameState)}, + }; status = env->Namespace_BindNativeFunctions(ns, kitFunctions.data(), kitFunctions.size()); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::APPMGR, "Namespace_BindNativeFunctions failed status : %{public}d", status); 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 index 500fa37d7d7..5844ad4197b 100644 --- a/frameworks/ets/ani/app_manager/src/ets_app_manager_utils.cpp +++ b/frameworks/ets/ani/app_manager/src/ets_app_manager_utils.cpp @@ -26,13 +26,20 @@ 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 *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/RunningMultiInstanceInfo/RunningMultiInstanceInfoInner;"; +constexpr const char *CLONE_INNER_CLASS_NAME = "Lapplication/RunningAppClone/RunningAppCloneInner;"; constexpr const char *PROCESS_DATA_CLASS_NAME = "Lapplication/ProcessData/ProcessData;"; constexpr const char *MULTI_APP_MODE_ENUM_NAME = "Lapplication/MultiAppMode/MultiAppMode;"; +constexpr const char *KEEP_ALIVE_APP_TYPE_ENUM_NAME = "L@ohos/app/ability/appManager/appManager/KeepAliveAppType;"; +constexpr const char *KEEP_ALIVE_APP_SETTER_ENUM_NAME = "L@ohos/app/ability/appManager/appManager/KeepAliveSetter;"; +constexpr const char *KEEP_ALIVE_BUNDLE_INFO_INNER_CLASS_NAME = + "L@ohos/app/ability/appManager/appManager/KeepAliveBundleInfoInner;"; +constexpr const char *ABILITY_FIRST_FRAME_STATE_DATA_CLASS_NAME = + "Lapplication/AbilityFirstFrameStateData/AbilityFirstFrameStateDataInner;"; } // namespace ani_object WrapAppStateData(ani_env *env, const AppExecFwk::AppStateData &appStateData) @@ -355,7 +362,8 @@ ani_object CreateRunningAppCloneArray(ani_env *env, const std::vectorObject_SetPropertyByName_Int(object, "uid", instanceInfo.uid)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "uid failed status:%{public}d", status); + return false; + } + ani_class arrayCls = nullptr; + status = env->FindClass(CLASSNAME_ARRAY, &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "find class failed status : %{public}d", status); + return false; + } + ani_method arrayCtor; + status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "find ctor failed status : %{public}d", status); + return false; + } + ani_object arrayObj; + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, instanceInfo.pids.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_New array failed status : %{public}d", status); + return false; + } + ani_size index = 0; + for (auto &pid : instanceInfo.pids) { + ani_object aniPid = AppExecFwk::CreateInt(env, pid); + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, aniPid); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "set failed status : %{public}d", status); + return false; + } + index++; + } + if ((status = env->Object_SetPropertyByName_Ref(object, "pids", arrayObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "pids failed status:%{public}d", status); + return false; + } return true; } @@ -524,12 +568,12 @@ bool SetRunningAppClone(ani_env *env, ani_object object, const AppExecFwk::Runni TAG_LOGE(AAFwkTag::APPMGR, "null env"); return false; } - ani_status status = env->Object_SetPropertyByName_Double(object, "appCloneIndex", runningAppClone.appCloneIndex); + ani_status status = env->Object_SetPropertyByName_Int(object, "appCloneIndex", runningAppClone.appCloneIndex); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::APPMGR, "appCloneIndex failed status:%{public}d", status); return false; } - status = env->Object_SetPropertyByName_Double(object, "uid", runningAppClone.uid); + status = env->Object_SetPropertyByName_Int(object, "uid", runningAppClone.uid); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::APPMGR, "uid failed status:%{public}d", status); return false; @@ -554,7 +598,8 @@ bool SetRunningAppClone(ani_env *env, ani_object object, const AppExecFwk::Runni } ani_size index = 0; for (auto &pid : runningAppClone.pids) { - status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ID;:V", index, pid); + ani_object aniPid = AppExecFwk::CreateInt(env, pid); + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, aniPid); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::APPMGR, "set failed status : %{public}d", status); return false; @@ -618,17 +663,17 @@ bool SetProcessData(ani_env *env, ani_object object, const AppExecFwk::ProcessDa TAG_LOGE(AAFwkTag::APPMGR, "bundleName failed status:%{public}d", status); return false; } - status = env->Object_SetFieldByName_Double(object, "pid", processData.pid); + status = env->Object_SetFieldByName_Int(object, "pid", processData.pid); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::APPMGR, "pid failed status:%{public}d", status); return false; } - status = env->Object_SetFieldByName_Double(object, "uid", processData.uid); + status = env->Object_SetFieldByName_Int(object, "uid", processData.uid); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::APPMGR, "uid failed status:%{public}d", status); return false; } - status = env->Object_SetFieldByName_Double(object, "state", static_cast(processData.state)); + status = env->Object_SetFieldByName_Int(object, "state", static_cast(processData.state)); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::APPMGR, "state failed status:%{public}d", status); return false; @@ -676,7 +721,7 @@ bool UnWrapArrayString(ani_env *env, ani_object arrayObj, std::vector &dataArry) +ani_object CreateIntAniArray(ani_env * env, const std::vector &dataArry) { ani_class arrayCls = nullptr; ani_status status = ANI_OK; @@ -707,7 +752,7 @@ ani_object CreateDoubleAniArray(ani_env * env, const std::vector &dataA } for (size_t i = 0; i < dataArry.size(); i++) { - ani_object intObj = AppExecFwk::CreateDouble(env, static_cast(dataArry[i])); + ani_object intObj = AppExecFwk::CreateInt(env, dataArry[i]); if (intObj == nullptr) { TAG_LOGE(AAFwkTag::APPMGR, "intObj nullptr"); return nullptr; @@ -720,5 +765,277 @@ ani_object CreateDoubleAniArray(ani_env * env, const std::vector &dataA } return arrayObj; } + +bool UnWrapArrayInt(ani_env *env, ani_object arrayObj, std::vector &list) +{ + if (env == nullptr || arrayObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null or arrayObj null"); + return false; + } + list.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; + 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::APPMGR, "status : %{public}d, index: %{public}zu", status, idx); + return false; + } + ani_int ival = 0; + if ((status = env->Object_CallMethodByName_Int(static_cast(ref), + "unboxed", nullptr, &ival)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_CallMethodByName_Int status : %{public}d", status); + return false; + } + list.push_back(ival); + } + return true; +} + +ani_object WrapKeepAliveInfo(ani_env *env, const AbilityRuntime::KeepAliveInfo &keepAliveInfo) +{ + ani_class cls {}; + ani_status status = ANI_ERROR; + ani_method method {}; + ani_object object = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + if ((status = env->FindClass(KEEP_ALIVE_BUNDLE_INFO_INNER_CLASS_NAME, &cls)) + != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "find class 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; + } + if (!SetKeepAliveInfo(env, object, keepAliveInfo)) { + TAG_LOGE(AAFwkTag::APPMGR, "SetKeepAliveInfo failed"); + return nullptr; + } + return object; +} + +bool SetKeepAliveInfo(ani_env *env, ani_object object, const AbilityRuntime::KeepAliveInfo &keepInfo) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return false; + } + ani_status status = ANI_OK; + if ((status = env->Object_SetPropertyByName_Ref(object, "bundleName", + OHOS::AppExecFwk::GetAniString(env, keepInfo.bundleName))) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "bundleName failed status:%{public}d", status); + return false; + } + ani_enum_item typeItem {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts( + env, KEEP_ALIVE_APP_TYPE_ENUM_NAME, keepInfo.appType, typeItem); + if ((status = env->Object_SetPropertyByName_Ref(object, "type", typeItem)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "state failed status:%{public}d", status); + return false; + } + ani_enum_item setterItem {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts( + env, KEEP_ALIVE_APP_SETTER_ENUM_NAME, keepInfo.setter, setterItem); + if ((status = env->Object_SetPropertyByName_Ref(object, "setter", setterItem)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "state failed status:%{public}d", status); + return false; + } + return true; +} + +ani_object CreateKeepAliveInfoArray(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, "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::APPMGR, "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::APPMGR, "Object_New array status : %{public}d", status); + return arrayObj; + } + ani_size index = 0; + for (auto &info : infos) { + ani_object ani_info = WrapKeepAliveInfo(env, info); + if (ani_info == nullptr) { + TAG_LOGW(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_LOGW(AAFwkTag::APPMGR, "Object_CallMethodByName_Void failed status : %{public}d", status); + break; + } + index++; + } + return arrayObj; +} +#ifdef SUPPORT_GRAPHICS +bool SetAbilityFirstFrameStateData(ani_env *env, ani_object object, + const AppExecFwk::AbilityFirstFrameStateData &abilityFirstFrameStateData) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return false; + } + ani_status status = ANI_OK; + const std::string &strBundleName = abilityFirstFrameStateData.bundleName; + if ((status = env->Object_SetPropertyByName_Ref(object, "bundleName", + OHOS::AppExecFwk::GetAniString(env, strBundleName))) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "bundleName failed status:%{public}d", status); + return false; + } + const std::string &strModuleName = abilityFirstFrameStateData.moduleName; + if ((status = env->Object_SetPropertyByName_Ref(object, "moduleName", + OHOS::AppExecFwk::GetAniString(env, strModuleName))) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "moduleName failed status:%{public}d", status); + return false; + } + const std::string &strAbilityName = abilityFirstFrameStateData.abilityName; + if ((status = env->Object_SetPropertyByName_Ref(object, "abilityName", + OHOS::AppExecFwk::GetAniString(env, strAbilityName))) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "abilityName failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetPropertyByName_Int(object, "appIndex", + abilityFirstFrameStateData.appIndex)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "appIndex failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetPropertyByName_Boolean(object, "isColdStart", + abilityFirstFrameStateData.coldStart)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "isColdStart failed status:%{public}d", status); + return false; + } + return true; +} + +ani_object WrapAbilityFirstFrameStateData(ani_env *env, + const AppExecFwk::AbilityFirstFrameStateData &abilityFirstFrameStateData) +{ + ani_class cls {}; + ani_status status = ANI_ERROR; + ani_method method {}; + ani_object object = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + if ((status = env->FindClass(ABILITY_FIRST_FRAME_STATE_DATA_CLASS_NAME, &cls) + ) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "find class 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 AbilityFirstFrameStateData failed status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + if (!SetAbilityFirstFrameStateData(env, object, abilityFirstFrameStateData)) { + TAG_LOGE(AAFwkTag::APPMGR, "SetAbilityFirstFrameStateData failed"); + return nullptr; + } + return object; +} +#endif + +bool AttachAniEnv(ani_vm *etsVm, ani_env *&env) +{ + if (etsVm == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "etsVm nullptr"); + return false; + } + ani_status status = ANI_ERROR; + if ((status = etsVm->GetEnv(ANI_VERSION_1, &env)) == ANI_OK) { + return env != nullptr; + } + ani_option interopEnabled { "--interop=disable", nullptr }; + ani_options aniArgs { 1, &interopEnabled }; + if ((status = (etsVm->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env))) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status: %{public}d", status); + return false; + } + return env != nullptr; +} + +void DetachAniEnv(ani_vm *etsVm) +{ + if (etsVm == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "etsVm nullptr"); + return; + } + ani_status status = ANI_ERROR; + if ((status = etsVm->DetachCurrentThread()) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status: %{public}d", status); + } +} + +void ReleaseObjectReference(ani_vm *etsVm, ani_ref etsObjRef) +{ + if (etsVm == nullptr || etsObjRef == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "etsVm null or etsObjRef null"); + return; + } + ani_status status = ANI_ERROR; + ani_env *env = nullptr; + if ((status = etsVm->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed status:%{public}d", status); + return; + } + if ((status = env->GlobalReference_Delete(etsObjRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "GlobalReference_Delete status: %{public}d", status); + } +} + } // namespace AppManagerEts } // namespace OHOS diff --git a/frameworks/ets/ani/app_manager/src/ets_app_state_observer.cpp b/frameworks/ets/ani/app_manager/src/ets_app_state_observer.cpp new file mode 100644 index 00000000000..624c7e114ce --- /dev/null +++ b/frameworks/ets/ani/app_manager/src/ets_app_state_observer.cpp @@ -0,0 +1,490 @@ +/* + * 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_state_observer.h" + +#include "ani_common_ability_state_data.h" +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "ani_task.h" +#include "hilog_tag_wrapper.h" +#include "ets_app_manager_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char *SIGNATURE_APP_STATE_DATA = "Lapplication/AppStateData/AppStateData;:V"; +constexpr const char *SIGNATURE_ABILITY_STATE_DATA = "Lapplication/AbilityStateData/AbilityStateData;:V"; +constexpr const char *SIGNATURE_PROCESS_DATA = "Lapplication/ProcessData/ProcessData;:V"; +constexpr const char *CLASS_NAME_APPLIACTION_STATE_OBSERVER = + "Lapplication/ApplicationStateObserver/ApplicationStateObserverImpl;"; +} + +EtsAppStateObserver::EtsAppStateObserver(ani_vm *etsVm) : etsVm_(etsVm) {} + +EtsAppStateObserver::~EtsAppStateObserver() +{ + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed"); + return; + } + std::lock_guard lock(etsObserverObjectMapLock_); + for (auto it = etsObserverObjectMap_.begin(); it != etsObserverObjectMap_.end();) { + env->GlobalReference_Delete(it->second); + it++; + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +}; + +void EtsAppStateObserver::OnForegroundApplicationChanged(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "OnForegroundApplicationChanged bundleName:%{public}s,uid:%{public}d, state:%{public}d", + appStateData.bundleName.c_str(), appStateData.uid, appStateData.state); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "invalid appmgr"); + return; + } + wptr etsObserver = this; + auto task = [appStateData, etsObserver]() { + sptr etsObserverSptr = etsObserver.promote(); + if (!etsObserverSptr) { + TAG_LOGW(AAFwkTag::APPMGR, "null stsObserver"); + return; + } + etsObserverSptr->HandleOnForegroundApplicationChanged(appStateData); + }; + if (AniTask::AniSendEvent(task) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to aniSendEvent"); + } +} + +void EtsAppStateObserver::HandleOnForegroundApplicationChanged(const AppStateData &appStateData) +{ + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed"); + return; + } + auto tmpMap = GetEtsObserverObjectMap(); + for (auto &item : tmpMap) { + auto appStateDataObj = AppManagerEts::WrapAppStateData(env, appStateData); + if (appStateDataObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null appStateDataObj"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + CallEtsFunction(env, item.second, "onForegroundApplicationChanged", SIGNATURE_APP_STATE_DATA, appStateDataObj); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +void EtsAppStateObserver::OnAbilityStateChanged(const AbilityStateData &abilityStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "OnAbilityStateChanged"); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "appMgr may has cancelled storage"); + return; + } + wptr etsObserver = this; + auto task = [abilityStateData, etsObserver] () { + sptr etsObserverSptr = etsObserver.promote(); + if (!etsObserverSptr) { + TAG_LOGW(AAFwkTag::APPMGR, "null stsObserver"); + return; + } + etsObserverSptr->HandleOnAbilityStateChanged(abilityStateData); + }; + if (AniTask::AniSendEvent(task) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to aniSendEvent"); + } +} + +void EtsAppStateObserver::HandleOnAbilityStateChanged(const AbilityStateData &abilityStateData) +{ + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed"); + return; + } + auto tmpMap = GetEtsObserverObjectMap(); + for (auto &item : tmpMap) { + auto abilityStateDataObj = OHOS::AppExecFwk::WrapAbilityStateData(env, abilityStateData); + if (abilityStateDataObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null abilityStateDataObj"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + } + CallEtsFunction(env, item.second, "onAbilityStateChanged", SIGNATURE_ABILITY_STATE_DATA, abilityStateDataObj); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +void EtsAppStateObserver::OnExtensionStateChanged(const AbilityStateData &abilityStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "appMgr may destroyed"); + return; + } + + wptr etsObserver = this; + auto task = [abilityStateData, etsObserver]() { + sptr etsObserverSptr = etsObserver.promote(); + if (!etsObserverSptr) { + TAG_LOGW(AAFwkTag::APPMGR, "null stsObserver"); + return; + } + etsObserverSptr->HandleOnExtensionStateChanged(abilityStateData); + }; + if (AniTask::AniSendEvent(task) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to aniSendEvent"); + } +} + +void EtsAppStateObserver::HandleOnExtensionStateChanged(const AbilityStateData &abilityStateData) +{ + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed"); + return; + } + auto tmpMap = GetEtsObserverObjectMap(); + for (auto &item : tmpMap) { + auto abilityStateDataObj = OHOS::AppExecFwk::WrapAbilityStateData(env, abilityStateData); + if (abilityStateDataObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null abilityStateDataObj"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + } + CallEtsFunction(env, item.second, "onAbilityStateChanged", SIGNATURE_ABILITY_STATE_DATA, abilityStateDataObj); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +void EtsAppStateObserver::OnProcessCreated(const ProcessData &processData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "OnProcessCreated"); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "appmgr may has cancelled storage"); + return; + } + + wptr etsObserver = this; + auto task = [processData, etsObserver]() { + sptr etsObserverSptr = etsObserver.promote(); + if (!etsObserverSptr) { + TAG_LOGW(AAFwkTag::APPMGR, "null stsObserver"); + return; + } + etsObserverSptr->HandleOnProcessCreated(processData); + }; + if (AniTask::AniSendEvent(task) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to aniSendEvent"); + } +} + +void EtsAppStateObserver::HandleOnProcessCreated(const ProcessData &processData) +{ + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed"); + return; + } + auto tmpMap = GetEtsObserverObjectMap(); + for (auto &item : tmpMap) { + auto processDataObj = AppManagerEts::WrapProcessData(env, processData); + if (processDataObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null processDataObj"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + CallEtsFunction(env, item.second, "onProcessCreated", SIGNATURE_PROCESS_DATA, processDataObj); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +void EtsAppStateObserver::OnProcessStateChanged(const ProcessData &processData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "appMgr may destroyed"); + return; + } + + wptr etsObserver = this; + auto task = [processData, etsObserver]() { + sptr etsObserverSptr = etsObserver.promote(); + if (!etsObserverSptr) { + TAG_LOGW(AAFwkTag::APPMGR, "null stsObserver"); + return; + } + etsObserverSptr->HandleOnProcessStateChanged(processData); + }; + if (AniTask::AniSendEvent(task) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to aniSendEvent"); + } +} + +void EtsAppStateObserver::HandleOnProcessStateChanged(const ProcessData &processData) +{ + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed"); + return; + } + auto tmpMap = GetEtsObserverObjectMap(); + for (auto &item : tmpMap) { + auto processDataObj = AppManagerEts::WrapProcessData(env, processData); + if (processDataObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null processDataObj"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + CallEtsFunction(env, item.second, "onProcessStateChanged", SIGNATURE_PROCESS_DATA, processDataObj); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +void EtsAppStateObserver::OnProcessDied(const ProcessData &processData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "appmgr may destroyed"); + return; + } + + wptr etsObserver = this; + auto task = [processData, etsObserver]() { + sptr etsObserverSptr = etsObserver.promote(); + if (!etsObserverSptr) { + TAG_LOGW(AAFwkTag::APPMGR, "null stsObserver"); + return; + } + etsObserverSptr->HandleOnProcessDied(processData); + }; + if (AniTask::AniSendEvent(task) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to aniSendEvent"); + } +} + +void EtsAppStateObserver::HandleOnProcessDied(const ProcessData &processData) +{ + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed"); + return; + } + auto tmpMap = GetEtsObserverObjectMap(); + for (auto &item : tmpMap) { + auto processDataObj = AppManagerEts::WrapProcessData(env, processData); + if (processDataObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null processDataObj"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + CallEtsFunction(env, item.second, "onProcessDied", SIGNATURE_PROCESS_DATA, processDataObj); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +void EtsAppStateObserver::OnAppStarted(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "bundleName:%{public}s, uid:%{public}d, state:%{public}d", + appStateData.bundleName.c_str(), appStateData.uid, appStateData.state); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "appMgr may destroyed"); + return; + } + + wptr etsObserver = this; + auto task = [appStateData, etsObserver]() { + sptr etsObserverSptr = etsObserver.promote(); + if (!etsObserverSptr) { + TAG_LOGW(AAFwkTag::APPMGR, "null stsObserver"); + return; + } + etsObserverSptr->HandleOnAppStarted(appStateData); + }; + if (AniTask::AniSendEvent(task) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to aniSendEvent"); + } +} + +void EtsAppStateObserver::HandleOnAppStarted(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "bundleName:%{public}s, uid:%{public}d, state:%{public}d", + appStateData.bundleName.c_str(), appStateData.uid, appStateData.state); + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed"); + return; + } + auto tmpMap = GetEtsObserverObjectMap(); + for (auto &item : tmpMap) { + auto appStateDataObj = AppManagerEts::WrapAppStateData(env, appStateData); + if (appStateDataObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null appStateDataObj"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + CallEtsFunction(env, item.second, "onAppStarted", SIGNATURE_APP_STATE_DATA, appStateDataObj); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +void EtsAppStateObserver::OnAppStopped(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "bundleName:%{public}s, uid:%{public}d, state:%{public}d", + appStateData.bundleName.c_str(), appStateData.uid, appStateData.state); + if (!valid_) { + TAG_LOGE(AAFwkTag::APPMGR, "appMgr may destroyed"); + return; + } + + wptr etsObserver = this; + auto task = [appStateData, etsObserver]() { + sptr etsObserverSptr = etsObserver.promote(); + if (!etsObserverSptr) { + TAG_LOGW(AAFwkTag::APPMGR, "null stsObserver"); + return; + } + etsObserverSptr->HandleOnAppStopped(appStateData); + }; + if (AniTask::AniSendEvent(task) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to aniSendEvent"); + } +} + +void EtsAppStateObserver::HandleOnAppStopped(const AppStateData &appStateData) +{ + TAG_LOGD(AAFwkTag::APPMGR, "bundleName:%{public}s, uid:%{public}d, state:%{public}d", + appStateData.bundleName.c_str(), appStateData.uid, appStateData.state); + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed"); + return; + } + auto tmpMap = GetEtsObserverObjectMap(); + for (auto &item : tmpMap) { + auto appStateDataObj = AppManagerEts::WrapAppStateData(env, appStateData); + if (appStateDataObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null appStateDataObj"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + CallEtsFunction(env, item.second, "onAppStopped", SIGNATURE_APP_STATE_DATA, appStateDataObj); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +void EtsAppStateObserver::CallEtsFunction( + ani_env *env, ani_object EtsObserverObject, const char *methodName, const char *signature, ...) +{ + TAG_LOGD(AAFwkTag::APPMGR, "call method:%{public}s", methodName); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return; + } + ani_class cls = nullptr; + ani_method method = nullptr; + ani_status status = ANI_OK; + status = env->FindClass(CLASS_NAME_APPLIACTION_STATE_OBSERVER, &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to find ApplicationStateObserver, status: %{public}d", status); + return; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null cls"); + return; + } + if ((status = env->Class_FindMethod(cls, methodName, signature, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to find method, status: %{public}d", status); + return; + } + if (method == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null method"); + return; + } + env->ResetError(); + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(EtsObserverObject, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to call %{public}s method,status: %{public}d", methodName, status); + return; + } + va_end(args); + return; +} + +void EtsAppStateObserver::AddEtsObserverObject(ani_env *env, const int32_t observerId, ani_object EtsObserverObject) +{ + TAG_LOGD(AAFwkTag::APPMGR, "AddEtsObserverObject"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return; + } + ani_ref global = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GlobalReference_Create(EtsObserverObject, &global)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status: %{public}d", status); + return; + } + if (global == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null EtsObserverObject ref"); + return; + } + std::lock_guard lock(etsObserverObjectMapLock_); + etsObserverObjectMap_.emplace(observerId, reinterpret_cast(global)); +} + +bool EtsAppStateObserver::RemoveEtsObserverObject(const int32_t observerId) +{ + TAG_LOGD(AAFwkTag::APPMGR, "RemoveEtsObserverObject"); + std::lock_guard lock(etsObserverObjectMapLock_); + return (etsObserverObjectMap_.erase(observerId) == 1); +} + +bool EtsAppStateObserver::FindObserverByObserverId(const int32_t observerId) +{ + std::lock_guard lock(etsObserverObjectMapLock_); + return etsObserverObjectMap_.find(observerId) != etsObserverObjectMap_.end(); +} + +size_t EtsAppStateObserver::GetEtsObserverMapSize() +{ + std::lock_guard lock(etsObserverObjectMapLock_); + return etsObserverObjectMap_.size(); +} + +void EtsAppStateObserver::SetValid(const bool valid) +{ + valid_ = valid; +} + +std::map EtsAppStateObserver::GetEtsObserverObjectMap() +{ + std::lock_guard lock(etsObserverObjectMapLock_); + return etsObserverObjectMap_; +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/application/include/ets_application.h b/frameworks/ets/ani/application/include/ets_application.h index 835754ac5c5..b1b23004d99 100644 --- a/frameworks/ets/ani/application/include/ets_application.h +++ b/frameworks/ets/ani/application/include/ets_application.h @@ -26,6 +26,7 @@ public: 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); + static ani_object GetApplicationContext(ani_env *env); }; void ApplicationInit(ani_env *env); } // namespace AbilityRuntime diff --git a/frameworks/ets/ani/application/src/ets_application.cpp b/frameworks/ets/ani/application/src/ets_application.cpp index aafc8797dcb..4d68d1ff724 100644 --- a/frameworks/ets/ani/application/src/ets_application.cpp +++ b/frameworks/ets/ani/application/src/ets_application.cpp @@ -22,6 +22,7 @@ #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" #include "permission_verification.h" @@ -243,6 +244,31 @@ void EtsApplication::CreateBundleContext(ani_env *env, SetCreateCompleteCallback(env, bundleContext, callback); } +ani_object EtsApplication::GetApplicationContext(ani_env *env) +{ + TAG_LOGD(AAFwkTag::APPKIT, "GetApplicationContext Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return nullptr; + } + auto etsReference = + AbilityRuntime::ApplicationContextManager::GetApplicationContextManager().GetEtsGlobalObject(); + if (etsReference == nullptr || etsReference->aniRef == nullptr) { + auto applicationContext = ApplicationContext::GetInstance(); + ani_object applicationContextObject = + EtsApplicationContextUtils::CreateEtsApplicationContext(env, applicationContext); + if (applicationContextObject == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContextObject"); + AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + ani_ref result = nullptr; + env->GetNull(&result); + return static_cast(result); + } + return applicationContextObject; + } + return reinterpret_cast(etsReference->aniRef); +} + void ApplicationInit(ani_env *env) { TAG_LOGD(AAFwkTag::APPKIT, "ApplicationInit Call"); @@ -270,6 +296,11 @@ void ApplicationInit(ani_env *env) "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", reinterpret_cast(EtsApplication::CreateBundleContext) }, + ani_native_function { + "nativeGetApplicationContext", + ":Lapplication/ApplicationContext/ApplicationContext;", + reinterpret_cast(EtsApplication::GetApplicationContext) + }, }; status = env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()); if (status != ANI_OK) { diff --git a/frameworks/ets/ani/featureAbility/BUILD.gn b/frameworks/ets/ani/featureAbility/BUILD.gn new file mode 100644 index 00000000000..402c63b24cf --- /dev/null +++ b/frameworks/ets/ani/featureAbility/BUILD.gn @@ -0,0 +1,45 @@ +# 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("featureability_ani") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ "./include" ] + + sources = [ "./src/ani_data_ability_helper.cpp" ] + + deps = [ + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_native_path}/ability/native:abilitykit_native", + "${ability_runtime_services_path}/common:perm_verification", + ] + + external_deps = [ + "runtime_core:ani", + "hilog:libhilog", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} \ No newline at end of file diff --git a/frameworks/ets/ani/featureAbility/include/ani_data_ability_helper.h b/frameworks/ets/ani/featureAbility/include/ani_data_ability_helper.h new file mode 100644 index 00000000000..f1d2a052653 --- /dev/null +++ b/frameworks/ets/ani/featureAbility/include/ani_data_ability_helper.h @@ -0,0 +1,27 @@ +/* + * 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_DATA_ABILITY_HELPER_H +#define OHOS_ABILITY_RUNTIME_ANI_DATA_ABILITY_HELPER_H + +#include "ani.h" +#include "data_ability_helper_impl.h" + +namespace OHOS { +namespace AppExecFwk { +void AnalysisPacMap(AppExecFwk::PacMap &pacMap, ani_env* env, const ani_object &aniObject); +} // namespace AppExecFwk +} // namespace OHOS +#endif /* OHOS_ABILITY_RUNTIME_ANI_DATA_ABILITY_HELPER_H */ \ No newline at end of file diff --git a/frameworks/ets/ani/featureAbility/src/ani_data_ability_helper.cpp b/frameworks/ets/ani/featureAbility/src/ani_data_ability_helper.cpp new file mode 100644 index 00000000000..14eb751d0ad --- /dev/null +++ b/frameworks/ets/ani/featureAbility/src/ani_data_ability_helper.cpp @@ -0,0 +1,148 @@ +/* + * 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_data_ability_helper.h" + +#include "ani_common_util.h" +#include "hilog_tag_wrapper.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_STRING = "Lstd/core/String;"; +constexpr const char* CLASSNAME_ARRAY = "Lescompat/Array;"; +} +bool IsInstanceOf(ani_env* env, const char* name, ani_object aniValue) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::FA, "env null"); + return false; + } + + ani_status status = ANI_ERROR; + ani_class cls = nullptr; + if ((status = env->FindClass(name, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } + ani_boolean isInstanceOf = ANI_FALSE; + if ((status = env->Object_InstanceOf(aniValue, cls, &isInstanceOf)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FA, "Object_InstanceOf status: %{public}d", status); + return false; + } + return isInstanceOf; +} + +void SetPacMapObject(AppExecFwk::PacMap &pacMap, ani_env* env, std::string keyStr, ani_object aniValue) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::FA, "env null"); + return; + } + ani_status status = ANI_ERROR; + ani_boolean isNull = ANI_FALSE; + if ((status = env->Reference_IsNull(aniValue, &isNull)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FA, "Reference_IsNull status: %{public}d", status); + return; + } + if (IsInstanceOf(env, CLASSNAME_DOUBLE, aniValue)) { + ani_double value = 0; + if ((status = env->Object_CallMethodByName_Double(aniValue, "doubleValue", nullptr, &value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FA, "Object_CallMethodByName_Double status: %{public}d", status); + return; + } + pacMap.PutDoubleValue(keyStr, static_cast(value)); + } else if (IsInstanceOf(env, CLASSNAME_BOOL, aniValue)) { + ani_boolean value = ANI_FALSE; + if ((status = env->Object_CallMethodByName_Boolean(aniValue, "unboxed", nullptr, &value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FA, "Object_CallMethodByName_Boolean status: %{public}d", status); + return; + } + pacMap.PutBooleanValue(keyStr, static_cast(value)); + } else if (IsInstanceOf(env, CLASSNAME_STRING, aniValue)) { + ani_string aniString = static_cast(aniValue); + std::string value = ""; + if (!GetStdString(env, aniString, value)) { + TAG_LOGE(AAFwkTag::FA, "GetStdString failed"); + return; + } + pacMap.PutStringValue(keyStr, value); + } else if (IsInstanceOf(env, CLASSNAME_ARRAY, aniValue)) { + std::vector stringList; + if (!UnwrapArrayString(env, aniValue, stringList)) { + TAG_LOGE(AAFwkTag::FA, "UnwrapArrayString failed"); + return; + } + pacMap.PutStringValueArray(keyStr, stringList); + } else if (isNull) { + pacMap.PutObject(keyStr, nullptr); + } else { + TAG_LOGE(AAFwkTag::FA, "pacMap type error"); + } +} + +void AnalysisPacMap(AppExecFwk::PacMap &pacMap, ani_env* env, const ani_object &aniObject) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::FA, "env null"); + return; + } + ani_ref iter = nullptr; + ani_status status = ANI_ERROR; + status = env->Object_CallMethodByName_Ref(aniObject, "$_iterator", nullptr, &iter); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::FA, "Failed to get keys iterator status: %{public}d", status); + return; + } + ani_ref next = nullptr; + ani_boolean done = ANI_FALSE; + while (ANI_OK == env->Object_CallMethodByName_Ref(static_cast(iter), "next", nullptr, &next)) { + status = env->Object_GetFieldByName_Boolean(static_cast(next), "done", &done); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::FA, "Failed to check iterator done status: %{public}d", status); + return; + } + if (done) { + TAG_LOGD(AAFwkTag::FA, "[forEachMapEntry] done break"); + return; + } + ani_ref keyValue = nullptr; + status = env->Object_GetFieldByName_Ref(static_cast(next), "value", &keyValue); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::FA, "Failed to get key value status: %{public}d", status); + return; + } + ani_ref aniKey = nullptr; + status = env->TupleValue_GetItem_Ref(static_cast(keyValue), 0, &aniKey); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::FA, "Failed to get key Item status: %{public}d", status); + return; + } + ani_ref aniVal = nullptr; + status = env->TupleValue_GetItem_Ref(static_cast(keyValue), 1, &aniVal); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::FA, "Failed to get key Item status: %{public}d", status); + return; + } + std::string mapKey = ""; + if (!GetStdString(env, static_cast(aniKey), mapKey)) { + TAG_LOGE(AAFwkTag::FA, "GetStdString failed"); + return; + } + SetPacMapObject(pacMap, env, mapKey, static_cast(aniVal)); + } +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file 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 index 13f04d7eac5..daabcb3ba97 100644 --- 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 @@ -29,6 +29,24 @@ namespace OHOS { namespace AbilityRuntime { +class ETSServiceExtensionConnection : public AbilityConnectCallback { +public: + explicit ETSServiceExtensionConnection(ani_vm *etsVm); + ~ETSServiceExtensionConnection(); + void OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int32_t resultCode) override; + void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int32_t resultCode) override; + void CallEtsFailed(int32_t errorCode); + void SetConnectionId(int32_t id); + int32_t GetConnectionId() { return connectionId_; } + void SetConnectionRef(ani_object connectOptionsObj); + void RemoveConnectionObject(); +protected: + ani_vm *etsVm_ = nullptr; + int32_t connectionId_ = -1; + ani_ref stsConnectionRef_ = nullptr; +}; + class EtsServiceExtensionContext final { public: explicit EtsServiceExtensionContext(std::shared_ptr context) @@ -39,6 +57,10 @@ public: 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 ani_long ConnectServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_object connectOptionsObj); + static void DisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_long connectId, + ani_object callback); 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); @@ -54,6 +76,10 @@ private: 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); + ani_long OnConnectServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_object connectOptionsObj); + void OnDisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_long connectId, + ani_object callback); void AddFreeInstallObserver(ani_env *env, const AAFwk::Want &want, ani_object callbackObj, std::shared_ptr context); @@ -61,6 +87,19 @@ private: sptr freeInstallObserver_ = nullptr; }; +struct EtsConnectionKey { + AAFwk::Want want; + int32_t id = 0; + int32_t accountId = 0; +}; + +struct EtsKeyCompare { + bool operator()(const EtsConnectionKey &key1, const EtsConnectionKey &key2) const + { + return key1.id < key2.id; + } +}; + ani_object CreateEtsServiceExtensionContext(ani_env *env, std::shared_ptr context); } // namespace AbilityRuntime } // namespace OHOS 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 c7f73714b6b..7b3ea41c9f1 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 @@ -48,7 +48,6 @@ constexpr const char *SERVICE_EXTENSION_CONTEXT_CLASS_NAME = 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"; -constexpr const char *ON_CONNECT_SIGNATURE = "L@ohos/app/ability/Want/Want;:Lstd/core/Object;"; 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;:Z"; @@ -219,7 +218,7 @@ sptr EtsServiceExtension::OnConnect(const AAFwk::Want &want) TAG_LOGE(AAFwkTag::SERVICE_EXT, "null wantRef"); return nullptr; } - ani_ref result = CallObjectMethod(true, "onConnect", ON_CONNECT_SIGNATURE, wantRef); + ani_ref result = CallObjectMethod(true, "onConnect", nullptr, wantRef); auto obj = reinterpret_cast(result); auto remoteObj = AniGetNativeRemoteObject(env, obj); if (remoteObj == nullptr) { @@ -257,7 +256,7 @@ sptr EtsServiceExtension::OnConnect(const AAFwk::Want &want, TAG_LOGE(AAFwkTag::SERVICE_EXT, "status : %{public}d", status); return nullptr; } - ani_ref aniRemoteRef = CallObjectMethod(true, "onConnect", ON_CONNECT_SIGNATURE, wantRef); + ani_ref aniRemoteRef = CallObjectMethod(true, "onConnect", nullptr, wantRef); auto aniRemoteobj = reinterpret_cast(aniRemoteRef); ani_method method {}; if ((status = env->Class_FindMethod(etsObj_->aniCls, "checkPromise", CHECK_PROMISE_SIGNATURE, &method)) != ANI_OK) { 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 index 7732288d650..3f40857d2bd 100644 --- 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 @@ -16,7 +16,9 @@ #include "ability_manager_client.h" #include "ani_common_start_options.h" +#include "ani_common_remote.h" #include "ani_common_want.h" +#include "ani_remote_object.h" #include "common_fun_ani.h" #include "ets_context_utils.h" #include "ets_error_utils.h" @@ -25,11 +27,21 @@ namespace OHOS { namespace AbilityRuntime { namespace { +std::recursive_mutex g_connectsLock; +uint32_t g_serialNumber = 0; +static std::mutex g_connectsMutex; +static std::map, EtsKeyCompare> g_connects; 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; +constexpr const int FAILED_CODE = -1; +constexpr const char *SIGNATURE_ONCONNECT = "LbundleManager/ElementName/ElementName;L@ohos/rpc/rpc/IRemoteObject;:V"; +constexpr const char *SIGNATURE_ONDISCONNECT = "LbundleManager/ElementName/ElementName;:V"; +constexpr const char *SIGNATURE_CONNECT_SERVICE_EXTENSION = + "L@ohos/app/ability/Want/Want;Lability/connectOptions/ConnectOptions;:J"; +constexpr const char *SIGNATURE_DISCONNECT_SERVICE_EXTENSION = "JLutils/AbilityUtils/AsyncCallbackWrapper;:V"; bool BindNativeMethods(ani_env *env, ani_class &cls) { @@ -49,6 +61,10 @@ bool BindNativeMethods(ani_env *env, ani_class &cls) ani_native_function { "nativeStopServiceExtensionAbility", "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", reinterpret_cast(EtsServiceExtensionContext::StopServiceExtensionAbility) }, + ani_native_function { "nativeConnectServiceExtensionAbility", SIGNATURE_CONNECT_SERVICE_EXTENSION, + reinterpret_cast(EtsServiceExtensionContext::ConnectServiceExtensionAbility) }, + ani_native_function { "nativeDisconnectServiceExtensionAbility", SIGNATURE_DISCONNECT_SERVICE_EXTENSION, + reinterpret_cast(EtsServiceExtensionContext::DisconnectServiceExtensionAbility) }, }; if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK && status != ANI_ALREADY_BINDED) { @@ -71,6 +87,43 @@ bool BindNativeMethods(ani_env *env, ani_class &cls) } return true; } + +int32_t InsertConnection(sptr connection, + const AAFwk::Want &want, int32_t accountId = -1) +{ + std::lock_guard lock(g_connectsLock); + if (connection == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null connection"); + return -1; + } + int32_t connectId = static_cast(g_serialNumber); + EtsConnectionKey key; + key.id = g_serialNumber; + key.want = want; + key.accountId = accountId; + connection->SetConnectionId(key.id); + g_connects.emplace(key, connection); + g_serialNumber++; + return connectId; +} + +void RemoveConnection(int32_t connectId) +{ + std::lock_guard lock(g_connectsLock); + auto item = std::find_if(g_connects.begin(), g_connects.end(), + [&connectId](const auto &obj) { + return connectId == obj.first.id; + }); + if (item != g_connects.end()) { + TAG_LOGD(AAFwkTag::SERVICE_EXT, "remove connection ability exist"); + if (item->second) { + item->second->RemoveConnectionObject(); + } + g_connects.erase(item); + } else { + TAG_LOGD(AAFwkTag::SERVICE_EXT, "remove connection ability not exist"); + } +} } // namespace void EtsServiceExtensionContext::Finalizer(ani_env *env, ani_object obj) @@ -168,6 +221,40 @@ void EtsServiceExtensionContext::StopServiceExtensionAbility( etsServiceExtensionContext->OnStopServiceExtensionAbility(env, aniObj, wantObj, callbackobj); } +ani_long EtsServiceExtensionContext::ConnectServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_object connectOptionsObj) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "ConnectServiceExtensionAbility"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return FAILED_CODE; + } + auto etsServiceExtensionContext = EtsServiceExtensionContext::GetEtsAbilityContext(env, aniObj); + if (etsServiceExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null etsServiceExtensionContext"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return FAILED_CODE; + } + return etsServiceExtensionContext->OnConnectServiceExtensionAbility(env, aniObj, wantObj, connectOptionsObj); +} + +void EtsServiceExtensionContext::DisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_long connectId, ani_object callback) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "DisconnectServiceExtensionAbility"); + 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->OnDisconnectServiceExtensionAbility(env, aniObj, connectId, callback); +} + EtsServiceExtensionContext *EtsServiceExtensionContext::GetEtsAbilityContext( ani_env *env, ani_object aniObj) { @@ -317,6 +404,90 @@ void EtsServiceExtensionContext::OnStartAbility( } } +ani_long EtsServiceExtensionContext::OnConnectServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_object connectOptionsObj) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "OnConnectServiceExtensionAbility call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return FAILED_CODE; + } + AAFwk::Want want; + if (!OHOS::AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to UnwrapWant"); + EtsErrorUtil::ThrowInvalidParamError(env, "Failed to UnwrapWant"); + return FAILED_CODE; + } + ani_vm *etsVm = nullptr; + if (env->GetVM(&etsVm) != ANI_OK || etsVm == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to getVM"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return FAILED_CODE; + } + sptr connection = sptr::MakeSptr(etsVm); + connection->SetConnectionRef(connectOptionsObj); + int32_t connectId = InsertConnection(connection, want); + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); + RemoveConnection(connectId); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return FAILED_CODE; + } + auto innerErrCode = context->ConnectAbility(want, connection); + int32_t errcode = static_cast(GetJsErrorCodeByNativeError(innerErrCode)); + if (errcode) { + connection->CallEtsFailed(errcode); + RemoveConnection(connectId); + return FAILED_CODE; + } + return connectId; +} + +void EtsServiceExtensionContext::OnDisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_long connectId, ani_object callback) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "OnDisconnectServiceExtensionAbility call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return; + } + auto context = context_.lock(); + ani_object errorObject = nullptr; + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); + errorObject = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + AppExecFwk::AsyncCallback(env, callback, errorObject, nullptr); + return; + } + sptr connection = nullptr; + AAFwk::Want want; + int32_t accountId = -1; + { + std::lock_guard lock(g_connectsMutex); + auto iter = std::find_if( + g_connects.begin(), g_connects.end(), [&connectId](const auto &obj) { return connectId == obj.first.id; }); + if (iter != g_connects.end()) { + want = iter->first.want; + connection = iter->second; + accountId = iter->first.accountId; + g_connects.erase(iter); + } else { + TAG_LOGI(AAFwkTag::SERVICE_EXT, "Failed to found connection"); + } + } + if (!connection) { + errorObject = EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)); + AppExecFwk::AsyncCallback(env, callback, errorObject, nullptr); + return; + } + context->DisconnectAbility(want, connection, accountId); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK), nullptr); +} + void EtsServiceExtensionContext::AddFreeInstallObserver( ani_env *env, const AAFwk::Want &want, ani_object callbackObj, std::shared_ptr context) { @@ -391,5 +562,135 @@ ani_object CreateEtsServiceExtensionContext(ani_env *env, std::shared_ptrGetAbilityInfo()); return contextObj; } + +ETSServiceExtensionConnection::ETSServiceExtensionConnection(ani_vm *etsVm) : etsVm_(etsVm) {} + +ETSServiceExtensionConnection::~ETSServiceExtensionConnection() +{ + RemoveConnectionObject(); +} + +void ETSServiceExtensionConnection::SetConnectionId(int32_t id) +{ + connectionId_ = id; +} + +void ETSServiceExtensionConnection::RemoveConnectionObject() +{ + if (etsVm_ != nullptr && stsConnectionRef_ != nullptr) { + ani_env *env = nullptr; + if (etsVm_->GetEnv(ANI_VERSION_1, &env) == ANI_OK && env != nullptr) { + env->GlobalReference_Delete(stsConnectionRef_); + stsConnectionRef_ = nullptr; + } + } +} + +void ETSServiceExtensionConnection::CallEtsFailed(int32_t errorCode) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "CallEtsFailed"); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null etsVm"); + return; + } + if (stsConnectionRef_ == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null stsConnectionRef_"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_OK; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to get env, status: %{public}d", status); + return; + } + status = env->Object_CallMethodByName_Void(reinterpret_cast(stsConnectionRef_), "onFailed", "I:V", + static_cast(errorCode)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to call onFailed, status: %{public}d", status); + } +} + +void ETSServiceExtensionConnection::SetConnectionRef(ani_object connectOptionsObj) +{ + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "etsVm_ is nullptr"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status: %{public}d", status); + return; + } + if ((status = env->GlobalReference_Create(connectOptionsObj, &stsConnectionRef_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status: %{public}d", status); + } +} + +void ETSServiceExtensionConnection::OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int32_t resultCode) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "OnAbilityConnectDone"); + if (etsVm_ == nullptr || stsConnectionRef_ == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null stsConnectionRef or etsVm"); + return; + } + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "GetEnv failed"); + return; + } + ani_ref refElement = AppExecFwk::WrapElementName(env, element); + if (refElement == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null refElement"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + if (remoteObject == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null remoteObject"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_object refRemoteObject = AniRemote::CreateAniRemoteObject(env, remoteObject); + if (refRemoteObject == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null refRemoteObject"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_status status = ANI_ERROR; + if ((status = env->Object_CallMethodByName_Void(reinterpret_cast(stsConnectionRef_), "onConnect", + SIGNATURE_ONCONNECT, refElement, refRemoteObject)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to call onConnect, status: %{public}d", status); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +void ETSServiceExtensionConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int32_t resultCode) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "OnAbilityDisconnectDone"); + if (etsVm_ == nullptr || stsConnectionRef_ == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null stsConnectionRef or etsVm"); + return; + } + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "GetEnv failed"); + return; + } + ani_ref refElement = AppExecFwk::WrapElementName(env, element); + if (refElement == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null refElement"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_status status = ANI_ERROR; + if ((status = env->Object_CallMethodByName_Void(reinterpret_cast(stsConnectionRef_), "onDisconnect", + SIGNATURE_ONDISCONNECT, refElement)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to call onDisconnect, status: %{public}d", status); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/ets/ani/ui_ability/include/ets_ability_context.h b/frameworks/ets/ani/ui_ability/include/ets_ability_context.h index 844d8ae859b..0e7a725ac8e 100644 --- a/frameworks/ets/ani/ui_ability/include/ets_ability_context.h +++ b/frameworks/ets/ani/ui_ability/include/ets_ability_context.h @@ -29,6 +29,25 @@ namespace OHOS { namespace AbilityRuntime { using OHOSApplication = AppExecFwk::OHOSApplication; + +class ETSAbilityConnection : public AbilityConnectCallback { +public: + explicit ETSAbilityConnection(ani_vm *etsVm); + ~ETSAbilityConnection(); + void OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int32_t resultCode) override; + void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int32_t resultCode) override; + void CallEtsFailed(int32_t errorCode); + void SetConnectionId(int32_t id); + int32_t GetConnectionId() { return connectionId_; } + void SetConnectionRef(ani_object connectOptionsObj); + void RemoveConnectionObject(); +protected: + ani_vm *etsVm_ = nullptr; + int32_t connectionId_ = -1; + ani_ref stsConnectionRef_ = nullptr; +}; + class EtsAbilityContext final { public: explicit EtsAbilityContext(std::shared_ptr context) : context_(std::move(context)) {} @@ -51,6 +70,19 @@ public: 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 void BackToCallerAbilityWithResult(ani_env *env, ani_object aniObj, + ani_object abilityResultObj, ani_string requestCodeObj, ani_object callBackObj); + static void SetMissionLabel(ani_env *env, ani_object aniObj, ani_string labelObj, + ani_object callbackObj); + static ani_long ConnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object connectOptionsObj); + static void DisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_long connectId, + ani_object callback); + static void SetColorMode(ani_env *env, ani_object aniObj, ani_enum_item colorMode); + static ani_object StartAbilityByType( + ani_env *env, ani_object aniObj, ani_string aniType, ani_ref aniWantParam, ani_object startCallback); + static void OpenAtomicService( + ani_env *env, ani_object aniObj, ani_string aniAppId, ani_object callbackObj, ani_object optionsObj); static void Clean(ani_env *env, ani_object object); static ani_object SetEtsAbilityContext(ani_env *env, std::shared_ptr context); @@ -78,18 +110,45 @@ private: 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 OnBackToCallerAbilityWithResult(ani_env *env, ani_object aniObj, + ani_object abilityResultObj, ani_string requestCodeObj, ani_object callBackObj); + void OnSetMissionLabel(ani_env *env, ani_object aniObj, ani_string labelObj, ani_object callbackObj); + ani_long OnConnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object connectOptionsObj); + void OnDisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_long connectId, + ani_object callback); + void OnSetColorMode(ani_env *env, ani_object aniObj, ani_enum_item colorMode); + ani_object OnStartAbilityByType( + ani_env *env, ani_object aniObj, ani_string aniType, ani_ref aniWantParam, ani_object startCallback); + void OnOpenAtomicService( + ani_env *env, ani_object aniObj, ani_string aniAppId, ani_object callbackObj, ani_object optionsObj); 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(); + void OpenAtomicServiceInner(ani_env *env, ani_object aniObj, AAFwk::Want &want, + AAFwk::StartOptions &options, std::string appId, ani_object callbackObj); std::weak_ptr context_; static std::mutex requestCodeMutex_; sptr freeInstallObserver_ = nullptr; }; +struct EtsConnectionKey { + AAFwk::Want want; + int32_t id = 0; + int32_t accountId = 0; +}; + +struct EtsKeyCompare { + bool operator()(const EtsConnectionKey &key1, const EtsConnectionKey &key2) const + { + return key1.id < key2.id; + } +}; + ani_object CreateEtsAbilityContext(ani_env *env, std::shared_ptr context); } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/ets/ani/ui_ability/include/ets_ui_ability.h b/frameworks/ets/ani/ui_ability/include/ets_ui_ability.h index 2c053f01c41..e660e6b8f50 100644 --- a/frameworks/ets/ani/ui_ability/include/ets_ui_ability.h +++ b/frameworks/ets/ani/ui_ability/include/ets_ui_ability.h @@ -32,6 +32,7 @@ using Want = AppExecFwk::Want; using InsightIntentExecuteResult = AppExecFwk::InsightIntentExecuteResult; using InsightIntentExecuteParam = AppExecFwk::InsightIntentExecuteParam; using InsightIntentExecutorAsyncCallback = AppExecFwk::InsightIntentExecutorAsyncCallback; +using Configuration = AppExecFwk::Configuration; class EtsUIAbility : public UIAbility { public: @@ -84,11 +85,23 @@ public: */ void OnStopCallback() override; + /** + * @brief Update configuration + * @param configuration Indicates the updated configuration information. + */ + void OnConfigurationUpdated(const Configuration &configuration) override; + /** * @brief Update Contextconfiguration */ void UpdateContextConfiguration() override; + /** + * @brief Called when the system configuration is updated. + * @param level Indicates the memory trim level, which shows the current memory usage status. + */ + void OnMemoryLevel(int level) override; + /** * @brief Called when the launch mode of an ability is set to singleInstance. This happens when you re-launch an * ability that has been at the top of the ability stack. @@ -113,6 +126,13 @@ public: static void CreateAndBindContext(const std::shared_ptr &abilityContext, const std::unique_ptr& runtime); + /** + * @brief dump ability info + * @param params dump params that indicate different dump targets + * @param info dump ability info + */ + void Dump(const std::vector ¶ms, std::vector &info) override; + #ifdef SUPPORT_SCREEN public: /** @@ -153,6 +173,20 @@ public: */ void CallOnForegroundFunc(const Want &want) override; + /** + * @brief Called before this ability enters the STATE_FOREGROUND state. + * The ability in the STATE_FOREGROUND state is invisible. + * You can override this function to implement your own processing logic. + */ + void OnWillForeground() override; + + /** + * @brief Called after wms show event. + * The ability in the STATE_FOREGROUND state is invisible. + * You can override this function to implement your own processing logic. + */ + void OnDidForeground() override; + /** * @brief Called when this ability enters the STATE_BACKGROUND state. * The ability in the STATE_BACKGROUND state is invisible. @@ -160,6 +194,20 @@ public: */ void OnBackground() override; + /** + * @brief Called before OnBackground. + * The ability in the STATE_BACKGROUND state is invisible. + * You can override this function to implement your own processing logic. + */ + void OnWillBackground() override; + + /** + * @brief Called after wms hiden event. + * The ability in the STATE_BACKGROUND state is invisible. + * You can override this function to implement your own processing logic. + */ + void OnDidBackground() override; + /** * Called when back press is dispatched. * Return true if ability will be moved to background; return false if will be terminated diff --git a/frameworks/ets/ani/ui_ability/src/ets_ability_context.cpp b/frameworks/ets/ani/ui_ability/src/ets_ability_context.cpp index 8c04bebaca9..21da21e51d9 100644 --- a/frameworks/ets/ani/ui_ability/src/ets_ability_context.cpp +++ b/frameworks/ets/ani/ui_ability/src/ets_ability_context.cpp @@ -15,16 +15,22 @@ #include "ets_ability_context.h" +#include + #include "ani_common_ability_result.h" #include "ani_common_configuration.h" #include "ani_common_start_options.h" +#include "ani_common_remote.h" #include "ani_common_want.h" +#include "ani_enum_convert.h" +#include "ani_remote_object.h" #include "app_utils.h" #include "common_fun_ani.h" #include "hilog_tag_wrapper.h" #include "hitrace_meter.h" #include "ets_context_utils.h" #include "ets_error_utils.h" +#include "ets_ui_extension_callback.h" #include "want.h" namespace OHOS { @@ -32,11 +38,87 @@ namespace AbilityRuntime { std::mutex EtsAbilityContext::requestCodeMutex_; namespace { static std::once_flag g_bindNativeMethodsFlag; +std::recursive_mutex g_connectsLock; +uint32_t g_serialNumber = 0; +constexpr uint64_t MAX_REQUEST_CODE = (1ULL << 49) - 1; +constexpr size_t MAX_REQUEST_CODE_LENGTH = 15; +constexpr int32_t BASE_REQUEST_CODE_NUM = 10;\ +constexpr const int FAILED_CODE = -1; +static std::mutex g_connectsMutex; +static std::map, EtsKeyCompare> g_connects; 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"; +constexpr const char *SIGNATURE_ONCONNECT = "LbundleManager/ElementName/ElementName;L@ohos/rpc/rpc/IRemoteObject;:V"; +constexpr const char *SIGNATURE_ONDISCONNECT = "LbundleManager/ElementName/ElementName;:V"; +constexpr const char *SIGNATURE_CONNECT_SERVICE_EXTENSION = + "L@ohos/app/ability/Want/Want;Lability/connectOptions/ConnectOptions;:J"; +constexpr const char *SIGNATURE_DISCONNECT_SERVICE_EXTENSION = "JLutils/AbilityUtils/AsyncCallbackWrapper;:V"; +constexpr const char* SIGNATURE_OPEN_ATOMIC_SERVICE = "Lstd/core/String;Lutils/AbilityUtils/AsyncCallbackWrapper;" + "L@ohos/app/ability/AtomicServiceOptions/AtomicServiceOptions;:V"; +const std::string ATOMIC_SERVICE_PREFIX = "com.atomicservice."; +constexpr const char *SIGNATURE_START_ABILITY_BY_TYPE = + "Lstd/core/String;Lescompat/Record;Lapplication/AbilityStartCallback/AbilityStartCallback;:L@ohos/base/" + "BusinessError;"; + +int64_t RequestCodeFromStringToInt64(const std::string &requestCode) +{ + if (requestCode.size() > MAX_REQUEST_CODE_LENGTH) { + TAG_LOGW(AAFwkTag::CONTEXT, "requestCode too long: %{public}s", requestCode.c_str()); + return 0; + } + std::regex formatRegex("^[1-9]\\d*|0$"); + std::smatch sm; + if (!std::regex_match(requestCode, sm, formatRegex)) { + TAG_LOGW(AAFwkTag::CONTEXT, "requestCode match failed: %{public}s", requestCode.c_str()); + return 0; + } + int64_t parsedRequestCode = 0; + parsedRequestCode = strtoll(requestCode.c_str(), nullptr, BASE_REQUEST_CODE_NUM); + if (parsedRequestCode < 0 || static_cast(parsedRequestCode) > MAX_REQUEST_CODE) { + TAG_LOGW(AAFwkTag::CONTEXT, "requestCode too large: %{public}s", requestCode.c_str()); + return 0; + } + return parsedRequestCode; +} + +int32_t InsertConnection(sptr connection, const AAFwk::Want &want, int32_t accountId = -1) +{ + std::lock_guard lock(g_connectsLock); + if (connection == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null connection"); + return -1; + } + int32_t connectId = static_cast(g_serialNumber); + EtsConnectionKey key; + key.id = g_serialNumber; + key.want = want; + key.accountId = accountId; + connection->SetConnectionId(key.id); + g_connects.emplace(key, connection); + g_serialNumber++; + return connectId; +} + +void RemoveConnection(int32_t connectId) +{ + std::lock_guard lock(g_connectsLock); + auto item = std::find_if(g_connects.begin(), g_connects.end(), + [&connectId](const auto &obj) { + return connectId == obj.first.id; + }); + if (item != g_connects.end()) { + TAG_LOGD(AAFwkTag::CONTEXT, "remove connection ability exist"); + if (item->second) { + item->second->RemoveConnectionObject(); + } + g_connects.erase(item); + } else { + TAG_LOGD(AAFwkTag::CONTEXT, "remove connection ability not exist"); + } +} } // namespace void EtsAbilityContext::Clean(ani_env *env, ani_object object) @@ -293,6 +375,90 @@ void EtsAbilityContext::RequestModalUIExtension(ani_env *env, ani_object aniObj, etsContext->OnRequestModalUIExtension(env, aniObj, pickerWantObj, callbackobj); } +void EtsAbilityContext::BackToCallerAbilityWithResult(ani_env *env, ani_object aniObj, + ani_object abilityResultObj, ani_string requestCodeObj, ani_object callBackObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "BackToCallerAbilityWithResult called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnBackToCallerAbilityWithResult(env, aniObj, abilityResultObj, requestCodeObj, callBackObj); +} + +void EtsAbilityContext::SetMissionLabel(ani_env *env, ani_object aniObj, ani_string labelObj, + ani_object callbackObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "SetMissionLabel called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnSetMissionLabel(env, aniObj, labelObj, callbackObj); +} + +ani_long EtsAbilityContext::ConnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object connectOptionsObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "ConnectServiceExtensionAbility called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return FAILED_CODE; + } + return etsContext->OnConnectServiceExtensionAbility(env, aniObj, wantObj, connectOptionsObj); +} + +void EtsAbilityContext::DisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_long connectId, + ani_object callback) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "DisconnectServiceExtensionAbility called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnDisconnectServiceExtensionAbility(env, aniObj, connectId, callback); +} + +void EtsAbilityContext::SetColorMode(ani_env *env, ani_object aniObj, ani_enum_item colorMode) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "SetColorMode called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnSetColorMode(env, aniObj, colorMode); +} + +ani_object EtsAbilityContext::StartAbilityByType( + ani_env *env, ani_object aniObj, ani_string aniType, ani_ref aniWantParam, ani_object startCallback) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "StartAbilityByType called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return nullptr; + } + return etsContext->OnStartAbilityByType(env, aniObj, aniType, aniWantParam, startCallback); +} + +void EtsAbilityContext::OpenAtomicService( + ani_env *env, ani_object aniObj, ani_string aniAppId, ani_object callbackObj, ani_object optionsObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "OpenAtomicService called"); + auto etsContext = GetEtsAbilityContext(env, aniObj); + if (etsContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsContext"); + return; + } + etsContext->OnOpenAtomicService(env, aniObj, aniAppId, callbackObj, optionsObj); +} + int32_t EtsAbilityContext::GenerateRequestCode() { static int32_t curRequestCode_ = 0; @@ -648,6 +814,256 @@ void EtsAbilityContext::OnRequestModalUIExtension(ani_env *env, ani_object aniOb AppExecFwk::AsyncCallback(env, callbackObj, errorObject, nullptr); } +void EtsAbilityContext::OnBackToCallerAbilityWithResult(ani_env *env, ani_object aniObj, + ani_object abilityResultObj, ani_string requestCodeObj, ani_object callBackObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "OnBackToCallerAbilityWithResult call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null env"); + return; + } + ani_object errorObject = nullptr; + AAFwk::Want want; + int resultCode = 0; + if (!OHOS::AppExecFwk::UnWrapAbilityResult(env, abilityResultObj, resultCode, want)) { + TAG_LOGE(AAFwkTag::CONTEXT, "UnWrapAbilityResult failed"); + errorObject = EtsErrorUtil::CreateInvalidParamError(env, "Failed to parse abilityResult."); + AppExecFwk::AsyncCallback(env, callBackObj, errorObject, nullptr); + return; + } + std::string requestCodeStr; + if (!AppExecFwk::GetStdString(env, requestCodeObj, requestCodeStr)) { + TAG_LOGE(AAFwkTag::CONTEXT, "Failed to parse label"); + errorObject = EtsErrorUtil::CreateInvalidParamError(env, "Failed to parse label."); + AppExecFwk::AsyncCallback(env, callBackObj, errorObject, nullptr); + return; + } + auto requestCode = RequestCodeFromStringToInt64(requestCodeStr); + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + AppExecFwk::AsyncCallback(env, callBackObj, + EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)), nullptr); + return; + } + + ErrCode ret = ERR_OK; + ret = context->BackToCallerAbilityWithResult(want, resultCode, requestCode); + errorObject = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callBackObj, errorObject, nullptr); +} + +void EtsAbilityContext::OnSetMissionLabel(ani_env *env, ani_object aniObj, ani_string labelObj, + ani_object callbackObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "OnSetMissionLabel call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null env"); + return; + } + ani_object errorObject = nullptr; + std::string label; + if (!AppExecFwk::GetStdString(env, labelObj, label)) { + TAG_LOGE(AAFwkTag::CONTEXT, "Failed to parse label"); + errorObject = EtsErrorUtil::CreateInvalidParamError(env, "Failed to parse label."); + AppExecFwk::AsyncCallback(env, callbackObj, errorObject, nullptr); + return; + } + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + AppExecFwk::AsyncCallback(env, callbackObj, + EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)), nullptr); + return; + } + auto errCode = context->SetMissionLabel(label); + errorObject = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(errCode)); + AppExecFwk::AsyncCallback(env, callbackObj, errorObject, nullptr); +} + +ani_long EtsAbilityContext::OnConnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object connectOptionsObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "OnConnectServiceExtensionAbility call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null env"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return FAILED_CODE; + } + AAFwk::Want want; + if (!OHOS::AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::CONTEXT, "Failed to UnwrapWant"); + EtsErrorUtil::ThrowInvalidParamError(env, "Failed to UnwrapWant"); + return FAILED_CODE; + } + ani_vm *etsVm = nullptr; + if (env->GetVM(&etsVm) != ANI_OK || etsVm == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "Failed to getVM"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return FAILED_CODE; + } + sptr connection = sptr::MakeSptr(etsVm); + connection->SetConnectionRef(connectOptionsObj); + int32_t connectId = InsertConnection(connection, want); + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + RemoveConnection(connectId); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return FAILED_CODE; + } + auto innerErrCode = context->ConnectAbility(want, connection); + int32_t errcode = static_cast(GetJsErrorCodeByNativeError(innerErrCode)); + if (errcode) { + connection->CallEtsFailed(errcode); + RemoveConnection(connectId); + return FAILED_CODE; + } + return static_cast(connectId); +} + +void EtsAbilityContext::OnDisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_long connectId, + ani_object callback) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "OnDisconnectServiceExtensionAbility call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null env"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return; + } + auto context = context_.lock(); + ani_object errorObject = nullptr; + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + errorObject = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + AppExecFwk::AsyncCallback(env, callback, errorObject, nullptr); + return; + } + sptr connection = nullptr; + AAFwk::Want want; + int32_t accountId = -1; + { + std::lock_guard lock(g_connectsMutex); + auto iter = std::find_if( + g_connects.begin(), g_connects.end(), [&connectId](const auto &obj) { return connectId == obj.first.id; }); + if (iter != g_connects.end()) { + want = iter->first.want; + connection = iter->second; + accountId = iter->first.accountId; + g_connects.erase(iter); + } else { + TAG_LOGI(AAFwkTag::CONTEXT, "Failed to found connection"); + } + } + if (!connection) { + errorObject = EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)); + AppExecFwk::AsyncCallback(env, callback, errorObject, nullptr); + return; + } + context->DisconnectAbility(want, connection, accountId); + AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK), nullptr); +} + +void EtsAbilityContext::OnSetColorMode(ani_env *env, ani_object aniObj, ani_enum_item colorMode) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null env"); + return; + } + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "context is already released"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return; + } + ani_int mode = 0; + if (!AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative(env, colorMode, mode)) { + TAG_LOGE(AAFwkTag::CONTEXT, "Parse colorMode failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param colorMode failed, colorMode must be number."); + return; + } + TAG_LOGD(AAFwkTag::CONTEXT, "colorMode is %{public}d", mode); + context->SetAbilityColorMode(static_cast(mode)); +} + +ani_object EtsAbilityContext::OnStartAbilityByType( + ani_env *env, ani_object aniObj, ani_string aniType, ani_ref aniWantParam, ani_object startCallback) +{ + ani_object aniObject = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INNER); + std::string type; + if (!AppExecFwk::GetStdString(env, aniType, type)) { + TAG_LOGE(AAFwkTag::CONTEXT, "parse type failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param type failed, type must be string."); + return aniObject; + } + + AAFwk::WantParams wantParam; + if (!AppExecFwk::UnwrapWantParams(env, aniWantParam, wantParam)) { + TAG_LOGE(AAFwkTag::CONTEXT, "parse wantParam failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param want failed, want must be Want."); + return aniObject; + } + + ani_vm *vm = nullptr; + if (env->GetVM(&vm) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "get vm failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Internal error."); + return aniObject; + } + ErrCode innerErrCode = ERR_OK; + std::shared_ptr callback = std::make_shared(vm); + callback->SetEtsCallbackObject(startCallback); + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + return EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + } +#ifdef SUPPORT_SCREEN + innerErrCode = context->StartAbilityByType(type, wantParam, callback); +#endif + if (innerErrCode == ERR_OK) { + return EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK); + } else if (innerErrCode == static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)) { + return EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + } else { + return EtsErrorUtil::CreateErrorByNativeErr(env, innerErrCode); + } +} + +void EtsAbilityContext::OnOpenAtomicService( + ani_env *env, ani_object aniObj, ani_string aniAppId, ani_object callbackObj, ani_object optionsObj) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "OnOpenAtomicService"); + ani_status status = ANI_ERROR; + ani_boolean isOptionsUndefined = true; + ani_object errorObject = nullptr; + if ((status = env->Reference_IsUndefined(optionsObj, &isOptionsUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return; + } + std::string appId; + if (!AppExecFwk::GetStdString(env, aniAppId, appId)) { + TAG_LOGE(AAFwkTag::CONTEXT, "parse appId failed"); + errorObject = EtsErrorUtil::CreateInvalidParamError(env, "Parse param appId failed, appId must be string."); + AppExecFwk::AsyncCallback(env, callbackObj, errorObject, nullptr); + return; + } + AAFwk::Want want; + AAFwk::StartOptions startOptions; + if (!isOptionsUndefined) { + if (!AppExecFwk::UnwrapAtomicServiceOptions(env, optionsObj, want, startOptions)) { + TAG_LOGE(AAFwkTag::CONTEXT, "UnwrapAtomicServiceOptions failed"); + errorObject = EtsErrorUtil::CreateInvalidParamError(env, "UnwrapAtomicServiceOptions failed."); + AppExecFwk::AsyncCallback(env, callbackObj, errorObject, nullptr); + return; + } + } + OpenAtomicServiceInner(env, aniObj, want, startOptions, appId, callbackObj); +} + void EtsAbilityContext::AddFreeInstallObserver(ani_env *env, const AAFwk::Want &want, ani_object callback, const std::shared_ptr &context, bool isAbilityResult, bool isOpenLink) { @@ -707,7 +1123,7 @@ void EtsAbilityContext::UnWrapOpenLinkOptions(ani_env *env, ani_object optionsOb } if ((status = env->Object_GetPropertyByName_Ref(optionsObj, APP_LINKING_ONLY.c_str(), &ParamRef)) == ANI_OK) { bool appLinkingOnly = false; - AppExecFwk::GetFieldBoolByName(env, optionsObj, "appLinkingOnly", appLinkingOnly); + AppExecFwk::GetBooleanPropertyObject(env, optionsObj, "appLinkingOnly", appLinkingOnly); openLinkOptions.SetAppLinkingOnly(appLinkingOnly); want.SetParam(APP_LINKING_ONLY, appLinkingOnly); } @@ -754,6 +1170,59 @@ void EtsAbilityContext::CreateOpenLinkTask(ani_env *env, const ani_object callba context->InsertResultCallbackTask(requestCode, std::move(task)); } +void EtsAbilityContext::OpenAtomicServiceInner(ani_env *env, ani_object aniObj, AAFwk::Want &want, + AAFwk::StartOptions &options, std::string appId, ani_object callbackObj) +{ + std::string bundleName = ATOMIC_SERVICE_PREFIX + appId; + TAG_LOGD(AAFwkTag::CONTEXT, "bundleName: %{public}s", bundleName.c_str()); + want.SetBundle(bundleName); + want.AddFlags(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); + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return; + } + AddFreeInstallObserver(env, want, callbackObj, context, true); + ani_vm *etsVm = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GetVM(&etsVm)) != ANI_OK || etsVm == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return; + } + RuntimeTask task = [etsVm, element = want.GetElement(), startTime, observer = freeInstallObserver_]( + int resultCode, const AAFwk::Want &want, bool isInner) { + ani_env *env = nullptr; + if (etsVm->GetEnv(ANI_VERSION_1, &env) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null env"); + return; + } + if (observer == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null observer"); + return; + } + std::string bundleName = element.GetBundleName(); + std::string abilityName = element.GetAbilityName(); + ani_object abilityResult = AppExecFwk::WrapAbilityResult(env, resultCode, want); + if (abilityResult == nullptr) { + TAG_LOGW(AAFwkTag::CONTEXT, "null abilityResult"); + isInner = true; + resultCode = ERR_INVALID_VALUE; + } + isInner ? observer->OnInstallFinished(bundleName, abilityName, startTime, resultCode) + : observer->OnInstallFinished(bundleName, abilityName, startTime, abilityResult); + }; + want.SetParam(AAFwk::Want::PARAM_RESV_FOR_RESULT, true); + auto requestCode = GenerateRequestCode(); + ErrCode ErrCode = context->OpenAtomicService(want, options, requestCode, std::move(task)); + if (ErrCode != ERR_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "OpenAtomicService failed, ErrCode: %{public}d", ErrCode); + } +} + namespace { bool BindNativeMethods(ani_env *env, ani_class &cls) { @@ -797,6 +1266,23 @@ bool BindNativeMethods(ani_env *env, ani_class &cls) ani_native_function { "nativeRequestModalUIExtension", "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", reinterpret_cast(EtsAbilityContext::RequestModalUIExtension) }, + ani_native_function { "nativeBackToCallerAbilityWithResult", + "Lability/abilityResult/AbilityResult;Lstd/core/String;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAbilityContext::BackToCallerAbilityWithResult) }, + ani_native_function { "nativeSetMissionLabel", + "Lstd/core/String;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAbilityContext::SetMissionLabel) }, + ani_native_function { "nativeConnectServiceExtensionAbility", SIGNATURE_CONNECT_SERVICE_EXTENSION, + reinterpret_cast(EtsAbilityContext::ConnectServiceExtensionAbility) }, + ani_native_function { "nativeDisconnectServiceExtensionAbility", SIGNATURE_DISCONNECT_SERVICE_EXTENSION, + reinterpret_cast(EtsAbilityContext::DisconnectServiceExtensionAbility) }, + ani_native_function {"nativeSetColorMode", + "L@ohos/app/ability/ConfigurationConstant/ConfigurationConstant/ColorMode;:V", + reinterpret_cast(EtsAbilityContext::SetColorMode)}, + ani_native_function { "nativeStartAbilityByTypeSync", SIGNATURE_START_ABILITY_BY_TYPE, + reinterpret_cast(EtsAbilityContext::StartAbilityByType) }, + ani_native_function { "nativeOpenAtomicService", SIGNATURE_OPEN_ATOMIC_SERVICE, + reinterpret_cast(EtsAbilityContext::OpenAtomicService) }, }; if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { TAG_LOGE(AAFwkTag::CONTEXT, "Class_BindNativeMethods failed status: %{public}d", status); @@ -867,5 +1353,134 @@ ani_object CreateEtsAbilityContext(ani_env *env, std::shared_ptr } return contextObj; } + +ETSAbilityConnection::ETSAbilityConnection(ani_vm *etsVm) : etsVm_(etsVm) {} + +ETSAbilityConnection::~ETSAbilityConnection() +{ + RemoveConnectionObject(); +} + +void ETSAbilityConnection::SetConnectionId(int32_t id) +{ + connectionId_ = id; +} + +void ETSAbilityConnection::RemoveConnectionObject() +{ + if (etsVm_ != nullptr && stsConnectionRef_ != nullptr) { + ani_env *env = nullptr; + if (etsVm_->GetEnv(ANI_VERSION_1, &env) == ANI_OK && env != nullptr) { + env->GlobalReference_Delete(stsConnectionRef_); + stsConnectionRef_ = nullptr; + } + } +} + +void ETSAbilityConnection::CallEtsFailed(int32_t errorCode) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "CallEtsFailed"); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null etsVm"); + return; + } + if (stsConnectionRef_ == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null stsConnectionRef_"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_OK; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "Failed to get env, status: %{public}d", status); + return; + } + status = env->Object_CallMethodByName_Void(reinterpret_cast(stsConnectionRef_), "onFailed", "I:V", + errorCode); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "Failed to call onFailed, status: %{public}d", status); + } +} + +void ETSAbilityConnection::SetConnectionRef(ani_object connectOptionsObj) +{ + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "etsVm_ is nullptr"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return; + } + if ((status = env->GlobalReference_Create(connectOptionsObj, &stsConnectionRef_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + } +} + +void ETSAbilityConnection::OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int32_t resultCode) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "OnAbilityConnectDone"); + if (etsVm_ == nullptr || stsConnectionRef_ == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null stsConnectionRef or etsVm"); + return; + } + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "GetEnv failed"); + return; + } + ani_ref refElement = AppExecFwk::WrapElementName(env, element); + if (refElement == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null refElement"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + if (remoteObject == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null remoteObject"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_object refRemoteObject = AniRemote::CreateAniRemoteObject(env, remoteObject); + if (refRemoteObject == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null refRemoteObject"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_status status = ANI_ERROR; + if ((status = env->Object_CallMethodByName_Void(reinterpret_cast(stsConnectionRef_), "onConnect", + SIGNATURE_ONCONNECT, refElement, refRemoteObject)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "Failed to call onConnect, status: %{public}d", status); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} +void ETSAbilityConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int32_t resultCode) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "OnAbilityDisconnectDone"); + if (etsVm_ == nullptr || stsConnectionRef_ == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null stsConnectionRef or etsVm"); + return; + } + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "GetEnv failed"); + return; + } + ani_ref refElement = AppExecFwk::WrapElementName(env, element); + if (refElement == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null refElement"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_status status = ANI_ERROR; + if ((status = env->Object_CallMethodByName_Void(reinterpret_cast(stsConnectionRef_), "onDisconnect", + SIGNATURE_ONDISCONNECT, refElement)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "Failed to call onDisconnect, status: %{public}d", status); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/ets/ani/ui_ability/src/ets_ui_ability.cpp b/frameworks/ets/ani/ui_ability/src/ets_ui_ability.cpp index c8a3c199bf7..10363f3745f 100644 --- a/frameworks/ets/ani/ui_ability/src/ets_ui_ability.cpp +++ b/frameworks/ets/ani/ui_ability/src/ets_ui_ability.cpp @@ -19,7 +19,9 @@ #include "ability_delegator_infos.h" #include "ability_delegator_registry.h" +#include "ani_common_configuration.h" #include "ani_common_want.h" +#include "ani_enum_convert.h" #ifdef SUPPORT_SCREEN #include "ani_window_stage.h" #endif @@ -55,6 +57,8 @@ const std::string METHOD_NAME = "WindowScene::GoForeground"; constexpr int32_t BASE_DISPLAY_ID_NUM(10); #endif constexpr const char *UI_ABILITY_CLASS_NAME = "L@ohos/app/ability/UIAbility/UIAbility;"; +constexpr const char *UI_ABILITY_SIGNATURE_VOID = ":V"; +constexpr const char *MEMORY_LEVEL_ENUM_NAME = "L@ohos/app/ability/AbilityConstant/AbilityConstant/MemoryLevel;"; void OnDestroyPromiseCallback(ani_env *env, ani_object aniObj) { @@ -665,13 +669,48 @@ void EtsUIAbility::DoOnForeground(const Want &want) TAG_LOGI(AAFwkTag::UIABILITY, "silent foreground, do not show window"); return; } - + OnWillForeground(); TAG_LOGD(AAFwkTag::UIABILITY, "move scene to foreground, sceneFlag_: %{public}d", UIAbility::sceneFlag_); HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, "scene_->GoForeground"); scene_->GoForeground(UIAbility::sceneFlag_); TAG_LOGD(AAFwkTag::UIABILITY, "DoOnForeground end"); } +void EtsUIAbility::OnWillForeground() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "OnWillForeground ability: %{public}s", GetAbilityName().c_str()); + UIAbility::OnWillForeground(); + CallObjectMethod(false, "onWillForeground", UI_ABILITY_SIGNATURE_VOID); +} + +void EtsUIAbility::OnDidForeground() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "OnDidForeground ability: %{public}s", GetAbilityName().c_str()); + UIAbility::OnDidForeground(); + CallObjectMethod(false, "onDidForeground", UI_ABILITY_SIGNATURE_VOID); + if (scene_ != nullptr) { + scene_->GoResume(); + } +} + +void EtsUIAbility::OnWillBackground() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "OnWillBackground ability: %{public}s", GetAbilityName().c_str()); + UIAbility::OnWillBackground(); + CallObjectMethod(false, "onWillBackground", UI_ABILITY_SIGNATURE_VOID); +} + +void EtsUIAbility::OnDidBackground() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "OnDidBackground ability: %{public}s", GetAbilityName().c_str()); + UIAbility::OnDidBackground(); + CallObjectMethod(false, "onDidBackground", UI_ABILITY_SIGNATURE_VOID); +} + void EtsUIAbility::DoOnForegroundForSceneIsNull(const Want &want) { TAG_LOGD(AAFwkTag::UIABILITY, "DoOnForegroundForSceneIsNull begin"); @@ -909,6 +948,63 @@ bool EtsUIAbility::GetInsightIntentExecutorInfo(const Want &want, } #endif +void EtsUIAbility::OnConfigurationUpdated(const Configuration &configuration) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + UIAbility::OnConfigurationUpdated(configuration); + TAG_LOGD(AAFwkTag::UIABILITY, "OnConfigurationUpdated called"); + if (abilityContext_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext"); + return; + } + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "env null"); + return; + } + auto abilityConfig = abilityContext_->GetAbilityConfiguration(); + auto fullConfig = abilityContext_->GetConfiguration(); + if (fullConfig == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null fullConfig"); + return; + } + auto realConfig = AppExecFwk::Configuration(*fullConfig); + if (abilityConfig != nullptr) { + std::vector changeKeyV; + realConfig.CompareDifferent(changeKeyV, *abilityConfig); + if (!changeKeyV.empty()) { + realConfig.Merge(changeKeyV, *abilityConfig); + } + } + TAG_LOGD(AAFwkTag::UIABILITY, "realConfig: %{public}s", realConfig.GetName().c_str()); + ani_object aniConfiguration = AppExecFwk::WrapConfiguration(env, realConfig); + CallObjectMethod(false, "onConfigurationUpdated", nullptr, aniConfiguration); + CallObjectMethod(false, "onConfigurationUpdate", nullptr, aniConfiguration); + auto realConfigPtr = std::make_shared(realConfig); + EtsAbilityContext::ConfigurationUpdated(env, shellContextRef_, realConfigPtr); +} + +void EtsUIAbility::OnMemoryLevel(int level) +{ + UIAbility::OnMemoryLevel(level); + TAG_LOGD(AAFwkTag::UIABILITY, "OnMemoryLevel called"); + if (etsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null etsAbilityObj_"); + return; + } + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + ani_enum_item levelEnum {}; + if (!AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts(env, MEMORY_LEVEL_ENUM_NAME, level, levelEnum)) { + TAG_LOGE(AAFwkTag::UIABILITY, "levelEnum NativeToEts failed"); + return; + } + CallObjectMethod(false, "onMemoryLevel", nullptr, levelEnum); +} + void EtsUIAbility::UpdateContextConfiguration() { TAG_LOGD(AAFwkTag::UIABILITY, "UpdateContextConfiguration called"); @@ -979,6 +1075,53 @@ void EtsUIAbility::OnAbilityResult(int requestCode, int resultCode, const Want & TAG_LOGD(AAFwkTag::UIABILITY, "OnAbilityResult end"); } +void EtsUIAbility::Dump(const std::vector ¶ms, std::vector &info) +{ + UIAbility::Dump(params, info); + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr || etsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env or etsAbilityObj"); + return; + } + ani_object arrayObj = nullptr; + if (!AppExecFwk::WrapArrayString(env, arrayObj, params)) { + TAG_LOGE(AAFwkTag::UIABILITY, "WrapArrayString failed"); + return; + } + if (!etsAbilityObj_->aniObj || !etsAbilityObj_->aniCls) { + TAG_LOGE(AAFwkTag::UIABILITY, "null aniObj or aniCls"); + return; + } + ani_status status = ANI_ERROR; + ani_method method = nullptr; + if ((status = env->Class_FindMethod(etsAbilityObj_->aniCls, "onDump", nullptr, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "Class_FindMethod FAILED: %{public}d", status); + return; + } + if (!method) { + TAG_LOGE(AAFwkTag::UIABILITY, "find method onDump failed"); + return; + } + ani_ref strArrayRef; + if ((status = env->Object_CallMethod_Ref(etsAbilityObj_->aniObj, method, &strArrayRef, arrayObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "Object_CallMethod_Ref FAILED: %{public}d", status); + return; + } + if (!strArrayRef) { + TAG_LOGE(AAFwkTag::UIABILITY, "null strArrayRef"); + return; + } + std::vector dumpInfoStrArray; + if (!AppExecFwk::UnwrapArrayString(env, reinterpret_cast(strArrayRef), dumpInfoStrArray)) { + TAG_LOGE(AAFwkTag::UIABILITY, "UnwrapArrayString failed"); + return; + } + for (auto dumpInfoStr:dumpInfoStrArray) { + info.push_back(dumpInfoStr); + } + TAG_LOGD(AAFwkTag::UIABILITY, "dump info size: %{public}zu", info.size()); +} + bool EtsUIAbility::CallObjectMethod(bool withResult, const char *name, const char *signature, ...) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name); diff --git a/frameworks/ets/ani/ui_extension_ability/include/ets_extension_common.h b/frameworks/ets/ani/ui_extension_ability/include/ets_extension_common.h new file mode 100644 index 00000000000..f4d7c6ab4a8 --- /dev/null +++ b/frameworks/ets/ani/ui_extension_ability/include/ets_extension_common.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_EXTENSION_COMMON_H +#define OHOS_ABILITY_RUNTIME_ETS_EXTENSION_COMMON_H + +#include "configuration.h" +#include "service_extension.h" + +namespace OHOS { +namespace AppExecFwk { +struct ETSNativeReference; +} +namespace AbilityRuntime { +class ServiceExtension; +class ETSRuntime; +/** + * @brief Basic ets extension common components. + */ +class EtsExtensionCommon : public ExtensionCommon, + public std::enable_shared_from_this { +public: + EtsExtensionCommon(ETSRuntime &etsRuntime, AppExecFwk::ETSNativeReference &etsObj, + const std::shared_ptr &shellContextRef); + + virtual ~EtsExtensionCommon() override; + + /** + * @brief Create JsServiceExtension. + * + * @param etsRuntime The runtime. + * @param etsObj The ets object instance. + * @return The JsServiceExtension instance. + */ + static std::shared_ptr Create(ETSRuntime &etsRuntime, AppExecFwk::ETSNativeReference &etsObj, + const std::shared_ptr &shellContextRef); + + /** + * @brief Called when the system configuration is updated. + * + * @param configuration Indicates the updated configuration information. + */ + void OnConfigurationUpdated(const std::shared_ptr &fullConfig) override; + + /** + * @brief Notify current memory level. + * + * @param level Current memory level. + */ + void OnMemoryLevel(int level) override; + +private: + void CallObjectMethod(const char *name, const char *signature, ...); + +private: + ETSRuntime& etsRuntime_; + AppExecFwk::ETSNativeReference& etsObj_; + std::shared_ptr shellContextRef_ = nullptr; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_EXTENSION_COMMON_H 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 156842cfad1..6a76379394b 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 @@ -86,13 +86,6 @@ public: void OnStop() override; void OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback) override; - /** - * @brief Called when the system configuration is updated. - * - * @param configuration Indicates the updated configuration information. - */ - void OnConfigurationUpdated(const AppExecFwk::Configuration &configuration) override; - /** * @brief Called when this extension enters the STATE_FOREGROUND state. * @@ -134,7 +127,14 @@ public: /** * @brief Called when configuration changed, including system configuration and window configuration. */ - void ConfigurationUpdated(); + void ConfigurationUpdated() override; + + /** + * @brief Called when the configuration changes, including system and window configuration. + * + * @param configuration The updated configuration information. + */ + void OnAbilityConfigurationUpdated(const AppExecFwk::Configuration &configuration) override; private: virtual void BindContext(ani_env *env, std::shared_ptr want); @@ -154,9 +154,9 @@ private: sptr sessionInfo); sptr CreateUIWindow(const std::shared_ptr context, 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); + bool BindNativeMethods(); ETSRuntime &etsRuntime_; std::shared_ptr etsObj_ = nullptr; 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 489cba8286d..2e4ffae1c19 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 @@ -20,6 +20,7 @@ #include "ets_runtime.h" #include "session_info.h" #include "start_options.h" +#include "ui_extension_context.h" #include "window.h" namespace OHOS { @@ -82,6 +83,8 @@ public: static void NativeSetReceiveDataCallback(ani_env *env, ani_object clsObj, ani_object funcObj); static void NativeSetReceiveDataForResultCallback(ani_env *env, ani_object clsObj, ani_object funcObj); static ani_object NativeGetUIExtensionHostWindowProxy(ani_env *env, ani_object obj); + static ani_object NativeStartAbilityByTypeSync( + ani_env *env, ani_object obj, ani_string type, ani_ref wantParam, ani_object startCallback); 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); @@ -101,6 +104,9 @@ public: private: void SetReceiveDataCallbackRegister(ani_env *env, ani_object functionObj); void SetReceiveDataForResultCallbackRegister(ani_env *env, ani_object funcObj); + ani_object StartAbilityByTypeSync(ani_env *env, ani_string aniType, ani_ref aniWantParam, ani_object startCallback); + bool CheckStartAbilityByTypeParam( + ani_env *env, ani_string aniType, ani_ref aniWantParam, std::string &type, AAFwk::WantParams &wantParam); sptr sessionInfo_; sptr uiWindow_; @@ -111,6 +117,9 @@ private: bool isSyncRegistered_ = false; std::shared_ptr listener_; bool isFirstTriggerBindModal_ = true; +#ifdef SUPPORT_SCREEN + void InitDisplayId(AAFwk::Want &want); +#endif }; } // namespace AbilityRuntime 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 870753a2f77..34549ec6d5a 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 @@ -31,6 +31,24 @@ namespace OHOS { namespace AbilityRuntime { ani_object CreateEtsUIExtensionContext(ani_env *env, std::shared_ptr context); +class EtsUIExtensionConnection : public AbilityConnectCallback { +public: + explicit EtsUIExtensionConnection(ani_vm *etsVm); + ~EtsUIExtensionConnection(); + void OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) override; + void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override; + void CallEtsFailed(int32_t errorCode); + void SetConnectionId(int32_t id); + int32_t GetConnectionId() { return connectionId_; } + void SetConnectionRef(ani_object connectOptionsObj); + +protected: + ani_vm *etsVm_ = nullptr; + int32_t connectionId_ = -1; + ani_ref stsConnectionRef_ = nullptr; +}; + class EtsUIExtensionContext final { public: explicit EtsUIExtensionContext(const std::shared_ptr &context) @@ -43,6 +61,15 @@ public: 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 ani_long ConnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object connectOptionsObj); + static void DisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_long connectId, + ani_object callback); + static void StartAbilityForResult(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object callback); + static void StartAbilityForResultWithOptions(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object startOptionsObj, ani_object callback); + static void SetColorMode(ani_env *env, ani_object aniObj, ani_enum_item aniColorMode); + static void ReportDrawnCompleted(ani_env *env, ani_object aniObj, ani_object callback); static bool BindNativePtrCleaner(ani_env *env); static void Clean(ani_env *env, ani_object object); @@ -51,13 +78,38 @@ private: 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 OnStartAbilityForResult(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object startOptinsObj, + ani_object callback); void AddFreeInstallObserver( ani_env *env, const AAFwk::Want &want, ani_object callbackObj, std::shared_ptr context); + ani_long OnConnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object connectOptionsObj); + void OnDisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, ani_long connectId, + ani_object callback); + static bool CheckConnectionParam(ani_env *env, ani_object connectOptionsObj, + sptr& connection, AAFwk::Want& want); + void OnSetColorMode(ani_env *env, ani_object aniCls, ani_enum_item aniColorMode); + void OnReportDrawnCompleted(ani_env *env, ani_object aniCls, ani_object callback); protected: std::weak_ptr context_; sptr freeInstallObserver_ = nullptr; }; + +struct EtsUIExtensionConnectionKey { + AAFwk::Want want; + int32_t id; +}; + +struct Etskey_compare { + bool operator()(const EtsUIExtensionConnectionKey &key1, const EtsUIExtensionConnectionKey &key2) const + { + if (key1.id < key2.id) { + return true; + } + return false; + } +}; } // namespace AbilityRuntime } // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_ETS_UI_EXTENSION_CONTEXT_H \ No newline at end of file diff --git a/frameworks/ets/ani/ui_extension_ability/src/ets_extension_common.cpp b/frameworks/ets/ani/ui_extension_ability/src/ets_extension_common.cpp new file mode 100644 index 00000000000..370642eb5e4 --- /dev/null +++ b/frameworks/ets/ani/ui_extension_ability/src/ets_extension_common.cpp @@ -0,0 +1,111 @@ +/* + * 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_extension_common.h" + +#include "ani_common_configuration.h" +#include "ani_enum_convert.h" +#include "ets_extension_context.h" +#include "ets_native_reference.h" +#include "ets_runtime.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char *MEMORY_LEVEL_ENUM_NAME = "L@ohos/app/ability/AbilityConstant/AbilityConstant/MemoryLevel;"; +} // namespace + +using namespace OHOS::AppExecFwk; + +std::shared_ptr EtsExtensionCommon::Create(ETSRuntime &etsRuntime, + AppExecFwk::ETSNativeReference &etsObj, const std::shared_ptr &shellContextRef) +{ + return std::make_shared(etsRuntime, etsObj, shellContextRef); +} + +EtsExtensionCommon::EtsExtensionCommon(ETSRuntime &etsRuntime, AppExecFwk::ETSNativeReference &etsObj, + const std::shared_ptr &shellContextRef) + : etsRuntime_(etsRuntime), etsObj_(etsObj), shellContextRef_(shellContextRef) +{} + +EtsExtensionCommon::~EtsExtensionCommon() {} + +void EtsExtensionCommon::OnConfigurationUpdated(const std::shared_ptr &fullConfig) +{ + TAG_LOGD(AAFwkTag::EXT, "OnConfigurationUpdated called"); + if (!fullConfig) { + TAG_LOGE(AAFwkTag::EXT, "invalid config"); + return; + } + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "env null"); + return; + } + if (shellContextRef_ == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "shellContextRef_ null"); + return; + } + EtsExtensionContext::ConfigurationUpdated(env, shellContextRef_, fullConfig); + + ani_object aniConfiguration = OHOS::AppExecFwk::WrapConfiguration(env, *fullConfig); + CallObjectMethod("onConfigurationUpdate", nullptr, aniConfiguration); +} + +void EtsExtensionCommon::OnMemoryLevel(int level) +{ + TAG_LOGD(AAFwkTag::EXT, "OnMemoryLevel called"); + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "env null"); + return; + } + + ani_enum_item levelEnum {}; + if (!OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts(env, MEMORY_LEVEL_ENUM_NAME, level, levelEnum)) { + TAG_LOGE(AAFwkTag::EXT, "levelEnum failed"); + return; + } + CallObjectMethod("onMemoryLevel", nullptr, levelEnum); +} + +void EtsExtensionCommon::CallObjectMethod(const char *name, const char *signature, ...) +{ + TAG_LOGD(AAFwkTag::EXT, "name: %{public}s", name); + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "null env"); + return; + } + ani_method method = nullptr; + ani_status status = env->Class_FindMethod(etsObj_.aniCls, name, signature, &method); + if (status != ANI_OK || method == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "Class_FindMethod status: %{public}d, or null method", status); + env->ResetError(); + return; + } + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(etsObj_.aniObj, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::EXT, "Object_CallMethod_Void_V status: %{public}d", status); + etsRuntime_.HandleUncaughtError(); + return; + } + va_end(args); + TAG_LOGI(AAFwkTag::EXT, "CallObjectMethod end, name: %{public}s", name); +} +} // namespace AbilityRuntime +} // namespace OHOS 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 b3fc24c8898..58157cb3f78 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 @@ -20,20 +20,22 @@ #include "ability_info.h" #include "ability_manager_client.h" #include "ability_start_setting.h" +#include "ani_common_configuration.h" #include "ani_common_want.h" #include "configuration_utils.h" #include "connection_manager.h" #include "context.h" #include "ets_data_struct_converter.h" +#include "ets_extension_common.h" +#include "ets_extension_context.h" #include "ets_native_reference.h" #include "ets_runtime.h" #include "ets_ui_extension_context.h" -#include "hitrace_meter.h" #include "hilog_tag_wrapper.h" +#include "hitrace_meter.h" #include "insight_intent_executor_info.h" #include "insight_intent_executor_mgr.h" #include "int_wrapper.h" -#include "ani_common_want.h" #include "ui_extension_window_command.h" #include "want_params_wrapper.h" @@ -46,27 +48,12 @@ namespace OHOS { namespace AbilityRuntime { using namespace OHOS::AppExecFwk; +namespace { +constexpr const char* UIEXTENSION_CLASS_NAME = "L@ohos/app/ability/UIExtensionAbility/UIExtensionAbility;"; -EtsUIExtension *EtsUIExtension::Create(const std::unique_ptr &runtime) -{ - return new (std::nothrow) EtsUIExtension(static_cast(*runtime)); -} - -EtsUIExtension::EtsUIExtension(ETSRuntime &eTSRuntime) : etsRuntime_(eTSRuntime) -{ -} - -EtsUIExtension::~EtsUIExtension() -{ - auto context = GetContext(); - if (context) { - context->Unbind(); - } - contentSessions_.clear(); -} - -void EtsUIExtension::PromiseCallback(ani_env *env, ani_object aniObj) +void OnDestroyPromiseCallback(ani_env* env, ani_object aniObj) { + TAG_LOGD(AAFwkTag::UI_EXT, "OnDestroyPromiseCallback called"); if (env == nullptr || aniObj == nullptr) { TAG_LOGE(AAFwkTag::UI_EXT, "null env or null aniObj"); return; @@ -74,7 +61,7 @@ void EtsUIExtension::PromiseCallback(ani_env *env, ani_object aniObj) ani_long destroyCallbackPoint = 0; ani_status status = ANI_ERROR; if ((status = env->Object_GetFieldByName_Long(aniObj, "destroyCallbackPoint", &destroyCallbackPoint)) != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + TAG_LOGE(AAFwkTag::UI_EXT, "destroyCallbackPoint GetField status: %{public}d", status); return; } auto *callbackInfo = reinterpret_cast *>(destroyCallbackPoint); @@ -87,10 +74,29 @@ void EtsUIExtension::PromiseCallback(ani_env *env, ani_object aniObj) if ((status = env->Object_SetFieldByName_Long(aniObj, "destroyCallbackPoint", static_cast(0))) != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status : %{public}d", status); + TAG_LOGE(AAFwkTag::UI_EXT, "destroyCallbackPoint SetField status: %{public}d", status); return; } } +} // namespace + +EtsUIExtension *EtsUIExtension::Create(const std::unique_ptr &runtime) +{ + return new (std::nothrow) EtsUIExtension(static_cast(*runtime)); +} + +EtsUIExtension::EtsUIExtension(ETSRuntime &eTSRuntime) : etsRuntime_(eTSRuntime) +{ +} + +EtsUIExtension::~EtsUIExtension() +{ + auto context = GetContext(); + if (context) { + context->Unbind(); + } + contentSessions_.clear(); +} void EtsUIExtension::Init(const std::shared_ptr &record, const std::shared_ptr &application, std::shared_ptr &handler, @@ -107,6 +113,7 @@ void EtsUIExtension::Init(const std::shared_ptr &record, return; } + RegisterAbilityConfigUpdateCallback(); if (record != nullptr) { token_ = record->GetToken(); } @@ -128,21 +135,37 @@ void EtsUIExtension::Init(const std::shared_ptr &record, TAG_LOGE(AAFwkTag::UI_EXT, "etsObj_ null"); return; } + if (!BindNativeMethods()) { + TAG_LOGE(AAFwkTag::UI_EXT, "BindNativeMethods failed"); + return; + } + BindContext(etsRuntime_.GetAniEnv(), record->GetWant()); + RegisterDisplayInfoChangedListener(); +} +bool EtsUIExtension::BindNativeMethods() +{ auto env = etsRuntime_.GetAniEnv(); if (env == nullptr) { TAG_LOGE(AAFwkTag::UI_EXT, "null env"); - return; + return false; } std::array functions = { - ani_native_function { "nativeOnDestroyCallback", ":V", reinterpret_cast(EtsUIExtension::PromiseCallback) }, + ani_native_function { "nativeOnDestroyCallback", ":V", reinterpret_cast(OnDestroyPromiseCallback) }, }; - ani_status status = ANI_ERROR; - if ((status = env->Class_BindNativeMethods(etsObj_->aniCls, functions.data(), functions.size())) != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + ani_class cls {}; + ani_status status = env->FindClass(UIEXTENSION_CLASS_NAME, &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "FindClass failed status: %{public}d", status); + return false; } - BindContext(env, record->GetWant()); - RegisterDisplayInfoChangedListener(); + if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Class_BindNativeMethods status: %{public}d", status); + return false; + } + SetExtensionCommon( + EtsExtensionCommon::Create(etsRuntime_, static_cast(*etsObj_), shellContextRef_)); + return true; } ani_object EtsUIExtension::CreateETSContext( @@ -175,18 +198,18 @@ void EtsUIExtension::BindContext(ani_env *env, std::shared_ptr want ani_field contextField = nullptr; auto status = env->Class_FindField(etsObj_->aniCls, "context", &contextField); if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::ETSRUNTIME, "status: %{public}d", status); + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); return; } ani_ref contextRef = nullptr; if ((status = env->GlobalReference_Create(contextObj, &contextRef)) != ANI_OK) { - TAG_LOGE(AAFwkTag::ETSRUNTIME, "status: %{public}d", status); + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); return; } if ((status = env->Object_SetField_Ref(etsObj_->aniObj, contextField, contextRef)) != ANI_OK) { - TAG_LOGE(AAFwkTag::ETSRUNTIME, "status: %{public}d", status); + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); } shellContextRef_ = std::make_shared(); shellContextRef_->aniObj = contextObj; @@ -210,6 +233,9 @@ void EtsUIExtension::OnStart(const AAFwk::Want &want, sptr s TAG_LOGE(AAFwkTag::UI_EXT, "env not found Ability.ets"); return; } + if (context != nullptr) { + EtsExtensionContext::ConfigurationUpdated(env, shellContextRef_, context->GetConfiguration()); + } const char *signature = "L@ohos/app/ability/AbilityConstant/AbilityConstant/LaunchParam;:V"; auto launchParam = Extension::GetLaunchParam(); @@ -605,18 +631,11 @@ bool EtsUIExtension::CallObjectMethod(bool withResult, const char *name, const c return false; } -void EtsUIExtension::OnConfigurationUpdated(const AppExecFwk::Configuration &configuration) +void EtsUIExtension::OnAbilityConfigurationUpdated(const AppExecFwk::Configuration &configuration) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - Extension::OnConfigurationUpdated(configuration); - auto context = GetContext(); - if (context == nullptr) { - TAG_LOGE(AAFwkTag::UI_EXT, "context null"); - return; - } - - auto configUtils = std::make_shared(); - configUtils->UpdateGlobalConfig(configuration, context->GetConfiguration(), context->GetResourceManager()); + TAG_LOGD(AAFwkTag::UI_EXT, "OnAbilityConfigurationUpdated called"); + UIExtension::OnAbilityConfigurationUpdated(configuration); ConfigurationUpdated(); } @@ -644,7 +663,7 @@ void EtsUIExtension::OnAbilityResult(int requestCode, int resultCode, const Want void EtsUIExtension::ConfigurationUpdated() { - ani_env* env = etsRuntime_.GetAniEnv(); + auto env = etsRuntime_.GetAniEnv(); if (env == nullptr) { TAG_LOGE(AAFwkTag::UI_EXT, "env null"); return; @@ -654,12 +673,24 @@ void EtsUIExtension::ConfigurationUpdated() TAG_LOGE(AAFwkTag::UI_EXT, "context null"); return; } - + auto abilityConfig = context->GetAbilityConfiguration(); auto fullConfig = context->GetConfiguration(); if (fullConfig == nullptr) { TAG_LOGE(AAFwkTag::UI_EXT, "fullConfig null"); return; } + auto realConfig = AppExecFwk::Configuration(*fullConfig); + if (abilityConfig != nullptr) { + std::vector changeKeyV; + realConfig.CompareDifferent(changeKeyV, *abilityConfig); + if (!changeKeyV.empty()) { + realConfig.Merge(changeKeyV, *abilityConfig); + } + } + auto realConfigPtr = std::make_shared(realConfig); + EtsExtensionContext::ConfigurationUpdated(env, shellContextRef_, realConfigPtr); + ani_object aniConfiguration = AppExecFwk::WrapConfiguration(env, realConfig); + CallObjectMethod(false, "onConfigurationUpdate", nullptr, aniConfiguration); } #ifdef SUPPORT_GRAPHICS 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 22761295957..7c1778944f5 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 @@ -21,6 +21,7 @@ #include "ani_common_want.h" #include "ani_extension_window.h" #include "ets_error_utils.h" +#include "ets_ui_extension_callback.h" #include "ets_ui_extension_context.h" #include "hilog_tag_wrapper.h" #include "ipc_skeleton.h" @@ -35,12 +36,18 @@ namespace OHOS { namespace AbilityRuntime { - +namespace { 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;"; +const std::string UIEXTENSION_TARGET_TYPE_KEY = "ability.want.params.uiExtensionTargetType"; +const std::string FLAG_AUTH_READ_URI_PERMISSION = "ability.want.params.uriPermissionFlag"; +constexpr const char *SIGNATURE_START_ABILITY_BY_TYPE = + "Lstd/core/String;Lescompat/Record;Lapplication/AbilityStartCallback/AbilityStartCallback;:L@ohos/base/" + "BusinessError;"; +} // namespace EtsUIExtensionContentSession* EtsUIExtensionContentSession::GetEtsContentSession(ani_env *env, ani_object obj) { @@ -170,6 +177,17 @@ ani_object EtsUIExtensionContentSession::NativeGetUIExtensionHostWindowProxy(ani return object; } +ani_object EtsUIExtensionContentSession::NativeStartAbilityByTypeSync( + ani_env *env, ani_object obj, ani_string type, ani_ref wantParam, ani_object startCallback) +{ + auto etsContentSession = EtsUIExtensionContentSession::GetEtsContentSession(env, obj); + ani_object object = nullptr; + if (etsContentSession != nullptr) { + object = etsContentSession->StartAbilityByTypeSync(env, type, wantParam, startCallback); + } + return object; +} + EtsUIExtensionContentSession::EtsUIExtensionContentSession( sptr sessionInfo, sptr uiWindow, std::weak_ptr &context, @@ -264,7 +282,9 @@ ani_object EtsUIExtensionContentSession::CreateEtsUIExtensionContentSession(ani_ ani_native_function {"nativeSetReceiveDataCallback", nullptr, reinterpret_cast(EtsUIExtensionContentSession::NativeSetReceiveDataCallback)}, ani_native_function {"nativeSetReceiveDataForResultCallback", nullptr, - reinterpret_cast(EtsUIExtensionContentSession::NativeSetReceiveDataForResultCallback)} + reinterpret_cast(EtsUIExtensionContentSession::NativeSetReceiveDataForResultCallback)}, + ani_native_function {"nativeStartAbilityByTypeSync", SIGNATURE_START_ABILITY_BY_TYPE, + reinterpret_cast(EtsUIExtensionContentSession::NativeStartAbilityByTypeSync)} }; status = env->Class_BindNativeMethods(cls, methods.data(), methods.size()); if (status != ANI_OK) { @@ -569,6 +589,77 @@ void EtsUIExtensionContentSession::SetReceiveDataForResultCallbackRegister(ani_e isSyncRegistered_ = true; } +ani_object EtsUIExtensionContentSession::StartAbilityByTypeSync( + ani_env *env, ani_string aniType, ani_ref aniWantParam, ani_object startCallback) +{ + std::string type; + AAFwk::WantParams wantParam; + if (!CheckStartAbilityByTypeParam(env, aniType, aniWantParam, type, wantParam)) { + TAG_LOGE(AAFwkTag::UI_EXT, "check startAbilityByCall param failed"); + return nullptr; + } + wantParam.SetParam(UIEXTENSION_TARGET_TYPE_KEY, AAFwk::String::Box(type)); + AAFwk::Want want; + want.SetParams(wantParam); + if (wantParam.HasParam(FLAG_AUTH_READ_URI_PERMISSION)) { + want.SetFlags(wantParam.GetIntParam(FLAG_AUTH_READ_URI_PERMISSION, 0)); + wantParam.Remove(FLAG_AUTH_READ_URI_PERMISSION); + } +#ifdef SUPPORT_SCREEN + InitDisplayId(want); +#endif + ani_object aniObject = EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INNER); + ani_vm *vm = nullptr; + if (env->GetVM(&vm) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "get vm failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Get vm failed."); + return aniObject; + } + std::shared_ptr uiExtensionCallback = std::make_shared(vm); + uiExtensionCallback->SetEtsCallbackObject(startCallback); + if (uiWindow_ == nullptr || uiWindow_->GetUIContent() == nullptr) { + return aniObject; + } +#ifdef SUPPORT_SCREEN + Ace::ModalUIExtensionCallbacks callback; + callback.onError = [uiExtensionCallback](int arg, const std::string &str1, const std::string &str2) { + uiExtensionCallback->OnError(arg); + }; + callback.onRelease = [uiExtensionCallback](const auto &arg) { uiExtensionCallback->OnRelease(arg); }; + Ace::ModalUIExtensionConfig config; + int32_t sessionId = uiWindow_->GetUIContent()->CreateModalUIExtension(want, callback, config); + if (sessionId == 0) { + return aniObject; + } else { + uiExtensionCallback->SetUIContent(uiWindow_->GetUIContent()); + uiExtensionCallback->SetSessionId(sessionId); + return EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK); + } +#endif // SUPPORT_SCREEN + return aniObject; +} + +bool EtsUIExtensionContentSession::CheckStartAbilityByTypeParam( + ani_env *env, ani_string aniType, ani_ref aniWantParam, std::string &type, AAFwk::WantParams &wantParam) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return false; + } + if (!AppExecFwk::GetStdString(env, aniType, type)) { + TAG_LOGE(AAFwkTag::UI_EXT, "parse type failed"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parameter error: Failed to parse type! Type must be a string."); + return false; + } + if (!AppExecFwk::UnwrapWantParams(env, aniWantParam, wantParam)) { + TAG_LOGE(AAFwkTag::UI_EXT, "parse wantParam failed"); + EtsErrorUtil::ThrowInvalidParamError( + env, "Parameter error: Failed to parse wantParam, must be a Record."); + return false; + } + return true; +} + void EtsUIExtensionContentSession::CallReceiveDataCallbackForResult(ani_vm* vm, ani_ref callbackRef, const AAFwk::WantParams& wantParams, AAFwk::WantParams& retWantParams) { @@ -619,5 +710,24 @@ sptr EtsUIExtensionContentSession::GetUIWindow() { return uiWindow_; } +#ifdef SUPPORT_SCREEN +void EtsUIExtensionContentSession::InitDisplayId(AAFwk::Want &want) +{ + auto context = AbilityRuntime::Context::ConvertTo(context_.lock()); + if (!context) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + return; + } + + auto window = context->GetWindow(); + if (window == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null window"); + return; + } + + TAG_LOGI(AAFwkTag::UI_EXT, "window displayId %{public}" PRIu64, window->GetDisplayId()); + want.SetParam(AAFwk::Want::PARAM_RESV_DISPLAY_ID, static_cast(window->GetDisplayId())); +} +#endif } // namespace AbilityRuntime -} // namespace OHOS \ No newline at end of file +} // namespace OHOS 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 b881c4bdbdd..91219a4a0d9 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,8 +15,12 @@ #include "ets_ui_extension_context.h" #include "ability_manager_client.h" +#include "ani_common_ability_result.h" #include "ani_common_start_options.h" +#include "ani_common_remote.h" #include "ani_common_want.h" +#include "ani_enum_convert.h" +#include "ani_remote_object.h" #include "common_fun_ani.h" #include "ets_context_utils.h" #include "ets_error_utils.h" @@ -26,9 +30,18 @@ namespace OHOS { namespace AbilityRuntime { -const char *INVOKE_METHOD_NAME = "invoke"; +static std::mutex g_connectsMutex; +int32_t g_serialNumber = 0; +static std::map, Etskey_compare> g_connects; const char *UI_EXTENSION_CONTEXT_CLASS_NAME = "Lapplication/UIExtensionContext/UIExtensionContext;"; const char *UI_EXTENSION_CONTEXT_CLEANER_CLASS_NAME = "Lapplication/UIExtensionContext/Cleaner;"; +constexpr const int FAILED_CODE = -1; +constexpr const char *CONNECT_OPTIONS_CLASS_NAME = "Lability/connectOptions/ConnectOptionsInner;"; +constexpr const char *SIGNATURE_ONCONNECT = "LbundleManager/ElementName/ElementName;L@ohos/rpc/rpc/IRemoteObject;:V"; +constexpr const char *SIGNATURE_ONDISCONNECT = "LbundleManager/ElementName/ElementName;:V"; +constexpr const char *SIGNATURE_CONNECT_SERVICE_EXTENSION = + "L@ohos/app/ability/Want/Want;Lability/connectOptions/ConnectOptions;:J"; +constexpr const char *SIGNATURE_DISCONNECT_SERVICE_EXTENSION = "JLutils/AbilityUtils/AsyncCallbackWrapper;:V"; void EtsUIExtensionContext::TerminateSelfSync(ani_env *env, ani_object obj, ani_object callback) { @@ -76,6 +89,31 @@ void EtsUIExtensionContext::StartAbility(ani_env *env, ani_object aniObj, ani_ob etsUiExtensionContext->OnStartAbility(env, aniObj, wantObj, nullptr, call); } +ani_long EtsUIExtensionContext::ConnectServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_object connectOptionsObj) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "ConnectServiceExtensionAbility"); + auto etsUiExtensionContext = GetEtsUIExtensionContext(env, aniObj); + if (etsUiExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsUiExtensionContext"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return FAILED_CODE; + } + return etsUiExtensionContext->OnConnectServiceExtensionAbility(env, aniObj, wantObj, connectOptionsObj); +} + +void EtsUIExtensionContext::DisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_long connectId, ani_object callback) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "DisconnectServiceExtensionAbility"); + auto etsUiExtensionContext = GetEtsUIExtensionContext(env, aniObj); + if (etsUiExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsUiExtensionContext"); + return; + } + etsUiExtensionContext->OnDisconnectServiceExtensionAbility(env, aniObj, connectId, callback); +} + void EtsUIExtensionContext::StartAbilityWithOption( ani_env *env, ani_object aniObj, ani_object wantObj, ani_object opt, ani_object call) { @@ -92,6 +130,38 @@ void EtsUIExtensionContext::StartAbilityWithOption( etsUiExtensionContext->OnStartAbility(env, aniObj, wantObj, opt, call); } +void EtsUIExtensionContext::StartAbilityForResult(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callback) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "StartAbilityForResult called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + auto etsUiExtensionContext = GetEtsUIExtensionContext(env, aniObj); + if (etsUiExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsUiExtensionContext"); + return; + } + etsUiExtensionContext->OnStartAbilityForResult(env, aniObj, wantObj, nullptr, callback); +} + +void EtsUIExtensionContext::StartAbilityForResultWithOptions(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object startOptionsObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "StartAbilityForResultWithOptions called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + auto etsUiExtensionContext = GetEtsUIExtensionContext(env, aniObj); + if (etsUiExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsUiExtensionContext"); + return; + } + etsUiExtensionContext->OnStartAbilityForResult(env, aniObj, wantObj, startOptionsObj, callback); +} + void EtsUIExtensionContext::OnTerminateSelf(ani_env *env, ani_object obj, ani_object callback) { ani_object aniObject = nullptr; @@ -202,6 +272,148 @@ void EtsUIExtensionContext::OnStartAbility( } } +void EtsUIExtensionContext::OnStartAbilityForResult(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object startOptionsObj, ani_object callback) +{ + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "context is nullptr"); + AppExecFwk::AsyncCallback(env, callback, + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT), nullptr); + return; + } + + AAFwk::Want want; + OHOS::AppExecFwk::UnwrapWant(env, wantObj, want); + if (!want.HasParameter(AAFwk::Want::PARAM_BACK_TO_OTHER_MISSION_STACK)) { + want.SetParam(AAFwk::Want::PARAM_BACK_TO_OTHER_MISSION_STACK, true); + } + AAFwk::StartOptions startOptions; + if (startOptionsObj) { + OHOS::AppExecFwk::UnwrapStartOptions(env, startOptionsObj, startOptions); + } + + ani_ref callbackRef = nullptr; + env->GlobalReference_Create(callback, &callbackRef); + ani_vm *etsVm = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GetVM(&etsVm)) != ANI_OK || etsVm == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetVM failed, status: %{public}d", status); + return; + } + RuntimeTask task = [etsVm, callbackRef] + (int resultCode, const AAFwk::Want &want, bool isInner) { + TAG_LOGD(AAFwkTag::UI_EXT, "start async callback"); + ani_status status = ANI_ERROR; + ani_env *env = nullptr; + if ((status = etsVm->GetEnv(ANI_VERSION_1, &env)) != ANI_OK || env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetEnv failed, status: %{public}d", status); + return; + } + + ani_object abilityResult = AppExecFwk::WrapAbilityResult(env, resultCode, want); + if (abilityResult == nullptr) { + TAG_LOGW(AAFwkTag::UI_EXT, "null abilityResult"); + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_CODE_INNER), nullptr); + env->GlobalReference_Delete(callbackRef); + return; + } + auto errCode = isInner ? resultCode : 0; + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + EtsErrorUtil::CreateErrorByNativeErr(env, errCode), abilityResult); + env->GlobalReference_Delete(callbackRef); + }; + want.SetParam(AAFwk::Want::PARAM_RESV_FOR_RESULT, true); + auto requestCode = context->GenerateCurRequestCode(); + (startOptionsObj == nullptr) ? context->StartAbilityForResult(want, requestCode, std::move(task)) + : context->StartAbilityForResult(want, startOptions, requestCode, std::move(task)); + return; +} + +ani_long EtsUIExtensionContext::OnConnectServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_object wantObj, ani_object connectOptionsObj) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "OnConnectServiceExtensionAbility"); + ani_status status = ANI_ERROR; + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + EtsErrorUtil::ThrowError(env, static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)); + return FAILED_CODE; + } + AAFwk::Want want; + if (!OHOS::AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to UnwrapWant"); + EtsErrorUtil::ThrowInvalidParamError(env, "Failed to UnwrapWant"); + return FAILED_CODE; + } + ani_vm *etsVm = nullptr; + if ((status = env->GetVM(&etsVm)) != ANI_OK || etsVm == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to getVM, status: %{public}d", status); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return FAILED_CODE; + } + sptr connection = new (std::nothrow) EtsUIExtensionConnection(etsVm); + if (connection == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null connection"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER); + return FAILED_CODE; + } + if (!CheckConnectionParam(env, connectOptionsObj, connection, want)) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to CheckConnectionParam"); + EtsErrorUtil::ThrowInvalidParamError(env, "Failed to CheckConnectionParam"); + return FAILED_CODE; + } + auto innerErrCode = context->ConnectAbility(want, connection); + int32_t errcode = static_cast(GetJsErrorCodeByNativeError(innerErrCode)); + double connectId = connection->GetConnectionId(); + if (errcode) { + TAG_LOGE(AAFwkTag::UI_EXT, "Faied to ConnectAbility, innerErrCode is %{public}d", innerErrCode); + connection->CallEtsFailed(errcode); + return FAILED_CODE; + } + return static_cast(connectId); +} + +void EtsUIExtensionContext::OnDisconnectServiceExtensionAbility(ani_env *env, ani_object aniObj, + ani_long connectId, ani_object callback) +{ + TAG_LOGE(AAFwkTag::UI_EXT, "OnDisconnectServiceExtensionAbility"); + ani_object aniObject = nullptr; + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + aniObject = EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); + return; + } + AAFwk::Want want; + sptr connection = nullptr; + { + std::lock_guard lock(g_connectsMutex); + auto item = std::find_if( + g_connects.begin(), g_connects.end(), [&connectId](const auto &obj) { return connectId == obj.first.id; }); + if (item != g_connects.end()) { + want = item->first.want; + connection = item->second; + g_connects.erase(item); + } else { + TAG_LOGI(AAFwkTag::UI_EXT, "Failed to found connection"); + } + } + if (!connection) { + aniObject = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(AbilityErrorCode::ERROR_CODE_INNER)); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); + TAG_LOGE(AAFwkTag::UI_EXT, "null connection"); + return; + } + ErrCode ret = context->DisconnectAbility(want, connection); + aniObject = EtsErrorUtil::CreateErrorByNativeErr(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); +} + void EtsUIExtensionContext::AddFreeInstallObserver( ani_env *env, const AAFwk::Want &want, ani_object callbackObj, std::shared_ptr context) { @@ -234,6 +446,46 @@ void EtsUIExtensionContext::AddFreeInstallObserver( freeInstallObserver_->AddEtsObserverObject(env, bundleName, abilityName, startTime, callbackObj); } +bool EtsUIExtensionContext::CheckConnectionParam(ani_env *env, ani_object connectOptionsObj, + sptr &connection, AAFwk::Want &want) +{ + ani_type type = nullptr; + ani_boolean res = ANI_FALSE; + ani_status status = ANI_ERROR; + if ((status = env->Object_GetType(connectOptionsObj, &type)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to Object_GetType, status: %{public}d", status); + return false; + } + if (type == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null type"); + return false; + } + if ((status = env->Object_InstanceOf(connectOptionsObj, type, &res)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to Object_InstanceOf, status: %{public}d", status); + return false; + } + if (res != ANI_TRUE) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to CheckConnectionParam"); + return false; + } + connection->SetConnectionRef(connectOptionsObj); + EtsUIExtensionConnectionKey key; + { + std::lock_guard guard(g_connectsMutex); + key.id = g_serialNumber; + key.want = want; + connection->SetConnectionId(key.id); + g_connects.emplace(key, connection); + if (g_serialNumber < INT32_MAX) { + g_serialNumber++; + } else { + g_serialNumber = 0; + } + } + TAG_LOGD(AAFwkTag::UI_EXT, "Failed to find connection, make new one"); + return true; +} + void EtsUIExtensionContext::Clean(ani_env *env, ani_object object) { ani_long ptr = 0; @@ -247,6 +499,71 @@ void EtsUIExtensionContext::Clean(ani_env *env, ani_object object) } } +void EtsUIExtensionContext::SetColorMode(ani_env *env, ani_object aniObj, ani_enum_item aniColorMode) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "SetColorMode called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + auto etsUiExtensionContext = GetEtsUIExtensionContext(env, aniObj); + if (etsUiExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsUiExtensionContext"); + return; + } + etsUiExtensionContext->OnSetColorMode(env, aniObj, aniColorMode); +} + +void EtsUIExtensionContext::ReportDrawnCompleted(ani_env *env, ani_object aniObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "ReportDrawnCompleted called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + auto etsUiExtensionContext = GetEtsUIExtensionContext(env, aniObj); + if (etsUiExtensionContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsUiExtensionContext"); + return; + } + etsUiExtensionContext->OnReportDrawnCompleted(env, aniObj, callback); +} + +void EtsUIExtensionContext::OnSetColorMode(ani_env *env, ani_object aniContext, ani_enum_item aniColorMode) +{ + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + EtsErrorUtil::ThrowError(env, static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)); + return; + } + ani_int colorMode = 0; + if (!AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative(env, aniColorMode, colorMode)) { + TAG_LOGE(AAFwkTag::UI_EXT, "param aniColorMode err"); + EtsErrorUtil::ThrowInvalidParamError(env, "Parse param colorMode failed, colorMode must be number."); + return; + } + context->SetAbilityColorMode(colorMode); + TAG_LOGD(AAFwkTag::UI_EXT, "NativeSetColorMode end"); +} + +void EtsUIExtensionContext::OnReportDrawnCompleted(ani_env* env, ani_object aniCls, ani_object callback) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "OnReportDrawnCompleted called"); + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + AppExecFwk::AsyncCallback(env, callback, + AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)), nullptr); + return; + } + int32_t innerErrorCode = context->ReportDrawnCompleted(); + AppExecFwk::AsyncCallback(env, callback, AbilityRuntime::EtsErrorUtil::CreateErrorByNativeErr(env, + static_cast(innerErrorCode)), nullptr); + TAG_LOGD(AAFwkTag::UI_EXT, "NativeReportDrawnCompleted end"); +} + bool EtsUIExtensionContext::BindNativePtrCleaner(ani_env *env) { if (env == nullptr) { @@ -301,17 +618,43 @@ ani_object CreateEtsUIExtensionContext(ani_env *env, std::shared_ptr(EtsUIExtensionContext::StartAbilityWithOption) }, + ani_native_function { "nativeConnectServiceExtensionAbility", SIGNATURE_CONNECT_SERVICE_EXTENSION, + reinterpret_cast(EtsUIExtensionContext::ConnectServiceExtensionAbility) }, + ani_native_function { "nativeDisconnectServiceExtensionAbilitySync", SIGNATURE_DISCONNECT_SERVICE_EXTENSION, + reinterpret_cast(EtsUIExtensionContext::DisconnectServiceExtensionAbility) }, + ani_native_function { "nativeStartAbilityForResult", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsUIExtensionContext::StartAbilityForResult) }, + ani_native_function { "nativeStartAbilityForResult", + "L@ohos/app/ability/Want/Want;L@ohos/app/ability/StartOptions/StartOptions;Lutils/AbilityUtils/" + "AsyncCallbackWrapper;:V", + reinterpret_cast(EtsUIExtensionContext::StartAbilityForResultWithOptions) }, + ani_native_function{"setColorMode", + "L@ohos/app/ability/ConfigurationConstant/ConfigurationConstant/ColorMode;:V", + reinterpret_cast(EtsUIExtensionContext::SetColorMode)}, + ani_native_function{"nativeReportDrawnCompleted", + "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsUIExtensionContext::ReportDrawnCompleted)} }; - if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK + && status != ANI_ALREADY_BINDED) { + TAG_LOGE(AAFwkTag::UI_EXT, "BindNativeMethods status: %{public}d", status); return nullptr; } - if ((status = env->Object_SetFieldByName_Long(contextObj, "nativeContext", (ani_long)context.get())) != ANI_OK) { - TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + auto workContext = new (std::nothrow) + std::weak_ptr(context); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null workContext"); + return nullptr; + } + if (!ContextUtil::SetNativeContextLong(env, contextObj, (ani_long)workContext)) { + TAG_LOGE(AAFwkTag::UI_EXT, "SetNativeContextLong failed"); + delete workContext; return nullptr; } if (!EtsUIExtensionContext::BindNativePtrCleaner(env)) { TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + delete workContext; return nullptr; } OHOS::AbilityRuntime::ContextUtil::CreateEtsBaseContext(env, cls, contextObj, context); @@ -339,5 +682,154 @@ EtsUIExtensionContext* EtsUIExtensionContext::GetEtsUIExtensionContext(ani_env * } return etsContext; } + +EtsUIExtensionConnection::EtsUIExtensionConnection(ani_vm *etsVm) : etsVm_(etsVm) {} + +EtsUIExtensionConnection::~EtsUIExtensionConnection() +{ + if (etsVm_ != nullptr && stsConnectionRef_ != nullptr) { + ani_env* env = nullptr; + if (etsVm_->GetEnv(ANI_VERSION_1, &env) == ANI_OK) { + env->GlobalReference_Delete(stsConnectionRef_); + stsConnectionRef_ = nullptr; + } + } +} + +void EtsUIExtensionConnection::SetConnectionId(int32_t id) +{ + connectionId_ = id; +} + +void EtsUIExtensionConnection::CallEtsFailed(int32_t errorCode) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "CallEtsFailed"); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "etsVm_ is nullptr"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_OK; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return; + } + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + if (stsConnectionRef_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null stsConnectionRef_"); + return; + } + ani_class cls = nullptr; + if ((status = env->FindClass(CONNECT_OPTIONS_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to find connectOptions calss, status: %{public}d", status); + return; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null class"); + return; + } + ani_method method = nullptr; + if ((status = env->Class_FindMethod(cls, "onFailed", "I:V", &method))) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to find onFailed method, status: %{public}d", status); + return; + } + if (method == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null method"); + return; + } + status = env->Object_CallMethod_Void( + reinterpret_cast(stsConnectionRef_), method, errorCode); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Object_CallMethod_Void status: %{public}d", status); + } +} + +void EtsUIExtensionConnection::SetConnectionRef(ani_object connectOptionsObj) +{ + TAG_LOGI(AAFwkTag::UI_EXT, "called"); + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null etsVm"); + return; + } + + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if ((status = etsVm_->GetEnv(ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Faied to getEnv, status: %{public}d", status); + return; + } + if ((status = env->GlobalReference_Create(connectOptionsObj, &stsConnectionRef_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Faied to createReference, status: %{public}d", status); + } +} + +void EtsUIExtensionConnection::OnAbilityConnectDone(const AppExecFwk::ElementName &element, + const sptr &remoteObject, int resultCode) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "OnAbilityConnectDone"); + if (etsVm_ == nullptr || stsConnectionRef_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null stsConnectionRef or etsVm"); + return; + } + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetEnv failed"); + return; + } + ani_ref refElement = AppExecFwk::WrapElementName(env, element); + if (refElement == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null refElement"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + if (remoteObject == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null remoteObject"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_object refRemoteObject = AniRemote::CreateAniRemoteObject(env, remoteObject); + if (refRemoteObject == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null refRemoteObject"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_status status = ANI_ERROR; + if ((status = env->Object_CallMethodByName_Void(reinterpret_cast(stsConnectionRef_), "onConnect", + SIGNATURE_ONCONNECT, refElement, refRemoteObject)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to call onConnect, status: %{public}d", status); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} + +void EtsUIExtensionConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "OnAbilityDisconnectDone"); + if (etsVm_ == nullptr || stsConnectionRef_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null stsConnectionRef or etsVm"); + return; + } + bool isAttachThread = false; + ani_env *env = AppExecFwk::AttachAniEnv(etsVm_, isAttachThread); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetEnv failed"); + return; + } + ani_ref refElement = AppExecFwk::WrapElementName(env, element); + if (refElement == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null refElement"); + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); + return; + } + ani_status status = ANI_ERROR; + if ((status = env->Object_CallMethodByName_Void(reinterpret_cast(stsConnectionRef_), "onDisconnect", + SIGNATURE_ONDISCONNECT, refElement)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "Failed to call onDisconnect, status: %{public}d", status); + } + AppExecFwk::DetachAniEnv(etsVm_, isAttachThread); +} } // namespace AbilityRuntime } // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ui_extension_callback/BUILD.gn b/frameworks/ets/ani/ui_extension_callback/BUILD.gn new file mode 100644 index 00000000000..e225d24e8de --- /dev/null +++ b/frameworks/ets/ani/ui_extension_callback/BUILD.gn @@ -0,0 +1,65 @@ +# 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("ani_ui_extension_callback") { + 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}/services/common/include", + ] + + sources = [ "src/ets_ui_extension_callback.cpp" ] + + deps = [ + "${ability_runtime_native_path}/ability:ability_context_native", + "${ability_runtime_native_path}/ability/native:ability_business_error", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] + + external_deps = [ + "ability_base:want", + "access_token:libtokenid_sdk", + "c_utils:utils", + "hilog:libhilog", + "image_framework:image_native", + "runtime_core:ani", + ] + + if (ability_runtime_graphics) { + external_deps += [ + "ace_engine:ace_uicontent", + "window_manager:libwsutils", + "window_manager:scene_session", + "window_manager:session_manager_lite", + ] + } + + 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/ui_extension_callback/include/ets_ui_extension_callback.h b/frameworks/ets/ani/ui_extension_callback/include/ets_ui_extension_callback.h new file mode 100644 index 00000000000..8dd295dd828 --- /dev/null +++ b/frameworks/ets/ani/ui_extension_callback/include/ets_ui_extension_callback.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_UI_EXTENSION_CALLBACK_H +#define OHOS_ABILITY_RUNTIME_ETS_UI_EXTENSION_CALLBACK_H + +#include + +#include "ui_extension_callback.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsUIExtensionCallback : public UIExtensionCallback { +public: + explicit EtsUIExtensionCallback(ani_vm *vm) : vm_(vm) {} + ~EtsUIExtensionCallback() override; + void OnError(int32_t number) override; + void OnResult(int32_t resultCode, const AAFwk::Want &want) override; + void SetEtsCallbackObject(ani_object aniObject); + +private: + ani_env *GetAniEnv(); + void CallObjectMethod(const char *name, const char *signature, ...); + + ani_vm *vm_ = nullptr; + ani_ref callback_ = nullptr; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_UI_EXTENSION_CALLBACK_H diff --git a/frameworks/ets/ani/ui_extension_callback/src/ets_ui_extension_callback.cpp b/frameworks/ets/ani/ui_extension_callback/src/ets_ui_extension_callback.cpp new file mode 100644 index 00000000000..d76e078079c --- /dev/null +++ b/frameworks/ets/ani/ui_extension_callback/src/ets_ui_extension_callback.cpp @@ -0,0 +1,181 @@ +/* + * 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_ui_extension_callback.h" + +#include "ability_business_error.h" +#include "ani_common_ability_result.h" +#include "ani_common_util.h" +#include "hilog_tag_wrapper.h" +#ifdef SUPPORT_SCREEN +#include "ui_content.h" +#include "ws_common.h" +#endif // SUPPORT_SCREEN + +namespace OHOS { +namespace AbilityRuntime { +#ifdef SUPPORT_SCREEN +constexpr const char* ERROR_MSG_INNER = "Inner error."; +#endif // SUPPORT_SCREEN + +namespace { +constexpr const char *ABILITY_START_CLASS_NAME = "Lapplication/AbilityStartCallback/AbilityStartCallback;"; +} + +EtsUIExtensionCallback::~EtsUIExtensionCallback() +{ + ani_env *env = GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + if (callback_ != nullptr) { + env->GlobalReference_Delete(callback_); + callback_ = nullptr; + } +} + +void EtsUIExtensionCallback::OnError(int32_t number) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "OnError call"); + std::string name; + std::string message; +#ifdef SUPPORT_SCREEN + if (number != static_cast(Rosen::WSError::WS_OK)) { + number = static_cast(AbilityErrorCode::ERROR_CODE_INNER); + name = ERROR_MSG_INNER; + message = "StartAbilityByType failed."; + } +#endif // SUPPORT_SCREEN + auto env = GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + ani_string aniName = nullptr; + ani_status status = env->String_NewUTF8(name.c_str(), name.length(), &aniName); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "aniName String_NewUTF8 failed, status: %{public}d", status); + return; + } + ani_string aniMsg = nullptr; + if ((status = env->String_NewUTF8(message.c_str(), message.length(), &aniMsg)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "aniMsg String_NewUTF8 failed, status: %{public}d", status); + return; + } + CallObjectMethod("onError", nullptr, (ani_double)number, aniName, aniMsg); + CloseModalUIExtension(); +} + +void EtsUIExtensionCallback::OnResult(int32_t resultCode, const AAFwk::Want &want) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "OnResult call"); + auto env = GetAniEnv(); + if (env == nullptr || callback_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env or callback_"); + return; + } + ani_object startCallback = reinterpret_cast(callback_); + ani_boolean isUndefined = true; + ani_ref onResultRef = nullptr; + if (!AppExecFwk::GetPropertyRef(env, startCallback, "onResult", onResultRef, isUndefined) || + onResultRef == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetPropertyRef failed, or null onResultRef"); + return; + } + if (isUndefined) { + TAG_LOGE(AAFwkTag::UI_EXT, "onResult is undefined"); + return; + } + ani_fn_object onResultFn = reinterpret_cast(onResultRef); + ani_object abilityResultObj = AppExecFwk::WrapAbilityResult(env, resultCode, want); + if (abilityResultObj == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "create abilityResultObj failed"); + return; + } + ani_ref argv[] = { abilityResultObj }; + ani_ref result = nullptr; + ani_status status = env->FunctionalObject_Call(onResultFn, 1, argv, &result); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "call onResult fn failed, status: %{public}d", status); + return; + } + CloseModalUIExtension(); +} + +void EtsUIExtensionCallback::CallObjectMethod(const char *name, const char *signature, ...) +{ + TAG_LOGD(AAFwkTag::EXT, "name: %{public}s", name); + auto env = GetAniEnv(); + if (env == nullptr || callback_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env or callback_"); + return; + } + ani_class clsCall = nullptr; + ani_status status = env->FindClass(ABILITY_START_CLASS_NAME, &clsCall); + if (status != ANI_OK || clsCall == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "find AbilityStartCallback class failed, status: %{public}d, or null cls", status); + return; + } + ani_method method = nullptr; + if ((status = env->Class_FindMethod(clsCall, name, signature, &method)) != ANI_OK || method == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "find onError method failed, status: %{public}d, or null method", status); + env->ResetError(); + return; + } + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(reinterpret_cast(callback_), method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::EXT, "Object_CallMethod name: %{public}s, status: %{public}d", name, status); + return; + } + va_end(args); + TAG_LOGI(AAFwkTag::EXT, "CallObjectMethod end, name: %{public}s", name); +} + +void EtsUIExtensionCallback::SetEtsCallbackObject(ani_object aniObject) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "SetEtsCallbackObject call"); + ani_env *env = GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + ani_ref callback = nullptr; + ani_status status = env->GlobalReference_Create(aniObject, &callback); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GlobalReference_Create failed, status: %{public}d", status); + return; + } + callback_ = callback; +} + +ani_env* EtsUIExtensionCallback::GetAniEnv() +{ + TAG_LOGD(AAFwkTag::UI_EXT, "GetAniEnv call"); + if (vm_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null vm_"); + return nullptr; + } + ani_env *env = nullptr; + ani_status status = vm_->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "get env failed, status: %{public}d", status); + return nullptr; + } + return env; +} +} // namespace AbilityRuntime +} // namespace OHOS 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 7f90db1c7f5..16823704aed 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 @@ -22,9 +22,9 @@ namespace OHOS { namespace AbilityRuntime { static void grantUriPermissionCallbackSync([[maybe_unused]]ani_env *env, - ani_string uri, ani_enum_item flagEnum, ani_string targetName, ani_double appCloneIndex, ani_object callback); + ani_string uri, ani_enum_item flagEnum, ani_string targetName, ani_int appCloneIndex, ani_object callback); static void revokeUriPermissionCallbackSync([[maybe_unused]]ani_env *env, - ani_string uri, ani_string targetName, ani_double appCloneIndex, ani_object callback); + ani_string uri, ani_string targetName, ani_int appCloneIndex, ani_object callback); void CreateJsUriPermMgr(ani_env *env); bool AsyncCallback(ani_env *env, ani_object call, ani_object error, ani_object result); ani_object WrapBusinessError(ani_env *env, ani_int code); 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 e825dce851f..0ba54b28cb1 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 @@ -83,7 +83,7 @@ static std::string GetStdString(ani_env* env, ani_string str) } static void grantUriPermissionCallbackSync([[maybe_unused]]ani_env *env, - ani_string uri, ani_enum_item flagEnum, ani_string targetName, ani_double appCloneIndex, ani_object callback) + ani_string uri, ani_enum_item flagEnum, ani_string targetName, ani_int appCloneIndex, ani_object callback) { TAG_LOGI(AAFwkTag::URIPERMMGR, "grantUriPermissionCallbackSync run"); if (env == nullptr) { @@ -105,10 +105,9 @@ static void grantUriPermissionCallbackSync([[maybe_unused]]ani_env *env, AAFwk::AniEnumConvertUtil::EnumConvert_EtsToNative(env, flagEnum, flag); int32_t flagId = static_cast(flag); std::string targetBundleName = GetStdString(env, targetName); - int32_t appCloneIndexId = static_cast(appCloneIndex); int32_t result = ERR_OK; int32_t errCode = AAFwk::UriPermissionManagerClient::GetInstance().GrantUriPermission(uriVec, flagId, - targetBundleName, appCloneIndexId); + targetBundleName, appCloneIndex); if (errCode != ERR_OK) { result = ERR_FAILURE; etsErrCode = EtsErrorUtil::CreateErrorByNativeErr(env, errCode); @@ -118,7 +117,7 @@ static void grantUriPermissionCallbackSync([[maybe_unused]]ani_env *env, } static void revokeUriPermissionCallbackSync([[maybe_unused]]ani_env *env, - ani_string uri, ani_string targetName, ani_double appCloneIndex, ani_object callback) + ani_string uri, ani_string targetName, ani_int appCloneIndex, ani_object callback) { TAG_LOGI(AAFwkTag::URIPERMMGR, "revokeUriPermissionCallbackSync run"); if (env == nullptr) { @@ -166,13 +165,13 @@ void EtsUriPermissionManagerInit(ani_env *env) std::array functions = { ani_native_function { "grantUriPermissionCallbackSync", - "Lstd/core/String;L@ohos/app/ability/wantConstant/wantConstant/Flags;Lstd/core/String;D" + "Lstd/core/String;L@ohos/app/ability/wantConstant/wantConstant/Flags;Lstd/core/String;I" "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", reinterpret_cast(grantUriPermissionCallbackSync) }, ani_native_function { "revokeUriPermissionCallbackSync", - "Lstd/core/String;Lstd/core/String;D" + "Lstd/core/String;Lstd/core/String;I" "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", reinterpret_cast(revokeUriPermissionCallbackSync) }, diff --git a/frameworks/ets/ani/wantagent/src/ani_want_agent.cpp b/frameworks/ets/ani/wantagent/src/ani_want_agent.cpp index 6135f178efe..48c85a27332 100644 --- a/frameworks/ets/ani/wantagent/src/ani_want_agent.cpp +++ b/frameworks/ets/ani/wantagent/src/ani_want_agent.cpp @@ -107,7 +107,7 @@ bool OnSendFinishedCallback(TriggerReceiveDataWorker *dataWorker) } env->Object_SetPropertyByName_Ref(object, "info", retObj); env->Object_SetPropertyByName_Ref(object, "want", WrapWant(env, dataWorker->want)); - env->Object_SetPropertyByName_Double(object, "finalCode", static_cast(dataWorker->resultCode)); + env->Object_SetPropertyByName_Int(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)); @@ -273,7 +273,7 @@ void EtsWantAgent::OnGetUid(ani_env *env, ani_object agent, ani_object call) if (resultCode != ERR_OK) { error = EtsErrorUtil::CreateError(env, resultCode, AbilityRuntimeErrorUtil::GetErrMessage(resultCode)); } - AsyncCallback(env, call, error, CreateDouble(env, static_cast(uid))); + AsyncCallback(env, call, error, CreateInt(env, uid)); } void EtsWantAgent::OnCancel(ani_env *env, ani_object agent, ani_object call) @@ -382,7 +382,7 @@ void EtsWantAgent::OnGetOperationType(ani_env *env, ani_object agent, ani_object if (retCode != NO_ERROR) { error = EtsErrorUtil::CreateError(env, retCode, AbilityRuntimeErrorUtil::GetErrMessage(retCode)); } - AsyncCallback(env, call, error, CreateDouble(env, static_cast(operType))); + AsyncCallback(env, call, error, CreateInt(env, operType)); } int32_t EtsWantAgent::GetWantAgentParam(ani_env *env, ani_object info, WantAgentParams ¶ms) diff --git a/frameworks/ets/ets/@ohos.ability.errorCode.ets b/frameworks/ets/ets/@ohos.ability.errorCode.ets new file mode 100644 index 00000000000..aaee5b0a9b5 --- /dev/null +++ b/frameworks/ets/ets/@ohos.ability.errorCode.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 enum ErrorCode { + PERMISSION_DENY = -3, + ABILITY_NOT_FOUND = -2, + INVALID_PARAMETER = -1, + NO_ERROR = 0 +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.Ability.ets b/frameworks/ets/ets/@ohos.app.ability.Ability.ets new file mode 100644 index 00000000000..02520bf6350 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.Ability.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. + */ + +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import { Configuration } from '@ohos.app.ability.Configuration'; + +export default class Ability { + onConfigurationUpdate(newConfig: Configuration): void { + } + + onMemoryLevel(level: AbilityConstant.MemoryLevel): void { + } +} diff --git a/frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets b/frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets index e2d28887f5c..8ad495d937d 100644 --- a/frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets +++ b/frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets @@ -23,14 +23,14 @@ namespace AbilityConstant { } export interface LastExitDetailInfo { - pid: number; + pid: int; processName: string; - uid: number; - exitSubReason: number; + uid: int; + exitSubReason: int; exitMsg: string; - rss: number; - pss: number; - timestamp: number; + rss: int; + pss: int; + timestamp: long; } export enum LaunchReason { @@ -118,14 +118,14 @@ class LaunchParamImpl implements AbilityConstant.LaunchParam { } class LastExitDetailInfoImpl implements AbilityConstant.LastExitDetailInfo { - pid: number = 0; + pid: int = 0; processName: string = ''; - uid: number = 0; - exitSubReason: number = 0; + uid: int = 0; + exitSubReason: int = 0; exitMsg: string = ''; - rss: number = 0; - pss: number = 0; - timestamp: number = 0; + rss: int = 0; + pss: int = 0; + timestamp: long = 0; } export default AbilityConstant; diff --git a/frameworks/ets/ets/@ohos.app.ability.ApplicationStateChangeCallback.ets b/frameworks/ets/ets/@ohos.app.ability.ApplicationStateChangeCallback.ets new file mode 100644 index 00000000000..32585e54e3f --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.ApplicationStateChangeCallback.ets @@ -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. + */ + +interface ApplicationStateChangeCallback { + onApplicationForeground(): void; + onApplicationBackground(): void; +} + +class ApplicationStateChangeCallbackInner implements ApplicationStateChangeCallback { + onApplicationForeground(): void { + } + + onApplicationBackground(): void { + } +} + +export default ApplicationStateChangeCallback; \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.AtomicServiceOptions.ets b/frameworks/ets/ets/@ohos.app.ability.AtomicServiceOptions.ets new file mode 100644 index 00000000000..366dc566859 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.AtomicServiceOptions.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. + */ + +import StartOptions from '@ohos.app.ability.StartOptions'; + +export default class AtomicServiceOptions extends StartOptions { + flags?: int; + parameters?: Record; +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.Configuration.ets b/frameworks/ets/ets/@ohos.app.ability.Configuration.ets index e9db058b47f..fb5972d09d7 100644 --- a/frameworks/ets/ets/@ohos.app.ability.Configuration.ets +++ b/frameworks/ets/ets/@ohos.app.ability.Configuration.ets @@ -20,11 +20,11 @@ export interface Configuration { colorMode?: ConfigurationConstant.ColorMode; direction?: ConfigurationConstant.Direction; screenDensity?: ConfigurationConstant.ScreenDensity; - displayId?: number; + displayId?: long; hasPointerDevice?: boolean; fontId?: string; - fontSizeScale?: number; - fontWeightScale?: number; + fontSizeScale?: double; + fontWeightScale?: double; mcc?: string; mnc?: string; } @@ -34,11 +34,11 @@ class ConfigurationImpl implements Configuration { colorMode?: ConfigurationConstant.ColorMode; direction?: ConfigurationConstant.Direction; screenDensity?: ConfigurationConstant.ScreenDensity; - displayId?: number; + displayId?: long; hasPointerDevice?: boolean; fontId?: string; - fontSizeScale?: number; - fontWeightScale?: number; + fontSizeScale?: double; + fontWeightScale?: double; mcc?: string; mnc?: string; } diff --git a/frameworks/ets/ets/@ohos.app.ability.EnvironmentCallback.ets b/frameworks/ets/ets/@ohos.app.ability.EnvironmentCallback.ets new file mode 100644 index 00000000000..908a4f82e0e --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.EnvironmentCallback.ets @@ -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. + */ + +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import { Configuration } from '@ohos.app.ability.Configuration'; + +interface EnvironmentCallback { + onConfigurationUpdated(config: Configuration): void; + onMemoryLevel(level: AbilityConstant.MemoryLevel): void; +} + +class EnvironmentCallbackInner implements EnvironmentCallback { + onConfigurationUpdated(config: Configuration): void { + } + + onMemoryLevel(level: AbilityConstant.MemoryLevel): void { + } +} +export default EnvironmentCallback; \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.ExtensionAbility.ets b/frameworks/ets/ets/@ohos.app.ability.ExtensionAbility.ets new file mode 100644 index 00000000000..09368e1869f --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.ExtensionAbility.ets @@ -0,0 +1,19 @@ +/* + * 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 Ability from '@ohos.app.ability.Ability'; + +export default class ExtensionAbility extends Ability { +} diff --git a/frameworks/ets/ets/@ohos.app.ability.ServiceExtensionAbility.ets b/frameworks/ets/ets/@ohos.app.ability.ServiceExtensionAbility.ets index 2c3c47ee0b4..97d20d1b8a0 100644 --- a/frameworks/ets/ets/@ohos.app.ability.ServiceExtensionAbility.ets +++ b/frameworks/ets/ets/@ohos.app.ability.ServiceExtensionAbility.ets @@ -48,22 +48,11 @@ export default class ServiceExtensionAbility { private native nativeOnDisconnectCallback(): void; private callOnDisconnect(want: Want): boolean { - const derivedClassType = AbilityUtils.getClassType(this); - if (derivedClassType === undefined) { - this.onDisconnect(want); - return false; - } - const serviceExtensionClassType = AbilityUtils.getClassType(new ServiceExtensionAbility()); - if (serviceExtensionClassType === undefined) { - this.onDisconnect(want); - return false; - } - const isOverride = AbilityUtils.isOverride(derivedClassType, "onDisconnectAsync", serviceExtensionClassType); - if (isOverride) { - this.onDisconnectAsync(want).then(() => this.nativeOnDisconnectCallback()); + let p = this.onDisconnect(want); + if (p instanceof Promise) { + p.then(() => this.nativeOnDisconnectCallback()); return true; } - this.onDisconnect(want); return false; } @@ -77,7 +66,7 @@ export default class ServiceExtensionAbility { onDestroy(): void { } - onRequest(want: Want, startld: double): void { + onRequest(want: Want, startld: int): void { } onConnect(want: Want): rpc.RemoteObject | Promise { @@ -85,11 +74,8 @@ export default class ServiceExtensionAbility { return myService; } - onDisconnect(want: Want): void { - } - - onDisconnectAsync(want: Want): Promise { - return new Promise((resolve: (a: undefined) => void, reject: (err: Error) => void): void => {}); + onDisconnect(want: Want): Promise | undefined { + return undefined; } onConfigurationUpdate(newConfig: Configuration): void { diff --git a/frameworks/ets/ets/@ohos.app.ability.ShareExtensionAbility.ets b/frameworks/ets/ets/@ohos.app.ability.ShareExtensionAbility.ets new file mode 100644 index 00000000000..b238c15ea6a --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.ShareExtensionAbility.ets @@ -0,0 +1,19 @@ +/* + * 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 UIExtensionAbility from '@ohos.app.ability.UIExtensionAbility'; + +export default class ShareExtensionAbility extends UIExtensionAbility { +} \ 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 2d25b6e930d..5924a678319 100644 --- a/frameworks/ets/ets/@ohos.app.ability.StartOptions.ets +++ b/frameworks/ets/ets/@ohos.app.ability.StartOptions.ets @@ -18,21 +18,21 @@ import image from '@ohos.multimedia.image'; import bundleManager from '@ohos.bundle.bundleManager'; export default class StartOptions { - windowMode?: number; - displayId?: number; + windowMode?: int; + displayId?: long; withAnimation?: boolean; - windowLeft?: number; - windowTop?: number; - windowWidth?: number; - windowHeight?: number; + windowLeft?: int; + windowTop?: int; + windowWidth?: int; + windowHeight?: int; windowFocused?: boolean; processMode?: contextConstant.ProcessMode; startupVisibility?: contextConstant.StartupVisibility; startWindowBackgroundColor?: string; startWindowIcon?: image.PixelMap; supportWindowModes?: Array; - minWindowWidth?: number; - minWindowHeight?: number; - maxWindowWidth?: number; - maxWindowHeight?: number; + minWindowWidth?: int; + minWindowHeight?: int; + maxWindowWidth?: int; + maxWindowHeight?: int; } \ 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 b3d25a9be05..34b43e1af1b 100644 --- a/frameworks/ets/ets/@ohos.app.ability.UIAbility.ets +++ b/frameworks/ets/ets/@ohos.app.ability.UIAbility.ets @@ -13,13 +13,14 @@ * limitations under the License. */ +import Ability from '@ohos.app.ability.Ability'; import AbilityConstant from '@ohos.app.ability.AbilityConstant'; import UIAbilityContext from 'application.UIAbilityContext'; import Want from '@ohos.app.ability.Want'; import window from '@ohos.window'; import { AbilityUtils } from './utils/AbilityUtils'; -export default class UIAbility { +export default class UIAbility extends Ability { private destroyCallbackPoint: long; private native nativeOnDestroyCallback(): void; @@ -35,8 +36,7 @@ export default class UIAbility { this.onDestroy(); return false; } - const isOverride = AbilityUtils.isOverride(derivedClassType, "onDestroyAsync", uiAbilityClassType); - if (isOverride) { + if (AbilityUtils.isOverride(derivedClassType, "onDestroyAsync", uiAbilityClassType)) { this.onDestroyAsync().then(() => this.nativeOnDestroyCallback()); return true; } @@ -74,9 +74,22 @@ export default class UIAbility { onForeground(): void { } + onWillForeground(): void { + } + + onDidForeground(): void { + } + onBackground(): void { } + onWillBackground(): void { + } + + onDidBackground(): void { + } + + onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void { } } diff --git a/frameworks/ets/ets/@ohos.app.ability.UIExtensionAbility.ets b/frameworks/ets/ets/@ohos.app.ability.UIExtensionAbility.ets index 5c22e51bb92..c50ef5780f9 100644 --- a/frameworks/ets/ets/@ohos.app.ability.UIExtensionAbility.ets +++ b/frameworks/ets/ets/@ohos.app.ability.UIExtensionAbility.ets @@ -14,27 +14,23 @@ */ import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import ExtensionAbility from '@ohos.app.ability.ExtensionAbility'; import Want from '@ohos.app.ability.Want'; import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; import UIExtensionContext from 'application.UIExtensionContext'; - -class ExtensionAbility{} +import { AbilityUtils } from './utils/AbilityUtils'; export default class UIExtensionAbility extends ExtensionAbility { - private isOnDestroyAsync: boolean = true; private destroyCallbackPoint: long; private native nativeOnDestroyCallback(): void; private callOnDestroy(): boolean { - let p = this.onDestroyAsync(); - if (this.isOnDestroyAsync) { - p.then((): void => { - this.nativeOnDestroyCallback(); - }); - } else { - this.onDestroy(); + let p = this.onDestroy(); + if (p instanceof Promise) { + p.then(() => this.nativeOnDestroyCallback()); + return true; } - return this.isOnDestroyAsync; + return false; } context: UIExtensionContext = {}; @@ -49,10 +45,7 @@ export default class UIExtensionAbility extends ExtensionAbility { onBackground(): void {} - onDestroy(): void {} - - onDestroyAsync(): Promise { - this.isOnDestroyAsync = false; - return new Promise((resolve: (a: undefined)=>void, reject: (err: Error)=>void): void => {}); + onDestroy(): Promise | undefined { + return undefined; } } diff --git a/frameworks/ets/ets/@ohos.app.ability.UIExtensionContentSession.ets b/frameworks/ets/ets/@ohos.app.ability.UIExtensionContentSession.ets index d48ecfb4593..266dbed17a1 100644 --- a/frameworks/ets/ets/@ohos.app.ability.UIExtensionContentSession.ets +++ b/frameworks/ets/ets/@ohos.app.ability.UIExtensionContentSession.ets @@ -19,6 +19,7 @@ import { BusinessError } from '@ohos.base'; import uiExtensionHost from '@ohos.uiExtensionHost'; import { LocalStorage } from '@ohos.arkui.stateManagement'; import AsyncCallbackWrapper from './utils/AbilityUtils'; +import AbilityStartCallback from 'application.AbilityStartCallback'; class Cleaner { static callback(cleaner: Cleaner): void { @@ -57,6 +58,7 @@ export default class UIExtensionContentSession { native nativeSetReceiveDataForResultCallback(callback: (data: Record) => Record): void; native terminateSelfSync(callback:AsyncCallbackWrapper): void; native terminateSelfWithResultSync(parameter: AbilityResult, callback:AsyncCallbackWrapper): void; + private native nativeStartAbilityByTypeSync(type: string, wantParam: Record, startCallback: AbilityStartCallback): BusinessError; sendData(data: Record): void { this.nativeSendData(data); @@ -115,4 +117,41 @@ export default class UIExtensionContentSession { }); return p; } + + startAbilityByType(type: string, wantParam: Record, startCallback: AbilityStartCallback, + callback: AsyncCallback): void { + let p1 = taskpool.execute((): BusinessError => { + return this.nativeStartAbilityByTypeSync(type, wantParam, startCallback); + }); + p1.then((e: NullishType) => { + let retError = e as BusinessError; + if (retError.code === 0) { + callback(null, undefined); + } else { + callback(retError, undefined); + } + }, (err: Error): void => { + callback(err as BusinessError, undefined); + }); + } + + startAbilityByType(type: string, wantParam: Record, + startCallback: AbilityStartCallback): Promise { + let p = new Promise((resolve: (v: undefined) => void, reject: (error: BusinessError) => void): void => { + let p1 = taskpool.execute((): BusinessError => { + return this.nativeStartAbilityByTypeSync(type, wantParam, startCallback); + }); + p1.then((e: NullishType) => { + let retError = e as BusinessError; + if (retError.code === 0) { + resolve(undefined); + } else { + reject(retError); + } + }).catch((err: Error): void => { + reject(err as BusinessError); + }); + }); + return p; + } } diff --git a/frameworks/ets/ets/@ohos.app.ability.Want.ets b/frameworks/ets/ets/@ohos.app.ability.Want.ets index 2d81ad45d82..1fbcdee6f0b 100644 --- a/frameworks/ets/ets/@ohos.app.ability.Want.ets +++ b/frameworks/ets/ets/@ohos.app.ability.Want.ets @@ -154,7 +154,7 @@ class RecordWriter { export class RecordSerializeTool { public static stringifyNoThrow(obj: Record): String { try { - return RecordSerializeTool.stringify(obj as Object as Record); + return JSON.stringify(obj as Object as Record); } catch (err) { hilog.error(DOMAIN_ID, TAG, `RecordSerializeTool.stringify error: ${err}`); return ''; @@ -224,9 +224,10 @@ export default class Want { deviceId?: string; uri?: string; type?: string; - flags?: number; + flags?: int; action?: string; parameters?: Record; entities?: Array; moduleName?: string; + readonly fds?: Record; } diff --git a/frameworks/ets/ets/@ohos.app.ability.abilityManager.ets b/frameworks/ets/ets/@ohos.app.ability.abilityManager.ets index 6a12cac59d8..55305727e72 100644 --- a/frameworks/ets/ets/@ohos.app.ability.abilityManager.ets +++ b/frameworks/ets/ets/@ohos.app.ability.abilityManager.ets @@ -17,6 +17,10 @@ import AbilityStateData from 'application.AbilityStateData'; import { ElementName } from 'bundleManager.ElementName' import { BusinessError, AsyncCallback } from '@ohos.base'; import AsyncCallbackWrapper from './utils/AbilityUtils'; +import { AbilityRunningInfo as _AbilityRunningInfo } from 'application.AbilityRunningInfo'; +import _AbilityStateData from 'application.AbilityStateData'; +import Context from 'application.Context'; +import _AbilityForegroundStateObserver from 'application.AbilityForegroundStateObserver'; export default namespace abilityManager { loadLibrary("ability_manager_ani_kit.z") @@ -25,6 +29,10 @@ export default namespace abilityManager { export native function getForegroundUIAbilitiesCallback(callback:AsyncCallbackWrapper>) : void; export native function nativeGetTopAbility(callback:AsyncCallbackWrapper) : void; export native function nativeCheckSystemApp() : void; + export native function nativeGetAbilityRunningInfos(callback:AsyncCallbackWrapper>) : void; + export native function nativeIsEmbeddedOpenAllowed(context: Context, appId: string, callback:AsyncCallbackWrapper) : void; + export native function nativeOn(type:string, observer: AbilityForegroundStateObserver): void; + export native function nativeOff(type:string, observer?: AbilityForegroundStateObserver): void; export function getForegroundUIAbilities():Promise> { let p = new Promise>((resolve: (data: Array) => void, reject: (error: Error) => void): void => { @@ -48,6 +56,7 @@ export default namespace abilityManager { abilityManager.getForegroundUIAbilitiesCallback(myCall); }) } + export function getTopAbility():Promise { abilityManager.nativeCheckSystemApp(); let p = new Promise((resolve: (data: ElementName)=>void, reject:(err: BusinessError)=>void):void => { @@ -63,13 +72,81 @@ export default namespace abilityManager { }); }); return p; -} + } -export function getTopAbility(callback: AsyncCallback): void { + export function getTopAbility(callback: AsyncCallback): void { abilityManager.nativeCheckSystemApp(); let myCall = new AsyncCallbackWrapper(callback); taskpool.execute( (): void => { - abilityManager.nativeGetTopAbility(myCall); + abilityManager.nativeGetTopAbility(myCall); + }); + } + + function getAbilityRunningInfos(): Promise> { + return new Promise>((resolve: (data: Array) => void, + reject: (err: BusinessError) => void): void => { + let syncCall = new AsyncCallbackWrapper>((err: BusinessError | null, + data: Array | undefined) => { + if (err == null || err.code == 0) { + resolve(data as Array); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + abilityManager.nativeGetAbilityRunningInfos(syncCall); + }); + }); + } + + function getAbilityRunningInfos(callback: AsyncCallback>): void { + let syncCall = new AsyncCallbackWrapper>(callback); + taskpool.execute((): void => { + abilityManager.nativeGetAbilityRunningInfos(syncCall); + }); + } + + function isEmbeddedOpenAllowed(context: Context, appId: string): Promise { + return new Promise((resolve:(data:boolean)=>void, reject:(err: BusinessError | null)=>void):void => { + let asyncCall = new AsyncCallbackWrapper((err: BusinessError | null, data: boolean | undefined)=>{ + if (err == null || err.code == 0) { + resolve(data as boolean); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + abilityManager.nativeIsEmbeddedOpenAllowed(context, appId, asyncCall); + }); }); -} + } + + export function on(type: 'abilityForegroundState', observer: AbilityForegroundStateObserver): void { + abilityManager.nativeOn('abilityForegroundState', observer); + } + + export function off(type: 'abilityForegroundState', observer?: AbilityForegroundStateObserver): void { + abilityManager.nativeOff('abilityForegroundState', observer); + } + + export enum AbilityState { + INITIAL = 0, + FOCUS = 2, + FOREGROUND = 9, + BACKGROUND = 10, + FOREGROUNDING = 11, + BACKGROUNDING = 12 + } + + export enum UserStatus { + ASSERT_TERMINATE = 0, + ASSERT_CONTINUE = 1, + ASSERT_RETRY = 2 + } + + export type AbilityRunningInfo = _AbilityRunningInfo; + + export type AbilityStateData = _AbilityStateData; + + export type AbilityForegroundStateObserver = _AbilityForegroundStateObserver; } \ 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 index a465ce4d46f..836870f7f0f 100644 --- a/frameworks/ets/ets/@ohos.app.ability.appManager.ets +++ b/frameworks/ets/ets/@ohos.app.ability.appManager.ets @@ -14,17 +14,29 @@ */ import { ProcessInformation as _ProcessInformation } from 'application.ProcessInformation'; import { RunningMultiAppInfo as _RunningMultiAppInfo } from 'application.RunningMultiAppInfo'; +import _AbilityStateData from 'application.AbilityStateData'; import _AppStateData from 'application.AppStateData'; -import hilog from '@ohos.hilog'; import { BusinessError, AsyncCallback } from '@ohos.base'; +import _ProcessData from 'application.ProcessData'; +import _ApplicationStateObserver from 'application.ApplicationStateObserver'; import AsyncCallbackWrapper from './utils/AbilityUtils'; +import bundleManager from '@ohos.bundle.bundleManager'; +import _AppForegroundStateObserver from 'application.AppForegroundStateObserver'; +import { AbilityFirstFrameStateObserver as _AbilityFirstFrameStateObserver } from 'application.AbilityFirstFrameStateObserver'; +import { AbilityFirstFrameStateData as _AbilityFirstFrameStateData } from 'application.AbilityFirstFrameStateData'; export default namespace appManager { loadLibrary("app_manager_ani.z") export type ProcessInformation = _ProcessInformation; +export type AbilityStateData = _AbilityStateData; export type AppStateData = _AppStateData; export type RunningMultiAppInfo = _RunningMultiAppInfo; +export type ProcessData = _ProcessData; +export type ApplicationStateObserver = _ApplicationStateObserver; +export type AppForegroundStateObserver = _AppForegroundStateObserver; +export type AbilityFirstFrameStateObserver = _AbilityFirstFrameStateObserver; +export type AbilityFirstFrameStateData = _AbilityFirstFrameStateData; export enum PreloadMode { PRESS_DOWN @@ -46,9 +58,32 @@ export enum ProcessState { 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{ +export enum KeepAliveAppType { + ALL = 0, + THIRD_PARTY = 1, + SYSTEM = 2 +} + +export enum KeepAliveSetter { + SYSTEM = 0, + USER = 1 +} + +export interface KeepAliveBundleInfo { + bundleName: string; + type: KeepAliveAppType; + setter: KeepAliveSetter; +} + +export class KeepAliveBundleInfoInner implements KeepAliveBundleInfo { + bundleName: string = ''; + type: KeepAliveAppType = KeepAliveAppType.ALL; + setter: KeepAliveSetter = KeepAliveSetter.SYSTEM; +} + +export native function nativePreloadApplication(callback: AsyncCallbackWrapper, bundleName: string, userId: int, + mode: PreloadMode, appIndex?: int): void; +export function preloadApplication(bundleName: string, userId: int, mode: PreloadMode, appIndex?: int): 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) { @@ -154,15 +189,15 @@ export function getRunningProcessInfoByBundleName(bundleName: string): Promise>):void; -export function getRunningProcessInfoByBundleName(bundleName: string, userId: number, callback: AsyncCallback>): void { + userId: int, callback:AsyncCallbackWrapper>):void; +export function getRunningProcessInfoByBundleName(bundleName: string, userId: int, callback: AsyncCallback>): void { let myCall = new AsyncCallbackWrapper>(callback); taskpool.execute((): void => { appManager.nativeGetRunningProcessInfoByBundleNameAndUserId(bundleName, userId, myCall); }); } -export function getRunningProcessInfoByBundleName(bundleName: string, userId: number): Promise> { +export function getRunningProcessInfoByBundleName(bundleName: string, userId: int): 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) { @@ -177,4 +212,363 @@ export function getRunningProcessInfoByBundleName(bundleName: string, userId: nu }); return p; } + +export native function nativeOn(type: string, observer: ApplicationStateObserver, bundleNameList?: Array) : int; +export native function nativeOn(type: string, observer: ApplicationStateObserver) : int; + +export function on(type: 'applicationState', observer: ApplicationStateObserver): int { + return appManager.nativeOn('applicationState', observer); +} + +export function on(type: 'applicationState', observer: ApplicationStateObserver, bundleNameList: Array): int { + return appManager.nativeOn('applicationState', observer, bundleNameList); +} + +export native function nativeOff(type:string, observerId: int, callback: AsyncCallbackWrapper) : void; +export function off(type: 'applicationState', observerId: int, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + appManager.nativeOff(type, observerId, myCall); + }); +} + +export function off(type: 'applicationState', observerId: int): 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.nativeOff(type, observerId, myCall); + }); + }); + return p; +} + +export native function nativeGetAppMemorySize(callback: AsyncCallbackWrapper) : void; +export function getAppMemorySize(callback: AsyncCallback): void +{ + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + appManager.nativeGetAppMemorySize(myCall); + }); +} +export function getAppMemorySize(): Promise { + let p = new Promise((resolve:(data:int)=>void, reject:(err: BusinessError | null)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: int | undefined)=>{ + if (err == null || err.code == 0) { + resolve(data as int); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeGetAppMemorySize(myCall); + }); + }); + return p; +} + +export native function nativeIsRamConstrainedDevice(callback: AsyncCallbackWrapper) : void; +export function isRamConstrainedDevice(callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + appManager.nativeIsRamConstrainedDevice(myCall); + }); +} +export function isRamConstrainedDevice(): Promise { + let p = new Promise((resolve:(data:boolean)=>void, reject:(err: BusinessError | null)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: boolean | undefined)=>{ + if (err == null || err.code == 0) { + resolve(data as boolean); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeIsRamConstrainedDevice(myCall); + }); + }); + return p; +} + +export native function nativeIsRunningInStabilityTest(callback: AsyncCallbackWrapper) : void; +export function isRunningInStabilityTest(callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + appManager.nativeIsRunningInStabilityTest(myCall); + }); +} +export function isRunningInStabilityTest(): Promise { + let p = new Promise((resolve:(data:boolean)=>void, reject:(err: BusinessError | null)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: boolean | undefined)=>{ + if (err == null || err.code == 0) { + resolve(data as boolean); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeIsRunningInStabilityTest(myCall); + }); + }); + return p; +} + +export native function nativeKillProcessesByBundleNameSync(bundleName: string, callback: AsyncCallbackWrapper) : void; +export native function nativeKillProcessesByBundleName(callback: AsyncCallbackWrapper, bundleName: string, clearPageStack: boolean, appIndex?: int) : void; +export function killProcessesByBundleName(bundleName: string, callback: AsyncCallback) : void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + appManager.nativeKillProcessesByBundleNameSync(bundleName, myCall); + }); +} +export function killProcessesByBundleName(bundleName: string): 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.nativeKillProcessesByBundleNameSync(bundleName, myCall); + }); + }); + return p; +} +export function killProcessesByBundleName(bundleName: string, clearPageStack: boolean, appIndex?: int): 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.nativeKillProcessesByBundleName(myCall, bundleName, clearPageStack, appIndex); + }); + }); + return p; +} + +export native function nativeOnAbilityFirstFrameState(type: string, observer: AbilityFirstFrameStateObserver, bundleName?: string) : void; +export function on(type: 'abilityFirstFrameState', observer: AbilityFirstFrameStateObserver, bundleName?: string) : void { + appManager.nativeOnAbilityFirstFrameState('abilityFirstFrameState', observer, bundleName); +} + +export native function nativeOffAbilityFirstFrameState(type: string, observer?: AbilityFirstFrameStateObserver) : void; +export function off(type: 'abilityFirstFrameState', observer?: AbilityFirstFrameStateObserver) : void { + appManager.nativeOffAbilityFirstFrameState('abilityFirstFrameState', observer); +} + +export native function nativeOnAppForeGroundState(type: string, observer: AppForegroundStateObserver) : void; +export function on(type: 'appForegroundState', observer: AppForegroundStateObserver) : void { + appManager.nativeOnAppForeGroundState('appForegroundState', observer); +} + +export native function nativeOffAppForeGroundState(type: string, observer?: AppForegroundStateObserver) : void; +export function off(type: 'appForegroundState', observer?: AppForegroundStateObserver) : void { + appManager.nativeOffAppForeGroundState('appForegroundState', observer); +} + +export native function nativeKillProcessWithAccountSync(bundleName: string, accountId: int, callback: AsyncCallbackWrapper) : void; +export function killProcessWithAccount(bundleName: string, accountId: int, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + appManager.nativeKillProcessWithAccountSync(bundleName, accountId, myCall); + }); +} +export function killProcessWithAccount(bundleName: string, accountId: int): 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 => { + appManager.nativeKillProcessWithAccountSync(bundleName, accountId, myCall); + }); + }); + return p; +} +export native function nativeKillProcessWithAccount(callback: AsyncCallbackWrapper, + bundleName: string, accountId: int, clearPageStack: boolean, appIndex?: int) : void; +export function killProcessWithAccount(bundleName: string, accountId: int, + clearPageStack: boolean, appIndex?: int): 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 => { + appManager.nativeKillProcessWithAccount(myCall, bundleName, accountId, clearPageStack, appIndex); + }); + }); + return p; +} + +export native function nativeGetProcessMemoryByPid(pid: int, callback: AsyncCallbackWrapper) : void; +export function getProcessMemoryByPid(pid: int, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + appManager.nativeGetProcessMemoryByPid(pid, myCall); + }); +} +export function getProcessMemoryByPid(pid: int): Promise { + let p = new Promise((resolve:(data:int)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: int | undefined)=>{ + if (err == null || err.code == 0) { + resolve(data as int); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeGetProcessMemoryByPid(pid, myCall); + }); + }); + return p; +} + +export native function nativeGetRunningProcessInformationByBundleType(bundleType: bundleManager.BundleType, + callback: AsyncCallbackWrapper>) : void; +export function getRunningProcessInformationByBundleType(bundleType: bundleManager.BundleType): 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.nativeGetRunningProcessInformationByBundleType(bundleType, myCall); + }); + }); + return p; +} + +export native function nativeIsSharedBundleRunning(bundleName: string, versionCode: long, callback: AsyncCallbackWrapper) : void; +export function isSharedBundleRunning(bundleName: string, versionCode: long, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + appManager.nativeIsSharedBundleRunning(bundleName, versionCode, myCall); + }); +} +export function isSharedBundleRunning(bundleName: string, versionCode: long): Promise { + let p = new Promise((resolve:(data:boolean)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: boolean | undefined)=>{ + if (err == null || err.code == 0) { + resolve(data as boolean); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeIsSharedBundleRunning(bundleName, versionCode, myCall); + }); + }); + return p; +} + +export native function nativeGetSupportedProcessCachePids(bundleName: string, callback: AsyncCallbackWrapper>) : void; +export function getSupportedProcessCachePids(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.nativeGetSupportedProcessCachePids(bundleName, myCall); + }); + }); + return p; +} + +export native function nativeKillProcessesInBatch(pids: Array, callback: AsyncCallbackWrapper) : void; +export function killProcessesInBatch(pids: Array) : 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 => { + appManager.nativeKillProcessesInBatch(pids, myCall); + }); + }); + return p; +} + +export native function nativeIsAppRunning(callback: AsyncCallbackWrapper, bundleName: string, appCloneIndex?: int) : void; +export function isAppRunning(bundleName: string, appCloneIndex?: int): Promise { + let p = new Promise((resolve:(data:boolean)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: boolean | undefined)=>{ + if (err == null || err.code == 0) { + resolve(data as boolean); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeIsAppRunning(myCall, bundleName, appCloneIndex); + }); + }); + return p; +} + +export native function nativeSetKeepAliveForBundle(bundleName: string, + userId: int, enable: boolean, callback: AsyncCallbackWrapper) : void; +export function setKeepAliveForBundle(bundleName: string, userId: int, enable: boolean): 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 => { + appManager.nativeSetKeepAliveForBundle(bundleName, userId, enable, myCall); + }); + }); + return p; +} + +export native function nativeGetKeepAliveBundles(callback: AsyncCallbackWrapper>, + type: KeepAliveAppType, userId?: int) : void; +export function getKeepAliveBundles(type: KeepAliveAppType, userId?: int): 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.nativeGetKeepAliveBundles(myCall, type, userId); + }); + }); + return p; +} + } // namespace appManager diff --git a/frameworks/ets/ets/@ohos.app.ability.application.ets b/frameworks/ets/ets/@ohos.app.ability.application.ets index f5654b6c45f..55c85944d62 100644 --- a/frameworks/ets/ets/@ohos.app.ability.application.ets +++ b/frameworks/ets/ets/@ohos.app.ability.application.ets @@ -16,6 +16,7 @@ import Context from 'application.Context'; import { BusinessError, AsyncCallback } from '@ohos.base'; import AsyncCallbackWrapper from './utils/AbilityUtils'; +import ApplicationContext from 'application.ApplicationContext'; export default namespace application { loadLibrary("application_ani.z") @@ -25,6 +26,8 @@ export default namespace application { export native function nativeCreateBundleContext(context: Context, bundleName: string, callback: AsyncCallbackWrapper): void; + export native function nativeGetApplicationContext(): ApplicationContext; + export function createModuleContext(context: Context, moduleName: string): Promise { let p = new Promise((resolve: (data: Context) => void, reject: (err: BusinessError) => void): void => { @@ -75,4 +78,8 @@ export default namespace application { }); return p; } + + export function getApplicationContext(): ApplicationContext { + return nativeGetApplicationContext(); + } } \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.dataUriUtils.ets b/frameworks/ets/ets/@ohos.app.ability.dataUriUtils.ets new file mode 100644 index 00000000000..5dfe03105d2 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.dataUriUtils.ets @@ -0,0 +1,94 @@ +/* + * 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 hilog from '@ohos.hilog'; + +let domainID = 0xD001320; +let TAG = 'ETSENV'; + +const URI_SPLIT = '/'; + +const ERROR_CODE_INVALID_PARAM = 401; +const ERROR_CODE_INNER_ERROR = 16000050; + +const ERROR_MSG_INVALID_PARAM = 'Invalid input parameter.'; +const ERROR_MSG_INNER_ERROR = 'Internal error.'; + +let errMap = new Map(); +errMap.set(ERROR_CODE_INVALID_PARAM, ERROR_MSG_INVALID_PARAM); +errMap.set(ERROR_CODE_INNER_ERROR, ERROR_MSG_INNER_ERROR); + +class DataUriError extends Error { + constructor(code: number) { + super(errMap.has(code) ? errMap.get(code) : ERROR_MSG_INNER_ERROR); + this.code = code; + } +} + +namespace dataUriUtils { + export function getId(uri: string): number { + hilog.debug(domainID, TAG, 'DataUriUtils getId called.'); + if (typeof uri !== 'string') { + throw new DataUriError(ERROR_CODE_INVALID_PARAM); + } + let index = uri.lastIndexOf(URI_SPLIT); + if (index === -1) { + throw new DataUriError(ERROR_CODE_INVALID_PARAM); + } + let ret = uri.substring(index + 1); + if (ret === '' || isNaN(Number(ret))) { + throw new DataUriError(ERROR_CODE_INVALID_PARAM); + } + return Number(ret); + } + + export function attachId(uri: string, id: number): string { + hilog.debug(domainID, TAG, 'DataUriUtils attachId called.'); + if (typeof uri !== 'string' || typeof id !== 'number') { + throw new DataUriError(ERROR_CODE_INVALID_PARAM); + } + return uri + URI_SPLIT + id; + } + + export function deleteId(uri: string): string { + hilog.debug(domainID, TAG, 'DataUriUtils deleteId called.'); + if (typeof uri !== 'string') { + throw new DataUriError(ERROR_CODE_INVALID_PARAM); + } + let index = uri.lastIndexOf(URI_SPLIT); + if (index === -1) { + throw new DataUriError(ERROR_CODE_INVALID_PARAM); + } + let id = uri.substring(index + 1); + if (id === '' || isNaN(Number(id))) { + throw new DataUriError(ERROR_CODE_INVALID_PARAM); + } + return uri.substring(0, index); + } + + export function updateId(uri: string, id: number): string { + hilog.debug(domainID, TAG, 'DataUriUtils updateId called.'); + if (typeof uri !== 'string' || typeof id !== 'number') { + throw new DataUriError(ERROR_CODE_INVALID_PARAM); + } + let ret = dataUriUtils.deleteId(uri); + if (ret === uri) { + throw new DataUriError(ERROR_CODE_INVALID_PARAM); + } + return ret + URI_SPLIT + id; + } +} + +export default dataUriUtils; \ 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 index cf3b65fefb5..0fcc3f864b6 100644 --- a/frameworks/ets/ets/@ohos.app.ability.insightIntent.ets +++ b/frameworks/ets/ets/@ohos.app.ability.insightIntent.ets @@ -26,17 +26,17 @@ namespace insightIntent { } export interface ExecuteResult { - code: number; + code: int; result?: Record; uris?: Array; - flags?: number; + flags?: int; } export class ExecuteResultInner implements ExecuteResult{ - code: number; + code: int; result?: Record; uris?: Array; - flags?: number; + flags?: int; } } diff --git a/frameworks/ets/ets/@ohos.app.ability.insightIntentDriver.ets b/frameworks/ets/ets/@ohos.app.ability.insightIntentDriver.ets index 0f9362e7e4a..20c9bcfe130 100644 --- a/frameworks/ets/ets/@ohos.app.ability.insightIntentDriver.ets +++ b/frameworks/ets/ets/@ohos.app.ability.insightIntentDriver.ets @@ -30,9 +30,9 @@ export default namespace insightIntentDriver { insightIntentName: string; insightIntentParam: Record; executeMode: insightIntent.ExecuteMode; - displayId?: number; + displayId?: long; uris?: Array; - flags?: number; + flags?: int; } export native function nativeExecuteSync(param: ExecuteParam, diff --git a/frameworks/ets/ets/@ohos.app.ability.missionManager.ets b/frameworks/ets/ets/@ohos.app.ability.missionManager.ets new file mode 100644 index 00000000000..ad2ec9c8f72 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.missionManager.ets @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { BusinessError, AsyncCallback } from '@ohos.base'; +import { MissionInfo as _MissionInfo } from 'application.MissionInfo'; +import AsyncCallbackWrapper from './utils/AbilityUtils'; + +export default namespace missionManager { + loadLibrary("missionmanager_ani.z") + export native function nativeClearAllMissions(callback: AsyncCallbackWrapper): void; + export native function nativeGetMissionInfo(deviceId: string, missionId: int, + callback: AsyncCallbackWrapper): void; + + export function clearAllMissions(callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + missionManager.nativeClearAllMissions(myCall); + }); + } + + export function clearAllMissions(): 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 => { + missionManager.nativeClearAllMissions(myCall); + }); + }); + return p; + } + + export function getMissionInfo(deviceId: string, missionId: int, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + missionManager.nativeGetMissionInfo(deviceId, missionId, myCall); + }); + } + + export function getMissionInfo(deviceId: string, missionId: int): Promise { + let p = + new Promise((resolve: (data: MissionInfo) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: MissionInfo | undefined) => { + if (err == null || err.code == 0) { + resolve(data as MissionInfo); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + missionManager.nativeGetMissionInfo(deviceId, missionId, myCall); + }); + }); + return p; + } + + export type MissionInfo = _MissionInfo; +} \ 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 index 0dd412c9a76..b0ba39051db 100644 --- a/frameworks/ets/ets/@ohos.app.ability.wantAgent.ets +++ b/frameworks/ets/ets/@ohos.app.ability.wantAgent.ets @@ -61,8 +61,8 @@ namespace wantAgent { } 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 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; @@ -99,8 +99,8 @@ namespace wantAgent { }); } - export function getUid(agent: WantAgent, callback: AsyncCallback): void { - let call = new AsyncCallbackWrapper(callback); + export function getUid(agent: WantAgent, callback: AsyncCallback): void { + let call = new AsyncCallbackWrapper(callback); taskpool.execute((): void => { try { nativeGetUid(agent, call); @@ -110,11 +110,11 @@ namespace wantAgent { }); } - 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) => { + export function getUid(agent: WantAgent): Promise { + return new Promise((resolve: (data: int) => void, reject: (err: BusinessError) => void): void => { + let call = new AsyncCallbackWrapper((err: BusinessError | null, data: int | undefined) => { if (err == null || err.code == 0) { - resolve(data as number); + resolve(data as int); } else { reject(err); } @@ -266,8 +266,8 @@ namespace wantAgent { }); } - export function getOperationType(agent: WantAgent, callback: AsyncCallback): void { - let call = new AsyncCallbackWrapper(callback); + export function getOperationType(agent: WantAgent, callback: AsyncCallback): void { + let call = new AsyncCallbackWrapper(callback); taskpool.execute((): void => { try { nativeGetOperationType(agent, call); @@ -277,11 +277,11 @@ namespace wantAgent { }); } - 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) => { + export function getOperationType(agent: WantAgent): Promise { + return new Promise((resolve: (data: int) => void, reject: (err: BusinessError) => void): void => { + let call = new AsyncCallbackWrapper((err: BusinessError | null, data: int | undefined) => { if (err == null || err.code == 0) { - resolve(data as number); + resolve(data as int); } else { reject(err); } @@ -321,7 +321,7 @@ namespace wantAgent { export interface CompleteData { info: WantAgent; want: Want; - finalCode: number; + finalCode: int; finalData: string; extraInfo?: Record; } @@ -329,7 +329,7 @@ namespace wantAgent { class CompleteDataImpl implements CompleteData { public info: WantAgent; public want: Want; - public finalCode: number; + public finalCode: int; public finalData: string; public extraInfo?: Record; } diff --git a/frameworks/ets/ets/@ohos.application.uriPermissionManager.ets b/frameworks/ets/ets/@ohos.application.uriPermissionManager.ets index 403a0c969ef..93bdc519cb1 100644 --- a/frameworks/ets/ets/@ohos.application.uriPermissionManager.ets +++ b/frameworks/ets/ets/@ohos.application.uriPermissionManager.ets @@ -21,8 +21,8 @@ export default namespace uriPermissionManager { loadLibrary("uri_permission_manager_ani_kit.z"); export native function grantUriPermissionCallbackSync(uri: string, flag: wantConstant.Flags, targetBundleName: string, - appCloneIndex: number, callback: AsyncCallbackWrapper): void; - export native function revokeUriPermissionCallbackSync(uri: string, targetBundleName: string, appCloneIndex: number, + appCloneIndex: int, callback: AsyncCallbackWrapper): void; + export native function revokeUriPermissionCallbackSync(uri: string, targetBundleName: string, appCloneIndex: int, callback: AsyncCallbackWrapper): void; export function grantUriPermission(uri: string, flag: wantConstant.Flags, targetBundleName: string): Promise { @@ -46,7 +46,7 @@ export default namespace uriPermissionManager { } export function grantUriPermission(uri: string, flag: wantConstant.Flags, targetBundleName: string, - appCloneIndex: number): Promise { + appCloneIndex: int): Promise { let p:Promise = new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: number | undefined)=>{ if (err === null || err.code === 0) { @@ -91,7 +91,7 @@ export default namespace uriPermissionManager { return p; } - export function revokeUriPermission(uri: string, targetBundleName: string, appCloneIndex: number): Promise { + export function revokeUriPermission(uri: string, targetBundleName: string, appCloneIndex: int): Promise { let p:Promise = new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: number | undefined)=>{ if (err === null || err.code === 0) { diff --git a/frameworks/ets/ets/BUILD.gn b/frameworks/ets/ets/BUILD.gn index 95c9e277e45..f8241e82adf 100644 --- a/frameworks/ets/ets/BUILD.gn +++ b/frameworks/ets/ets/BUILD.gn @@ -230,6 +230,22 @@ ohos_prebuilt_etc("ability_runtime_configuration_constant_abc_etc") { deps = [ ":ability_runtime_configuration_constant_abc" ] } +generate_static_abc("ability_runtime_data_uri_utils_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.dataUriUtils.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_data_uri_utils_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_data_uri_utils_abc_etc") { + source = "$target_out_dir/ability_runtime_data_uri_utils_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_data_uri_utils_abc" ] +} + generate_static_abc("ability_runtime_ability_result_abc") { base_url = "./" files = [ "./ability/abilityResult.ets" ] @@ -807,6 +823,345 @@ ohos_prebuilt_etc("ability_runtime_vertical_panel_manager_abc_etc") { deps = [ ":ability_runtime_vertical_panel_manager_abc" ] } +generate_static_abc("ability_runtime_environment_callback_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.EnvironmentCallback.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_environment_callback_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_environment_callback_abc_etc") { + source = "$target_out_dir/ability_runtime_environment_callback_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_environment_callback_abc" ] +} + +generate_static_abc("ability_runtime_application_state_change_callback_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.ApplicationStateChangeCallback.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_application_state_change_callback_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_application_state_change_callback_abc_etc") { + source = "$target_out_dir/ability_runtime_application_state_change_callback_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_application_state_change_callback_abc" ] +} + +generate_static_abc("ability_runtime_AbilityRunningInfo_abc") { + base_url = "./" + files = [ "./application/AbilityRunningInfo.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_AbilityRunningInfo_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_AbilityRunningInfo_abc_etc") { + source = "$target_out_dir/ability_runtime_AbilityRunningInfo_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_AbilityRunningInfo_abc" ] +} + +generate_static_abc("ability_runtime_connect_options_abc") { + base_url = "./" + files = [ "./ability/connectOptions.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_connect_options_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_connect_options_abc_etc") { + source = "$target_out_dir/ability_runtime_connect_options_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_connect_options_abc" ] +} + +generate_static_abc("ability_runtime_error_code_abc") { + base_url = "./" + files = [ "./@ohos.ability.errorCode.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_error_code_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_error_code_abc_etc") { + source = "$target_out_dir/ability_runtime_error_code_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_error_code_abc" ] +} + +generate_static_abc("ability_runtime_custom_data_abc") { + base_url = "./" + files = [ "./application/CustomData.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_custom_data_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_custom_data_abc_etc") { + source = "$target_out_dir/ability_runtime_custom_data_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_custom_data_abc" ] +} + +generate_static_abc("ability_runtime_extension_ability_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.ExtensionAbility.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_extension_ability_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_extension_ability_abc_etc") { + source = "$target_out_dir/ability_runtime_extension_ability_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_extension_ability_abc" ] +} + +generate_static_abc("ability_runtime_ability_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.Ability.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_ability_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_abc" ] +} + +generate_static_abc("ability_runtime_extension_running_info_abc") { + base_url = "./" + files = [ "./application/ExtensionRunningInfo.ets" ] + + is_boot_abc = "True" + device_dst_file ="/system/framework/ability_runtime_extension_running_info_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_extension_running_info_abc_etc") { + source = "$target_out_dir/ability_runtime_extension_running_info_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_extension_running_info_abc" ] +} + +generate_static_abc("ability_runtime_ability_start_callback_abc") { + base_url = "./" + files = [ "./application/AbilityStartCallback.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_ability_start_callback_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_start_callback_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_start_callback_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_start_callback_abc" ] +} + +generate_static_abc("ability_runtime_data_ability_helper_abc") { + base_url = "./" + files = [ "./ability/dataAbilityHelper.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_data_ability_helper_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_data_ability_helper_abc_etc") { + source = "$target_out_dir/ability_runtime_data_ability_helper_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_data_ability_helper_abc" ] +} + +generate_static_abc("ability_runtime_mission_info_abc") { + base_url = "./" + files = [ "./application/MissionInfo.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_mission_info_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_mission_info_abc_etc") { + source = "$target_out_dir/ability_runtime_mission_info_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_mission_info_abc" ] +} + +generate_static_abc("ability_runtime_ability_mission_manager_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.missionManager.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_ability_mission_manager_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_mission_manager_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_mission_manager_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_mission_manager_abc" ] +} + +generate_static_abc("atomic_service_options_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.AtomicServiceOptions.ets" ] + + is_boot_abc = "True" + device_dst_file ="/system/framework/atomic_service_options_abc.abc" +} + +ohos_prebuilt_etc("atomic_service_options_abc_etc") { + source = "$target_out_dir/atomic_service_options_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":atomic_service_options_abc" ] +} +generate_static_abc("ability_first_frame_state_data_abc") { + base_url = "./" + files = [ "./application/AbilityFirstFrameStateData.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_first_frame_state_data_abc.abc" +} + +ohos_prebuilt_etc("ability_first_frame_state_data_abc_etc") { + source = "$target_out_dir/ability_first_frame_state_data_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_first_frame_state_data_abc" ] +} + +generate_static_abc("ability_first_frame_state_observer_abc") { + base_url = "./" + files = [ "./application/AbilityFirstFrameStateObserver.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_first_frame_state_observer_abc.abc" +} + +ohos_prebuilt_etc("ability_first_frame_state_observer_abc_etc") { + source = "$target_out_dir/ability_first_frame_state_observer_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_first_frame_state_observer_abc" ] +} + +generate_static_abc("app_foreground_state_observer_abc") { + base_url = "./" + files = [ "./application/AppForegroundStateObserver.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/app_foreground_state_observer_abc.abc" +} + +ohos_prebuilt_etc("app_foreground_state_observer_abc_etc") { + source = "$target_out_dir/app_foreground_state_observer_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":app_foreground_state_observer_abc" ] +} + +generate_static_abc("ability_foreground_state_observer_abc") { + base_url = "." + files = [ "./application/AbilityForegroundStateObserver.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_foreground_state_observer_abc.abc" +} + +ohos_prebuilt_etc("ability_foreground_state_observer_abc_etc") { + source = "$target_out_dir/ability_foreground_state_observer_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_foreground_state_observer_abc" ] +} + +generate_static_abc("application_state_observer_abc") { + base_url = "./" + files = [ "./application/ApplicationStateObserver.ets" ] + + is_boot_abc = "True" + device_dst_file ="/system/framework/application_state_observer_abc.abc" +} + +ohos_prebuilt_etc("application_state_observer_abc_etc") { + source = "$target_out_dir/application_state_observer_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":application_state_observer_abc" ] +} + +generate_static_abc("ability_runtime_share_extension_ability_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.ShareExtensionAbility.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_share_extension_ability_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_share_extension_ability_abc_etc") { + source = "$target_out_dir/ability_runtime_share_extension_ability_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_share_extension_ability_abc" ] +} + +generate_static_abc("ability_runtime_running_multi_instance_info_abc") { + base_url = "./" + files = [ "./application/RunningMultiInstanceInfo.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_running_multi_instance_info_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_running_multi_instance_info_abc_etc") { + source = "$target_out_dir/ability_runtime_running_multi_instance_info_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_running_multi_instance_info_abc" ] +} + group("ets_packages") { deps = [ ":ability_application_abc_etc", @@ -815,33 +1170,52 @@ group("ets_packages") { ":ability_delegator_application_testRunner_abc_etc", ":ability_delegator_args_abc_etc", ":ability_delegator_registry_abc_etc", + ":ability_foreground_state_observer_abc_etc", + ":ability_first_frame_state_data_abc_etc", + ":ability_first_frame_state_observer_abc_etc", + ":ability_runtime_AbilityRunningInfo_abc_etc", + ":ability_runtime_ability_abc_etc", ":ability_runtime_ability_constant_abc_etc", ":ability_runtime_ability_context_constant_abc_etc", ":ability_runtime_ability_manager_abc_etc", + ":ability_runtime_ability_mission_manager_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_start_callback_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_application_state_change_callback_abc_etc", ":ability_runtime_base_context_abc_etc", ":ability_runtime_configuration_abc_etc", ":ability_runtime_configuration_constant_abc_etc", + ":ability_runtime_connect_options_abc_etc", ":ability_runtime_context_abc_etc", + ":ability_runtime_custom_data_abc_etc", + ":ability_runtime_data_ability_helper_abc_etc", + ":ability_runtime_data_uri_utils_abc_etc", + ":ability_runtime_environment_callback_abc_etc", + ":ability_runtime_error_code_abc_etc", + ":ability_runtime_extension_ability_abc_etc", ":ability_runtime_extension_context_abc_etc", + ":ability_runtime_extension_running_info_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_multi_app_mode_abc_etc", + ":ability_runtime_mission_info_abc_etc", ":ability_runtime_openLink_options_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_running_multi_instance_info_abc_etc", + ":ability_runtime_share_extension_ability_abc_etc", ":ability_runtime_shell_cmd_result_abc_etc", ":ability_runtime_start_options_abc_etc", ":ability_runtime_trigger_info_abc_etc", @@ -852,6 +1226,9 @@ group("ets_packages") { ":ability_runtime_want_agent_abc_etc", ":ability_runtime_want_agent_info_abc_etc", ":ability_runtime_want_constant_abc_etc", + ":atomic_service_options_abc_etc", + ":application_state_observer_abc_etc", + ":app_foreground_state_observer_abc_etc", ":form_extension_ability_etc", ":service_extension_ability_abc_etc", ":ui_extension_ability_ani_etc", diff --git a/frameworks/ets/ets/ability/abilityResult.ets b/frameworks/ets/ets/ability/abilityResult.ets index 012a9d9cc6b..ee4b6a5ba84 100644 --- a/frameworks/ets/ets/ability/abilityResult.ets +++ b/frameworks/ets/ets/ability/abilityResult.ets @@ -16,11 +16,11 @@ import Want from '@ohos.app.ability.Want'; export interface AbilityResult { - resultCode: number; + resultCode: int; want?: Want; } class AbilityResultInner implements AbilityResult { - resultCode: number; + resultCode: int; want?: Want | undefined = {}; } diff --git a/frameworks/ets/ets/ability/connectOptions.ets b/frameworks/ets/ets/ability/connectOptions.ets new file mode 100644 index 00000000000..f19b251c967 --- /dev/null +++ b/frameworks/ets/ets/ability/connectOptions.ets @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ElementName } from 'bundleManager.ElementName' +import rpc from '@ohos.rpc'; + +export interface ConnectOptions { + onConnect(elementName: ElementName, remote: rpc.IRemoteObject): void; + onDisconnect(elementName: ElementName): void; + onFailed(code: int): void; +} + +class ConnectOptionsInner implements ConnectOptions { + onConnect(elementName: ElementName, remote: rpc.IRemoteObject): void { + console.log('onConnect'); + } + onDisconnect(elementName: ElementName): void { + console.log('onDisconnect'); + } + onFailed(code: int): void { + console.log('onFailed'); + } +} diff --git a/frameworks/ets/ets/ability/dataAbilityHelper.ets b/frameworks/ets/ets/ability/dataAbilityHelper.ets new file mode 100644 index 00000000000..7eabf2a7eb0 --- /dev/null +++ b/frameworks/ets/ets/ability/dataAbilityHelper.ets @@ -0,0 +1,16 @@ +/* + * 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. +*/ + +type PacMap = Record | null>; \ No newline at end of file diff --git a/frameworks/ets/ets/application/AbilityDelegator.ets b/frameworks/ets/ets/application/AbilityDelegator.ets index cdc88980dca..0632a37e2c8 100644 --- a/frameworks/ets/ets/application/AbilityDelegator.ets +++ b/frameworks/ets/ets/application/AbilityDelegator.ets @@ -28,9 +28,9 @@ export interface AbilityDelegator { getAppContext(): Context; - finishTest(msg: string, code: number, callback: AsyncCallback): void; + finishTest(msg: string, code: long, callback: AsyncCallback): void; - finishTest(msg: string, code: number): Promise; + finishTest(msg: string, code: long): Promise; executeShellCommand(cmd: String, callback: AsyncCallback): void; @@ -52,9 +52,9 @@ export interface AbilityDelegator { waitAbilityMonitor(monitor: AbilityMonitor, callback: AsyncCallback): void; - waitAbilityMonitor(monitor: AbilityMonitor, timeout: number, callback: AsyncCallback): void; + waitAbilityMonitor(monitor: AbilityMonitor, timeout: long, callback: AsyncCallback): void; - waitAbilityMonitor(monitor: AbilityMonitor, timeout?: number): Promise; + waitAbilityMonitor(monitor: AbilityMonitor, timeout?: long): Promise; addAbilityStageMonitor(monitor: AbilityStageMonitor, callback: AsyncCallback): void; @@ -70,9 +70,9 @@ export interface AbilityDelegator { waitAbilityStageMonitor(monitor: AbilityStageMonitor, callback: AsyncCallback): void; - waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout: number, callback: AsyncCallback): void; + waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout: long, callback: AsyncCallback): void; - waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout?: number): Promise; + waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout?: long): Promise; doAbilityForeground(ability: UIAbility, callback: AsyncCallback): void; @@ -86,7 +86,7 @@ export interface AbilityDelegator { print(msg: string): Promise; - getAbilityState(ability: UIAbility): number; + getAbilityState(ability: UIAbility): int; setMockList(mockList: Record): void; @@ -106,7 +106,7 @@ class AbilityDelegatorInner implements AbilityDelegator { public native getAppContext(): Context; - public native nativeFinishTest(msg: String, code: number, callback: AsyncCallbackWrapper): void; + public native nativeFinishTest(msg: String, code: long, callback: AsyncCallbackWrapper): void; public native nativeExecuteShellCommand(cmd: string, timeoutSecs: number, callback: AsyncCallbackWrapper): void; @@ -119,7 +119,7 @@ class AbilityDelegatorInner implements AbilityDelegator { public native removeAbilityMonitorSync(monitor: AbilityMonitor): void; - public native waitAbilityMonitorAsync(monitor: AbilityMonitor, timeout: number, + public native waitAbilityMonitorAsync(monitor: AbilityMonitor, timeout: long, callback: AsyncCallbackWrapper): void; public native addAbilityStageMonitorAsync(monitor: AbilityStageMonitor, callback: AsyncCallbackWrapper): void; @@ -131,7 +131,7 @@ class AbilityDelegatorInner implements AbilityDelegator { public native removeAbilityStageMonitorSync(monitor: AbilityStageMonitor): void; - public native waitAbilityStageMonitorAsync(monitor: AbilityStageMonitor, timeout: number, + public native waitAbilityStageMonitorAsync(monitor: AbilityStageMonitor, timeout: long, callback: AsyncCallbackWrapper): void; public native doAbilityForegroundAsync(ability: UIAbility, callback: AsyncCallbackWrapper): void; @@ -142,17 +142,17 @@ class AbilityDelegatorInner implements AbilityDelegator { public native setMockList(mockList: Record): void; - public native getAbilityState(ability: UIAbility): number; + public native getAbilityState(ability: UIAbility): int; public native nativeStartAbility(want: Want, callback: AsyncCallbackWrapper): void; - finishTest(msg: string, code: number, callback: AsyncCallback): void { + finishTest(msg: string, code: long, callback: AsyncCallback): void { let myCall = new AsyncCallbackWrapper(callback); taskpool.execute((): void => { this.nativeFinishTest(msg, code, myCall); }); } - finishTest(msg: string, code: number): Promise { + finishTest(msg: string, code: long): Promise { let p: Promise = new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { let myCall = new AsyncCallbackWrapper((err: BusinessError | null) => { @@ -257,13 +257,13 @@ class AbilityDelegatorInner implements AbilityDelegator { this.waitAbilityMonitorAsync(monitor, timeout, myCall); }); } - waitAbilityMonitor(monitor: AbilityMonitor, timeout: number, callback: AsyncCallback): void { + waitAbilityMonitor(monitor: AbilityMonitor, timeout: long, callback: AsyncCallback): void { let myCall = new AsyncCallbackWrapper(callback); taskpool.execute((): void => { this.waitAbilityMonitorAsync(monitor, timeout, myCall); }); } - waitAbilityMonitor(monitor: AbilityMonitor, timeout?: number): Promise { + waitAbilityMonitor(monitor: AbilityMonitor, timeout?: long): Promise { let p = new Promise((resolve: (data: UIAbility) => void, reject: (err: BusinessError) => void): void => { let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: UIAbility | undefined) => { @@ -277,7 +277,7 @@ class AbilityDelegatorInner implements AbilityDelegator { if (timeout == null) { this.waitAbilityMonitorAsync(monitor, -1, myCall); } else { - this.waitAbilityMonitorAsync(monitor, timeout as double, myCall); + this.waitAbilityMonitorAsync(monitor, timeout as long, myCall); } }); }); @@ -337,14 +337,14 @@ class AbilityDelegatorInner implements AbilityDelegator { this.waitAbilityStageMonitorAsync(monitor, timeout, myCall); }); } - waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout: number, + waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout: long, callback: AsyncCallback): void { let myCall = new AsyncCallbackWrapper(callback); taskpool.execute((): void => { this.waitAbilityStageMonitorAsync(monitor, timeout, myCall); }); } - waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout?: number): Promise { + waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout?: long): Promise { let p = new Promise((resolve: (data: AbilityStage) => void, reject: (err: BusinessError) => void): void => { let myCall = @@ -359,7 +359,7 @@ class AbilityDelegatorInner implements AbilityDelegator { if (timeout == null) { this.waitAbilityStageMonitorAsync(monitor, -1, myCall); } else { - this.waitAbilityStageMonitorAsync(monitor, timeout as double, myCall); + this.waitAbilityStageMonitorAsync(monitor, timeout as long, myCall); } }); }); diff --git a/frameworks/ets/ets/application/AbilityFirstFrameStateData.ets b/frameworks/ets/ets/application/AbilityFirstFrameStateData.ets new file mode 100644 index 00000000000..fdb728d0cf3 --- /dev/null +++ b/frameworks/ets/ets/application/AbilityFirstFrameStateData.ets @@ -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. + */ + +export interface AbilityFirstFrameStateData { + bundleName: string; + moduleName: string; + abilityName: string; + appIndex: int; + isColdStart: boolean; +} + +export default class AbilityFirstFrameStateDataInner implements AbilityFirstFrameStateData { + bundleName: string = ''; + moduleName: string = ''; + abilityName: string = ''; + appIndex: int; + isColdStart: boolean; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/AbilityFirstFrameStateObserver.ets b/frameworks/ets/ets/application/AbilityFirstFrameStateObserver.ets new file mode 100644 index 00000000000..9e7a836fa70 --- /dev/null +++ b/frameworks/ets/ets/application/AbilityFirstFrameStateObserver.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. + */ + +import { AbilityFirstFrameStateData } from 'application.AbilityFirstFrameStateData'; + +export interface AbilityFirstFrameStateObserver { + onAbilityFirstFrameDrawn(data: AbilityFirstFrameStateData): void; +} + +export default class AbilityFirstFrameStateObserverInner implements AbilityFirstFrameStateObserver { + onAbilityFirstFrameDrawn(data: AbilityFirstFrameStateData): void {} +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/AbilityForegroundStateObserver.ets b/frameworks/ets/ets/application/AbilityForegroundStateObserver.ets new file mode 100644 index 00000000000..bda11186d26 --- /dev/null +++ b/frameworks/ets/ets/application/AbilityForegroundStateObserver.ets @@ -0,0 +1,23 @@ +/* + * 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'; + +interface AbilityForegroundStateObserver { + onAbilityStateChanged(abilityStateData: AbilityStateData): void; +} + +export default class AbilityForegroundStateObserverInner implements AbilityForegroundStateObserver { + onAbilityStateChanged(abilityStateData: AbilityStateData): void {} +} diff --git a/frameworks/ets/ets/application/AbilityRunningInfo.ets b/frameworks/ets/ets/application/AbilityRunningInfo.ets new file mode 100644 index 00000000000..82381b06f68 --- /dev/null +++ b/frameworks/ets/ets/application/AbilityRunningInfo.ets @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ElementName } from 'bundleManager.ElementName' +import abilityManager from '@ohos.app.ability.abilityManager'; + +export interface AbilityRunningInfo { + ability: ElementName; + pid: int; + uid: int; + processName: string; + startTime: long; + abilityState: abilityManager.AbilityState; +} + +class AbilityRunningInfoImpl implements AbilityRunningInfo { + ability: ElementName = {}; + pid: int; + uid: int; + processName: string = ''; + startTime: long; + abilityState: abilityManager.AbilityState = abilityManager.AbilityState.INITIAL; +} diff --git a/frameworks/ets/ets/application/AbilityStartCallback.ets b/frameworks/ets/ets/application/AbilityStartCallback.ets new file mode 100644 index 00000000000..d5680df1519 --- /dev/null +++ b/frameworks/ets/ets/application/AbilityStartCallback.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. + */ + +import { AbilityResult } from 'ability.abilityResult'; + +type OnResultFn = (parameter: AbilityResult) => void; + +export default interface AbilityStartCallback { + onError(code: number, name: string, message: string): void; + + onResult?: OnResultFn; +} diff --git a/frameworks/ets/ets/application/AppForegroundStateObserver.ets b/frameworks/ets/ets/application/AppForegroundStateObserver.ets new file mode 100644 index 00000000000..2ffa63fe916 --- /dev/null +++ b/frameworks/ets/ets/application/AppForegroundStateObserver.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. + */ + +import AppStateData from 'application.AppStateData'; + +export interface AppForegroundStateObserver { + onAppStateChanged(appStateData: AppStateData): void; +} + +export default class AppForegroundStateObserverInner implements AppForegroundStateObserver { + onAppStateChanged(appStateData: AppStateData): void {} +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/ApplicationContext.ets b/frameworks/ets/ets/application/ApplicationContext.ets index c48da89fe52..5239b314feb 100644 --- a/frameworks/ets/ets/application/ApplicationContext.ets +++ b/frameworks/ets/ets/application/ApplicationContext.ets @@ -19,6 +19,8 @@ import AsyncCallbackWrapper from '../utils/AbilityUtils'; import Want from '@ohos.app.ability.Want'; import { ProcessInformation } from 'application.ProcessInformation'; import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant'; +import EnvironmentCallback from '@ohos.app.ability.EnvironmentCallback'; +import type ApplicationStateChangeCallback from '@ohos.app.ability.ApplicationStateChangeCallback'; class Cleaner { public ptr: long = 0; @@ -62,10 +64,17 @@ export default class ApplicationContext extends Context { 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 nativesetFontSizeScale(fontSizeScale: double): void; public native nativesetColorMode(colorMode: ConfigurationConstant.ColorMode): void; public native nativesetFont(font: string): void; public native nativerestartApp(want: Want): void; + public native nativeGetAllRunningInstanceKeys(callback: AsyncCallbackWrapper>): void; + public native nativeOnEnvironmentSync(callback: EnvironmentCallback): int; + public native nativeOffEnvironmentSync(callbackId: int, callback: AsyncCallbackWrapper): void; + public native nativeOnApplicationStateChangeSync(callback: ApplicationStateChangeCallback): void; + public native nativeOffApplicationStateChangeSync(callback?: ApplicationStateChangeCallback): void; + public native nativegetCurrentAppCloneIndex(): int; + public native nativegetCurrentInstanceKey(): string; setSupportedProcessCache(isSupported : boolean):void { this.setSupportedProcessCacheSync(isSupported); @@ -181,7 +190,7 @@ export default class ApplicationContext extends Context { this.nativesetLanguage(language); } - setFontSizeScale(fontSizeScale: number): void { + setFontSizeScale(fontSizeScale: double): void { this.nativesetFontSizeScale(fontSizeScale); } @@ -196,4 +205,70 @@ export default class ApplicationContext extends Context { restartApp(want: Want): void { this.nativerestartApp(want); } + + getAllRunningInstanceKeys(): 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.nativeGetAllRunningInstanceKeys(myCall); + }); + }); + return p; + } + + on(type: 'environment', callback: EnvironmentCallback): int { + return this.nativeOnEnvironmentSync(callback); + } + + off(type: string, callbackId: int, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + if (type == 'environment') { + this.nativeOffEnvironmentSync(callbackId, myCall); + } + }); + } + + off(type: string, callbackId: int): Promise { + let p = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null) => { + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + if (type == 'environment') { + this.nativeOffEnvironmentSync(callbackId, myCall); + } + }); + }); + return p; + } + + on(type: 'applicationStateChange', callback: ApplicationStateChangeCallback): void { + this.nativeOnApplicationStateChangeSync(callback); + } + + off(type: 'applicationStateChange', callback?: ApplicationStateChangeCallback): void { + this.nativeOffApplicationStateChangeSync(callback); + } + + getCurrentInstanceKey(): string { + return this.nativegetCurrentInstanceKey(); + } + + getCurrentAppCloneIndex(): int { + return this.nativegetCurrentAppCloneIndex(); + } } \ No newline at end of file diff --git a/frameworks/ets/ets/application/ApplicationStateObserver.ets b/frameworks/ets/ets/application/ApplicationStateObserver.ets new file mode 100644 index 00000000000..e67cae97100 --- /dev/null +++ b/frameworks/ets/ets/application/ApplicationStateObserver.ets @@ -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. + */ +import AppStateData from 'application.AppStateData'; +import AbilityStateData from 'application.AbilityStateData'; +import processData from 'application.ProcessData'; + +export interface ApplicationStateObserver { + + onForegroundApplicationChanged(appStateData: AppStateData): void; + + onAbilityStateChanged(abilityStateData: AbilityStateData): void; + + onProcessCreated(processData: ProcessData): void; + + onProcessDied(processData: ProcessData): void; + + onProcessStateChanged(processData: ProcessData): void; + + onAppStarted(appStateData: AppStateData): void; + + onAppStopped(appStateData: AppStateData): void; +} + +export default class ApplicationStateObserverImpl implements ApplicationStateObserver { + onForegroundApplicationChanged(appStateData: AppStateData): void {} + + onAbilityStateChanged(abilityStateData: AbilityStateData): void {} + + onProcessCreated(processData: ProcessData): void {} + + onProcessDied(processData: ProcessData): void {} + + onProcessStateChanged(processData: ProcessData): void {} + + onAppStarted(appStateData: AppStateData): void {} + + onAppStopped(appStateData: AppStateData): void {} +} + +export type ProcessData = processData; diff --git a/frameworks/ets/ets/application/Context.ets b/frameworks/ets/ets/application/Context.ets index 94092f175c5..077e237c974 100644 --- a/frameworks/ets/ets/application/Context.ets +++ b/frameworks/ets/ets/application/Context.ets @@ -15,6 +15,9 @@ import BaseContext from 'application.BaseContext' import ApplicationContext from 'application.ApplicationContext' +import AsyncCallbackWrapper from '../utils/AbilityUtils'; +import { AsyncCallback } from '@ohos.base'; +import { BusinessError } from '@ohos.base'; import contextConstant from '@ohos.app.ability.contextConstant' import { ApplicationInfo } from 'bundleManager.ApplicationInfo' import resmgr from '@ohos.resourceManager' @@ -43,8 +46,13 @@ export class Context extends BaseContext { preferencesDir: string = ""; databaseDir: string = ""; cacheDir: string = ""; + cloudFileDir: string = ""; + distributedFilesDir: string = ""; + bundleCodeDir: string = ""; + resourceDir: string = ""; applicationInfo: ApplicationInfo; resourceManager: resmgr.ResourceManager; + processName: string = ""; native constructor(); constructor(applicationInfo: ApplicationInfo, resourceManager: resmgr.ResourceManager) { super(); @@ -68,6 +76,10 @@ export class Context extends BaseContext { public native createModuleResourceManagerSync(bundleName: string, moduleName: string): resmgr.ResourceManager; private native switchArea(mode: contextConstant.AreaMode): void; private native getArea(): contextConstant.AreaMode; + public native nativeGetGroupDir(dataGroupID: string, callback: AsyncCallbackWrapper): void; + public native nativeCreateDisplayContext(displayId: long): Context; + public native nativeCreateAreaModeContext(areaMode: contextConstant.AreaMode): Context; + public native nativeCreateSystemHspModuleResourceManager(bundleName: string, moduleName: string): resmgr.ResourceManager; getApplicationContext(): ApplicationContext { return this.getApplicationContextSync(); @@ -84,4 +96,38 @@ export class Context extends BaseContext { get area(): contextConstant.AreaMode { return this.getArea(); } + + getGroupDir(dataGroupID: string, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeGetGroupDir(dataGroupID, myCall); + }); + } + + getGroupDir(dataGroupID: string): Promise { + return new Promise((resolve: (data: string) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: string | undefined) => { + if (err == null || err.code == 0) { + resolve(data as string); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeGetGroupDir(dataGroupID, myCall); + }); + }); + } + + createDisplayContext(displayId: long): Context { + return this.nativeCreateDisplayContext(displayId); + } + + createAreaModeContext(areaMode: contextConstant.AreaMode): Context { + return this.nativeCreateAreaModeContext(areaMode); + } + + createSystemHspModuleResourceManager(bundleName: string, moduleName: string): resmgr.ResourceManager { + return this.nativeCreateSystemHspModuleResourceManager(bundleName, moduleName); + } } diff --git a/frameworks/ets/ets/application/CustomData.ets b/frameworks/ets/ets/application/CustomData.ets new file mode 100644 index 00000000000..5e588bee98f --- /dev/null +++ b/frameworks/ets/ets/application/CustomData.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 interface CustomData { + data: Record; +} + +class CustomDataInner implements CustomData { + public data: Record = {}; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/ExtensionRunningInfo.ets b/frameworks/ets/ets/application/ExtensionRunningInfo.ets new file mode 100644 index 00000000000..7b0fe012bb5 --- /dev/null +++ b/frameworks/ets/ets/application/ExtensionRunningInfo.ets @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ElementName } from 'bundleManager.ElementName'; +import bundle from '@ohos.bundle.bundleManager'; + +export interface ExtensionRunningInfo { + extension: ElementName; + pid: int; + uid: int; + processName: string; + startTime: long; + clientPackage: Array; + type: bundle.ExtensionAbilityType; +} + +class ExtensionRunningInfoInner implements ExtensionRunningInfo { + extension: ElementName = {}; + pid: int; + uid: int; + processName: string = ''; + startTime: long; + clientPackage: Array = new Array(); + type: bundle.ExtensionAbilityType = bundle.ExtensionAbilityType.FORM; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/MissionInfo.ets b/frameworks/ets/ets/application/MissionInfo.ets new file mode 100644 index 00000000000..8973240a7d3 --- /dev/null +++ b/frameworks/ets/ets/application/MissionInfo.ets @@ -0,0 +1,41 @@ +/* + * 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'; +export interface MissionInfo { + missionId: int; + runningState: int; + lockedState: boolean; + timestamp: string; + want: Want; + label: string; + iconPath: string; + continuable: boolean; + abilityState: int; + unclearable: boolean; +} + +class MissionInfoInner implements MissionInfo { + public missionId: int; + public runningState: int; + public lockedState: boolean; + public timestamp: string = ''; + public want: Want = {}; + public label: string = ''; + public iconPath: string = ''; + public continuable: boolean; + public abilityState: int; + public unclearable: boolean; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/ProcessData.ets b/frameworks/ets/ets/application/ProcessData.ets index 5bec6929cbf..fcce5a1e1b3 100644 --- a/frameworks/ets/ets/application/ProcessData.ets +++ b/frameworks/ets/ets/application/ProcessData.ets @@ -14,9 +14,9 @@ */ export default class ProcessData { bundleName: string = ''; - pid: number; - uid: number; - state: number; + pid: int; + uid: int; + state: int; isContinuousTask: boolean; isKeepAlive: boolean; } diff --git a/frameworks/ets/ets/application/ProcessInformation.ets b/frameworks/ets/ets/application/ProcessInformation.ets index 3ecd61ca6da..69cab734109 100644 --- a/frameworks/ets/ets/application/ProcessInformation.ets +++ b/frameworks/ets/ets/application/ProcessInformation.ets @@ -18,21 +18,21 @@ import appManager from '@ohos.app.ability.appManager'; import bundleManager from '@ohos.bundle.bundleManager'; export interface ProcessInformation { - pid: number; - uid: number; + pid: int; + uid: int; processName: string; bundleNames: Array; state: appManager.ProcessState; bundleType: bundleManager.BundleType; - appCloneIndex?: number; + appCloneIndex?: int; } export default class ProcessInformationInner implements ProcessInformation { - pid: number; - uid: number; + pid: int; + uid: int; processName: string = ''; bundleNames: Array = new Array(); state: appManager.ProcessState = appManager.ProcessState.STATE_CREATE; bundleType: bundleManager.BundleType = bundleManager.BundleType.APP; - appCloneIndex?: number; + appCloneIndex?: int; } diff --git a/frameworks/ets/ets/application/RunningAppClone.ets b/frameworks/ets/ets/application/RunningAppClone.ets index 90334b03447..6097396f0da 100644 --- a/frameworks/ets/ets/application/RunningAppClone.ets +++ b/frameworks/ets/ets/application/RunningAppClone.ets @@ -13,13 +13,13 @@ * limitations under the License. */ export interface RunningAppClone { - appCloneIndex: number; - uid: number; - pids: Array; + appCloneIndex: int; + uid: int; + pids: Array; } class RunningAppCloneInner implements RunningAppClone { - appCloneIndex: number; - uid: number; - pids: Array = new Array(); + appCloneIndex: int; + uid: int; + pids: Array = new Array(); } \ No newline at end of file diff --git a/frameworks/ets/ets/application/RunningMultiInstanceInfo.ets b/frameworks/ets/ets/application/RunningMultiInstanceInfo.ets index 10ce3036172..0bc5a6e9c84 100644 --- a/frameworks/ets/ets/application/RunningMultiInstanceInfo.ets +++ b/frameworks/ets/ets/application/RunningMultiInstanceInfo.ets @@ -14,8 +14,12 @@ */ export interface RunningMultiInstanceInfo { instanceKey: string; + uid: int; + pids: Array; } -class RunningMultiInstanceInfoInner implements RunningMultiInstanceInfo { +export class RunningMultiInstanceInfoInner implements RunningMultiInstanceInfo { instanceKey: string = ''; + uid: int; + pids: Array = []; } \ No newline at end of file diff --git a/frameworks/ets/ets/application/ServiceExtensionContext.ets b/frameworks/ets/ets/application/ServiceExtensionContext.ets index abd9a4dc7ec..2bb11c2f1f5 100644 --- a/frameworks/ets/ets/application/ServiceExtensionContext.ets +++ b/frameworks/ets/ets/application/ServiceExtensionContext.ets @@ -16,6 +16,7 @@ import { AsyncCallback } from '@ohos.base'; import AsyncCallbackWrapper from '../utils/AbilityUtils'; import { BusinessError } from '@ohos.base'; +import { ConnectOptions } from 'ability.connectOptions'; import ExtensionContext from 'application.ExtensionContext'; import StartOptions from '@ohos.app.ability.StartOptions'; import Want from '@ohos.app.ability.Want'; @@ -67,6 +68,10 @@ export default class ServiceExtensionContext extends ExtensionContext { native nativeStopServiceExtensionAbility(want: Want, callback: AsyncCallbackWrapper): void; + native nativeConnectServiceExtensionAbility(want: Want, options: ConnectOptions): long; + + native nativeDisconnectServiceExtensionAbility(connection: long, callback: AsyncCallbackWrapper): void; + terminateSelf(callback: AsyncCallback): void { let myCall = new AsyncCallbackWrapper(callback); taskpool.execute((): void => { @@ -96,26 +101,25 @@ export default class ServiceExtensionContext extends ExtensionContext { }); } - 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 { + 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); - }); + let myCall = new AsyncCallbackWrapper((err: BusinessError | null) => { + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } }); + taskpool.execute((): void => { + if (options == null) { + this.nativeStartAbility(want, myCall); + } else { + this.nativeStartAbility(want, options as StartOptions, myCall); + } + }).catch((err: Error): void => { + reject(err as BusinessError); + }); + }); } startServiceExtensionAbility(want: Want, callback: AsyncCallback): void { @@ -161,4 +165,30 @@ export default class ServiceExtensionContext extends ExtensionContext { }); }); } + + connectServiceExtensionAbility(want: Want, options: ConnectOptions): long { + return this.nativeConnectServiceExtensionAbility(want, options); + } + + disconnectServiceExtensionAbility(connection: long, callback: AsyncCallback): void { + let asyncCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeDisconnectServiceExtensionAbility(connection, asyncCall); + }); + } + + disconnectServiceExtensionAbility(connection: long): Promise { + return new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let asyncCall = new AsyncCallbackWrapper((err: BusinessError | null) => { + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeDisconnectServiceExtensionAbility(connection, asyncCall); + }) + }); + } } diff --git a/frameworks/ets/ets/application/UIAbilityContext.ets b/frameworks/ets/ets/application/UIAbilityContext.ets index 9a916d88efe..f71cc330abb 100644 --- a/frameworks/ets/ets/application/UIAbilityContext.ets +++ b/frameworks/ets/ets/application/UIAbilityContext.ets @@ -19,11 +19,15 @@ import StartOptions from '@ohos.app.ability.StartOptions'; import { BusinessError, AsyncCallback } from '@ohos.base'; import { AbilityResult } from 'ability.abilityResult'; import { Configuration } from '@ohos.app.ability.Configuration'; +import { ConnectOptions } from 'ability.connectOptions'; 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'; +import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant'; +import AbilityStartCallback from 'application.AbilityStartCallback'; +import AtomicServiceOptions from '@ohos.app.ability.AtomicServiceOptions'; class Cleaner { public ptr: long = 0; @@ -105,6 +109,20 @@ export default class UIAbilityContext extends Context { private native nativeRequestModalUIExtension(pickerWant: Want, callback: AsyncCallbackWrapper): void; + private native nativeBackToCallerAbilityWithResult(abilityResult: AbilityResult, requestCode: string, callback: AsyncCallbackWrapper): void; + + private native nativeSetMissionLabel(label: string, callback: AsyncCallbackWrapper): void; + + private native nativeConnectServiceExtensionAbility(want: Want, options: ConnectOptions): long; + + private native nativeDisconnectServiceExtensionAbility(connection: long, callback: AsyncCallbackWrapper): void; + + private native nativeSetColorMode(colorMode: ConfigurationConstant.ColorMode): void; + + private native nativeStartAbilityByTypeSync(type: string, wantParam: Record, + startCallback: AbilityStartCallback): BusinessError; + + private native nativeOpenAtomicService(appId: string, callback: AsyncCallbackWrapper, options?: AtomicServiceOptions): void; startAbility(want: Want, callback: AsyncCallback): void { let myCall = new AsyncCallbackWrapper(callback); taskpool.execute((): void => { @@ -119,38 +137,25 @@ export default class UIAbilityContext extends Context { }); } - startAbility(want: Want): 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.nativeStartAbilitySync(want, 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); + } }); - return p; - } - - startAbility(want: Want, options: StartOptions): Promise { - let p = - new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { - let myCall = new AsyncCallbackWrapper((err: BusinessError | null) => { - if (err == null || err.code == 0) { - resolve(undefined); - } else { - reject(err); - } - }); - taskpool.execute((): void => { - this.nativeStartAbilitySync(want, options, myCall); - }); + taskpool.execute((): void => { + if (options == null) { + this.nativeStartAbilitySync(want, myCall); + } else { + this.nativeStartAbilitySync(want, options as StartOptions, myCall); + } + }).catch((err: Error): void => { + reject(err as BusinessError); }); - return p; + }); } startAbilityForResult(want: Want, callback: AsyncCallback): void { @@ -167,38 +172,27 @@ export default class UIAbilityContext extends Context { }); } - startAbilityForResult(want: Want): Promise { - let p = new Promise((resolve: (data: AbilityResult) => void, + startAbilityForResult(want: Want, startOptions?: StartOptions): Promise { + return new Promise((resolve: (data: AbilityResult) => void, reject: (err: BusinessError) => void): void => { - let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: AbilityResult | undefined) => { - if (err == null || err.code == 0) { - resolve(data as AbilityResult); - } else { - reject(err); - } - }); + let myCall = + new AsyncCallbackWrapper((err: BusinessError | null, data: AbilityResult | undefined) => { + if (err == null || err.code == 0) { + resolve(data as AbilityResult); + } else { + reject(err); + } + }); taskpool.execute((): void => { - this.nativeStartAbilityForResult(want, myCall); - }); - }); - return p; - } - - startAbilityForResult(want: Want, startOptions: StartOptions): Promise { - let p = new Promise((resolve: (data: AbilityResult) => void, - reject: (err: BusinessError) => void): void => { - let myCall = new AsyncCallbackWrapper((err: BusinessError | null, data: AbilityResult | undefined) => { - if (err == null || err.code == 0) { - resolve(data as AbilityResult); + if (startOptions == null) { + this.nativeStartAbilityForResult(want, myCall); } else { - reject(err); + this.nativeStartAbilityForResult(want, startOptions as StartOptions, myCall); } - }); - taskpool.execute((): void => { - this.nativeStartAbilityForResult(want, startOptions, myCall); + }).catch((err: Error): void => { + reject(err as BusinessError); }); }); - return p; } terminateSelf(callback: AsyncCallback): void { @@ -333,4 +327,123 @@ export default class UIAbilityContext extends Context { }); }); } + + backToCallerAbilityWithResult(abilityResult: AbilityResult, requestCode: string): 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.nativeBackToCallerAbilityWithResult(abilityResult, requestCode, syncCall); + }); + }); + } + + setMissionLabel(label: string, callback: AsyncCallback): void { + let syncCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeSetMissionLabel(label, syncCall); + }); + } + + setMissionLabel(label: string): 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.nativeSetMissionLabel(label, syncCall); + }); + }); + } + + connectServiceExtensionAbility(want: Want, options: ConnectOptions): long { + return this.nativeConnectServiceExtensionAbility(want, options); + } + + disconnectServiceExtensionAbility(connection: long, callback: AsyncCallback): void { + let syncCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeDisconnectServiceExtensionAbility(connection, syncCall); + }); + } + + disconnectServiceExtensionAbility(connection: long): Promise { + return new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let callback = new AsyncCallbackWrapper((err: BusinessError | null) => { + if (err == null || err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeDisconnectServiceExtensionAbility(connection, callback); + }) + }); + } + + setColorMode(colorMode: ConfigurationConstant.ColorMode): void { + this.nativeSetColorMode(colorMode); + } + + startAbilityByType(type: string, wantParam: Record, startCallback: AbilityStartCallback, + callback: AsyncCallback): void { + let p1 = taskpool.execute((): BusinessError => { + return this.nativeStartAbilityByTypeSync(type, wantParam, startCallback); + }); + p1.then((e: NullishType) => { + let retError = e as BusinessError; + if (retError.code === 0) { + callback(null, undefined); + } else { + callback(retError, undefined); + } + }, (err: Error): void => { + callback(err as BusinessError, undefined); + }); + } + + startAbilityByType(type: string, wantParam: Record, + startCallback: AbilityStartCallback): Promise { + let p = new Promise((resolve: (v: undefined) => void, reject: (error: BusinessError) => void): void => { + let p1 = taskpool.execute((): BusinessError => { + return this.nativeStartAbilityByTypeSync(type, wantParam, startCallback); + }); + p1.then((e: NullishType) => { + let retError = e as BusinessError; + if (retError.code === 0) { + resolve(undefined); + } else { + reject(retError); + } + }).catch((err: Error): void => { + reject(err as BusinessError); + }); + }); + return p; + } + + openAtomicService(appId: string, options?: AtomicServiceOptions): Promise { + return new Promise((resolve: (data: AbilityResult) => void, reject: (err: BusinessError) => void): void => { + let asyncCall = new AsyncCallbackWrapper((err: BusinessError | null, data: AbilityResult | undefined) => { + if (err == null || err.code == 0) { + resolve(data as AbilityResult); + } else { + reject(err); + } + }); + taskpool.execute(() => { + this.nativeOpenAtomicService(appId, asyncCall, options); + }); + }); + } } diff --git a/frameworks/ets/ets/application/UIExtensionContext.ets b/frameworks/ets/ets/application/UIExtensionContext.ets index 7fd231110d3..fc684e9764f 100644 --- a/frameworks/ets/ets/application/UIExtensionContext.ets +++ b/frameworks/ets/ets/application/UIExtensionContext.ets @@ -16,10 +16,12 @@ import { AbilityResult } from 'ability.abilityResult'; import { AsyncCallback } from '@ohos.base'; import { BusinessError } from '@ohos.base'; +import { ConnectOptions } from 'ability.connectOptions'; import AsyncCallbackWrapper from '../utils/AbilityUtils'; import ExtensionContext from 'application.ExtensionContext'; import StartOptions from '@ohos.app.ability.StartOptions'; import Want from '@ohos.app.ability.Want'; +import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant'; class Cleaner { static callback(cleaner: Cleaner): void { @@ -54,6 +56,14 @@ export default class UIExtensionContext extends ExtensionContext { native terminateSelfWithResultSync(parameter: AbilityResult, callback: AsyncCallbackWrapper): void; native nativeStartAbility(want: Want, callback: AsyncCallbackWrapper): void; native nativeStartAbility(want: Want, options: StartOptions, callback:AsyncCallbackWrapper): void; + private native nativeConnectServiceExtensionAbility(want: Want, options: ConnectOptions): long; + private native nativeDisconnectServiceExtensionAbilitySync(connection: long, callback: AsyncCallbackWrapper): void; + private native nativeStartAbilityForResultAsCaller(want: Want, callback: AsyncCallbackWrapper, options?: StartOptions): void; + private native nativeStartAbilityForResult(want: Want, callback:AsyncCallbackWrapper): void; + private native nativeStartAbilityForResult(want: Want, startOptions: StartOptions, + callback:AsyncCallbackWrapper): void; + native setColorMode(colorMode: ConfigurationConstant.ColorMode): void; + native nativeReportDrawnCompleted(callback:AsyncCallbackWrapper): void; terminateSelf(callback:AsyncCallback): void { let myCall = new AsyncCallbackWrapper(callback); @@ -115,7 +125,7 @@ export default class UIExtensionContext extends ExtensionContext { }); } - startAbility(want: Want, options: StartOptions): Promise { + 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) { @@ -125,8 +135,84 @@ export default class UIExtensionContext extends ExtensionContext { } }); taskpool.execute((): void => { - this.nativeStartAbility(want, options, myCall); + if (options == null) { + this.nativeStartAbility(want, myCall); + } else { + this.nativeStartAbility(want, options as StartOptions, myCall); + } + }).catch((err: Error): void => { + reject(err as BusinessError); + }); + }); + } + + connectServiceExtensionAbility(want: Want, options: ConnectOptions): long { + return this.nativeConnectServiceExtensionAbility(want, options); + } + + disconnectServiceExtensionAbility(connection: long, callback: AsyncCallback): void { + let syncCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeDisconnectServiceExtensionAbilitySync(connection, syncCall); + }); + } + + disconnectServiceExtensionAbility(connection: long): 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((): void => { + this.nativeDisconnectServiceExtensionAbilitySync(connection, syncCall); + }) + }); + } + + startAbilityForResult(want: Want, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartAbilityForResult(want, myCall); + }); + } + + startAbilityForResult(want: Want, startOptions: StartOptions, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartAbilityForResult(want, startOptions, myCall); + }); + } + + startAbilityForResult(want: Want, startOptions?: StartOptions): Promise { + return new Promise((resolve: (data: AbilityResult) => void, + reject: (err: BusinessError) => void): void => { + let myCall = + new AsyncCallbackWrapper((err: BusinessError | null, data: AbilityResult | undefined) => { + if (err == null || err.code == 0) { + resolve(data as AbilityResult); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + if (startOptions == null) { + this.nativeStartAbilityForResult(want, myCall); + } else { + this.nativeStartAbilityForResult(want, startOptions as StartOptions, myCall); + } + }).catch((err: Error): void => { + reject(err as BusinessError); + }); + }); + } + + reportDrawnCompleted(callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeReportDrawnCompleted(myCall); }); } } \ No newline at end of file diff --git a/frameworks/ets/ets/application/shellCmdResult.ets b/frameworks/ets/ets/application/shellCmdResult.ets index 5250b377d4d..01b64339038 100644 --- a/frameworks/ets/ets/application/shellCmdResult.ets +++ b/frameworks/ets/ets/application/shellCmdResult.ets @@ -15,12 +15,12 @@ interface ShellCmdResult { stdResult: string; - exitCode: number; + exitCode: int; } class ShellCmdResultImpl implements ShellCmdResult { public stdResult: string = ''; - public exitCode: number = 0; + public exitCode: int = 0; } export default ShellCmdResult; diff --git a/frameworks/native/ability/BUILD.gn b/frameworks/native/ability/BUILD.gn index 916127116dd..2116d267d0d 100644 --- a/frameworks/native/ability/BUILD.gn +++ b/frameworks/native/ability/BUILD.gn @@ -65,6 +65,7 @@ ohos_shared_library("ability_context_native") { "ability_runtime/start_vertical_panel.cpp", "native/js_ui_extension_callback.cpp", "native/panel_start_callback.cpp", + "native/ui_extension_callback.cpp", ] deps = [ diff --git a/frameworks/native/ability/ability_runtime/ability_context_impl.cpp b/frameworks/native/ability/ability_runtime/ability_context_impl.cpp index 508332afb22..359bb6bb93a 100644 --- a/frameworks/native/ability/ability_runtime/ability_context_impl.cpp +++ b/frameworks/native/ability/ability_runtime/ability_context_impl.cpp @@ -1061,8 +1061,8 @@ Ace::UIContent* AbilityContextImpl::GetUIContent() return abilityCallback->GetUIContent(); } -ErrCode AbilityContextImpl::StartAbilityByType(const std::string &type, - AAFwk::WantParams &wantParams, const std::shared_ptr &uiExtensionCallbacks) +ErrCode AbilityContextImpl::StartAbilityByType( + const std::string &type, AAFwk::WantParams &wantParams, std::shared_ptr uiExtensionCallback) { TAG_LOGD(AAFwkTag::CONTEXT, "call"); auto uiContent = GetUIContent(); @@ -1079,20 +1079,24 @@ ErrCode AbilityContextImpl::StartAbilityByType(const std::string &type, wantParams.Remove(FLAG_AUTH_READ_URI_PERMISSION); } Ace::ModalUIExtensionCallbacks callback; - callback.onError = [uiExtensionCallbacks](int32_t arg, const std::string &str1, const std::string &str2) { - uiExtensionCallbacks->OnError(arg); + if (uiExtensionCallback == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null uiExtensionCallback"); + return ERR_INVALID_VALUE; + } + callback.onError = [uiExtensionCallback](int32_t arg, const std::string &str1, const std::string &str2) { + uiExtensionCallback->OnError(arg); }; - callback.onRelease = [uiExtensionCallbacks](int32_t arg) { - uiExtensionCallbacks->OnRelease(arg); + callback.onRelease = [uiExtensionCallback](int32_t arg) { + uiExtensionCallback->OnRelease(arg); }; - callback.onResult = [uiExtensionCallbacks](int32_t arg1, const OHOS::AAFwk::Want arg2) { - uiExtensionCallbacks->OnResult(arg1, arg2); + callback.onResult = [uiExtensionCallback](int32_t arg1, const OHOS::AAFwk::Want arg2) { + uiExtensionCallback->OnResult(arg1, arg2); }; - callback.onReceive = [uiExtensionCallbacks](const AAFwk::WantParams& data) { + callback.onReceive = [uiExtensionCallback](const AAFwk::WantParams& data) { if (data.HasParam("onRequestSuccess")) { auto successParam = data.GetWantParams("onRequestSuccess"); auto elementName = successParam.GetStringParam("name"); - uiExtensionCallbacks->OnRequestSuccess(elementName); + uiExtensionCallback->OnRequestSuccess(elementName); } else if (data.HasParam("onRequestFailure")) { auto failureParam = data.GetWantParams("onRequestFailure"); auto elementName = failureParam.GetStringParam("name"); @@ -1102,7 +1106,7 @@ ErrCode AbilityContextImpl::StartAbilityByType(const std::string &type, return; } std::string failureMsg = failureParam.GetStringParam("failureMessage"); - uiExtensionCallbacks->OnRequestFailure(elementName, failureCode, failureMsg); + uiExtensionCallback->OnRequestFailure(elementName, failureCode, failureMsg); } }; Ace::ModalUIExtensionConfig config; @@ -1111,8 +1115,8 @@ ErrCode AbilityContextImpl::StartAbilityByType(const std::string &type, TAG_LOGE(AAFwkTag::CONTEXT, "createModalUIExtension failed"); return ERR_INVALID_VALUE; } - uiExtensionCallbacks->SetUIContent(uiContent); - uiExtensionCallbacks->SetSessionId(sessionId); + uiExtensionCallback->SetUIContent(uiContent); + uiExtensionCallback->SetSessionId(sessionId); return ERR_OK; } diff --git a/frameworks/native/ability/native/BUILD.gn b/frameworks/native/ability/native/BUILD.gn index 07b861117bc..af5d04d306f 100644 --- a/frameworks/native/ability/native/BUILD.gn +++ b/frameworks/native/ability/native/BUILD.gn @@ -898,7 +898,9 @@ ohos_shared_library("ui_ability_ani") { include_dirs = [ "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", "${ability_runtime_path}/frameworks/ets/ani/ui_ability/include", + "${ability_runtime_path}/frameworks/ets/ani/ui_extension_callback/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", @@ -927,12 +929,14 @@ ohos_shared_library("ui_ability_ani") { "${ability_runtime_innerkits_path}/ability_manager:process_options", "${ability_runtime_innerkits_path}/runtime:runtime", "${ability_runtime_native_path}/ability:ability_context_native", + "${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}/appkit:appkit_delegator", "${ability_runtime_native_path}/insight_intent/insight_intent_context:insightintentcontext", "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_path}/frameworks/ets/ani/ui_extension_callback:ani_ui_extension_callback", "${ability_runtime_path}/utils/global/freeze:freeze_util", "${ability_runtime_services_path}/common:app_util", "${ability_runtime_services_path}/common:event_report", @@ -953,6 +957,7 @@ ohos_shared_library("ui_ability_ani") { "hitrace:hitrace_meter", "ipc:ipc_core", "ipc:ipc_napi", + "ipc:rpc_ani", "resource_management:global_resmgr", "runtime_core:ani", "runtime_core:ani_helpers", @@ -2140,6 +2145,7 @@ ohos_shared_library("ui_extension_ani") { include_dirs = [ "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", + "${ability_runtime_path}/frameworks/ets/ani/ui_extension_callback/include", "${ability_runtime_path}/frameworks/ets/ani/ui_extension_ability/include", "${ability_runtime_path}/frameworks/ets/ani/enum_convert", "${ability_runtime_path}/interfaces/inner_api/insight_intent/insight_intent_context", @@ -2149,6 +2155,7 @@ ohos_shared_library("ui_extension_ani") { ] sources = [ + "${ability_runtime_path}/frameworks/ets/ani/ui_extension_ability/src/ets_extension_common.cpp", "${ability_runtime_path}/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension.cpp", "${ability_runtime_path}/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension_content_session.cpp", "${ability_runtime_path}/frameworks/ets/ani/ui_extension_ability/src/ets_ui_extension_context.cpp", @@ -2172,6 +2179,7 @@ ohos_shared_library("ui_extension_ani") { "${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_path}/frameworks/ets/ani/ui_extension_callback:ani_ui_extension_callback", ] external_deps = [ @@ -2190,6 +2198,7 @@ ohos_shared_library("ui_extension_ani") { "hitrace:hitrace_meter", "ipc:ipc_core", "ipc:ipc_napi", + "ipc:rpc_ani", "window_manager:embeddablewindowstage_kit", "window_manager:embeddablewindowstageani_kit", "window_manager:extensionwindow_napi", @@ -2925,6 +2934,42 @@ ohos_shared_library("auto_fill_extension") { part_name = "ability_runtime" } +ohos_shared_library("auto_fill_extension_util") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + public_configs = [ ":auto_fill_extension_config" ] + + sources = [] + + deps = [ + ":abilitykit_native", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] + + external_deps = [ + "ability_base:view_data", + "ace_engine:ace_uicontent", + ] + + if (ability_runtime_auto_fill) { + sources += [ + "${ability_runtime_native_path}/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.cpp", + ] + } + + subsystem_name = "ability" + part_name = "ability_runtime" +} + ohos_shared_library("auto_fill_extension_module") { sources = [ "${ability_runtime_native_path}/ability/native/auto_fill_extension_ability/auto_fill_extension_module_loader.cpp" ] @@ -2955,6 +3000,7 @@ ohos_shared_library("auto_fill_extension_module") { ] if (ability_runtime_auto_fill) { deps += [ ":auto_fill_extension" ] + deps += [ ":auto_fill_extension_util" ] } if (ability_runtime_graphics) { external_deps += [] diff --git a/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp b/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp index 911c4c18951..4df80b9acbe 100644 --- a/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp +++ b/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp @@ -34,6 +34,7 @@ #include "js_error_utils.h" #include "js_runtime_utils.h" #include "js_uiservice_ability_connection.h" +#include "js_ui_extension_callback.h" #include "js_ui_service_proxy.h" #include "json_utils.h" #include "mission_info.h" diff --git a/frameworks/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.cpp b/frameworks/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.cpp new file mode 100644 index 00000000000..ee3405f5d72 --- /dev/null +++ b/frameworks/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.cpp @@ -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. + */ + +#include "ets_auto_fill_extension_util.h" + +#include "ani_common_execute_result.h" +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "hilog_tag_wrapper.h" +#include "want_params.h" + +namespace OHOS { +namespace AbilityRuntime { +using namespace OHOS::AppExecFwk; +constexpr const char* CUSTOM_DATA_INNER_CLASS_NAME = "Lapplication/CustomData/CustomDataInner;"; + +ani_object EtsAutoFillExtensionUtil::WrapCustomData(ani_env *env, const CustomData &customdata) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null env"); + return nullptr; + } + + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method ctor = nullptr; + ani_object objValue = {}; + + if ((status = env->FindClass(CUSTOM_DATA_INNER_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "status: %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &ctor)) != ANI_OK || ctor == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "Class_FindMethod status: %{public}d or null ctor", status); + return nullptr; + } + if ((status = env->Object_New(cls, ctor, &objValue)) != ANI_OK) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "status: %{public}d", status); + return nullptr; + } + if (objValue == nullptr) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "null objValue"); + return nullptr; + } + if (!SetRefProperty(env, objValue, "data", WrapWantParams(env, customdata.data))) { + TAG_LOGE(AAFwkTag::AUTOFILL_EXT, "SetRefProperty failed"); + return nullptr; + } + return objValue; +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/ability/native/js_ui_extension_callback.cpp b/frameworks/native/ability/native/js_ui_extension_callback.cpp index 3f66566f465..ff09654c334 100644 --- a/frameworks/native/ability/native/js_ui_extension_callback.cpp +++ b/frameworks/native/ability/native/js_ui_extension_callback.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -69,16 +69,7 @@ JsUIExtensionCallback::~JsUIExtensionCallback() } } -void JsUIExtensionCallback::SetSessionId(int32_t sessionId) -{ - sessionId_ = sessionId; -} #ifdef SUPPORT_SCREEN -void JsUIExtensionCallback::SetUIContent(Ace::UIContent* uiContent) -{ - uiContent_ = uiContent; -} - void JsUIExtensionCallback::SetJsCallbackObject(napi_value jsCallbackObject) { napi_ref ref = nullptr; @@ -108,11 +99,7 @@ void JsUIExtensionCallback::OnError(int32_t number) std::unique_ptr execute = nullptr; NapiAsyncTask::Schedule("JsUIExtensionCallback::OnError:", env_, std::make_unique(callback, std::move(execute), std::move(complete))); - if (uiContent_ == nullptr) { - TAG_LOGE(AAFwkTag::UI_EXT, "null uiContent_"); - return; - } - uiContent_->CloseModalUIExtension(sessionId_); + CloseModalUIExtension(); } void JsUIExtensionCallback::OnResult(int32_t resultCode, const AAFwk::Want &want) @@ -134,11 +121,7 @@ void JsUIExtensionCallback::OnResult(int32_t resultCode, const AAFwk::Want &want std::unique_ptr execute = nullptr; NapiAsyncTask::Schedule("JsUIExtensionCallback::OnResult:", env_, std::make_unique(callback, std::move(execute), std::move(complete))); - if (uiContent_ == nullptr) { - TAG_LOGE(AAFwkTag::UI_EXT, "null uiContent_"); - return; - } - uiContent_->CloseModalUIExtension(sessionId_); + CloseModalUIExtension(); } void JsUIExtensionCallback::CallJsResult(int32_t resultCode, const AAFwk::Want &want) @@ -177,15 +160,6 @@ void JsUIExtensionCallback::CallJsResult(int32_t resultCode, const AAFwk::Want & TAG_LOGI(AAFwkTag::UI_EXT, "end"); } -void JsUIExtensionCallback::OnRelease(int32_t code) -{ - TAG_LOGI(AAFwkTag::UI_EXT, "call, code:%{public}d", code); - if (uiContent_ == nullptr) { - TAG_LOGE(AAFwkTag::UI_EXT, "null uiContent_"); - return; - } - uiContent_->CloseModalUIExtension(sessionId_); -} #endif // SUPPORT_SCREEN void JsUIExtensionCallback::CallJsError(int32_t number) { diff --git a/frameworks/native/ability/native/ui_extension_ability/js_ui_extension.cpp b/frameworks/native/ability/native/ui_extension_ability/js_ui_extension.cpp index 92e4913a82a..f05ede2a805 100755 --- a/frameworks/native/ability/native/ui_extension_ability/js_ui_extension.cpp +++ b/frameworks/native/ability/native/ui_extension_ability/js_ui_extension.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -45,7 +45,6 @@ #include "string_wrapper.h" #include "ui_extension_window_command.h" #include "want_params_wrapper.h" -#include "application_configuration_manager.h" #include "ohos_application.h" namespace OHOS { @@ -181,57 +180,6 @@ void JsUIExtension::Init(const std::shared_ptr &record, RegisterDisplayInfoChangedListener(); } -void JsUIExtension::RegisterAbilityConfigUpdateCallback() -{ - auto context = GetContext(); - auto uiExtensionAbility = std::static_pointer_cast(shared_from_this()); - std::weak_ptr abilityWptr = uiExtensionAbility; - context->RegisterAbilityConfigUpdateCallback( - [abilityWptr, abilityContext = context](AppExecFwk::Configuration &config) { - std::shared_ptr abilitySptr = abilityWptr.lock(); - if (abilitySptr == nullptr) { - TAG_LOGE(AAFwkTag::UIABILITY, "null abilitySptr"); - return; - } - if (abilityContext == nullptr || abilityContext->GetAbilityInfo() == nullptr) { - TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext or null GetAbilityInfo"); - return; - } - if (abilityContext->GetAbilityConfiguration() == nullptr) { - auto abilityModuleContext = abilityContext->CreateModuleContext( - abilityContext->GetAbilityInfo()->moduleName); - if (abilityModuleContext == nullptr) { - TAG_LOGE(AAFwkTag::UIABILITY, "null abilityModuleContext"); - return; - } - auto abilityResourceMgr = abilityModuleContext->GetResourceManager(); - abilityContext->SetAbilityResourceManager(abilityResourceMgr); - AbilityRuntime::ApplicationConfigurationManager::GetInstance(). - AddIgnoreContext(abilityContext, abilityResourceMgr); - TAG_LOGE(AAFwkTag::UIABILITY, "%{public}zu", - AbilityRuntime::ApplicationConfigurationManager::GetInstance().GetIgnoreContext().size()); - } - abilityContext->SetAbilityConfiguration(config); - if (config.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE). - compare(AppExecFwk::ConfigurationInner::COLOR_MODE_AUTO) == 0) { - config.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE, - AbilityRuntime::ApplicationConfigurationManager::GetInstance().GetColorMode()); - - if (AbilityRuntime::ApplicationConfigurationManager::GetInstance(). - GetColorModeSetLevel() > AbilityRuntime::SetLevel::System) { - config.AddItem(AAFwk::GlobalConfigurationKey::COLORMODE_IS_SET_BY_APP, - AppExecFwk::ConfigurationInner::IS_SET_BY_APP); - } - abilityContext->GetAbilityConfiguration()-> - RemoveItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE); - abilityContext->GetAbilityConfiguration()-> - RemoveItem(AAFwk::GlobalConfigurationKey::COLORMODE_IS_SET_BY_APP); - } - - abilitySptr->OnAbilityConfigurationUpdated(config); - }); -} - void JsUIExtension::CreateJSContext(napi_env env, napi_value &contextObj, std::shared_ptr context, int32_t screenMode) { @@ -910,62 +858,11 @@ napi_value JsUIExtension::CallOnDisconnect(const AAFwk::Want &want, bool withRes } } -void JsUIExtension::OnConfigurationUpdated(const AppExecFwk::Configuration& configuration) -{ - HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - Extension::OnConfigurationUpdated(configuration); - TAG_LOGD(AAFwkTag::UI_EXT, "called"); - - // Notify extension context - auto context = GetContext(); - if (context == nullptr) { - TAG_LOGE(AAFwkTag::UI_EXT, "null context"); - return; - } - - auto abilityConfig = context->GetAbilityConfiguration(); - auto configUtils = std::make_shared(); - - if (abilityConfig != nullptr) { - auto newConfig = configUtils->UpdateGlobalConfig(configuration, context->GetConfiguration(), - abilityConfig, context->GetResourceManager()); - if (newConfig.GetItemSize() == 0) { - return; - } - if (context->GetWindow()) { - TAG_LOGI(AAFwkTag::UIABILITY, "newConfig: %{public}s", newConfig.GetName().c_str()); - auto diffConfiguration = std::make_shared(newConfig); - context->GetWindow()->UpdateConfigurationForSpecified(diffConfiguration, context->GetResourceManager()); - } - } else { - auto configUtils = std::make_shared(); - configUtils->UpdateGlobalConfig(configuration, context->GetConfiguration(), context->GetResourceManager()); - } - - ConfigurationUpdated(); -} - void JsUIExtension::OnAbilityConfigurationUpdated(const AppExecFwk::Configuration& configuration) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - Extension::OnConfigurationUpdated(configuration); - TAG_LOGD(AAFwkTag::UI_EXT, "called"); - - auto context = GetContext(); - if (context == nullptr) { - TAG_LOGE(AAFwkTag::UI_EXT, "null context"); - return; - } - - auto configUtils = std::make_shared(); - configUtils->UpdateAbilityConfig(configuration, context->GetResourceManager()); - - if (context->GetWindow()) { - TAG_LOGI(AAFwkTag::UIABILITY, "newConfig: %{public}s", configuration.GetName().c_str()); - auto diffConfiguration = std::make_shared(configuration); - context->GetWindow()->UpdateConfigurationForSpecified(diffConfiguration, context->GetResourceManager()); - } - + UIExtension::OnAbilityConfigurationUpdated(configuration); + TAG_LOGD(AAFwkTag::UI_EXT, "OnAbilityConfigurationUpdated called"); ConfigurationUpdated(); } diff --git a/frameworks/native/ability/native/ui_extension_ability/ui_extension.cpp b/frameworks/native/ability/native/ui_extension_ability/ui_extension.cpp index 13fc93d7c0c..89f608dd9f6 100755 --- a/frameworks/native/ability/native/ui_extension_ability/ui_extension.cpp +++ b/frameworks/native/ability/native/ui_extension_ability/ui_extension.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -14,11 +14,13 @@ */ #include "ui_extension.h" -#include "ets_ui_extension_instance.h" #include "ability_manager_client.h" +#include "application_configuration_manager.h" #include "array_wrapper.h" +#include "configuration_utils.h" #include "connection_manager.h" #include "ets_ui_extension.h" +#include "ets_ui_extension_instance.h" #include "hilog_tag_wrapper.h" #include "hitrace_meter.h" #include "int_wrapper.h" @@ -258,5 +260,110 @@ void UIExtension::OnInsightIntentExecuteDone(const sptr &ses } TAG_LOGD(AAFwkTag::UI_EXT, "end"); } + +void UIExtension::OnConfigurationUpdated(const AppExecFwk::Configuration &configuration) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + Extension::OnConfigurationUpdated(configuration); + TAG_LOGD(AAFwkTag::UI_EXT, "OnConfigurationUpdated called"); + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + return; + } + auto abilityConfig = context->GetAbilityConfiguration(); + auto configUtils = std::make_shared(); + if (abilityConfig != nullptr) { + auto newConfig = configUtils->UpdateGlobalConfig( + configuration, context->GetConfiguration(), abilityConfig, context->GetResourceManager()); + if (newConfig.GetItemSize() == 0) { + return; + } + if (context->GetWindow()) { + TAG_LOGI(AAFwkTag::UI_EXT, "newConfig: %{public}s", newConfig.GetName().c_str()); + auto diffConfiguration = std::make_shared(newConfig); + context->GetWindow()->UpdateConfigurationForSpecified(diffConfiguration, context->GetResourceManager()); + } + } else { + auto configUtils = std::make_shared(); + configUtils->UpdateGlobalConfig(configuration, context->GetConfiguration(), context->GetResourceManager()); + } + ConfigurationUpdated(); +} + +void UIExtension::ConfigurationUpdated() +{ + TAG_LOGD(AAFwkTag::UI_EXT, "ConfigurationUpdated called"); +} + +void UIExtension::OnAbilityConfigurationUpdated(const AppExecFwk::Configuration &configuration) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + Extension::OnConfigurationUpdated(configuration); + TAG_LOGD(AAFwkTag::UI_EXT, "OnAbilityConfigurationUpdated called"); + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + return; + } + auto configUtils = std::make_shared(); + configUtils->UpdateAbilityConfig(configuration, context->GetResourceManager()); + if (context->GetWindow()) { + TAG_LOGI(AAFwkTag::UI_EXT, "newConfig: %{public}s", configuration.GetName().c_str()); + auto diffConfiguration = std::make_shared(configuration); + context->GetWindow()->UpdateConfigurationForSpecified(diffConfiguration, context->GetResourceManager()); + } +} + +void UIExtension::RegisterAbilityConfigUpdateCallback() +{ + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + return; + } + auto uiExtensionAbility = std::static_pointer_cast(shared_from_this()); + std::weak_ptr abilityWptr = uiExtensionAbility; + context->RegisterAbilityConfigUpdateCallback( + [abilityWptr, abilityContext = context](AppExecFwk::Configuration &config) { + std::shared_ptr abilitySptr = abilityWptr.lock(); + if (abilitySptr == nullptr || abilityContext == nullptr || abilityContext->GetAbilityInfo() == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null abilitySptr or abilityContext or GetAbilityInfo"); + return; + } + if (abilityContext->GetAbilityConfiguration() == nullptr) { + auto abilityModuleContext = abilityContext->CreateModuleContext( + abilityContext->GetAbilityInfo()->moduleName); + if (abilityModuleContext == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null abilityModuleContext"); + return; + } + auto abilityResourceMgr = abilityModuleContext->GetResourceManager(); + abilityContext->SetAbilityResourceManager(abilityResourceMgr); + AbilityRuntime::ApplicationConfigurationManager::GetInstance(). + AddIgnoreContext(abilityContext, abilityResourceMgr); + TAG_LOGE(AAFwkTag::UI_EXT, "%{public}zu", + AbilityRuntime::ApplicationConfigurationManager::GetInstance().GetIgnoreContext().size()); + } + abilityContext->SetAbilityConfiguration(config); + if (config.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE). + compare(AppExecFwk::ConfigurationInner::COLOR_MODE_AUTO) == 0) { + config.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE, + AbilityRuntime::ApplicationConfigurationManager::GetInstance().GetColorMode()); + + if (AbilityRuntime::ApplicationConfigurationManager::GetInstance(). + GetColorModeSetLevel() > AbilityRuntime::SetLevel::System) { + config.AddItem(AAFwk::GlobalConfigurationKey::COLORMODE_IS_SET_BY_APP, + AppExecFwk::ConfigurationInner::IS_SET_BY_APP); + } + abilityContext->GetAbilityConfiguration()-> + RemoveItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE); + abilityContext->GetAbilityConfiguration()-> + RemoveItem(AAFwk::GlobalConfigurationKey::COLORMODE_IS_SET_BY_APP); + } + + abilitySptr->OnAbilityConfigurationUpdated(config); + }); +} } } diff --git a/frameworks/native/ability/native/ui_extension_base/js_ui_extension_content_session.cpp b/frameworks/native/ability/native/ui_extension_base/js_ui_extension_content_session.cpp index 20cabb77d37..0cd31ba1ff5 100644 --- a/frameworks/native/ability/native/ui_extension_base/js_ui_extension_content_session.cpp +++ b/frameworks/native/ability/native/ui_extension_base/js_ui_extension_content_session.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -24,6 +24,7 @@ #include "js_error_utils.h" #include "js_extension_window.h" #include "js_runtime_utils.h" +#include "js_ui_extension_callback.h" #include "js_ui_extension_context.h" #include "napi_common_start_options.h" #include "napi_common_util.h" diff --git a/frameworks/native/ability/native/ui_extension_base/ui_extension_context.cpp b/frameworks/native/ability/native/ui_extension_base/ui_extension_context.cpp index b1055074ee5..41a42cf1ce4 100755 --- a/frameworks/native/ability/native/ui_extension_base/ui_extension_context.cpp +++ b/frameworks/native/ability/native/ui_extension_base/ui_extension_context.cpp @@ -15,13 +15,15 @@ #include "ui_extension_context.h" +#include "ability_business_error.h" #include "ability_manager_client.h" #include "bool_wrapper.h" +#include "configuration.h" +#include "configuration_convertor.h" #include "connection_manager.h" #include "hilog_tag_wrapper.h" #include "hitrace_meter.h" -#include "configuration_convertor.h" -#include "configuration.h" +#include "string_wrapper.h" #include "ui_content.h" namespace OHOS { diff --git a/frameworks/native/ability/native/ui_extension_callback.cpp b/frameworks/native/ability/native/ui_extension_callback.cpp new file mode 100644 index 00000000000..0a75887e816 --- /dev/null +++ b/frameworks/native/ability/native/ui_extension_callback.cpp @@ -0,0 +1,63 @@ +/* + * 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 "ui_extension_callback.h" + +#include "hilog_tag_wrapper.h" +#ifdef SUPPORT_SCREEN +#include "ui_content.h" +#include "ws_common.h" +#endif // SUPPORT_SCREEN + +namespace OHOS { +namespace AbilityRuntime { +void UIExtensionCallback::SetSessionId(int32_t sessionId) +{ + sessionId_ = sessionId; +} +#ifdef SUPPORT_SCREEN +void UIExtensionCallback::SetUIContent(Ace::UIContent* uiContent) +{ + uiContent_ = uiContent; +} + +void UIExtensionCallback::OnRelease(int32_t code) +{ + TAG_LOGI(AAFwkTag::UI_EXT, "call, code:%{public}d", code); + CloseModalUIExtension(); +} + +void UIExtensionCallback::CloseModalUIExtension() +{ + if (uiContent_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null uiContent_"); + return; + } + uiContent_->CloseModalUIExtension(sessionId_); +} +#endif // SUPPORT_SCREEN +void UIExtensionCallback::OnRequestSuccess(const std::string& name) +{ + TAG_LOGI(AAFwkTag::UI_EXT, "call OnRequestSuccess, name:%{public}s", name.c_str()); +} + +void UIExtensionCallback::OnRequestFailure( + const std::string &name, int32_t failureCode, const std::string &failureMessage) +{ + TAG_LOGI(AAFwkTag::UI_EXT, + "call OnRequestFailure, name:%{public}s failureCode:%{public}d failureMessage:%{public}s", name.c_str(), + failureCode, failureMessage.c_str()); +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/ability/native/ui_service_extension_ability/js_ui_service_extension_context.cpp b/frameworks/native/ability/native/ui_service_extension_ability/js_ui_service_extension_context.cpp index 1f3c8e24a0b..7dc6a699b18 100644 --- a/frameworks/native/ability/native/ui_service_extension_ability/js_ui_service_extension_context.cpp +++ b/frameworks/native/ability/native/ui_service_extension_ability/js_ui_service_extension_context.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -26,6 +26,7 @@ #include "js_data_struct_converter.h" #include "js_runtime.h" #include "js_runtime_utils.h" +#include "js_ui_extension_callback.h" #include "napi/native_api.h" #include "napi_common_ability.h" #include "napi_common_want.h" 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 6fe5166f8be..d7dc364ea8e 100644 --- a/frameworks/native/appkit/ability_runtime/app/ets_ability_stage.cpp +++ b/frameworks/native/appkit/ability_runtime/app/ets_ability_stage.cpp @@ -126,6 +126,16 @@ void ETSAbilityStage::OnDestroy() const CallObjectMethod(false, "onDestroy", ":V"); } +std::string ETSAbilityStage::OnAcceptWant(const AAFwk::Want &want) +{ + return std::string(); +} + +std::string ETSAbilityStage::OnNewProcessRequest(const AAFwk::Want &want) +{ + return std::string(); +} + void ETSAbilityStage::OnConfigurationUpdated(const AppExecFwk::Configuration &configuration) { TAG_LOGD(AAFwkTag::APPKIT, "OnConfigurationUpdated called"); @@ -154,6 +164,10 @@ void ETSAbilityStage::OnConfigurationUpdated(const AppExecFwk::Configuration &co CallObjectMethod(false, "onConfigurationUpdate", "L@ohos/app/ability/Configuration/Configuration;:V", configObj); } +void ETSAbilityStage::OnMemoryLevel(int32_t level) +{ +} + bool ETSAbilityStage::CallObjectMethod(bool withResult, const char *name, const char *signature, ...) const { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name); @@ -232,6 +246,12 @@ void ETSAbilityStage::SetEtsAbilityStage(const std::shared_ptr &context TAG_LOGE(AAFwkTag::ABILITY, "context nullptr"); return; } + + if (!etsAbilityStageObj_) { + TAG_LOGE(AAFwkTag::APPKIT, "Not found AbilityStage.js"); + return; + } + auto env = etsRuntime_.GetAniEnv(); if (env == nullptr) { TAG_LOGE(AAFwkTag::ABILITY, "env nullptr"); diff --git a/frameworks/native/appkit/ability_runtime/ui_service_extension_context.cpp b/frameworks/native/appkit/ability_runtime/ui_service_extension_context.cpp index 7bb53283f6f..b4a1fa9a77e 100644 --- a/frameworks/native/appkit/ability_runtime/ui_service_extension_context.cpp +++ b/frameworks/native/appkit/ability_runtime/ui_service_extension_context.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -74,12 +74,12 @@ Ace::UIContent* UIServiceExtensionContext::GetUIContent() return window_->GetUIContent(); } -ErrCode UIServiceExtensionContext::StartAbilityByType(const std::string &type, - AAFwk::WantParams &wantParam, const std::shared_ptr &uiExtensionCallbacks) +ErrCode UIServiceExtensionContext::StartAbilityByType( + const std::string &type, AAFwk::WantParams &wantParam, std::shared_ptr uiExtensionCallback) { TAG_LOGD(AAFwkTag::UISERVC_EXT, "StartAbilityByType begin."); - if (uiExtensionCallbacks == nullptr) { - TAG_LOGE(AAFwkTag::UISERVC_EXT, "null uiExtensionCallbacks"); + if (uiExtensionCallback == nullptr) { + TAG_LOGE(AAFwkTag::UISERVC_EXT, "null uiExtensionCallback"); return ERR_INVALID_VALUE; } auto uiContent = GetUIContent(); @@ -98,20 +98,20 @@ ErrCode UIServiceExtensionContext::StartAbilityByType(const std::string &type, OHOS::Ace::ModalUIExtensionCallbacks callback; OHOS::Ace::ModalUIExtensionConfig config; - callback.onError = [uiExtensionCallbacks](int32_t arg, const std::string &str1, const std::string &str2) { - uiExtensionCallbacks->OnError(arg); + callback.onError = [uiExtensionCallback](int32_t arg, const std::string &str1, const std::string &str2) { + uiExtensionCallback->OnError(arg); }; - callback.onRelease = [uiExtensionCallbacks](int32_t arg) { - uiExtensionCallbacks->OnRelease(arg); + callback.onRelease = [uiExtensionCallback](int32_t arg) { + uiExtensionCallback->OnRelease(arg); }; - callback.onResult = [uiExtensionCallbacks](int32_t arg1, const OHOS::AAFwk::Want arg2) { - uiExtensionCallbacks->OnResult(arg1, arg2); + callback.onResult = [uiExtensionCallback](int32_t arg1, const OHOS::AAFwk::Want arg2) { + uiExtensionCallback->OnResult(arg1, arg2); }; - callback.onReceive = [uiExtensionCallbacks](const AAFwk::WantParams& data) { + callback.onReceive = [uiExtensionCallback](const AAFwk::WantParams& data) { if (data.HasParam("onRequestSuccess")) { auto successParam = data.GetWantParams("onRequestSuccess"); auto elementName = successParam.GetStringParam("name"); - uiExtensionCallbacks->OnRequestSuccess(elementName); + uiExtensionCallback->OnRequestSuccess(elementName); } else if (data.HasParam("onRequestFailure")) { auto failureParam = data.GetWantParams("onRequestFailure"); auto elementName = failureParam.GetStringParam("name"); @@ -121,7 +121,7 @@ ErrCode UIServiceExtensionContext::StartAbilityByType(const std::string &type, return; } std::string failureMsg = failureParam.GetStringParam("failureMessage"); - uiExtensionCallbacks->OnRequestFailure(elementName, failureCode, failureMsg); + uiExtensionCallback->OnRequestFailure(elementName, failureCode, failureMsg); } }; int32_t sessionId = uiContent->CreateModalUIExtension(want, callback, config); @@ -129,8 +129,8 @@ ErrCode UIServiceExtensionContext::StartAbilityByType(const std::string &type, TAG_LOGE(AAFwkTag::UISERVC_EXT, "sessionId zero"); return ERR_INVALID_VALUE; } - uiExtensionCallbacks->SetUIContent(uiContent); - uiExtensionCallbacks->SetSessionId(sessionId); + uiExtensionCallback->SetUIContent(uiContent); + uiExtensionCallback->SetSessionId(sessionId); return ERR_OK; } diff --git a/frameworks/native/runtime/ets_runtime.cpp b/frameworks/native/runtime/ets_runtime.cpp index bd546e081bb..31cce266683 100644 --- a/frameworks/native/runtime/ets_runtime.cpp +++ b/frameworks/native/runtime/ets_runtime.cpp @@ -161,7 +161,7 @@ bool ETSRuntime::PostFork(const Options &options, std::unique_ptr &js g_etsEnvFuncs->PostFork(reinterpret_cast(napiEnv), aotFilePath); return true; } - + std::unique_ptr ETSRuntime::Create(const Options &options, std::unique_ptr &jsRuntime) { TAG_LOGD(AAFwkTag::ETSRUNTIME, "Create called"); diff --git a/interfaces/kits/native/ability/ability_runtime/ability_context.h b/interfaces/kits/native/ability/ability_runtime/ability_context.h index 251d25d18fd..b1ad27d0c52 100644 --- a/interfaces/kits/native/ability/ability_runtime/ability_context.h +++ b/interfaces/kits/native/ability/ability_runtime/ability_context.h @@ -23,7 +23,7 @@ #include "context.h" #include "free_install_observer_interface.h" #include "iability_callback.h" -#include "js_ui_extension_callback.h" +#include "ui_extension_callback.h" #include "mission_info.h" #include "native_engine/native_reference.h" #include "native_engine/native_value.h" @@ -455,7 +455,7 @@ public: */ virtual Ace::UIContent* GetUIContent() = 0; virtual ErrCode StartAbilityByType(const std::string &type, AAFwk::WantParams &wantParam, - const std::shared_ptr &uiExtensionCallbacks) = 0; + std::shared_ptr uiExtensionCallback) = 0; virtual ErrCode CreateModalUIExtensionWithApp(const AAFwk::Want &want) = 0; virtual void EraseUIExtension(int32_t sessionId) = 0; #endif diff --git a/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h b/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h index b644eff67a0..071a077e02e 100644 --- a/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h +++ b/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h @@ -230,8 +230,8 @@ public: */ ErrCode SetMissionContinueState(const AAFwk::ContinueState &state) override; #ifdef SUPPORT_SCREEN - ErrCode StartAbilityByType(const std::string &type, - AAFwk::WantParams &wantParam, const std::shared_ptr &uiExtensionCallbacks) override; + ErrCode StartAbilityByType(const std::string &type, AAFwk::WantParams &wantParam, + std::shared_ptr uiExtensionCallback) override; #endif ErrCode RequestModalUIExtension(const Want &want) override; diff --git a/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.h b/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.h new file mode 100644 index 00000000000..00fc9831dd6 --- /dev/null +++ b/interfaces/kits/native/ability/native/auto_fill_extension_ability/ets_auto_fill_extension_util.h @@ -0,0 +1,34 @@ +/* + * 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_AUTO_FILL_EXTENSION_UTIL_H +#define OHOS_ABILITY_RUNTIME_ETS_AUTO_FILL_EXTENSION_UTIL_H + +#include +#include "ets_runtime.h" +#include "js_auto_fill_extension_util.h" + +namespace OHOS { +namespace AbilityRuntime { + +struct CustomData; + +class EtsAutoFillExtensionUtil { +public: + ani_object WrapCustomData(ani_env *env, const CustomData &customdata); +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_AUTO_FILL_EXTENSION_UTIL_H \ No newline at end of file diff --git a/interfaces/kits/native/ability/native/js_ui_extension_callback.h b/interfaces/kits/native/ability/native/js_ui_extension_callback.h index 65f8186c870..d4133630053 100644 --- a/interfaces/kits/native/ability/native/js_ui_extension_callback.h +++ b/interfaces/kits/native/ability/native/js_ui_extension_callback.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,35 +16,27 @@ #ifndef OHOS_ABILITY_RUNTIME_JS_UI_EXTENSION_CALLBACK_H #define OHOS_ABILITY_RUNTIME_JS_UI_EXTENSION_CALLBACK_H -#include #include "native_engine/native_reference.h" -#include "want.h" +#include "ui_extension_callback.h" namespace OHOS { -namespace Ace { -class UIContent; -} namespace AbilityRuntime { -class JsUIExtensionCallback : public std::enable_shared_from_this { +class JsUIExtensionCallback : public UIExtensionCallback, + public std::enable_shared_from_this { public: explicit JsUIExtensionCallback(napi_env env) : env_(env) {} - ~JsUIExtensionCallback(); - void OnError(int32_t number); - void OnRelease(int32_t code); - void OnResult(int32_t resultCode, const AAFwk::Want &want); + ~JsUIExtensionCallback() override; + void OnError(int32_t number) override; + void OnResult(int32_t resultCode, const AAFwk::Want &want) override; void CallJsResult(int32_t resultCode, const AAFwk::Want &want); void SetJsCallbackObject(napi_value jsCallbackObject); void CallJsError(int32_t number); - void SetSessionId(int32_t sessionId); - void SetUIContent(Ace::UIContent* uiContent); void SetCompletionHandler(napi_env env, napi_value completionHandler); void OnRequestSuccess(const std::string& name); void OnRequestFailure(const std::string& name, int32_t failureCode, const std::string& failureMessage); private: napi_env env_ = nullptr; std::unique_ptr jsCallbackObject_ = nullptr; - int32_t sessionId_ = 0; - Ace::UIContent* uiContent_ = nullptr; napi_ref onRequestSuccess_ = nullptr; napi_ref onRequestFailure_ = nullptr; }; diff --git a/interfaces/kits/native/ability/native/ui_extension_ability/js_ui_extension.h b/interfaces/kits/native/ability/native/ui_extension_ability/js_ui_extension.h index 606c423011b..5ae6d1cef38 100755 --- a/interfaces/kits/native/ability/native/ui_extension_ability/js_ui_extension.h +++ b/interfaces/kits/native/ability/native/ui_extension_ability/js_ui_extension.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -119,13 +119,6 @@ public: */ virtual void OnStopCallBack() override; - /** - * @brief Called when the system configuration is updated. - * - * @param configuration Indicates the updated configuration information. - */ - virtual void OnConfigurationUpdated(const AppExecFwk::Configuration& configuration) override; - /** * @brief Called when this extension enters the STATE_FOREGROUND state. * @@ -167,17 +160,15 @@ public: /** * @brief Called when configuration changed, including system configuration and window configuration. */ - void ConfigurationUpdated(); + void ConfigurationUpdated() override; - void OnAbilityConfigurationUpdated(const AppExecFwk::Configuration& configuration); + void OnAbilityConfigurationUpdated(const AppExecFwk::Configuration& configuration) override; private: virtual void BindContext(napi_env env, napi_value obj, std::shared_ptr want); void CreateJSContext(napi_env env, napi_value &contextObj, std::shared_ptr context, int32_t screenMode); - void RegisterAbilityConfigUpdateCallback(); - napi_value CallObjectMethod(const char *name, napi_value const *argv = nullptr, size_t argc = 0, bool withResult = false); bool CheckPromise(napi_value result); diff --git a/interfaces/kits/native/ability/native/ui_extension_ability/ui_extension.h b/interfaces/kits/native/ability/native/ui_extension_ability/ui_extension.h index 6274ded001b..c14f42fc880 100755 --- a/interfaces/kits/native/ability/native/ui_extension_ability/ui_extension.h +++ b/interfaces/kits/native/ability/native/ui_extension_ability/ui_extension.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -81,6 +81,14 @@ public: virtual void OnInsightIntentExecuteDone(const sptr &sessionInfo, const AppExecFwk::InsightIntentExecuteResult &result) override; + void OnConfigurationUpdated(const AppExecFwk::Configuration& configuration) override; + + virtual void ConfigurationUpdated(); + + virtual void OnAbilityConfigurationUpdated(const AppExecFwk::Configuration &configuration); + + void RegisterAbilityConfigUpdateCallback(); + protected: virtual void ForegroundWindow(const AAFwk::Want &want, const sptr &sessionInfo); virtual void BackgroundWindow(const sptr &sessionInfo); diff --git a/interfaces/kits/native/ability/native/ui_extension_callback.h b/interfaces/kits/native/ability/native/ui_extension_callback.h new file mode 100644 index 00000000000..354ef685323 --- /dev/null +++ b/interfaces/kits/native/ability/native/ui_extension_callback.h @@ -0,0 +1,46 @@ +/* + * 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_UI_EXTENSION_CALLBACK_H +#define OHOS_ABILITY_RUNTIME_UI_EXTENSION_CALLBACK_H + +#include + +#include "want.h" + +namespace OHOS { +namespace Ace { +class UIContent; +} +namespace AbilityRuntime { +class UIExtensionCallback { +public: + UIExtensionCallback() = default; + virtual ~UIExtensionCallback() = default; + virtual void OnError(int32_t number) = 0; + virtual void OnResult(int32_t resultCode, const AAFwk::Want &want) = 0; + void OnRelease(int32_t code); + void SetSessionId(int32_t sessionId); + void SetUIContent(Ace::UIContent *uiContent); + void CloseModalUIExtension(); + void OnRequestSuccess(const std::string& name); + void OnRequestFailure(const std::string& name, int32_t failureCode, const std::string& failureMessage); +private: + int32_t sessionId_ = 0; + Ace::UIContent *uiContent_ = nullptr; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_UI_EXTENSION_CALLBACK_H diff --git a/interfaces/kits/native/ability/native/ui_service_extension_ability/ui_service_extension_context.h b/interfaces/kits/native/ability/native/ui_service_extension_ability/ui_service_extension_context.h index 8891e989682..1d6da435bb5 100644 --- a/interfaces/kits/native/ability/native/ui_service_extension_ability/ui_service_extension_context.h +++ b/interfaces/kits/native/ability/native/ui_service_extension_ability/ui_service_extension_context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -68,8 +68,8 @@ public: * @brief Start a new ability using type; * @return errCode ERR_OK on success, others on failure. */ - ErrCode StartAbilityByType(const std::string &type, - AAFwk::WantParams &wantParam, const std::shared_ptr &uiExtensionCallbacks); + ErrCode StartAbilityByType(const std::string &type, AAFwk::WantParams &wantParam, + std::shared_ptr uiExtensionCallback); /** * @brief Connects the current ServiceExtensionAbility to an ability using 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 c8f6cde637c..6f7c7c43be3 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 @@ -34,7 +34,7 @@ public: static AbilityStage *Create( const std::unique_ptr& runtime, const AppExecFwk::HapModuleInfo& hapModuleInfo); - ETSAbilityStage(ETSRuntime &etsRuntime, std::unique_ptr &&ETSAbilityStageObj); + ETSAbilityStage(ETSRuntime &etsRuntime, std::unique_ptr &&etsAbilityStageObj); ~ETSAbilityStage() override; void Init(const std::shared_ptr &context, @@ -44,8 +44,13 @@ public: void OnDestroy() const override; + std::string OnAcceptWant(const AAFwk::Want &want) override; + + std::string OnNewProcessRequest(const AAFwk::Want &want) override; + void OnConfigurationUpdated(const AppExecFwk::Configuration &configuration) override; + void OnMemoryLevel(int32_t level) override; private: bool CallObjectMethod(bool withResult, const char *name, const char *signature, ...) const; diff --git a/test/unittest/frameworks_kits_ability_ability_runtime_test/ability_context_impl_test.cpp b/test/unittest/frameworks_kits_ability_ability_runtime_test/ability_context_impl_test.cpp index a36706463ce..7160b0c601b 100644 --- a/test/unittest/frameworks_kits_ability_ability_runtime_test/ability_context_impl_test.cpp +++ b/test/unittest/frameworks_kits_ability_ability_runtime_test/ability_context_impl_test.cpp @@ -27,6 +27,7 @@ #include "hilog_tag_wrapper.h" #include "iability_callback.h" #include "ipc_object_stub.h" +#include "js_ui_extension_callback.h" #include "mock_context.h" #include "mock_lifecycle_observer.h" #include "mock_serviceability_manager_service.h" diff --git a/test/unittest/frameworks_kits_ability_ability_runtime_test/ability_context_test.cpp b/test/unittest/frameworks_kits_ability_ability_runtime_test/ability_context_test.cpp index d75cd75a1ae..2cf84324cb5 100644 --- a/test/unittest/frameworks_kits_ability_ability_runtime_test/ability_context_test.cpp +++ b/test/unittest/frameworks_kits_ability_ability_runtime_test/ability_context_test.cpp @@ -476,7 +476,7 @@ public: return nullptr; } virtual ErrCode StartAbilityByType(const std::string &type, AAFwk::WantParams &wantParam, - const std::shared_ptr &uiExtensionCallbacks) + std::shared_ptr uiExtensionCallback) { return ERR_OK; } diff --git a/test/unittest/frameworks_kits_ability_native_test/BUILD.gn b/test/unittest/frameworks_kits_ability_native_test/BUILD.gn index 7b965dc47b4..3aa30f9ceec 100644 --- a/test/unittest/frameworks_kits_ability_native_test/BUILD.gn +++ b/test/unittest/frameworks_kits_ability_native_test/BUILD.gn @@ -3212,6 +3212,7 @@ ohos_unittest("js_ui_extension_Callback_test") { sources = [ "${ability_runtime_native_path}/ability/native/js_ui_extension_callback.cpp", + "${ability_runtime_native_path}/ability/native/ui_extension_callback.cpp", "js_ui_extension_Callback_test.cpp", ] diff --git a/test/unittest/ui_service_extension_test/ui_service_extension_test.cpp b/test/unittest/ui_service_extension_test/ui_service_extension_test.cpp index 7d28ad3a565..4f41dbac2e5 100644 --- a/test/unittest/ui_service_extension_test/ui_service_extension_test.cpp +++ b/test/unittest/ui_service_extension_test/ui_service_extension_test.cpp @@ -21,6 +21,7 @@ #include "ui_service_extension_module_loader.h" #include "ui_service_extension_context.h" #include "ability_manager_client.h" +#include "js_ui_extension_callback.h" #undef private #undef protected -- Gitee