diff --git a/bundle.json b/bundle.json index 578a705eb6285b7870b0d7d8a92ec7e6891e87f4..828e84bca031c863226a8af5fb53f3c19a08cc58 100644 --- a/bundle.json +++ b/bundle.json @@ -128,8 +128,11 @@ "//foundation/ability/ability_runtime/frameworks/c/ability_runtime:ability_runtime", "//foundation/ability/ability_runtime/frameworks/cj:cj_ability_packages", "//foundation/ability/ability_runtime/frameworks/js/napi:napi_packages", + "//foundation/ability/ability_runtime/frameworks/ets/ani:ani_packages", + "//foundation/ability/ability_runtime/frameworks/ets/ets:ets_packages", "//foundation/ability/ability_runtime/cj_environment/frameworks/cj_environment:cj_environment", "//foundation/ability/ability_runtime/js_environment/frameworks/js_environment:js_environment", + "//foundation/ability/ability_runtime/sts_environment/frameworks/sts_environment:sts_environment", "//foundation/ability/ability_runtime/services/abilitymgr/etc:appfwk_etc", "//foundation/ability/ability_runtime/services/dialog_ui/ams_system_dialog:dialog_hap", "//foundation/ability/ability_runtime/service_router_framework:srms_target", @@ -248,6 +251,15 @@ }, "name": "//foundation/ability/ability_runtime/js_environment/frameworks/js_environment:js_environment" }, + { + "header": { + "header_base": "//foundation/ability/ability_runtime/sts_environment/interfaces/inner_api", + "header_files": [ + "sts_environment.h" + ] + }, + "name": "//foundation/ability/ability_runtime/sts_environment/frameworks/sts_environment:sts_environment" + }, { "header": { "header_base": "//foundation/ability/ability_runtime/cj_environment/interfaces/inner_api", @@ -262,7 +274,8 @@ "header_base": "//foundation/ability/ability_runtime/interfaces/inner_api/runtime/include/", "header_files": [ "js_runtime.h", - "runtime.h" + "runtime.h", + "sts_runtime.h" ] }, "name": "//foundation/ability/ability_runtime/interfaces/inner_api/runtime:runtime" @@ -276,6 +289,15 @@ }, "name": "//foundation/ability/ability_runtime/interfaces/inner_api/napi_base_context:napi_base_context" }, + { + "header": { + "header_base": "//foundation/ability/ability_runtime/interfaces/inner_api/ani_base_context/include", + "header_files": [ + "ani_base_context.h" + ] + }, + "name": "//foundation/ability/ability_runtime/interfaces/inner_api/ani_base_context:ani_base_context" + }, { "header": { "header_base": "//foundation/ability/ability_runtime/frameworks/js/napi/inner/napi_common", @@ -288,6 +310,20 @@ }, "name": "//foundation/ability/ability_runtime/frameworks/js/napi/inner/napi_common:napi_common" }, + { + "header": { + "header_base": "//foundation/ability/ability_runtime/frameworks/ets/ani/ani_common/include", + "header_files": [ + "ani_common_ability_result.h", + "ani_common_ability_state_data.h", + "ani_common_configuration.h", + "ani_common_start_options.h", + "ani_common_util.h", + "ani_common_want.h" + ] + }, + "name": "//foundation/ability/ability_runtime/frameworks/ets/ani/ani_common:ani_common" + }, { "header": { "header_base": "//foundation/ability/ability_runtime/frameworks/js/napi/inner/napi_ability_common", @@ -296,6 +332,15 @@ }, "name": "//foundation/ability/ability_runtime/frameworks/js/napi/inner/napi_ability_common:napi_ability_common" }, + { + "header": { + "header_base": "//foundation/ability/ability_runtime/frameworks/ets/ani/ani_wantagent_common", + "header_files": [ + "ani_common_want_agent.h" + ] + }, + "name": "//foundation/ability/ability_runtime/frameworks/ets/ani/ani_wantagent_common:ani_wantagent_common" + }, { "header": { "header_base": "//foundation/ability/ability_runtime/frameworks/js/napi/inner/napi_wantagent_common", @@ -613,7 +658,8 @@ "//foundation/ability/ability_runtime/tools/test:unittest", "//foundation/ability/ability_runtime/cj_environment/test/unittest:unittest", "//foundation/ability/ability_runtime/js_environment/test/unittest:unittest", - "//foundation/ability/ability_runtime/service_router_framework:test_target" + "//foundation/ability/ability_runtime/service_router_framework:test_target", + "//foundation/ability/ability_runtime/sts_environment/test/unittest:unittest" ] } } diff --git a/frameworks/cj/ffi/BUILD.gn b/frameworks/cj/ffi/BUILD.gn index 6a877424cd2aa3f91809672c32e514b1c95c5ea5..9b93d02fbe8852740ae8a2d0a53d5ac8b45a9557 100644 --- a/frameworks/cj/ffi/BUILD.gn +++ b/frameworks/cj/ffi/BUILD.gn @@ -66,6 +66,7 @@ ohos_shared_library("cj_ability_ffi") { "napi:ace_napi", "napi:cj_bind_ffi", "napi:cj_bind_native", + "runtime_core:ani", ] sources = [ diff --git a/frameworks/ets/ani/BUILD.gn b/frameworks/ets/ani/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..4bccd1b37cae1e4f74949455b0920dd1010e1650 --- /dev/null +++ b/frameworks/ets/ani/BUILD.gn @@ -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("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +group("ani_packages") { + deps = [ + "${ability_runtime_path}/frameworks/ets/ani/ability_delegator:ability_delegator_registry_ani_kit", + "${ability_runtime_path}/frameworks/ets/ani/ability_manager:ability_ability_manager_ani_kit", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_path}/frameworks/ets/ani/ani_wantagent_common:ani_wantagent_common", + "${ability_runtime_path}/frameworks/ets/ani/app/ability_stage_context:ability_stage_context_ani_kit", + "${ability_runtime_path}/frameworks/ets/ani/app/application_context:application_context_ani_kit", + "${ability_runtime_path}/frameworks/ets/ani/app/context:context_ani_kit", + "${ability_runtime_path}/frameworks/ets/ani/app_manager:ability_app_manager_ani_kit", + "${ability_runtime_path}/frameworks/ets/ani/form_extension_ability:form_extension_ability_etc", + "${ability_runtime_path}/frameworks/ets/ani/insight_intent/insight_intent_driver:insight_intent_driver_ani_kit", + "${ability_runtime_path}/frameworks/ets/ani/native_constructor:context_ani", + "${ability_runtime_path}/frameworks/ets/ani/uri_permission_manager:uri_permission_manager_abc_etc", + "${ability_runtime_path}/frameworks/ets/ani/uri_permission_manager:uri_permission_manager_ani_kit", + "${ability_runtime_path}/frameworks/ets/ani/wantagent:aniwantagent", + "${ability_runtime_path}/frameworks/ets/ani/application:application_ani", + ] +} \ No newline at end of file diff --git a/frameworks/ets/ani/ability_delegator/BUILD.gn b/frameworks/ets/ani/ability_delegator/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d711786523b0ffc34bf674ca2a9e90366ddb886f --- /dev/null +++ b/frameworks/ets/ani/ability_delegator/BUILD.gn @@ -0,0 +1,83 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("ability_delegator_registry_ani_kit") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/ability_delegator/include", + "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/interfaces/kits/native/ability/native", + "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", + "${ability_runtime_path}/frameworks/js/napi/app/ability_delegator", + "${ability_runtime_path}/interfaces/inner_api/runtime/include", + ] + + configs = [] + + public_configs = [] + + sources = [ + "./src/ets_ability_delegator.cpp", + "./src/ets_ability_delegator_registry.cpp", + "./src/ets_ability_delegator_utils.cpp", + "./src/ets_ability_monitor.cpp", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/ability_manager:ability_start_options", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_native_path}/appkit:app_context_utils", + "${ability_runtime_native_path}/appkit:appkit_delegator", + "${ability_runtime_native_path}/appkit:delegator_mgmt", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] + + external_deps = [ + "ability_base:want", + "bundle_framework:appexecfwk_base", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "eventhandler:libeventhandler", + "hilog:libhilog", + "ipc:ipc_core", + "json:nlohmann_json_static", + "napi:ace_napi", + "runtime_core:ani", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator.h b/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator.h new file mode 100644 index 0000000000000000000000000000000000000000..87b05936a13803511e1b4f28dae66092d55d2ebc --- /dev/null +++ b/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator.h @@ -0,0 +1,131 @@ +/* +* 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_DELEGATOR_H +#define OHOS_ABILITY_RUNTIME_ETS_ABILITY_DELEGATOR_H + +#include +#include "ability_delegator.h" +#include "context.h" +#include "ets_ability_stage_monitor.h" +#include "ets_ability_delegator_registry.h" +#include "ets_ability_monitor.h" +#include "iability_monitor.h" +#include "sts_runtime.h" +#include "want.h" +namespace OHOS { +namespace AbilityDelegatorEts { +using namespace OHOS::AbilityRuntime; +class EtsAbilityDelegator { +public: + static EtsAbilityDelegator& GetInstance() + { + static EtsAbilityDelegator instance; + return instance; + } + EtsAbilityDelegator(); + ~EtsAbilityDelegator(); + static void ExecuteShellCommand(ani_env* env, [[maybe_unused]]ani_object object, + ani_string cmd, ani_double timeoutSecs, ani_object callback); + + static void FinishTest(ani_env* env, [[maybe_unused]]ani_object object, + ani_string msg, ani_double code, ani_object callback); + + static ani_object CreateEtsBaseContext(ani_env* aniEnv, ani_class contextClass, + std::shared_ptr context); + + static ani_object GetAppContext(ani_env* env, [[maybe_unused]]ani_object object, ani_class clss); + + static void PrintSync(ani_env *env, [[maybe_unused]]ani_class aniClass, ani_string msg); + + static void AddAbilityMonitor(ani_env *env, [[maybe_unused]]ani_class aniClass, + ani_object monitorObj, ani_object callback); + + static void AddAbilityMonitorSync(ani_env* env, [[maybe_unused]]ani_class aniClass, ani_object monitorObj); + + static void RemoveAbilityMonitor(ani_env* env, [[maybe_unused]]ani_class aniClass, + ani_object monitorObj, ani_object callback); + + 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); + + static void AddAbilityStageMonitor(ani_env* env, [[maybe_unused]]ani_class aniClass, + ani_object stageMonitorObj, ani_object callback); + + static void AddAbilityStageMonitorSync(ani_env* env, [[maybe_unused]]ani_class aniClass, + ani_object stageMonitorObj); + + static void RemoveAbilityStageMonitor(ani_env* env, [[maybe_unused]]ani_class aniClass, + ani_object stageMonitorObj, ani_object callback); + + static void RemoveAbilityStageMonitorSync(ani_env* env, [[maybe_unused]]ani_class aniClass, + ani_object stageMonitorObj); + + static void WaitAbilityStageMonitor(ani_env* env, [[maybe_unused]]ani_class aniClass, + ani_object stageMonitorObj, ani_double timeout, ani_object callback); + + static void DoAbilityForeground(ani_env* env, [[maybe_unused]]ani_object object, + ani_object abilityObj, ani_object callback); + + static void DoAbilityBackground(ani_env* env, [[maybe_unused]]ani_object object, + ani_object abilityObj, ani_object callback); + + 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 void StartAbility(ani_env* env, [[maybe_unused]]ani_object object, ani_object wantObj, ani_object callback); + + static ani_ref GetCurrentTopAbility(ani_env* env, ani_object callback); + +private: + [[maybe_unused]] void RetrieveStringFromAni(ani_env *env, ani_string string, std::string &resString); + + ani_object WrapShellCmdResult(ani_env* env, std::unique_ptr result); + + bool ParseMonitorPara(ani_env *env, ani_object monitorObj, + std::shared_ptr &monitorImpl); + + bool ParseMonitorParaInner(ani_env *env, ani_object monitorObj, + std::shared_ptr &monitorImpl); + + bool ParseStageMonitorPara(ani_env *env, ani_object stageMonitorObj, + std::shared_ptr &stageMonitor, bool &isExisted); + + bool ParseStageMonitorParaInner(ani_env *env, ani_object stageMonitorObj, + std::shared_ptr &stageMonitor); + + void AddStageMonitorRecord(ani_env *env, ani_object stageMonitorObj, + const std::shared_ptr &stageMonitor); + + void RemoveStageMonitorRecord(ani_env *env, ani_object stageMonitorObj); + + bool ParseWaitAbilityStageMonitorPara(ani_env *env, ani_object stageMonitorObj, + std::shared_ptr &stageMonitor); + + bool ParseAbilityCommonPara(ani_env *env, ani_object abilityObj, sptr &remoteObject); + + void AbilityLifecycleStateToEts(const AbilityDelegator::AbilityState &lifeState, + AbilityLifecycleState &abilityLifeState); + + bool CheckPropertyValue(ani_env *env, int &resultCode, ani_object &resultAniOj, + std::shared_ptr etsProperty); +}; +} // namespace AbilityDelegatorEts +} // namespace OHOS + +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_DELEGATOR_H diff --git a/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator_registry.h b/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator_registry.h new file mode 100644 index 0000000000000000000000000000000000000000..9834a32d94679742cdcce93eb7e68272a65495db --- /dev/null +++ b/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator_registry.h @@ -0,0 +1,48 @@ +/* + * 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_DELEGATOR_REGISTRY_H +#define OHOS_ABILITY_RUNTIME_ETS_ABILITY_DELEGATOR_REGISTRY_H + +#include "sts_runtime.h" + +namespace OHOS { +namespace AbilityDelegatorEts { +enum class AbilityLifecycleState { + /** + * Indicates that the ability has not been initialized. + */ + UNINITIALIZED, + /** + * Indicates that the ability is in the created state. + */ + CREATE, + /** + * Indicates that the ability is in the foreground state. + */ + FOREGROUND, + /** + * Indicates that the ability is in the background state. + */ + BACKGROUND, + /** + * Indicates that the ability is in the destroyed state. + */ + DESTROY, +}; +void EtsAbilityDelegatorRegistryInit(ani_env *env); +} // namespace AbilityDelegatorEts +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_DELEGATOR_REGISTRY_H diff --git a/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator_utils.h b/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..8d6efc019405870c1a86355c9ae5adf177fcb600 --- /dev/null +++ b/frameworks/ets/ani/ability_delegator/include/ets_ability_delegator_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_ABILITY_DELEGATOR_UTILS_H +#define OHOS_ABILITY_RUNTIME_ETS_ABILITY_DELEGATOR_UTILS_H + +#include "ability_delegator.h" +#include "ability_delegator_args.h" +#include "sts_runtime.h" + +namespace OHOS { +namespace AbilityDelegatorEts { +ani_object CreateEtsAbilityDelegator(ani_env *env); +ani_object CreateEtsAbilityDelegatorArguments(ani_env *env, + const std::shared_ptr abilityDelegatorArgs); +} // namespace AbilityDelegatorEts +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_DELEGATOR_UTILS_H diff --git a/frameworks/ets/ani/ability_delegator/include/ets_ability_monitor.h b/frameworks/ets/ani/ability_delegator/include/ets_ability_monitor.h new file mode 100644 index 0000000000000000000000000000000000000000..dc2b333e23601ba81b51d7e7717ba7ac859aa293 --- /dev/null +++ b/frameworks/ets/ani/ability_delegator/include/ets_ability_monitor.h @@ -0,0 +1,140 @@ +/* + * 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_MONITOR_H +#define OHOS_ABILITY_RUNTIME_ETS_ABILITY_MONITOR_H + +#include +#include +#include "iability_monitor.h" +#include "sts_runtime.h" + +namespace OHOS { +namespace AbilityDelegatorEts { +class EtsAbilityMonitor : public AppExecFwk::IAbilityMonitor { +public: + /** + * A constructor used to create a EtsAbilityMonitor instance with the input parameter passed. + * + * @param abilityName Indicates the specified ability name for monitoring the lifecycle state changes + * of the ability. + */ + explicit EtsAbilityMonitor(const std::string &abilityName); + + /** + * A constructor used to create a EtsAbilityMonitor instance with the input parameter passed. + * + * @param abilityName Indicates the specified ability name for monitoring the lifecycle state changes + * of the ability. + * + * @param moduleName Indicates the specified module name for monitoring the lifecycle state changes + * of the ability. + */ + explicit EtsAbilityMonitor(const std::string &abilityName, const std::string &moduleName); + + /** + * Default deconstructor used to deconstruct. + */ + ~EtsAbilityMonitor() = default; + + /** + * Called when ability is started. + * Then call the corresponding method on the ets side through the saved ets object. + * + * @param abilityObj Indicates the ability object. + */ + void OnAbilityStart(const std::weak_ptr &abilityObj) override; + + /** + * Called when ability is in foreground. + * Then call the corresponding method on the ets side through the saved ets object. + * + * @param abilityObj Indicates the ability object. + */ + void OnAbilityForeground(const std::weak_ptr &abilityObj) override; + + /** + * Called when ability is in background. + * Then call the corresponding method on the ets side through the saved ets object. + * + * @param abilityObj Indicates the ability object. + */ + void OnAbilityBackground(const std::weak_ptr &abilityObj) override; + + /** + * Called when ability is stopped. + * Then call the corresponding method on the ets side through the saved ets object. + * + * @param abilityObj Indicates the ability object. + */ + void OnAbilityStop(const std::weak_ptr &abilityObj) override; + + /** + * Called when window stage is created. + * Then call the corresponding method on the ets side through the saved ets object. + * + * @param abilityObj Indicates the ability object. + */ + void OnWindowStageCreate(const std::weak_ptr &abilityObj) override; + + /** + * Called when window stage is restored. + * Then call the corresponding method on the ets side through the saved ets object. + * + * @param abilityObj Indicates the ability object. + */ + void OnWindowStageRestore(const std::weak_ptr &abilityObj) override; + + /** + * Called when window stage is destroyed. + * Then call the corresponding method on the ets side through the saved ets object. + * + * @param abilityObj Indicates the ability object. + */ + void OnWindowStageDestroy(const std::weak_ptr &abilityObj) override; + + /** + * Sets the ets object. + * + * @param abilityMonitorObj Indicates the ets object. + */ + void SetEtsAbilityMonitor(ani_env *env, ani_object &abilityMonitorObj); + + /** + * Obtains the saved ets object. + * + * @return the saved ets object. + */ + std::unique_ptr &GetEtsAbilityMonitor() + { + return EtsAbilityMonitor_; + } + +private: + void CallLifecycleCBFunction(const std::string &functionName, + const std::shared_ptr &abilityObj); + ani_env* GetAniEnv(); + std::shared_ptr GetRuntimeObject( + const std::weak_ptr &abilityObj); + +private: + ani_vm* vm_ = nullptr; + std::string abilityName_ = ""; + std::string moduleName_ = ""; + std::unique_ptr EtsAbilityMonitor_ = nullptr; +}; +} // namespace AbilityDelegatorJs +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_MONITOR_H diff --git a/frameworks/ets/ani/ability_delegator/include/ets_ability_stage_monitor.h b/frameworks/ets/ani/ability_delegator/include/ets_ability_stage_monitor.h new file mode 100644 index 0000000000000000000000000000000000000000..e25197e2781f8f5f4ca742a85ad69c31efea4ddc --- /dev/null +++ b/frameworks/ets/ani/ability_delegator/include/ets_ability_stage_monitor.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_ABILITY_STAGE_MONITOR_H +#define OHOS_ABILITY_RUNTIME_ETS_ABILITY_STAGE_MONITOR_H + +#include "iability_stage_monitor.h" + +namespace OHOS { +namespace AbilityDelegatorEts { +using namespace OHOS::AppExecFwk; +class EtsAbilityStageMonitor : public IAbilityStageMonitor { +public: + /** + * A constructor used to create a AbilityStageMonitor instance with the input parameter passed. + * + * @param moduleName Indicates the specified module name. + * @param srcEntrance Indicates the abilityStage source path. + */ + EtsAbilityStageMonitor(const std::string &moduleName, const std::string &srcEntrance) + : IAbilityStageMonitor(moduleName, srcEntrance) {} + + /** + * Default deconstructor used to deconstruct. + */ + ~EtsAbilityStageMonitor() = default; +}; +} // namespace AbilityDelegatorEts +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_STAGE_MONITOR_H diff --git a/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator.cpp b/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d9a2829c6748bb5515996b042a8b56654039f3ae --- /dev/null +++ b/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator.cpp @@ -0,0 +1,1271 @@ +/* + * 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_delegator.h" + +#include "ability_delegator_registry.h" +#include "ability_stage_monitor.h" +#include "ani_common_want.h" +#include "ani_enum_convert.h" +#include "ets_ability_monitor.h" +#include "ets_ability_stage_monitor.h" +#include "hilog_tag_wrapper.h" +#include "shell_cmd_result.h" +#include "sts_context_utils.h" +#include "sts_error_utils.h" +#include +#include +namespace OHOS { +namespace AbilityDelegatorEts { + +using namespace OHOS::AbilityRuntime; + +std::map, std::shared_ptr> g_monitorRecord; +std::map, std::shared_ptr> g_stageMonitorRecord; +std::map, sptr, std::owner_less<>> g_abilityRecord; +std::mutex g_mtxMonitorRecord; +std::mutex g_mtxStageMonitorRecord; +std::mutex g_mutexAbilityRecord; + +enum ERROR_CODE { + INCORRECT_PARAMETERS = 401, +}; + +#ifdef ENABLE_ERRCODE +constexpr int COMMON_FAILED = 16000100; +#else +constexpr int COMMON_FAILED = -1; +#endif + +namespace { +constexpr const char* AREA_MODE_ENUM_NAME = "L@ohos/app/ability/contextConstant/contextConstant/AreaMode;"; +constexpr const char* CONTEXT_CLASS_NAME = "Lapplication/Context/Context;"; +constexpr const char* SHELL_CMD_RESULT_CLASS_NAME = "Lapplication/shellCmdResult/ShellCmdResultImpl;"; +constexpr const char* ABILITY_MONITOR_INNER_CLASS_NAME = "Lapplication/AbilityMonitor/AbilityMonitorInner;"; +constexpr const char* ABILITY_STAGE_MONITOR_INNER_CLASS_NAME = + "Lapplication/AbilityStageMonitor/AbilityStageMonitorInner;"; +constexpr const char* ABILITY_STAGE_CLASS_NAME = "L@ohos/app/ability/AbilityStage/AbilityStage;"; +} + +EtsAbilityDelegator::EtsAbilityDelegator() +{ + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (delegator) { + auto clearFunc = [](const std::shared_ptr &baseProperty) { + auto property = std::static_pointer_cast(baseProperty); + if (!property) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid property type"); + return; + } + + std::unique_lock lck(g_mutexAbilityRecord); + for (auto it = g_abilityRecord.begin(); it != g_abilityRecord.end();) { + if (it->second == property->token_) { + it = g_abilityRecord.erase(it); + continue; + } + ++it; + } + }; + + delegator->RegisterClearFunc(clearFunc); + } +} + +EtsAbilityDelegator::~EtsAbilityDelegator() = default; + +ani_object EtsAbilityDelegator::CreateEtsBaseContext(ani_env* aniEnv, ani_class contextClass, + std::shared_ptr context) +{ + if (aniEnv == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv or context"); + return {}; + } + ani_object contextObj = nullptr; + ani_method method = nullptr; + ani_status status = aniEnv->Class_FindMethod(contextClass, "", ":V", &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod ctor failed status: %{public}d", status); + return {}; + } + if ((status = aniEnv->Object_New(contextClass, method, &contextObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_New failed status: %{public}d", status); + return {}; + } + ani_field areaField; + if (aniEnv->Class_FindField(contextClass, "area", &areaField) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "find area failed"); + return {}; + } + ani_enum_item areaModeItem {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvertNativeToSts(aniEnv, + AREA_MODE_ENUM_NAME, context->GetArea(), areaModeItem); + if (aniEnv->Object_SetField_Ref(contextObj, areaField, (ani_ref)areaModeItem) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_SetField_Int failed"); + return {}; + } + ani_field filesDirField; + if (aniEnv->Class_FindField(contextClass, "filesDir", &filesDirField) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "find filesDir failed"); + return {}; + } + auto filesDir = context->GetFilesDir(); + ani_string filesDir_string{}; + aniEnv->String_NewUTF8(filesDir.c_str(), filesDir.size(), &filesDir_string); + if (aniEnv->Object_SetField_Ref(contextObj, filesDirField, reinterpret_cast(filesDir_string)) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_SetField_Ref failed"); + return {}; + } + ani_field tempDirField; + if (aniEnv->Class_FindField(contextClass, "tempDir", &tempDirField) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "find find tempDir failed"); + return {}; + } + auto tempDir = context->GetTempDir(); + ani_string tempDir_string{}; + aniEnv->String_NewUTF8(tempDir.c_str(), tempDir.size(), &tempDir_string); + if (aniEnv->Object_SetField_Ref(contextObj, tempDirField, reinterpret_cast(tempDir_string)) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_SetField_Ref failed"); + return {}; + } + ContextUtil::BindApplicationInfo(aniEnv, contextClass, contextObj, context); + ContextUtil::BindResourceManager(aniEnv, contextClass, contextObj, context); + return contextObj; +} + +ani_object EtsAbilityDelegator::WrapShellCmdResult(ani_env* env, std::unique_ptr result) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "WrapShellCmdResult called"); + if (result == nullptr || env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "result or env is null"); + return {}; + } + 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 {}; + } + 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 {}; + } + 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 {}; + } + TAG_LOGD(AAFwkTag::DELEGATOR, "Object_New success"); + ani_field filed; + status = env->Class_FindField(cls, "stdResult", &filed); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindField failed status: %{public}d", status); + } + ani_string aniStringVal {}; + std::string strResult = result->GetStdResult(); + status = env->String_NewUTF8(strResult.c_str(), strResult.size(), &aniStringVal); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "String_NewUTF8 failed status: %{public}d", status); + } + status = env->Object_SetField_Ref(object, filed, aniStringVal); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "set strResult failed status: %{public}d", status); + } + int32_t exitCode = result->GetExitCode(); + status = env->Object_SetPropertyByName_Double(object, "exitCode", exitCode); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "set exitCode failed status: %{public}d", status); + } + return object; +} + +ani_object EtsAbilityDelegator::GetAppContext(ani_env* env, [[maybe_unused]]ani_object object, ani_class clss) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "GetAppContext call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return {}; + } + ani_class cls; + ani_object nullobj = nullptr; + if (ANI_OK != env->FindClass(CONTEXT_CLASS_NAME, &cls)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "FindClass Context Failed"); + return nullobj; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (!delegator) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + return nullobj; + } + std::shared_ptr context = delegator->GetAppContext(); + if (!context) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null context"); + return nullobj; + } + ani_object objectContext = CreateEtsBaseContext(env, cls, context); + TAG_LOGD(AAFwkTag::DELEGATOR, "GetAppContext end"); + return objectContext; +} + +void EtsAbilityDelegator::ExecuteShellCommand(ani_env *env, [[maybe_unused]]ani_object object, + ani_string cmd, ani_double timeoutSecs, ani_object callback) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "ExecuteShellCommand called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null env"); + return; + } + std::string stdCmd = ""; + if (!OHOS::AppExecFwk::GetStdString(env, cmd, stdCmd)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "GetStdString Failed"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (!delegator) { + TAG_LOGE(AAFwkTag::DELEGATOR, "delegator is nullptr"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + int resultCode = 0; + auto result = delegator->ExecuteShellCommand(stdCmd, static_cast(timeoutSecs)); + ani_object objValue = GetInstance().WrapShellCmdResult(env, std::move(result)); + if (objValue == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null objValue"); + resultCode = COMMON_FAILED; + ani_class cls = nullptr; + ani_status status = env->FindClass(SHELL_CMD_RESULT_CLASS_NAME, &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "find AbilityDelegator failed status: %{public}d", status); + } + ani_method method = nullptr; + status = env->Class_FindMethod(cls, "", ":V", &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod ctor failed status: %{public}d", status); + } + if (env->Object_New(cls, method, &objValue) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_New failed status: %{public}d", status); + } + } + ani_ref callbackRef = nullptr; + ani_status createStatus = env->GlobalReference_Create(callback, &callbackRef); + if (createStatus != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", createStatus); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), + objValue); + return; +} + +void EtsAbilityDelegator::FinishTest(ani_env* env, [[maybe_unused]]ani_object object, + ani_string msg, ani_double code, ani_object callback) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null env"); + return; + } + std::string stdMsg = ""; + if (!OHOS::AppExecFwk::GetStdString(env, msg, stdMsg)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "GetStdString Failed"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return; + } + int resultCode = 0; + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (!delegator) { + TAG_LOGE(AAFwkTag::DELEGATOR, "FinishTest delegator is null"); + resultCode = COMMON_FAILED; + } else { + delegator->FinishUserTest(stdMsg, static_cast(code)); + } + ani_ref callbackRef = nullptr; + auto status = env->GlobalReference_Create(callback, &callbackRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", status); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), + nullptr); + TAG_LOGD(AAFwkTag::DELEGATOR, "FinishTest END"); + return; +} + +void EtsAbilityDelegator::PrintSync(ani_env *env, [[maybe_unused]]ani_class aniClass, ani_string msg) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "PrintSync"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + std::string msgStr; + ani_size sz {}; + env->String_GetUTF8Size(msg, &sz); + msgStr.resize(sz + 1); + env->String_GetUTF8SubString(msg, 0, sz, msgStr.data(), msgStr.size(), &sz); + TAG_LOGD(AAFwkTag::DELEGATOR, "PrintSync %{public}s", msgStr.c_str()); + + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + return; + } + + delegator->Print(msgStr); + return; +} + +void EtsAbilityDelegator::RetrieveStringFromAni(ani_env *env, ani_string str, std::string &res) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + ani_size sz {}; + ani_status status = ANI_ERROR; + if ((status = env->String_GetUTF8Size(str, &sz)) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "status: %{public}d", status); + return; + } + res.resize(sz + 1); + if ((status = env->String_GetUTF8SubString(str, 0, sz, res.data(), res.size(), &sz)) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "status: %{public}d", status); + return; + } + res.resize(sz); +} + +void EtsAbilityDelegator::AddAbilityMonitor(ani_env *env, [[maybe_unused]]ani_class aniClass, + ani_object monitorObj, ani_object callback) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + std::shared_ptr monitorImpl = nullptr; + if (!GetInstance().ParseMonitorPara(env, monitorObj, monitorImpl)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "ParseMonitorPara failed"); + AbilityRuntime::ThrowStsError(env, INCORRECT_PARAMETERS, + "Parse param monitor failed, monitor must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + int resultCode = 0; + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + resultCode = COMMON_FAILED; + } else { + delegator->AddAbilityMonitor(monitorImpl); + } + ani_ref callbackRef = nullptr; + ani_status status = env->GlobalReference_Create(callback, &callbackRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Create Gloabl ref for delegator failed %{public}d", status); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), + nullptr); + return; +} + +void EtsAbilityDelegator::AddAbilityMonitorSync(ani_env* env, [[maybe_unused]]ani_class aniClass, ani_object monitorObj) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "AddAbilityMonitorSync"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + std::shared_ptr monitorImpl = nullptr; + if (!GetInstance().ParseMonitorPara(env, monitorObj, monitorImpl)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "ParseMonitorPara failed"); + AbilityRuntime::ThrowStsError(env, INCORRECT_PARAMETERS, + "Parse param monitor failed, monitor must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (delegator) { + delegator->AddAbilityMonitor(monitorImpl); + } else { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + AbilityRuntime::ThrowStsError(env, COMMON_FAILED, "Calling AddAbilityMonitorSync failed."); + } + return; +} + +void EtsAbilityDelegator::StartAbility(ani_env* env, [[maybe_unused]]ani_object object, + ani_object wantObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "StartAbility"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "UnwrapWant failed"); + AbilityRuntime::ThrowStsError(env, (int32_t)AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM, + "Parse want failed, want must be Want."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + AbilityRuntime::ThrowStsError(env, COMMON_FAILED); + return; + } + int resultCode = 0; + int result = delegator->StartAbility(want); + if (result != ERR_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "start ability failed: %{public}d", result); + resultCode = result; + } + ani_ref callbackRef = nullptr; + auto status = env->GlobalReference_Create(callback, &callbackRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", status); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), + nullptr); + return; +} + +ani_ref EtsAbilityDelegator::GetCurrentTopAbility(ani_env* env, ani_object callback) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "called"); + ani_object objValue = nullptr; + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + int32_t resultCode = 0; + if (delegator != nullptr) { + auto property = delegator->GetCurrentTopAbility(); + auto etsbaseProperty = std::static_pointer_cast(property); + if (!etsbaseProperty || etsbaseProperty->object_.expired()) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid property"); + resultCode = COMMON_FAILED; + } else { + std::unique_lock lck(g_mutexAbilityRecord); + g_abilityRecord.emplace(etsbaseProperty->object_, etsbaseProperty->token_); + objValue = etsbaseProperty->object_.lock()->aniObj; + } + } + ani_ref callbackRef = nullptr; + auto status = env->GlobalReference_Create(callback, &callbackRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", status); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), objValue); + return objValue; +} + +void EtsAbilityDelegator::RemoveAbilityMonitor(ani_env* env, [[maybe_unused]]ani_class aniClass, + ani_object monitorObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "RemoveAbilityMonitor called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + std::shared_ptr monitorImpl = nullptr; + if (!GetInstance().ParseMonitorPara(env, monitorObj, monitorImpl)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "ParseMonitorPara failed"); + AbilityRuntime::ThrowStsError(env, INCORRECT_PARAMETERS, + "Parse monitor failed, removeAbilityMonitor must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + int resultCode = 0; + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + resultCode = COMMON_FAILED; + } else { + delegator->RemoveAbilityMonitor(monitorImpl); + std::unique_lock lck(g_mtxMonitorRecord); + for (auto iter = g_monitorRecord.begin(); iter != g_monitorRecord.end(); ++iter) { + std::shared_ptr etsMonitor = iter->first; + ani_boolean result = false; + ani_status status = env->Reference_StrictEquals(reinterpret_cast(monitorObj), + reinterpret_cast(etsMonitor->aniObj), &result); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Reference_StrictEquals failed status: %{public}d", status); + } + if (result) { + g_monitorRecord.erase(iter); + break; + } + } + } + ani_ref callbackRef = nullptr; + auto status = env->GlobalReference_Create(callback, &callbackRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed: %{public}d", status); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), + nullptr); + return; +} + +void EtsAbilityDelegator::RemoveAbilityMonitorSync(ani_env* env, [[maybe_unused]]ani_class aniClass, + ani_object monitorObj) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "RemoveAbilityMonitorSync called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + std::shared_ptr monitorImpl = nullptr; + if (!GetInstance().ParseMonitorPara(env, monitorObj, monitorImpl)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "ParseMonitorPara failed"); + AbilityRuntime::ThrowStsError(env, INCORRECT_PARAMETERS, + "Parse monitor failed, RemoveAbilityMonitorSync must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + AbilityRuntime::ThrowStsError(env, COMMON_FAILED, "Calling RemoveAbilityMonitorSync failed."); + return; + } + delegator->RemoveAbilityMonitor(monitorImpl); + { + std::unique_lock lck(g_mtxMonitorRecord); + for (auto iter = g_monitorRecord.begin(); iter != g_monitorRecord.end(); ++iter) { + std::shared_ptr etsMonitor = iter->first; + ani_boolean result = false; + ani_status status = env->Reference_StrictEquals(reinterpret_cast(monitorObj), + reinterpret_cast(etsMonitor->aniObj), &result); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Reference_StrictEquals failed status: %{public}d", status); + } + if (result) { + g_monitorRecord.erase(iter); + break; + } + } + } + return; +} + +void EtsAbilityDelegator::WaitAbilityMonitor(ani_env* env, [[maybe_unused]]ani_class aniClass, + ani_object monitorObj, ani_double timeout, ani_object callback) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "WaitAbilityMonitor called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + std::shared_ptr monitorImpl = nullptr; + if (!GetInstance().ParseMonitorPara(env, monitorObj, monitorImpl)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::ThrowStsError(env, INCORRECT_PARAMETERS, + "Parse monitor want failed, WaitAbilityMonitor must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + std::shared_ptr property = (static_cast(timeout) > 0) ? + delegator->WaitAbilityMonitor(monitorImpl, static_cast(timeout)) : + delegator->WaitAbilityMonitor(monitorImpl); + int resultCode = 0; + ani_object resultAniOj = nullptr; + auto etsbaseProperty = std::static_pointer_cast(property); + if (!etsbaseProperty || etsbaseProperty->object_.expired()) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid etsbaseProperty"); + resultCode = COMMON_FAILED; + } else { + std::unique_lock lck(g_mutexAbilityRecord); + g_abilityRecord.emplace(etsbaseProperty->object_, etsbaseProperty->token_); + resultAniOj = etsbaseProperty->object_.lock()->aniObj; + } + ani_ref callbackRef = nullptr; + auto status = env->GlobalReference_Create(callback, &callbackRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", status); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), + resultAniOj); + return; +} + +void EtsAbilityDelegator::AddAbilityStageMonitor(ani_env* env, [[maybe_unused]]ani_class aniClass, + ani_object stageMonitorObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "AddAbilityStageMonitor called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + bool isExisted = false; + std::shared_ptr stageMonitor = nullptr; + if (!GetInstance().ParseStageMonitorPara(env, stageMonitorObj, stageMonitor, isExisted)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::ThrowStsError(env, INCORRECT_PARAMETERS, + "Parse parameters failed, monitor must be Monitor and isExited must be boolean."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + int resultCode = 0; + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + resultCode = COMMON_FAILED; + } else { + delegator->AddAbilityStageMonitor(stageMonitor); + if (!isExisted) { + GetInstance().AddStageMonitorRecord(env, stageMonitorObj, stageMonitor); + } + ani_ref callbackRef = nullptr; + auto status = env->GlobalReference_Create(callback, &callbackRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", status); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), + nullptr); + } + return; +} + +void EtsAbilityDelegator::AddAbilityStageMonitorSync(ani_env* env, [[maybe_unused]]ani_class aniClass, + ani_object stageMonitorObj) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "AddAbilityStageMonitorSync called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + bool isExisted = false; + std::shared_ptr stageMonitor = nullptr; + if (!GetInstance().ParseStageMonitorPara(env, stageMonitorObj, stageMonitor, isExisted)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::ThrowStsError(env, INCORRECT_PARAMETERS, + "Parse parameters failed, monitor must be Monitor and isExited must be boolean."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (delegator) { + delegator->AddAbilityStageMonitor(stageMonitor); + if (!isExisted) { + GetInstance().AddStageMonitorRecord(env, stageMonitorObj, stageMonitor); + } + } else { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + AbilityRuntime::ThrowStsError(env, COMMON_FAILED, "Calling AddAbilityStageMonitorSync failed."); + } + return; +} + +void EtsAbilityDelegator::RemoveAbilityStageMonitor(ani_env* env, [[maybe_unused]]ani_class aniClass, + ani_object stageMonitorObj, ani_object callback) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "RemoveAbilityStageMonitor called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + bool isExisted = false; + std::shared_ptr stageMonitor = nullptr; + if (!GetInstance().ParseStageMonitorPara(env, stageMonitorObj, stageMonitor, isExisted)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::ThrowStsError(env, INCORRECT_PARAMETERS, + "Parse monitor failed, removeAbilityMonitor must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + int resultCode = 0; + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + resultCode = COMMON_FAILED; + } else { + delegator->RemoveAbilityStageMonitor(stageMonitor); + } + ani_ref callbackRef = nullptr; + auto status = env->GlobalReference_Create(callback, &callbackRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", status); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), + nullptr); + if (isExisted) { + GetInstance().RemoveStageMonitorRecord(env, stageMonitorObj); + } + return; +} + +void EtsAbilityDelegator::RemoveAbilityStageMonitorSync(ani_env* env, [[maybe_unused]]ani_class aniClass, + ani_object stageMonitorObj) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "RemoveAbilityStageMonitorSync called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + bool isExisted = false; + std::shared_ptr stageMonitor = nullptr; + if (!GetInstance().ParseStageMonitorPara(env, stageMonitorObj, stageMonitor, isExisted)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::ThrowStsError(env, INCORRECT_PARAMETERS, + "Parse monitor failed, removeAbilityMonitor must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (delegator) { + delegator->RemoveAbilityStageMonitor(stageMonitor); + } else { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + AbilityRuntime::ThrowStsError(env, COMMON_FAILED, "Calling RemoveAbilityStageMonitorSync failed."); + } + + if (isExisted) { + GetInstance().RemoveStageMonitorRecord(env, stageMonitorObj); + } + return; +} + +void EtsAbilityDelegator::WaitAbilityStageMonitor(ani_env* env, [[maybe_unused]]ani_class aniClass, + ani_object stageMonitorObj, ani_double timeout, ani_object callback) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "WaitAbilityStageMonitor called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + std::shared_ptr stageMonitor = nullptr; + if (!GetInstance().ParseWaitAbilityStageMonitorPara(env, stageMonitorObj, stageMonitor)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::ThrowStsError(env, INCORRECT_PARAMETERS, + "Parse monitor failed, removeAbilityMonitor must be Monitor."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (!delegator) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + std::shared_ptr result; + result = (static_cast(timeout) > 0) ? + delegator->WaitAbilityStageMonitor(stageMonitor, static_cast(timeout)) : + delegator->WaitAbilityStageMonitor(stageMonitor); + int resultCode = 0; + ani_object resultAniOj = nullptr; + auto etsbaseProperty = std::static_pointer_cast(result); + if (GetInstance().CheckPropertyValue(env, resultCode, resultAniOj, etsbaseProperty)) { + resultAniOj = etsbaseProperty->object_.lock()->aniObj; + } + ani_ref callbackRef = nullptr; + ani_status createStatus = env->GlobalReference_Create(callback, &callbackRef); + if (createStatus != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", createStatus); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), + resultAniOj); + return; +} + +void EtsAbilityDelegator::DoAbilityForeground(ani_env* env, [[maybe_unused]]ani_object object, + ani_object abilityObj, ani_object callback) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "DoAbilityForeground called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + sptr remoteObject = nullptr; + if (!GetInstance().ParseAbilityCommonPara(env, abilityObj, remoteObject)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::ThrowStsError(env, INCORRECT_PARAMETERS, + "Parse remoteObject failed, remoteObject must be RemoteObject."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + int resultCode = 0; + if (!delegator) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + resultCode = COMMON_FAILED; + } else { + if (!delegator->DoAbilityForeground(remoteObject)) { + resultCode = COMMON_FAILED; + } + } + ani_ref callbackRef = nullptr; + ani_status createStatus = env->GlobalReference_Create(callback, &callbackRef); + if (createStatus != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", createStatus); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), + nullptr); + return; +} + +void EtsAbilityDelegator::DoAbilityBackground(ani_env* env, [[maybe_unused]]ani_object object, + ani_object abilityObj, ani_object callback) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "DoAbilityBackground called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + sptr remoteObject = nullptr; + if (!GetInstance().ParseAbilityCommonPara(env, abilityObj, remoteObject)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + AbilityRuntime::ThrowStsError(env, INCORRECT_PARAMETERS, + "Parse remoteObject failed, remoteObject must be RemoteObject."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + int resultCode = 0; + if (!delegator) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + resultCode = COMMON_FAILED; + } else { + if (!delegator->DoAbilityBackground(remoteObject)) { + resultCode = COMMON_FAILED; + } + } + ani_ref callbackRef = nullptr; + ani_status createStatus = env->GlobalReference_Create(callback, &callbackRef); + if (createStatus != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", createStatus); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), + nullptr); + return; +} + +void EtsAbilityDelegator::Print(ani_env* env, [[maybe_unused]]ani_object object, + ani_string msg, ani_object callback) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "Print called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + std::string strMsg = ""; + if (!OHOS::AppExecFwk::GetStdString(env, msg, strMsg)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "GetStdString Failed"); + AbilityRuntime::ThrowStsError(env, INCORRECT_PARAMETERS, + "Parse msg failed, msg must be string."); + return; + } + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + int resultCode = 0; + if (!delegator) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + resultCode = COMMON_FAILED; + } else { + delegator->Print(strMsg); + } + ani_ref callbackRef = nullptr; + ani_status createStatus = env->GlobalReference_Create(callback, &callbackRef); + if (createStatus != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Create Gloabl ref for delegator failed %{public}d", createStatus); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), + nullptr); + return; +} + +ani_double EtsAbilityDelegator::GetAbilityState(ani_env* env, [[maybe_unused]]ani_object object, ani_object abilityObj) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "GetAbilityState called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return COMMON_FAILED; + } + sptr remoteObject = nullptr; + if (!GetInstance().ParseAbilityCommonPara(env, abilityObj, remoteObject)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + return COMMON_FAILED; + } + + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (!delegator) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + return COMMON_FAILED; + } + AbilityDelegator::AbilityState lifeState = delegator->GetAbilityState(remoteObject); + AbilityLifecycleState abilityLifeState = AbilityLifecycleState::UNINITIALIZED; + GetInstance().AbilityLifecycleStateToEts(lifeState, abilityLifeState); + int res = static_cast(abilityLifeState); + return res; +} + +void EtsAbilityDelegator::AbilityLifecycleStateToEts( + const AbilityDelegator::AbilityState &lifeState, AbilityLifecycleState &abilityLifeState) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "lifeState: %{public}d", static_cast(lifeState)); + switch (lifeState) { + case AbilityDelegator::AbilityState::STARTED: + abilityLifeState = AbilityLifecycleState::CREATE; + break; + case AbilityDelegator::AbilityState::FOREGROUND: + abilityLifeState = AbilityLifecycleState::FOREGROUND; + break; + case AbilityDelegator::AbilityState::BACKGROUND: + abilityLifeState = AbilityLifecycleState::BACKGROUND; + break; + case AbilityDelegator::AbilityState::STOPPED: + abilityLifeState = AbilityLifecycleState::DESTROY; + break; + default: + abilityLifeState = AbilityLifecycleState::UNINITIALIZED; + break; + } +} + +bool EtsAbilityDelegator::ParseMonitorPara(ani_env *env, ani_object monitorObj, + std::shared_ptr &monitorImpl) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "monitorRecord size: %{public}zu", g_monitorRecord.size()); + if (env == nullptr || monitorObj == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env or monitorObj is nullptr"); + return false; + } + { + std::unique_lock lck(g_mtxMonitorRecord); + for (auto iter = g_monitorRecord.begin(); iter != g_monitorRecord.end(); ++iter) { + std::shared_ptr etsMonitor = iter->first; + ani_boolean result = false; + ani_status status = env->Reference_StrictEquals(reinterpret_cast(monitorObj), + reinterpret_cast(etsMonitor->aniObj), &result); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Reference_StrictEquals failed status: %{public}d", status); + } + if (result) { + monitorImpl = iter->second; + return monitorImpl ? true : false; + } + } + } + if (!ParseMonitorParaInner(env, monitorObj, monitorImpl)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "ParseMonitorParaInner failed"); + return false; + } + return true; +} + +bool EtsAbilityDelegator::ParseMonitorParaInner(ani_env *env, ani_object monitorObj, + std::shared_ptr &monitorImpl) +{ + if (env == nullptr || monitorObj == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env or monitorObj is nullptr"); + return false; + } + ani_class monitorCls; + ani_status status = env->FindClass(ABILITY_MONITOR_INNER_CLASS_NAME, &monitorCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "FindClass failed status: %{public}d", status); + return false; + } + ani_ref moduleNameRef; + status = env->Object_GetPropertyByName_Ref(monitorObj, "moduleName", &moduleNameRef); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_GetField_Ref "); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return false; + } + std::string strModuleName; + ani_string aniModuleString = static_cast(moduleNameRef); + GetInstance().RetrieveStringFromAni(env, aniModuleString, strModuleName); + ani_ref abilityNameRef; + status = env->Object_GetPropertyByName_Ref(monitorObj, "abilityName", &abilityNameRef); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_GetField_Ref "); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return false; + } + std::string strAbilityName; + ani_string aniAbilityName = static_cast(abilityNameRef); + GetInstance().RetrieveStringFromAni(env, aniAbilityName, strAbilityName); + + std::shared_ptr abilityMonitor = nullptr; + if (strModuleName.empty()) { + abilityMonitor = std::make_shared(strAbilityName); + abilityMonitor->SetEtsAbilityMonitor(env, monitorObj); + } else { + abilityMonitor = std::make_shared(strAbilityName, strModuleName); + abilityMonitor->SetEtsAbilityMonitor(env, monitorObj); + } + monitorImpl = abilityMonitor; + std::shared_ptr reference = std::make_shared(); + if (reference != nullptr) { + reference->aniObj = monitorObj; + } + std::unique_lock lck(g_mtxMonitorRecord); + g_monitorRecord.emplace(reference, monitorImpl); + return true; +} + +bool EtsAbilityDelegator::ParseStageMonitorPara(ani_env *env, ani_object stageMonitorObj, + std::shared_ptr &stageMonitor, bool &isExisted) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "stageMonitorRecord size: %{public}zu", g_stageMonitorRecord.size()); + if (env == nullptr || stageMonitorObj == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env or stageMonitorObj is nullptr"); + return false; + } + isExisted = false; + { + std::unique_lock lck(g_mtxStageMonitorRecord); + for (auto iter = g_stageMonitorRecord.begin(); iter != g_stageMonitorRecord.end(); ++iter) { + std::shared_ptr etsMonitor = iter->first; + ani_boolean result = false; + if (etsMonitor == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "etsMonitor is nullptr"); + } + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + } + ani_status status = env->Reference_StrictEquals(reinterpret_cast(stageMonitorObj), + reinterpret_cast(etsMonitor->aniObj), &result); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Reference_StrictEquals failed status: %{public}d", status); + } + if (result) { + TAG_LOGW(AAFwkTag::DELEGATOR, "abilityStage monitor exist"); + isExisted = true; + stageMonitor = iter->second; + return stageMonitor ? true : false; + } + } + } + if (!ParseStageMonitorParaInner(env, stageMonitorObj, stageMonitor)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "ParseStageMonitorParaInner failed"); + return false; + } + return true; +} + +bool EtsAbilityDelegator::ParseStageMonitorParaInner(ani_env *env, ani_object stageMonitorObj, + std::shared_ptr &stageMonitor) +{ + if (env == nullptr || stageMonitorObj == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env or stageMonitorObj is nullptr"); + return false; + } + ani_class monitorCls; + ani_status status = env->FindClass(ABILITY_STAGE_MONITOR_INNER_CLASS_NAME, &monitorCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "FindClass failed status: %{public}d", status); + return false; + } + ani_ref moduleNameRef; + status = env->Object_GetPropertyByName_Ref(stageMonitorObj, "moduleName", &moduleNameRef); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_GetField_Ref failed status: %{public}d", status); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return false; + } + std::string strModuleName; + ani_string aniModuleString = static_cast(moduleNameRef); + GetInstance().RetrieveStringFromAni(env, aniModuleString, strModuleName); + TAG_LOGD(AAFwkTag::DELEGATOR, "strModuleName %{public}s ", strModuleName.c_str()); + ani_ref srcEntranceRef; + status = env->Object_GetPropertyByName_Ref(stageMonitorObj, "srcEntrance", &srcEntranceRef); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_GetField_Ref "); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return false; + } + std::string srcEntrance; + ani_string aniSrcEntranceRef = static_cast(srcEntranceRef); + GetInstance().RetrieveStringFromAni(env, aniSrcEntranceRef, srcEntrance); + TAG_LOGD(AAFwkTag::DELEGATOR, "srcEntrance %{public}s ", srcEntrance.c_str()); + stageMonitor = std::make_shared(strModuleName, srcEntrance); + return true; +} + +void EtsAbilityDelegator::AddStageMonitorRecord(ani_env *env, ani_object stageMonitorObj, + const std::shared_ptr &stageMonitor) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "AddStageMonitorRecord called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + if (!AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + return; + } + std::shared_ptr reference = nullptr; + ani_ref objRef = nullptr; + ani_status status = env->GlobalReference_Create(stageMonitorObj, &objRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "GlobalReference_Create failed status: %{public}d", status); + return; + } + reference.reset(reinterpret_cast(objRef)); + { + std::unique_lock lck(g_mtxStageMonitorRecord); + if (reference == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null reference"); + } + if (stageMonitor == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null reference"); + } + TAG_LOGE(AAFwkTag::DELEGATOR, "Add g_stageMonitorRecord test"); + g_stageMonitorRecord.emplace(reference, stageMonitor); + } + TAG_LOGI(AAFwkTag::DELEGATOR, "end, size: %{public}zu", g_stageMonitorRecord.size()); +} + +void EtsAbilityDelegator::RemoveStageMonitorRecord(ani_env *env, ani_object stageMonitorObj) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return; + } + if (!AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + return; + } + std::unique_lock lck(g_mtxStageMonitorRecord); + for (auto iter = g_stageMonitorRecord.begin(); iter != g_stageMonitorRecord.end(); ++iter) { + std::shared_ptr etsMonitor = iter->first; + ani_boolean result = false; + ani_status status = env->Reference_StrictEquals(reinterpret_cast(stageMonitorObj), + reinterpret_cast(etsMonitor->aniObj), &result); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Reference_StrictEquals failed status: %{public}d", status); + } + if (result) { + g_stageMonitorRecord.erase(iter); + TAG_LOGI(AAFwkTag::DELEGATOR, "end, size: %{public}zu", g_stageMonitorRecord.size()); + break; + } + } +} + +bool EtsAbilityDelegator::ParseWaitAbilityStageMonitorPara(ani_env *env, ani_object stageMonitorObj, + std::shared_ptr &stageMonitor) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "ParseWaitAbilityStageMonitorPara called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return false; + } + bool isExisted = false; + if (!ParseStageMonitorPara(env, stageMonitorObj, stageMonitor, isExisted)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid params"); + return false; + } + if (!isExisted) { + AddStageMonitorRecord(env, stageMonitorObj, stageMonitor); + } + return true; +} + +bool EtsAbilityDelegator::ParseAbilityCommonPara(ani_env *env, ani_object abilityObj, + sptr &remoteObject) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "g_abilityRecord size: %{public}zu", g_abilityRecord.size()); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return false; + } + std::unique_lock lck(g_mutexAbilityRecord); + for (auto iter = g_abilityRecord.begin(); iter != g_abilityRecord.end();) { + if (iter->first.expired()) { + iter = g_abilityRecord.erase(iter); + continue; + } + ani_boolean result = false; + ani_status status = env->Reference_StrictEquals(reinterpret_cast(iter->first.lock()->aniObj), + reinterpret_cast(abilityObj), &result); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Reference_StrictEquals failed status: %{public}d", status); + } + if (result) { + remoteObject = iter->second; + TAG_LOGI(AAFwkTag::DELEGATOR, "ability exist"); + return remoteObject ? true : false; + } + ++iter; + } + TAG_LOGE(AAFwkTag::DELEGATOR, "ability not exist"); + remoteObject = nullptr; + return false; +} + +bool EtsAbilityDelegator::CheckPropertyValue(ani_env *env, int &resultCode, ani_object &resultAniOj, + std::shared_ptr etsProperty) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "env is nullptr"); + return false; + } + if (!etsProperty || etsProperty->object_.expired()) { + TAG_LOGE(AAFwkTag::DELEGATOR, "waitAbilityStageMonitor failed"); + resultCode = COMMON_FAILED; + ani_class cls = nullptr; + ani_status status = env->FindClass(ABILITY_STAGE_CLASS_NAME, &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "find AbilityDelegator failed status: %{public}d", status); + } + ani_method method = nullptr; + status = env->Class_FindMethod(cls, "", ":V", &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod ctor failed status: %{public}d", status); + } + if (env->Object_New(cls, method, &resultAniOj) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_New failed status: %{public}d", status); + } + return false; + } + return true; +} +} // namespace AbilityDelegatorEts +} // namespace OHOS diff --git a/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator_registry.cpp b/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator_registry.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f24752fe8ff311ad9663619355034e2cfa5d970c --- /dev/null +++ b/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator_registry.cpp @@ -0,0 +1,144 @@ +/* + * 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_delegator_registry.h" + +#include +#include "ability_delegator.h" +#include "ability_delegator_registry.h" +#include "ets_ability_delegator.h" +#include "ets_ability_delegator_utils.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityDelegatorEts { +std::unique_ptr etsReference; +std::mutex etsReferenceMutex; + +static ani_object GetAbilityDelegator(ani_env *env, [[maybe_unused]]ani_class aniClass) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null env"); + return {}; + } + + std::lock_guard lock(etsReferenceMutex); + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (delegator == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); + return {}; + } + + if (etsReference == nullptr) { + ani_object value = CreateEtsAbilityDelegator(env); + if (value == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "value is nullptr"); + return {}; + } + ani_boolean isValue; + env->Reference_IsNullishValue(value, &isValue); + if (isValue) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Reference_IsNullishValue"); + return {}; + } + etsReference = std::make_unique(); + ani_ref result; + 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 {}; + } + etsReference->aniObj = static_cast(result); + return etsReference->aniObj; + } else { + return etsReference->aniObj; + } +} + +static ani_object GetArguments(ani_env *env, [[maybe_unused]]ani_class aniClass) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null env"); + return {}; + } + + auto abilityDelegatorArgs = AppExecFwk::AbilityDelegatorRegistry::GetArguments(); + if (abilityDelegatorArgs == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "get argument failed"); + return {}; + } + + return CreateEtsAbilityDelegatorArguments(env, abilityDelegatorArgs); +} + +void EtsAbilityDelegatorRegistryInit(ani_env *env) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "EtsAbilityDelegatorRegistryInit call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null env"); + return; + } + ani_status status = ANI_ERROR; + if (env->ResetError() != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "ResetError failed"); + } + + ani_namespace ns; + status = env->FindNamespace("L@ohos/app/ability/abilityDelegatorRegistry/abilityDelegatorRegistry;", &ns); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "FindNamespace abilityDelegatorRegistry failed status: %{public}d", status); + return; + } + + std::array kitFunctions = { + ani_native_function {"getAbilityDelegator", nullptr, reinterpret_cast(GetAbilityDelegator)}, + ani_native_function {"getArguments", nullptr, reinterpret_cast(GetArguments)}, + }; + + status = env->Namespace_BindNativeFunctions(ns, kitFunctions.data(), kitFunctions.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Namespace_BindNativeFunctions failed status: %{public}d", status); + } + + if (env->ResetError() != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "ResetError failed"); + } + TAG_LOGD(AAFwkTag::DELEGATOR, "EtsAbilityDelegatorRegistryInit end"); +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "ANI_Constructor"); + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if (vm == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null vm"); + return ANI_ERROR; + } + status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "GetEnv failed status: %{public}d", status); + return ANI_NOT_FOUND; + } + + EtsAbilityDelegatorRegistryInit(env); + *result = ANI_VERSION_1; + TAG_LOGD(AAFwkTag::DELEGATOR, "ANI_Constructor finish"); + return ANI_OK; +} +} +} // namespace AbilityDelegatorEts +} // namespace OHOS 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 new file mode 100644 index 0000000000000000000000000000000000000000..e1ee4887856d0ad960ecccd200de2ed53a959a21 --- /dev/null +++ b/frameworks/ets/ani/ability_delegator/src/ets_ability_delegator_utils.cpp @@ -0,0 +1,331 @@ +/* + * 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_delegator_utils.h" + +#include +#include "ets_ability_delegator.h" +#include "hilog_tag_wrapper.h" + + +namespace OHOS { +namespace AbilityDelegatorEts { +namespace { +constexpr const char* ABILITY_DELEGATOR_CLASS_NAME = "Lapplication/AbilityDelegator/AbilityDelegatorInner;"; +constexpr const char* RECORD_CLASS_NAME = "Lescompat/Record;"; +constexpr const char* ARGS_ABILITY_DELEGATOR_CLASS_NAME = + "Lapplication/abilityDelegatorArgs/AbilityDelegatorArgsInner;"; +} + +bool BindFunctions(ani_env *aniEnv, ani_class abilityDelegator) +{ + if (aniEnv == nullptr) { + return false; + } + std::array functions = { + ani_native_function {"getAppContext", nullptr, reinterpret_cast(EtsAbilityDelegator::GetAppContext)}, + ani_native_function {"nativeExecuteShellCommand", nullptr, + reinterpret_cast(EtsAbilityDelegator::ExecuteShellCommand)}, + ani_native_function {"nativeFinishTest", nullptr, reinterpret_cast(EtsAbilityDelegator::FinishTest)}, + ani_native_function {"printSync", nullptr, reinterpret_cast(EtsAbilityDelegator::PrintSync)}, + ani_native_function {"nativeAddAbilityMonitor", nullptr, + reinterpret_cast(EtsAbilityDelegator::AddAbilityMonitor)}, + ani_native_function {"addAbilityMonitorSync", nullptr, + reinterpret_cast(EtsAbilityDelegator::AddAbilityMonitorSync)}, + ani_native_function {"removeAbilityMonitorAsync", nullptr, + reinterpret_cast(EtsAbilityDelegator::RemoveAbilityMonitor)}, + ani_native_function {"removeAbilityMonitorSync", nullptr, + reinterpret_cast(EtsAbilityDelegator::RemoveAbilityMonitorSync)}, + ani_native_function {"waitAbilityMonitorAsync", nullptr, + reinterpret_cast(EtsAbilityDelegator::WaitAbilityMonitor)}, + ani_native_function {"addAbilityStageMonitorAsync", nullptr, + reinterpret_cast(EtsAbilityDelegator::AddAbilityStageMonitor)}, + ani_native_function {"addAbilityStageMonitorSync", nullptr, + reinterpret_cast(EtsAbilityDelegator::AddAbilityStageMonitorSync)}, + ani_native_function {"removeAbilityStageMonitorAsync", nullptr, + reinterpret_cast(EtsAbilityDelegator::RemoveAbilityStageMonitor)}, + ani_native_function {"removeAbilityStageMonitorSync", nullptr, + reinterpret_cast(EtsAbilityDelegator::RemoveAbilityStageMonitorSync)}, + ani_native_function {"waitAbilityStageMonitorAsync", nullptr, + reinterpret_cast(EtsAbilityDelegator::WaitAbilityStageMonitor)}, + ani_native_function {"doAbilityForegroundAsync", nullptr, + reinterpret_cast(EtsAbilityDelegator::DoAbilityForeground)}, + ani_native_function {"doAbilityBackgroundAsync", nullptr, + reinterpret_cast(EtsAbilityDelegator::DoAbilityBackground)}, + ani_native_function {"printAsync", nullptr, reinterpret_cast(EtsAbilityDelegator::Print)}, + ani_native_function {"getAbilityState", nullptr, + reinterpret_cast(EtsAbilityDelegator::GetAbilityState)}, + ani_native_function {"nativeStartAbility", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsAbilityDelegator::StartAbility)}, + ani_native_function {"nativeGetCurrentTopAbility", nullptr, + reinterpret_cast(EtsAbilityDelegator::GetCurrentTopAbility)} + }; + ani_status status = aniEnv->Class_BindNativeMethods(abilityDelegator, functions.data(), functions.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Class_BindNativeMethods failed status: %{public}d", status); + return false; + } + return true; +} + +ani_object CreateEtsAbilityDelegator(ani_env *aniEnv) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "CreateEtsAbilityDelegator"); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv"); + return {}; + } + 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 {}; + } + TAG_LOGD(AAFwkTag::DELEGATOR, "find AbilityDelegator success"); + + if (!BindFunctions(aniEnv, abilityDelegator)) { + TAG_LOGE(AAFwkTag::DELEGATOR, "BindFunctions failed"); + return {}; + } + + 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 {}; + } + 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 {}; + } + + TAG_LOGD(AAFwkTag::DELEGATOR, "CreateEtsAbilityDelegator success"); + return object; +} + +void SetBundleName(ani_env *aniEnv, ani_class arguments, ani_object argumentObject, const std::string &bundleName) +{ + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv"); + return; + } + ani_status status = ANI_ERROR; + ani_string aniStr; + // Get a ani_string from std::string + status = aniEnv->String_NewUTF8(bundleName.c_str(), bundleName.length(), &aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "String_NewUTF8 failed status: %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::DELEGATOR, "String_NewUTF8 success"); + + // find the setter method + ani_method nameSetter; + status = aniEnv->Class_FindMethod(arguments, "bundleName", nullptr, &nameSetter); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::DELEGATOR, "Class_FindMethod success"); + + // call set bundleName(n:string) + status = aniEnv->Object_CallMethod_Void(argumentObject, nameSetter, aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_CallMethod_Void failed status: %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::DELEGATOR, "Object_CallMethod_Void success"); +} + +void SetParameters(ani_env *aniEnv, ani_class arguments, ani_object argumentObject, + const std::map ¶s) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "SetParameters begin"); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv"); + return; + } + ani_status status = ANI_ERROR; + ani_class recordCls; + status = aniEnv->FindClass(RECORD_CLASS_NAME, &recordCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "FindClass failed status: %{public}d", status); + return; + } + ani_method recordGetMethod; + status = aniEnv->Class_FindMethod(recordCls, "$_get", "Lstd/core/Object;:Lstd/core/Object;", &recordGetMethod); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status); + return; + } + ani_method recordSetMethod; + status = aniEnv->Class_FindMethod(recordCls, "$_set", "Lstd/core/Object;Lstd/core/Object;:V", &recordSetMethod); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status); + return; + } + ani_ref parameterRef; + status = aniEnv->Object_CallMethodByName_Ref(argumentObject, "parameters", ":Lescompat/Record;", + ¶meterRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_CallMethodByName_Ref failed status: %{public}d", status); + return; + } + ani_object parameterObject = static_cast(parameterRef); + for (auto iter = paras.begin(); iter != paras.end(); ++iter) { + std::string key = iter->first; + std::string value = iter->second; + ani_string ani_key; + ani_string ani_value; + status = aniEnv->String_NewUTF8(key.c_str(), key.length(), &ani_key); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "String_NewUTF8 key failed status: %{public}d", status); + return; + } + status = aniEnv->String_NewUTF8(value.c_str(), value.length(), &ani_value); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "String_NewUTF8 value failed status: %{public}d", status); + return; + } + status = aniEnv->Object_CallMethod_Void(parameterObject, recordSetMethod, ani_key, ani_value); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_CallMethod_Void failed status: %{public}d", status); + return; + } + } + TAG_LOGD(AAFwkTag::DELEGATOR, "SetParameters end"); +} + +void SetTestCaseNames(ani_env *aniEnv, ani_class arguments, ani_object argumentObject, const std::string &testcaseNames) +{ + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv"); + return; + } + ani_status status = ANI_ERROR; + ani_string aniStr; + status = aniEnv->String_NewUTF8(testcaseNames.c_str(), testcaseNames.length(), &aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "String_NewUTF8 failed status: %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::DELEGATOR, "String_NewUTF8 success"); + + // find the setter method + ani_method nameSetter; + status = aniEnv->Class_FindMethod(arguments, "testCaseNames", nullptr, &nameSetter); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::DELEGATOR, "Class_FindMethod success"); + + // call set testcaseNames(n:string) + status = aniEnv->Object_CallMethod_Void(argumentObject, nameSetter, aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_CallMethod_Void failed status: %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::DELEGATOR, "Object_CallMethod_Void success"); +} + +void SetTestRunnerClassName(ani_env *aniEnv, ani_class arguments, ani_object argumentObject, + const std::string &className) +{ + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv"); + return; + } + ani_status status = ANI_ERROR; + ani_string aniStr; + status = aniEnv->String_NewUTF8(className.c_str(), className.length(), &aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "String_NewUTF8 failed status: %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::DELEGATOR, "String_NewUTF8 success"); + + // find the setter method + ani_method nameSetter; + status = aniEnv->Class_FindMethod(arguments, "testRunnerClassName", nullptr, &nameSetter); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod failed status: %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::DELEGATOR, "Class_FindMethod success"); + + // call set testRunnerClassName(n:string) + status = aniEnv->Object_CallMethod_Void(argumentObject, nameSetter, aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_CallMethod_Void failed status: %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::DELEGATOR, "Object_CallMethod_Void success"); +} + +ani_object CreateEtsAbilityDelegatorArguments( + ani_env *aniEnv, const std::shared_ptr abilityDelegatorArgs) +{ + TAG_LOGD(AAFwkTag::DELEGATOR, "CreateJsAbilityDelegatorArguments"); + if (aniEnv == nullptr || abilityDelegatorArgs == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null aniEnv or abilityDelegatorArgs"); + return {}; + } + 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 {}; + } + TAG_LOGD(AAFwkTag::DELEGATOR, "find AbilityDelegatorArgs success"); + + ani_method method = nullptr; + status = aniEnv->Class_FindMethod(arguments, "", ":V", &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Class_FindMethod ctor failed status: %{public}d", status); + return {}; + } + TAG_LOGD(AAFwkTag::DELEGATOR, "Class_FindMethod ctor success"); + + ani_object argumentObject = nullptr; + status = aniEnv->Object_New(arguments, method, &argumentObject); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_New failed status: %{public}d", status); + return {}; + } + TAG_LOGD(AAFwkTag::DELEGATOR, "Object_New success"); + + std::string bundleName = abilityDelegatorArgs->GetTestBundleName(); + SetBundleName(aniEnv, arguments, argumentObject, bundleName); + + std::string testcaseName = abilityDelegatorArgs->GetTestCaseName(); + SetTestCaseNames(aniEnv, arguments, argumentObject, testcaseName); + + std::string className = abilityDelegatorArgs->GetTestRunnerClassName(); + SetTestRunnerClassName(aniEnv, arguments, argumentObject, className); + + auto parameters = abilityDelegatorArgs->GetTestParam(); + SetParameters(aniEnv, arguments, argumentObject, parameters); + + return argumentObject; +} +} // namespace AbilityDelegatorEts +} // namespace OHOS diff --git a/frameworks/ets/ani/ability_delegator/src/ets_ability_monitor.cpp b/frameworks/ets/ani/ability_delegator/src/ets_ability_monitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fc1177df867c3b6296b5532ecb25df36cc3c5107 --- /dev/null +++ b/frameworks/ets/ani/ability_delegator/src/ets_ability_monitor.cpp @@ -0,0 +1,195 @@ +/* + * 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 "ability_delegator_registry.h" +#include "ets_ability_monitor.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityDelegatorEts { +using namespace OHOS::AbilityRuntime; +EtsAbilityMonitor::EtsAbilityMonitor(const std::string &abilityName) + : IAbilityMonitor(abilityName), abilityName_(abilityName) +{} + +EtsAbilityMonitor::EtsAbilityMonitor(const std::string &abilityName, const std::string &moduleName) + : IAbilityMonitor(abilityName), abilityName_(abilityName), moduleName_(moduleName) +{} + +void EtsAbilityMonitor::OnAbilityStart(const std::weak_ptr &abilityObj) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "called OnAbilityStart"); + auto runtimeObj = GetRuntimeObject(abilityObj); + if (!runtimeObj) { + return; + } + CallLifecycleCBFunction("onAbilityCreate", runtimeObj); +} + +void EtsAbilityMonitor::OnAbilityForeground(const std::weak_ptr &abilityObj) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "called OnAbilityForeground"); + auto runtimeObj = GetRuntimeObject(abilityObj); + if (!runtimeObj) { + return; + } + CallLifecycleCBFunction("onAbilityForeground", runtimeObj); +} + +void EtsAbilityMonitor::OnAbilityBackground(const std::weak_ptr &abilityObj) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "called OnAbilityBackground"); + auto runtimeObj = GetRuntimeObject(abilityObj); + if (!runtimeObj) { + return; + } + CallLifecycleCBFunction("onAbilityBackground", runtimeObj); +} + +void EtsAbilityMonitor::OnAbilityStop(const std::weak_ptr &abilityObj) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "called OnAbilityStop"); + auto runtimeObj = GetRuntimeObject(abilityObj); + if (!runtimeObj) { + return; + } + CallLifecycleCBFunction("onAbilityDestroy", runtimeObj); +} + +void EtsAbilityMonitor::OnWindowStageCreate(const std::weak_ptr &abilityObj) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "called OnWindowStageCreate"); + auto runtimeObj = GetRuntimeObject(abilityObj); + if (!runtimeObj) { + return; + } + CallLifecycleCBFunction("onWindowStageCreate", runtimeObj); +} + +void EtsAbilityMonitor::OnWindowStageRestore(const std::weak_ptr &abilityObj) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "called OnWindowStageRestore"); + auto runtimeObj = GetRuntimeObject(abilityObj); + if (!runtimeObj) { + return; + } + CallLifecycleCBFunction("onWindowStageRestore", runtimeObj); +} + +void EtsAbilityMonitor::OnWindowStageDestroy(const std::weak_ptr &abilityObj) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "called OnWindowStageDestroy"); + auto runtimeObj = GetRuntimeObject(abilityObj); + if (!runtimeObj) { + return; + } + CallLifecycleCBFunction("onWindowStageDestroy", runtimeObj); +} + +void EtsAbilityMonitor::SetEtsAbilityMonitor(ani_env *env, ani_object &abilityMonitorObj) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "called SetEtsAbilityMonitor"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null env"); + return; + } + EtsAbilityMonitor_ = std::make_unique(); + ani_ref objRef = nullptr; + if (env->GlobalReference_Create(abilityMonitorObj, &objRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "GlobalReference_Create failed"); + return; + } + + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "GetVM failed"); + return; + } + vm_ = aniVM; + if (EtsAbilityMonitor_ == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null EtsAbilityMonitor_"); + return; + } + EtsAbilityMonitor_->aniObj = abilityMonitorObj; + EtsAbilityMonitor_->aniRef = objRef; +} + +void EtsAbilityMonitor::CallLifecycleCBFunction(const std::string &functionName, + const std::shared_ptr &abilityObj) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "CallLifecycleCBFunction, name: %{public}s start", functionName.c_str()); + if (functionName.empty()) { + TAG_LOGE(AAFwkTag::DELEGATOR, "empty funcName"); + return; + } + + if (abilityObj == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null EtsAbilityMonitor"); + return; + } + + ani_env *env = GetAniEnv(); + if (env == nullptr || EtsAbilityMonitor_ == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null env or EtsAbilityMonitor_"); + return; + } + + ani_status status = ANI_OK; + ani_object monitorObj = reinterpret_cast(EtsAbilityMonitor_->aniRef); + ani_ref funRef; + status = env->Object_GetPropertyByName_Ref(monitorObj, functionName.c_str(), &funRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_GetField_Ref failed status: %{public}d", status); + return; + } + + ani_fn_object onFn = reinterpret_cast(funRef); + ani_ref resutlt; + std::vector argv = { abilityObj->aniRef }; + if ((status = env->FunctionalObject_Call(onFn, 1, argv.data(), &resutlt)) != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "FunctionalObject_Call failed, status: %{public}d", status); + return; + } +} + +ani_env* EtsAbilityMonitor::GetAniEnv() +{ + if (vm_ == nullptr) { + return nullptr; + } + ani_env* aniEnv = nullptr; + if (vm_->GetEnv(ANI_VERSION_1, &aniEnv) != ANI_OK) { + return nullptr; + } + return aniEnv; +} + +std::shared_ptr EtsAbilityMonitor::GetRuntimeObject( + const std::weak_ptr &abilityObj) +{ + auto baseProperty = abilityObj.lock(); + if (!baseProperty) { + TAG_LOGE(AAFwkTag::DELEGATOR, "abilityObj is expired"); + return nullptr; + } + auto etsbaseProperty = std::static_pointer_cast(baseProperty); + auto runtimeObj = etsbaseProperty->object_.lock(); + if (!runtimeObj) { + TAG_LOGE(AAFwkTag::DELEGATOR, "runtimeObj is nullptr"); + return nullptr; + } + return runtimeObj; +} +} // namespace AbilityDelegatorJs +} // namespace OHOS diff --git a/frameworks/ets/ani/ability_manager/BUILD.gn b/frameworks/ets/ani/ability_manager/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..fedaa89c1c00b27b8891e796b271b8f18e6ce01c --- /dev/null +++ b/frameworks/ets/ani/ability_manager/BUILD.gn @@ -0,0 +1,78 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("ability_ability_manager_ani_kit") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", + "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/interfaces/kits/native/ability/native", + "${ability_runtime_path}/interfaces/inner_api/runtime/include", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", + ] + + configs = [] + + public_configs = [] + + sources = [ + "./src/sts_ability_manager.cpp", + "./src/sts_ability_manager_utils.cpp", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/app_manager:app_manager", + "${ability_runtime_innerkits_path}/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}/appkit:app_context", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] + + external_deps = [ + "ability_base:base", + "ability_base:configuration", + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "ipc:ipc_core", + "ipc:ipc_napi", + "napi:ace_napi", + "runtime_core:ani", + "samgr:samgr_proxy", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/ability_manager/include/sts_ability_manager.h b/frameworks/ets/ani/ability_manager/include/sts_ability_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..a04a51bd1bdc6d721db514df29284f2116930a1f --- /dev/null +++ b/frameworks/ets/ani/ability_manager/include/sts_ability_manager.h @@ -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. + */ + +#ifndef OHOS_ABILITY_RUNTIME_STS_ABILITY_MANAGER_H +#define OHOS_ABILITY_RUNTIME_STS_ABILITY_MANAGER_H + +#include "sts_runtime.h" +#include "ability_running_info.h" + +namespace OHOS { +namespace AbilityManagerSts { +void StsAbilityManagerRegistryInit(ani_env *env); + +class StsAbilityManager final { +public: + static StsAbilityManager &GetInstance() + { + static StsAbilityManager instance; + return instance; + } + static void GetAbilityRunningInfos(ani_env *env, ani_object callback); +}; +} // namespace AbilityManagerSts +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_ABILITY_MANAGER_H diff --git a/frameworks/ets/ani/ability_manager/include/sts_ability_manager_utils.h b/frameworks/ets/ani/ability_manager/include/sts_ability_manager_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..294769ed7a52a579f538d62232ac4b9648637e27 --- /dev/null +++ b/frameworks/ets/ani/ability_manager/include/sts_ability_manager_utils.h @@ -0,0 +1,36 @@ +/* + * 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_STS_ABILITY_MANAGER_UTILS_H +#define OHOS_ABILITY_RUNTIME_STS_ABILITY_MANAGER_UTILS_H + +#include "ability_running_info.h" +#include "extension_running_info.h" +#include "sts_runtime.h" + +namespace OHOS { +namespace AbilityManagerSts { +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 AbilityManagerSts +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_ABILITY_MANAGER_UTILS_H \ No newline at end of file diff --git a/frameworks/ets/ani/ability_manager/src/sts_ability_manager.cpp b/frameworks/ets/ani/ability_manager/src/sts_ability_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7759ce7b8ef6e8600c38c21d84da825c23055893 --- /dev/null +++ b/frameworks/ets/ani/ability_manager/src/sts_ability_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 "sts_ability_manager.h" + +#include "ability_manager_client.h" +#include "ability_business_error.h" +#include "ability_manager_errors.h" +#include "ability_runtime_error_util.h" +#include "ani_common_ability_state_data.h" +#include "ani_common_want.h" +#include "hilog_tag_wrapper.h" +#include "ability_manager_interface.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "sts_ability_manager_utils.h" +#include "sts_error_utils.h" +#include "system_ability_definition.h" + +namespace OHOS { +namespace AbilityManagerSts { + +constexpr int32_t ERR_FAILURE = -1; + +sptr GetAbilityManagerInstance() +{ + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + sptr abilityManagerObj = + systemAbilityManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + return iface_cast(abilityManagerObj); +} + +static ani_object GetForegroundUIAbilities(ani_env *env) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "call GetForegroundUIAbilities"); + + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return nullptr; + } + + sptr abilityManager = GetAbilityManagerInstance(); + if (abilityManager == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityManager is null"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return nullptr; + } + std::vector list; + int32_t ret = abilityManager->GetForegroundUIAbilities(list); + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "failed: ret=%{public}d", ret); + AbilityRuntime::AbilityErrorCode code = AbilityRuntime::GetJsErrorCodeByNativeError(ret); + AbilityRuntime::ThrowStsError(env, code); + return nullptr; + } + TAG_LOGD(AAFwkTag::ABILITYMGR, "GetForegroundUIAbilities succeeds, list.size=%{public}zu", list.size()); + ani_object aniArray = AppExecFwk::CreateAniAbilityStateDataArray(env, list); + if (aniArray == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null aniArray"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return nullptr; + } + return aniArray; +} + +static void GetTopAbility(ani_env *env, ani_object callback) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "call GetTopAbility"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return; + } +#ifdef ENABLE_ERRCODE + auto selfToken = IPCSkeleton::GetSelfTokenID(); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "not system app"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); + return; + } +#endif + AppExecFwk::ElementName elementName = AAFwk::AbilityManagerClient::GetInstance()->GetTopAbility(); + int resultCode = 0; + ani_object elementNameobj = AppExecFwk::WrapElementName(env, elementName); + if (elementNameobj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null elementNameobj"); + resultCode = ERR_FAILURE; + } + ani_ref callbackRef = nullptr; + auto status = env->GlobalReference_Create(callback, &callbackRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Create Gloabl ref for abilitymanager failed %{public}d", status); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, resultCode), + elementNameobj); + return; +} + +void StsAbilityManagerRegistryInit(ani_env *env) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "call StsAbilityManagerRegistryInit"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return; + } + ani_status status = ANI_ERROR; + if (env->ResetError() != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "ResetError failed"); + } + ani_namespace ns; + status = env->FindNamespace("L@ohos/app/ability/abilityManager/abilityManager;", &ns); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "FindNamespace abilityManager failed status : %{public}d", status); + return; + } + std::array methods = { + ani_native_function { + "nativeGetForegroundUIAbilities", + ":Lescompat/Array;", + reinterpret_cast(GetForegroundUIAbilities) + }, + ani_native_function {"nativeGetTopAbility", nullptr, reinterpret_cast(GetTopAbility)}, + ani_native_function { "nativeGetAbilityRunningInfos", "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(StsAbilityManager::GetAbilityRunningInfos) }, + }; + status = env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Namespace_BindNativeFunctions failed status : %{public}d", status); + } + if (env->ResetError() != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "ResetError failed"); + } +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "in AbilityManagerSts.ANI_Constructor"); + if (vm == nullptr || result == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null vm or result"); + return ANI_INVALID_ARGS; + } + + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "GetEnv failed, status=%{public}d", status); + return ANI_NOT_FOUND; + } + StsAbilityManagerRegistryInit(env); + *result = ANI_VERSION_1; + TAG_LOGD(AAFwkTag::ABILITYMGR, "AbilityManagerSts.ANI_Constructor finished"); + return ANI_OK; +} +} + +void StsAbilityManager::GetAbilityRunningInfos(ani_env *env, ani_object callback) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "GetAbilityRunningInfos"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return; + } + std::vector infos; + auto errcode = AAFwk::AbilityManagerClient::GetInstance()->GetAbilityRunningInfos(infos); + ani_object retObject = nullptr; + WrapAbilityRunningInfoArray(env, retObject, infos); + AppExecFwk::AsyncCallback(env, callback, OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, errcode), retObject); +} +} // namespace AbilityManagerSts +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ability_manager/src/sts_ability_manager_utils.cpp b/frameworks/ets/ani/ability_manager/src/sts_ability_manager_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6185737a75ff8fa1315beec161843e3204cdd6ff --- /dev/null +++ b/frameworks/ets/ani/ability_manager/src/sts_ability_manager_utils.cpp @@ -0,0 +1,290 @@ +/* + * 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 "sts_ability_manager_utils.h" + +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "ani_enum_convert.h" + +namespace OHOS { +namespace AbilityManagerSts { +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; + 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_Double(infoObj, "pid", info.pid)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set pid failed, status: %{public}d", status); + return false; + } + if ((status = env->Object_SetPropertyByName_Double(infoObj, "uid", info.uid)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set uid failed, status: %{public}d", status); + return false; + } + if (!AppExecFwk::SetFieldString(env, cls, infoObj, "processName", info.processName)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set processName failed"); + return false; + } + if ((status = env->Object_SetPropertyByName_Double(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::EnumConvertNativeToSts( + 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_Double(infoObj, "pid", info.pid)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set pid failed, status: %{public}d", status); + return false; + } + if ((status = env->Object_SetPropertyByName_Double(infoObj, "uid", info.uid)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set uid failed, status: %{public}d", status); + return false; + } + if (!AppExecFwk::SetFieldString(env, cls, infoObj, "processName", info.processName)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set processName failed"); + return false; + } + if ((status = env->Object_SetPropertyByName_Double(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::EnumConvertNativeToSts( + 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; +} + +} // namespace AbilityManagerSts +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/BUILD.gn b/frameworks/ets/ani/ani_common/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..2bf78ab797a90482f3d18c047dee88c79bb75726 --- /dev/null +++ b/frameworks/ets/ani/ani_common/BUILD.gn @@ -0,0 +1,76 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +config("ani_common_public_config") { + visibility = [ ":*" ] + include_dirs = [ "include" ] +} + +ohos_shared_library("ani_common") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", + ] + + public_configs = [ ":ani_common_public_config" ] + + sources = [ + "src/ani_common_ability_result.cpp", + "src/ani_common_ability_state_data.cpp", + "src/ani_common_configuration.cpp", + "src/ani_common_execute_param.cpp", + "src/ani_common_execute_result.cpp", + "src/ani_common_start_options.cpp", + "src/ani_common_util.cpp", + "src/ani_common_want.cpp", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/ability_manager:ability_start_options", + "${ability_runtime_innerkits_path}/ability_manager:process_options", + "${ability_runtime_innerkits_path}/ability_manager:start_window_option", + "${ability_runtime_innerkits_path}/app_manager:app_manager", + "${ability_runtime_innerkits_path}/runtime:runtime", + ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "c_utils:utils", + "hilog:libhilog", + "image_framework:image_ani", + "json:nlohmann_json_static", + "runtime_core:ani", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/ani_common/include/ani_common_ability_result.h b/frameworks/ets/ani/ani_common/include/ani_common_ability_result.h new file mode 100644 index 0000000000000000000000000000000000000000..50b6442853ca0fe3650d0ed4925b247cf3fd4573 --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_ability_result.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNNTIME_ANICOMMON_ABILITY_RESULT_H +#define OHOS_ABILITY_RUNNTIME_ANICOMMON_ABILITY_RESULT_H + +#include "ani.h" +#include "want.h" + +namespace OHOS { +namespace AppExecFwk { + +ani_object WrapAbilityResult(ani_env *env, int32_t resultCode, const AAFwk::Want &want); + +} // namespace AppExecFwk +} // namespace OHOS + +#endif // OHOS_ABILITY_RUNNTIME_ANICOMMON_ABILITY_RESULT_H \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/include/ani_common_ability_state_data.h b/frameworks/ets/ani/ani_common/include/ani_common_ability_state_data.h new file mode 100644 index 0000000000000000000000000000000000000000..9a6d68f555a5a1dad5407a7545558445677cb103 --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_ability_state_data.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNNTIME_ANICOMMON_ABILITY_STATE_DATA_H +#define OHOS_ABILITY_RUNNTIME_ANICOMMON_ABILITY_STATE_DATA_H + +#include "ani_common_util.h" +#include "ability_state_data.h" + +namespace OHOS { +namespace AppExecFwk { + ani_object WrapAbilityStateData(ani_env *env, const AbilityStateData &data); + ani_object WrapAbilityStateDataInner(ani_env *env, ani_class cls, ani_object object, + const AbilityStateData &data); + ani_object CreateAniAbilityStateDataArray(ani_env *env, const std::vector &list); +} // namespace AppExecFwk +} // namespace OHOS + +#endif // OHOS_ABILITY_RUNNTIME_ANICOMMON_ABILITY_STATE_DATA_H \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/include/ani_common_configuration.h b/frameworks/ets/ani/ani_common/include/ani_common_configuration.h new file mode 100644 index 0000000000000000000000000000000000000000..c3f7a0086a44515f86e84ac7dcd592d9c02e9a89 --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_configuration.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_NAPI_COMMON_CONFIGURATION_H +#define OHOS_ABILITY_RUNTIME_NAPI_COMMON_CONFIGURATION_H + +#include "ani_common_util.h" +#include "configuration.h" + +namespace OHOS { +namespace AppExecFwk { + +void SetBasicConfiguration( + ani_env *env, ani_class cls, ani_object object, const AppExecFwk::Configuration &configuration); +void SetAdditionalConfiguration( + ani_env *env, ani_class cls, ani_object object, const AppExecFwk::Configuration &configuration); +ani_object WrapConfiguration(ani_env *env, const AppExecFwk::Configuration &configuration); +bool UnwrapConfiguration(ani_env *env, ani_object param, Configuration &config); + +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_NAPI_COMMON_CONFIGURATION_H diff --git a/frameworks/ets/ani/ani_common/include/ani_common_execute_param.h b/frameworks/ets/ani/ani_common/include/ani_common_execute_param.h new file mode 100644 index 0000000000000000000000000000000000000000..9d254bf371a4ba2446c2b0c29f1e08f9bba35860 --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_execute_param.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ANI_EXECUTE_PARAM_H +#define OHOS_ABILITY_RUNTIME_ANI_EXECUTE_PARAM_H + +#include "insight_intent_execute_param.h" +#include "ani_common_util.h" + +namespace OHOS { +namespace AbilityRuntime { + +bool UnwrapExecuteParam(ani_env *env, ani_object param, AppExecFwk::InsightIntentExecuteParam &executeParam); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANI_EXECUTE_PARAM_H diff --git a/frameworks/ets/ani/ani_common/include/ani_common_execute_result.h b/frameworks/ets/ani/ani_common/include/ani_common_execute_result.h new file mode 100644 index 0000000000000000000000000000000000000000..3073fc546b74165c980b33922ee33b52786d0a1e --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_execute_result.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ANI_EXECUTE_RESULT_H +#define OHOS_ABILITY_RUNTIME_ANI_EXECUTE_RESULT_H + +#include "insight_intent_execute_result.h" +#include "ani_common_util.h" + +namespace OHOS { +namespace AbilityRuntime { + +bool UnwrapExecuteResult(ani_env *env, ani_object ¶m, AppExecFwk::InsightIntentExecuteResult &executeResult); +ani_object WrapExecuteResult(ani_env *env, AppExecFwk::InsightIntentExecuteResult &executeResult); +ani_object CreateNullExecuteResult(ani_env *env); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANI_EXECUTE_RESULT_H diff --git a/frameworks/ets/ani/ani_common/include/ani_common_start_options.h b/frameworks/ets/ani/ani_common/include/ani_common_start_options.h new file mode 100644 index 0000000000000000000000000000000000000000..94ffbecc182dcc253acbca4d17c78f6dbd0a9e0f --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_start_options.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_ANI_COMMON_START_OPTIONS_H +#define OHOS_ABILITY_RUNTIME_ANI_COMMON_START_OPTIONS_H + +#include "ani_common_util.h" +#include "start_options.h" +#ifdef START_WINDOW_OPTIONS_WITH_PIXELMAP +#include "pixel_map_ani.h" +#include "image_ani_utils.h" +#endif + +namespace OHOS { +namespace AppExecFwk { + +bool UnwrapStartOptionsWithProcessOption(ani_env *env, ani_object param, AAFwk::StartOptions &startOptions); +bool UnwrapStartOptions(ani_env *env, ani_object param, AAFwk::StartOptions &startOptions); +bool UnwrapProcessOptions(ani_env *env, ani_object param, std::shared_ptr &processOptions); + +#ifdef START_WINDOW_OPTIONS_WITH_PIXELMAP +bool UnwrapPixelMapByPropertyName( + ani_env *env, ani_object EnvObject, const char *propertyName, std::shared_ptr &value); +bool UnwrapPixelMapFromAni(ani_env *env, ani_object param, std::shared_ptr &value); +#endif + +bool UnwrapStartWindowOption(ani_env *env, ani_object param, + std::shared_ptr &startWindowOption); +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_NAPI_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 new file mode 100644 index 0000000000000000000000000000000000000000..6c04d37037f6b7c4338430d87cd4c7c01351f2b2 --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_util.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ANI_COMMON_UTIL_H +#define OHOS_ABILITY_RUNTIME_ANI_COMMON_UTIL_H + +#include + +#include "ani.h" +namespace OHOS { +namespace AppExecFwk { + +bool GetDoubleOrUndefined(ani_env *env, ani_object param, const char *name, ani_double &value); +bool GetBoolOrUndefined(ani_env *env, ani_object param, const char *name); +bool GetStringOrUndefined(ani_env *env, ani_object param, const char *name, std::string &res); +bool GetIntByName(ani_env *env, ani_object param, const char *name, int &value); +bool GetStringArrayOrUndefined(ani_env *env, ani_object param, const char *name, std::vector &res); + +bool GetStdString(ani_env *env, ani_string str, std::string &res); + +ani_string GetAniString(ani_env *env, const std::string &str); +bool GetRefFieldByName(ani_env *env, ani_object param, const char *name, ani_ref &ref); + +ani_object createDouble(ani_env *env, ani_double value); +ani_object createBoolean(ani_env *env, ani_boolean value); +ani_object createInt(ani_env *env, ani_int value); +ani_object createLong(ani_env *env, ani_long value); +bool SetFieldString(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, + const std::string &value); +bool SetFieldBoolean(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, bool value); +bool SetFieldInt(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, int value); +bool SetOptionalFieldInt(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, int value); + +bool SetStringProperty(ani_env *env, ani_object param, const char *name, const std::string &value); +bool SetFieldArrayString(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, + const std::vector &values); +bool SetFieldRef(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, ani_ref value); +bool AniStringToStdString(ani_env *env, ani_string aniString, std::string &stdString); + +bool GetPropertyRef(ani_env *env, ani_object obj, const char *name, ani_ref &ref, ani_boolean &isUndefined); +bool GetFieldRef(ani_env *env, ani_object obj, const char *name, ani_ref &ref, ani_boolean &isUndefined); +bool AsyncCallback(ani_env *env, ani_object call, ani_object error, ani_object result); + +ani_object GetPropertyValueByName(ani_env *env, ani_object param, const char *propertyName); +bool IsExistsProperty(ani_env *env, ani_object param, const char *name); +bool GetStringProperty(ani_env *env, ani_object param, const char *name, std::string &value); +bool GetStringArrayProperty(ani_env *env, ani_object param, const char *name, std::vector &value); +bool GetDoublePropertyObject(ani_env *env, ani_object param, const char *name, double &value); +bool GetDoublePropertyValue(ani_env *env, ani_object param, const char *name, double &value); +bool GetRefProperty(ani_env *env, ani_object param, const char *name, ani_ref &value); + +bool SetDoublePropertyObject(ani_env *env, ani_object param, const char *name, double value); +bool SetDoublePropertyValue(ani_env *env, ani_object param, const char *name, double value); +bool SetStringArrayProperty(ani_env *env, ani_object param, const char *name, const std::vector &values); +bool SetRefProperty(ani_env *env, ani_object param, const char *name, ani_ref value); +bool WrapArrayString(ani_env *env, ani_object &arrayObj, const std::vector &values); +bool UnwrapArrayString(ani_env *env, const ani_object &arrayObj, std::vector &stringList); +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANI_COMMON_UTIL_H + \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/include/ani_common_want.h b/frameworks/ets/ani/ani_common/include/ani_common_want.h new file mode 100644 index 0000000000000000000000000000000000000000..b187433814b6468faa5a734dd0ff6a15d16f152e --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/ani_common_want.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_ANICOMMON_WANT_H +#define OHOS_ABILITY_RUNTIME_ANICOMMON_WANT_H + +#include +#include +#include + +#include "ani_common_util.h" +#include "want.h" +#include "want_params.h" + +namespace OHOS { +namespace AppExecFwk { + +ani_object WrapWant(ani_env *env, const AAFwk::Want &want); +ani_ref WrapWantParams(ani_env *env, const AAFwk::WantParams &wantParams); + +bool UnwrapWant(ani_env *env, ani_object param, AAFwk::Want &want); +bool UnwrapWantParams(ani_env *env, ani_ref param, AAFwk::WantParams &wantParams); +bool UnWrapAbilityResult(ani_env *env, ani_object param, int &resultCode, AAFwk::Want &want); +ani_object WrapElementName(ani_env *env, const AppExecFwk::ElementName &elementNameParam); +ani_object WrapElementNameInner(ani_env *env, ani_class elementNameObj, ani_object object, + const AppExecFwk::ElementName &elementNameParam); + +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANICOMMON_WANT_H + \ No newline at end of file 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 new file mode 100644 index 0000000000000000000000000000000000000000..acdaac1322fac74411ea1a86ae7ce053248a5bc2 --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_ability_result.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_common_ability_result.h" + +#include "ani_common_want.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { + +ani_object WrapAbilityResult(ani_env *env, int32_t resultCode, const AAFwk::Want &want) +{ + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method ctor = nullptr; + ani_object result_obj = {}; + static const char *className = "Lability/abilityResult/AbilityResultInner;"; + + if ((status = env->FindClass(className, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + return nullptr; + } + + if ((status = env->Class_FindMethod(cls, "", nullptr, &ctor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + return nullptr; + } + + if ((status = env->Object_New(cls, ctor, &result_obj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + return nullptr; + } + + ani_method resultCodeSetter = nullptr; + if ((status = env->Class_FindMethod(cls, "resultCode", nullptr, &resultCodeSetter)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + } + + ani_double dResultCode {resultCode}; + if ((status = env->Object_CallMethod_Void(result_obj, resultCodeSetter, dResultCode)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + return nullptr; + } + + ani_method wantSetter = nullptr; + if ((status = env->Class_FindMethod(cls, "want", nullptr, &wantSetter)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + } + + ani_object wantObj = AppExecFwk::WrapWant(env, want); + if ((status = env->Object_CallMethod_Void(result_obj, wantSetter, wantObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + return nullptr; + } + + return result_obj; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/src/ani_common_ability_state_data.cpp b/frameworks/ets/ani/ani_common/src/ani_common_ability_state_data.cpp new file mode 100644 index 0000000000000000000000000000000000000000..56e2f9da611bbac49e25f1f9bb5858f93d0c6c8d --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_ability_state_data.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_common_ability_state_data.h" + +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +ani_object WrapAbilityStateDataInner(ani_env *env, ani_class cls, ani_object object, + const AbilityStateData &data) +{ + if (env == nullptr || cls == nullptr || object == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid args"); + return nullptr; + } + + if (!SetFieldString(env, cls, object, "moduleName", data.moduleName)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set moduleName failed"); + return nullptr; + } + + if (!SetFieldString(env, cls, object, "bundleName", data.bundleName)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set bundleName failed"); + return nullptr; + } + + if (!SetFieldString(env, cls, object, "abilityName", data.abilityName)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set abilityName failed"); + return nullptr; + } + + if (!SetFieldInt(env, cls, object, "pid", data.pid)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set pid failed"); + return nullptr; + } + + if (!SetFieldInt(env, cls, object, "uid", data.uid)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set uid failed"); + return nullptr; + } + + if (!SetFieldInt(env, cls, object, "state", data.abilityState)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set state failed"); + return nullptr; + } + + if (!SetFieldInt(env, cls, object, "abilityType", data.abilityType)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set type failed"); + return nullptr; + } + + if (!SetFieldBoolean(env, cls, object, "isAtomicService", data.isAtomicService)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set isAtomicService failed"); + return nullptr; + } + + if (data.appCloneIndex != -1 && !SetOptionalFieldInt(env, cls, object, "appCloneIndex", data.appCloneIndex)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set appCloneIndex failed"); + return nullptr; + } + + return object; +} + +ani_object WrapAbilityStateData(ani_env *env, const AbilityStateData &data) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return nullptr; + } + + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method ctor = nullptr; + ani_object object = {}; + static const char *className = "Lapplication/AbilityStateData/AbilityStateData;"; + + if ((status = env->FindClass(className, &cls)) != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "FindClass status : %{public}d or null cls", status); + return nullptr; + } + + if ((status = env->Class_FindMethod(cls, "", ":V", &ctor)) != ANI_OK || ctor == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Class_FindMethod status : %{public}d or null ctor", status); + return nullptr; + } + + if ((status = env->Object_New(cls, ctor, &object)) != ANI_OK || object == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Object_New status : %{public}d or null object", status); + return nullptr; + } + + return WrapAbilityStateDataInner(env, cls, object, data); +} + +ani_object CreateAniAbilityStateDataArray(ani_env *env, const std::vector &list) +{ + TAG_LOGI(AAFwkTag::ABILITYMGR, "call CreateAniAbilityStateDataArray, list.size=%{public}zu", list.size()); + + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return nullptr; + } + + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method ctor = nullptr; + ani_object object = {}; + static const char *className = "Lescompat/Array;"; + + if ((status = env->FindClass(className, &cls)) != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "FindClass status : %{public}d or null cls", status); + return nullptr; + } + + if ((status = env->Class_FindMethod(cls, "", "I:V", &ctor)) != ANI_OK || ctor == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Class_FindMethod status : %{public}d or null ctor", status); + return nullptr; + } + + if ((status = env->Object_New(cls, ctor, &object, list.size())) != ANI_OK || object == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Object_New status : %{public}d or null object", status); + return nullptr; + } + + ani_size index = 0; + for (const auto &data : list) { + ani_object obj = WrapAbilityStateData(env, data); + if (obj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null obj"); + return nullptr; + } + if (ANI_OK != env->Object_CallMethodByName_Void(object, "$_set", "ILstd/core/Object;:V", index, obj)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Object_CallMethodByName_Void failed"); + return nullptr; + } + index++; + } + return object; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/src/ani_common_configuration.cpp b/frameworks/ets/ani/ani_common/src/ani_common_configuration.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a887efd207b7062a6f8b9e53e01607347af60915 --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_configuration.cpp @@ -0,0 +1,162 @@ +/* + * 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_configuration.h" + +#include "ani_enum_convert.h" +#include "configuration_convertor.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +namespace { +constexpr double FONT_SIZE_MIN_SCALE = 0.0; +constexpr double FONT_SIZE_MAX_SCALE = 3.2; +constexpr double FONT_WEIGHT_MIN_SCALE = 0.0; +constexpr double FONT_WEIGHT_MAX_SCALE = 1.25; +constexpr const char* COLOR_MODE_ENUM_NAME = + "L@ohos/app/ability/ConfigurationConstant/ConfigurationConstant/ColorMode;"; +constexpr const char* DIRECTION_ENUM_NAME = + "L@ohos/app/ability/ConfigurationConstant/ConfigurationConstant/Direction;"; +constexpr const char* DENSITY_ENUM_NAME = + "L@ohos/app/ability/ConfigurationConstant/ConfigurationConstant/ScreenDensity;"; +constexpr const char* CONFIGURATION_IMPL_CLASS_NAME = "L@ohos/app/ability/Configuration/ConfigurationImpl;"; +} + +void SetBasicConfiguration( + ani_env *env, ani_class cls, ani_object object, const AppExecFwk::Configuration &configuration) +{ + std::string str = configuration.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_LANGUAGE); + env->Object_SetPropertyByName_Ref(object, "language", GetAniString(env, str)); + + ani_enum_item colorModeItem {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvertNativeToSts(env, + COLOR_MODE_ENUM_NAME, + ConvertColorMode(configuration.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE)), colorModeItem); + 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))); + + std::string direction = configuration.GetItem(displayId, ConfigurationInner::APPLICATION_DIRECTION); + ani_enum_item directionItem {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvertNativeToSts(env, + DIRECTION_ENUM_NAME, ConvertDirection(direction), + directionItem); + env->Object_SetPropertyByName_Ref(object, "direction", directionItem); + + std::string density = configuration.GetItem(displayId, ConfigurationInner::APPLICATION_DENSITYDPI); + ani_enum_item densityItem {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvertNativeToSts(env, + DENSITY_ENUM_NAME, ConvertDensity(density), densityItem); + env->Object_SetPropertyByName_Ref(object, "screenDensity", densityItem); +} + +void SetAdditionalConfiguration( + ani_env *env, ani_class cls, ani_object object, const AppExecFwk::Configuration &configuration) +{ + std::string hasPointerDevice = configuration.GetItem(AAFwk::GlobalConfigurationKey::INPUT_POINTER_DEVICE); + env->Object_SetPropertyByName_Ref( + object, "hasPointerDevice", createBoolean(env, hasPointerDevice == "true" ? true : false)); + + std::string str = configuration.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_ID); + env->Object_SetPropertyByName_Ref(object, "fontId", GetAniString(env, str)); + + std::string fontSizeScale = configuration.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_SIZE_SCALE); + env->Object_SetPropertyByName_Ref( + object, "fontSizeScale", createDouble(env, fontSizeScale != "" ? std::stod(fontSizeScale) : 1.0)); + + std::string fontWeightScale = configuration.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_WEIGHT_SCALE); + env->Object_SetPropertyByName_Ref( + object, "fontWeightScale", createDouble(env, fontWeightScale != "" ? std::stod(fontWeightScale) : 1.0)); + + str = configuration.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_MCC); + env->Object_SetPropertyByName_Ref(object, "mcc", GetAniString(env, str)); + + str = configuration.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_MNC); + env->Object_SetPropertyByName_Ref(object, "mnc", GetAniString(env, str)); +} + +ani_object WrapConfiguration(ani_env *env, const AppExecFwk::Configuration &configuration) +{ + ani_class cls {}; + ani_status status = ANI_ERROR; + ani_method method {}; + ani_object object = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null env"); + return nullptr; + } + if ((status = env->FindClass(CONFIGURATION_IMPL_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null Configuration"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null object"); + return nullptr; + } + SetBasicConfiguration(env, cls, object, configuration); + SetAdditionalConfiguration(env, cls, object, configuration); + return object; +} + +bool UnwrapConfiguration(ani_env *env, ani_object param, Configuration &config) +{ + std::string language { "" }; + if (GetStringOrUndefined(env, param, "language", language)) { + TAG_LOGD(AAFwkTag::JSNAPI, "The parsed language part %{public}s", language.c_str()); + if (!config.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_LANGUAGE, language)) { + TAG_LOGE(AAFwkTag::JSNAPI, "language Parsing failed"); + return false; + } + } + + ani_double fontSizeScale = 0.0; + if (GetDoubleOrUndefined(env, param, "fontSizeScale", fontSizeScale)) { + if (fontSizeScale < FONT_SIZE_MIN_SCALE || fontSizeScale > FONT_SIZE_MAX_SCALE) { + TAG_LOGE(AAFwkTag::JSNAPI, "invalid fontSizeScale"); + return false; + } + if (!config.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_SIZE_SCALE, std::to_string(fontSizeScale))) { + return false; + } + } + + ani_double fontWeightScale = 0.0; + if (GetDoubleOrUndefined(env, param, "fontWeightScale", fontWeightScale)) { + if (fontWeightScale < FONT_WEIGHT_MIN_SCALE || fontWeightScale > FONT_WEIGHT_MAX_SCALE) { + TAG_LOGE(AAFwkTag::JSNAPI, "invalid fontWeightScale"); + return false; + } + if (!config.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_WEIGHT_SCALE, std::to_string(fontWeightScale))) { + return false; + } + } + return true; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/frameworks/ets/ani/ani_common/src/ani_common_execute_param.cpp b/frameworks/ets/ani/ani_common/src/ani_common_execute_param.cpp new file mode 100644 index 0000000000000000000000000000000000000000..981cbc4dcef83d40f30e5dbcba5010b349a69da2 --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_execute_param.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_common_execute_param.h" + +#include "hilog_tag_wrapper.h" +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "ani_enum_convert.h" + +namespace OHOS { +namespace AbilityRuntime { +using namespace OHOS::AppExecFwk; + +bool UnwrapExecuteParam(ani_env *env, ani_object param, AppExecFwk::InsightIntentExecuteParam &executeParam) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return false; + } + if (param == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null param"); + return false; + } + + std::string bundleName {""}; + if (!GetStringProperty(env, param, "bundleName", bundleName)) { + TAG_LOGE(AAFwkTag::INTENT, "Wrong argument type bundleName"); + return false; + } + executeParam.bundleName_ = bundleName; + + std::string moduleName {""}; + if (!GetStringProperty(env, param, "moduleName", moduleName)) { + TAG_LOGE(AAFwkTag::INTENT, "Wrong argument type moduleName"); + return false; + } + executeParam.moduleName_ = moduleName; + + std::string abilityName {""}; + if (!GetStringProperty(env, param, "abilityName", abilityName)) { + TAG_LOGE(AAFwkTag::INTENT, "Wrong argument type abilityName"); + return false; + } + executeParam.abilityName_ = abilityName; + + std::string insightIntentName {""}; + if (!GetStringProperty(env, param, "insightIntentName", insightIntentName)) { + TAG_LOGE(AAFwkTag::INTENT, "Wrong argument type insightIntentName"); + return false; + } + executeParam.insightIntentName_ = insightIntentName; + + ani_ref aniIntentParam = nullptr; + if (!GetRefProperty(env, param, "insightIntentParam", aniIntentParam)) { + TAG_LOGE(AAFwkTag::INTENT, "null aniIntentParam"); + return false; + } + auto wp = std::make_shared(); + if (!UnwrapWantParams(env, aniIntentParam, *wp)) { + TAG_LOGE(AAFwkTag::INTENT, "unwrap want fail"); + return false; + } + executeParam.insightIntentParam_ = wp; + + int32_t executeMode = 0; + ani_ref executeModeRef = nullptr; + if (!GetRefProperty(env, param, "executeMode", executeModeRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "Wrong argument type executeMode"); + return false; + } + AAFwk::AniEnumConvertUtil::EnumConvertStsToNative(env, + static_cast(executeModeRef), executeMode); + executeParam.executeMode_ = executeMode; + + double displayIdD = 0.0; + int32_t displayId = INVALID_DISPLAY_ID; + if (executeMode == ExecuteMode::UI_ABILITY_FOREGROUND && + IsExistsProperty(env, param, "displayId")) { + if (GetDoublePropertyObject(env, param, "displayId", displayIdD)) { + displayId = static_cast(displayIdD); + if (displayId < 0) { + TAG_LOGE(AAFwkTag::INTENT, "invalid displayId"); + return false; + } + TAG_LOGI(AAFwkTag::INTENT, "displayId %{public}d", displayId); + executeParam.displayId_ = displayId; + } + } + if (IsExistsProperty(env, param, "uris")) { + std::vector uris; + if (!GetStringArrayProperty(env, param, "uris", uris)) { + TAG_LOGE(AAFwkTag::INTENT, "Wrong argument uris fail"); + return false; + } + executeParam.uris_ = uris; + } + if (IsExistsProperty(env, param, "flags")) { + double flags = 0.0; + if (!GetDoublePropertyObject(env, param, "flags", flags)) { + TAG_LOGE(AAFwkTag::INTENT, "Wrong argument flags fail"); + return false; + } + executeParam.flags_ = static_cast(flags); + } + + return true; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/ani_common/src/ani_common_execute_result.cpp b/frameworks/ets/ani/ani_common/src/ani_common_execute_result.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f165c6d6855ee411611ef2a9fbf04470349d8c5 --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_execute_result.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_common_execute_result.h" + +#include "hilog_tag_wrapper.h" +#include "insight_intent_execute_result.h" +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "want_params.h" +#include + +namespace OHOS { +namespace AbilityRuntime { +using namespace OHOS::AppExecFwk; +bool UnwrapResultOfExecuteResult(ani_env *env, ani_object ¶m, InsightIntentExecuteResult &executeResult) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return false; + } + ani_status status = ANI_OK; + ani_ref wantParamRef = nullptr; + if (!GetRefProperty(env, param, "result", wantParamRef)) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return false; + } + + auto wantParams = std::make_shared(); + if (!UnwrapWantParams(env, wantParamRef, *wantParams)) { + TAG_LOGE(AAFwkTag::INTENT, "failed to unwrap want parameter"); + return false; + } + + if (!executeResult.CheckResult(wantParams)) { + TAG_LOGE(AAFwkTag::INTENT, "Check wp fail"); + return false; + } + executeResult.result = wantParams; + + return true; +} + +bool UnwrapExecuteResult(ani_env *env, ani_object ¶m, InsightIntentExecuteResult &executeResult) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return false; + } + + if (param == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "param is nullptr"); + return false; + } + + ani_double code = 0; + if (!GetDoublePropertyValue(env, param, "code", code)) { + TAG_LOGE(AAFwkTag::INTENT, "parse code fail"); + return false; + } + executeResult.code = static_cast(code); + + if (IsExistsProperty(env, param, "result")) { + if (!UnwrapResultOfExecuteResult(env, param, executeResult)) { + TAG_LOGE(AAFwkTag::INTENT, "unwrap execute result fail"); + return false; + } + } + + if (IsExistsProperty(env, param, "uris")) { + std::vector uris; + if (!GetStringArrayProperty(env, param, "uris", uris)) { + TAG_LOGE(AAFwkTag::INTENT, "unwrap uris is null"); + return false; + } + executeResult.uris = uris; + } + + if (IsExistsProperty(env, param, "flags")) { + double flags = 0.0; + if (!GetDoublePropertyObject(env, param, "flags", flags)) { + TAG_LOGE(AAFwkTag::INTENT, "unwrap flags is null"); + return false; + } + executeResult.flags = static_cast(flags); + } + + return true; +} + +ani_object WrapExecuteResult(ani_env *env, AppExecFwk::InsightIntentExecuteResult &executeResult) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return nullptr; + } + + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method ctor = nullptr; + ani_object objValue = {}; + + if ((status = env->FindClass("L@ohos/app/ability/insightIntent/insightIntent/ExecuteResultInner;", + &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + + if ((status = env->Class_FindMethod(cls, "", nullptr, &ctor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + + if ((status = env->Object_New(cls, ctor, &objValue)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + + if (!SetDoublePropertyValue(env, objValue, "code", static_cast(executeResult.code))) { + TAG_LOGE(AAFwkTag::INTENT, "SetDoubleProperty failded"); + return nullptr; + } + if (executeResult.result != nullptr) { + SetRefProperty(env, objValue, "result", WrapWantParams(env, *executeResult.result)); + } + if (executeResult.uris.size() > 0) { + SetStringArrayProperty(env, objValue, "uris", executeResult.uris); + } + SetDoublePropertyObject(env, objValue, "flags", static_cast(executeResult.flags)); + + return objValue; +} + +ani_object CreateNullExecuteResult(ani_env *env) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return nullptr; + } + + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method ctor = nullptr; + ani_object objValue = {}; + + if ((status = env->FindClass("L@ohos/app/ability/insightIntent/insightIntent/ExecuteResultInner;", + &cls)) + != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + + if ((status = env->Class_FindMethod(cls, "", nullptr, &ctor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + + if ((status = env->Object_New(cls, ctor, &objValue)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + + return objValue; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/ani_common/src/ani_common_start_options.cpp b/frameworks/ets/ani/ani_common/src/ani_common_start_options.cpp new file mode 100644 index 0000000000000000000000000000000000000000..746cdd2c76258d748b9f122846e6ff367e60251c --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_start_options.cpp @@ -0,0 +1,289 @@ +/* + * 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_start_options.h" + +#include "ability_info.h" +#include "ani_enum_convert.h" +#include "hilog_tag_wrapper.h" +#include "int_wrapper.h" +#include "parcel.h" +#include "process_options.h" +#include "start_window_option.h" + +namespace OHOS { +namespace AppExecFwk { + +bool UnwrapStartOptionsWithProcessOption(ani_env* env, ani_object param, AAFwk::StartOptions &startOptions) +{ + UnwrapStartOptions(env, param, startOptions); + if (!UnwrapProcessOptions(env, param, startOptions.processOptions)) { + TAG_LOGE(AAFwkTag::JSNAPI, "Unwrap processOptions failed"); + return false; + } + if (!UnwrapStartWindowOption(env, param, startOptions.startWindowOption)) { + TAG_LOGE(AAFwkTag::JSNAPI, "Unwrap startWindowOption failed"); + return false; + } + return true; +} + +void UnwrapStartOptionsWindowOptions(ani_env *env, ani_object param, AAFwk::StartOptions &startOptions) +{ + ani_double windowLeft = 0.0; + if (GetDoubleOrUndefined(env, param, "windowLeft", windowLeft)) { + TAG_LOGD(AAFwkTag::JSNAPI, "windowLeft:%{public}f", windowLeft); + startOptions.SetWindowLeft(windowLeft); + startOptions.windowLeftUsed_ = true; + } + + ani_double windowTop = 0.0; + if (GetDoubleOrUndefined(env, param, "windowTop", windowTop)) { + TAG_LOGD(AAFwkTag::JSNAPI, "windowTop:%{public}f", windowTop); + startOptions.SetWindowTop(windowTop); + startOptions.windowTopUsed_ = true; + } + + ani_double windowWidth = 0.0; + if (GetDoubleOrUndefined(env, param, "windowWidth", windowWidth)) { + TAG_LOGD(AAFwkTag::JSNAPI, "windowWidth:%{public}f", windowWidth); + startOptions.SetWindowWidth(windowWidth); + startOptions.windowWidthUsed_ = true; + } + + ani_double windowHeight = 0.0; + if (GetDoubleOrUndefined(env, param, "windowHeight", windowHeight)) { + TAG_LOGD(AAFwkTag::JSNAPI, "windowHeight:%{public}f", windowHeight); + startOptions.SetWindowHeight(windowHeight); + startOptions.windowHeightUsed_ = true; + } + + ani_double minWindowWidth = 0.0; + if (GetDoubleOrUndefined(env, param, "minWindowWidth", minWindowWidth)) { + TAG_LOGD(AAFwkTag::JSNAPI, "minWindowWidth:%{public}f", minWindowWidth); + startOptions.SetMinWindowWidth(minWindowWidth); + startOptions.minWindowWidthUsed_ = true; + } + + ani_double minWindowHeight = 0.0; + if (GetDoubleOrUndefined(env, param, "minWindowHeight", minWindowHeight)) { + TAG_LOGD(AAFwkTag::JSNAPI, "minWindowHeight:%{public}f", minWindowHeight); + startOptions.SetMinWindowHeight(minWindowHeight); + startOptions.minWindowHeightUsed_ = true; + } + + ani_double maxWindowWidth = 0.0; + if (GetDoubleOrUndefined(env, param, "maxWindowWidth", maxWindowWidth)) { + TAG_LOGD(AAFwkTag::JSNAPI, "maxWindowWidth:%{public}f", maxWindowWidth); + startOptions.SetMaxWindowWidth(maxWindowWidth); + startOptions.maxWindowWidthUsed_ = true; + } + + ani_double maxWindowHeight = 0.0; + if (GetDoubleOrUndefined(env, param, "maxWindowHeight", maxWindowHeight)) { + TAG_LOGD(AAFwkTag::JSNAPI, "maxWindowHeight:%{public}f", maxWindowHeight); + startOptions.SetMaxWindowHeight(maxWindowHeight); + startOptions.maxWindowHeightUsed_ = true; + } +} + +bool SetSupportWindowModes(ani_env *env, ani_object param, AAFwk::StartOptions &startOptions) +{ + ani_ref supportWindowModesRef = nullptr; + ani_boolean hasValue = true; + if (GetPropertyRef(env, param, "supportWindowModes", supportWindowModesRef, hasValue) && !hasValue) { + ani_array_ref supportWindowModesArr = reinterpret_cast(supportWindowModesRef); + ani_size supportWindowModesLen = 0; + if (env->Array_GetLength(supportWindowModesArr, &supportWindowModesLen) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "Array_GetLength failed"); + return false; + } + for (size_t i = 0; i < supportWindowModesLen; ++i) { + ani_ref supportWindowModeRef = nullptr; + int32_t supportWindowMode = 0; + if (env->Array_Get_Ref(supportWindowModesArr, i, &supportWindowModeRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "Array_Get_Ref failed"); + return false; + } + AAFwk::AniEnumConvertUtil::EnumConvertStsToNative( + env, reinterpret_cast(supportWindowModeRef), supportWindowMode); + TAG_LOGD(AAFwkTag::JSNAPI, "supportWindowMode:%{public}d", supportWindowMode); + startOptions.supportWindowModes_.emplace_back( + static_cast(supportWindowMode)); + } + } + return true; +} + +bool UnwrapStartOptions(ani_env *env, ani_object param, AAFwk::StartOptions &startOptions) +{ + TAG_LOGD(AAFwkTag::JSNAPI, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null env"); + return false; + } + + ani_double windowMode = 0.0; + if (GetDoubleOrUndefined(env, param, "windowMode", windowMode)) { + TAG_LOGD(AAFwkTag::JSNAPI, "windowMode:%{public}f", windowMode); + startOptions.SetWindowMode(windowMode); + } + + ani_double displayId = 0.0; + if (GetDoubleOrUndefined(env, param, "displayId", displayId)) { + TAG_LOGD(AAFwkTag::JSNAPI, "displayId:%{public}f", displayId); + startOptions.SetDisplayID(static_cast(displayId)); + } + + ani_boolean withAnimation = true; + if (IsExistsProperty(env, param, "withAnimation")) { + withAnimation = GetBoolOrUndefined(env, param, "withAnimation"); + TAG_LOGD(AAFwkTag::JSNAPI, "withAnimation:%{public}hhu", withAnimation); + startOptions.SetWithAnimation(withAnimation); + } + + UnwrapStartOptionsWindowOptions(env, param, startOptions); + + ani_boolean windowFocused = true; + if (IsExistsProperty(env, param, "windowFocused")) { + windowFocused = GetBoolOrUndefined(env, param, "windowFocused"); + TAG_LOGD(AAFwkTag::JSNAPI, "windowFocused:%{public}hhu", windowFocused); + startOptions.SetWindowFocused(windowFocused); + } + + if (!SetSupportWindowModes(env, param, startOptions)) { + TAG_LOGE(AAFwkTag::JSNAPI, "SetSupportWindowModes failed"); + return false; + } + + return true; +} + +bool UnwrapProcessOptions(ani_env* env, ani_object param, std::shared_ptr &processOptions) +{ + auto option = std::make_shared(); + + ani_boolean isProcessModeUndefined = true; + ani_ref processModeRef = nullptr; + if (!GetPropertyRef(env, param, "processMode", processModeRef, isProcessModeUndefined)) { + TAG_LOGE(AAFwkTag::JSNAPI, "Unwrap processMode failed"); + return false; + } + + ani_boolean isStartupVisibilityUndefined = true; + ani_ref startupVisibilityRef = nullptr; + if (!GetPropertyRef(env, param, "startupVisibility", startupVisibilityRef, isStartupVisibilityUndefined)) { + TAG_LOGE(AAFwkTag::JSNAPI, "Unwrap startupVisibility failed"); + return false; + } + + if (isProcessModeUndefined && isStartupVisibilityUndefined) { + return true; + } + + int32_t processMode = 0; + if (isProcessModeUndefined) { + TAG_LOGE(AAFwkTag::JSNAPI, "Unwrap processMode failed"); + return false; + } + AAFwk::AniEnumConvertUtil::EnumConvertStsToNative( + env, reinterpret_cast(processModeRef), processMode); + TAG_LOGD(AAFwkTag::JSNAPI, "processMode: %{public}d", processMode); + option->processMode = AAFwk::ProcessOptions::ConvertInt32ToProcessMode(processMode); + if (option->processMode == AAFwk::ProcessMode::UNSPECIFIED) { + TAG_LOGE(AAFwkTag::JSNAPI, "Convert processMode failed"); + return false; + } + + int32_t startupVisibility = 0; + if (isStartupVisibilityUndefined) { + TAG_LOGE(AAFwkTag::JSNAPI, "Unwrap startupVisibility failed"); + return false; + } + AAFwk::AniEnumConvertUtil::EnumConvertStsToNative( + env, reinterpret_cast(startupVisibilityRef), startupVisibility); + TAG_LOGD(AAFwkTag::JSNAPI, "startupVisibility: %{public}d", startupVisibility); + option->startupVisibility = AAFwk::ProcessOptions::ConvertInt32ToStartupVisibility(startupVisibility); + if (option->startupVisibility == AAFwk::StartupVisibility::UNSPECIFIED) { + TAG_LOGE(AAFwkTag::JSNAPI, "Convert startupVisibility failed"); + return false; + } + + processOptions = option; + return true; +} + +#ifdef START_WINDOW_OPTIONS_WITH_PIXELMAP +bool UnwrapPixelMapFromAni(ani_env *env, ani_object param, std::shared_ptr &value) +{ + auto pixelMap = OHOS::Media::ImageAniUtils::GetPixelMapFromEnvSp(env, param); + if (!pixelMap) { + TAG_LOGE(AAFwkTag::JSNAPI, "Unwrap pixelMap failed"); + return false; + } + + value = pixelMap; + return true; +} + +bool UnwrapPixelMapByPropertyName( + ani_env *env, ani_object param, const char *propertyName, std::shared_ptr &value) +{ + ani_object envValue = GetPropertyValueByName(env, param, propertyName); + if (envValue == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "UnwrapPixelMapByPropertyName failed"); + return false; + } + return UnwrapPixelMapFromAni(env, envValue, value); +} +#endif + +bool UnwrapStartWindowOption(ani_env *env, ani_object param, + std::shared_ptr &startWindowOption) +{ + auto option = std::make_shared(); + std::string startWindowBackgroundColor; + if (IsExistsProperty(env, param, "startWindowBackgroundColor")) { + if (!GetStringOrUndefined(env, param, "startWindowBackgroundColor", startWindowBackgroundColor)) { + TAG_LOGE(AAFwkTag::JSNAPI, "Unwrap startWindowBackgroundColor failed"); + return false; + } + option->startWindowBackgroundColor = startWindowBackgroundColor; + } + if (!startWindowBackgroundColor.empty()) { + option->hasStartWindow = true; + } +#ifdef START_WINDOW_OPTIONS_WITH_PIXELMAP + + std::shared_ptr startWindowIcon = nullptr; + ani_boolean isIconUndefined = true; + ani_ref valueRef = nullptr; + if (GetFieldRef(env, param, "startWindowIcon", valueRef, isIconUndefined) && !isIconUndefined) { + if (!UnwrapPixelMapByPropertyName(env, param, "startWindowIcon", startWindowIcon)) { + TAG_LOGE(AAFwkTag::JSNAPI, "Unwrap startWindowIcon failed"); + return false; + } + option->startWindowIcon = startWindowIcon; + } + + if (startWindowIcon != nullptr) { + option->hasStartWindow = true; + } +#endif + startWindowOption = option; + return true; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/src/ani_common_util.cpp b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..51a122518bdf0626fac292fc512aa93f15c41b06 --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp @@ -0,0 +1,1025 @@ +/* + * 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_util.h" + +#include + +#include "hilog_tag_wrapper.h" +#include "securec.h" + +namespace OHOS { +namespace AppExecFwk { +namespace { +constexpr const char* CLASSNAME_DOUBLE = "Lstd/core/Double;"; +constexpr const char* CLASSNAME_BOOLEAN = "Lstd/core/Boolean;"; +constexpr const char* CLASSNAME_INT = "Lstd/core/Int;"; +constexpr const char* CLASSNAME_LONG = "Lstd/core/Long;"; +constexpr const char* CLASSNAME_STRING = "Lstd/core/String;"; +constexpr const char* CLASSNAME_ARRAY = "Lescompat/Array;"; +constexpr const char* CLASSNAME_ASYNC_CALLBACK_WRAPPER = "Lutils/AbilityUtils/AsyncCallbackWrapper;"; +constexpr const char* SET_OBJECT_VOID_SIGNATURE = "ILstd/core/Object;:V"; +} + +bool GetIntByName(ani_env *env, ani_object param, const char *name, int &value) +{ + ani_int res; + ani_status status; + + status = env->Object_GetFieldByName_Int(param, name, &res); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + value = static_cast(res); + return true; +} + +bool GetDoubleOrUndefined(ani_env *env, ani_object param, const char *name, ani_double &value) +{ + ani_ref obj = nullptr; + ani_status status = ANI_ERROR; + ani_boolean hasValue = true; + if (GetPropertyRef(env, param, name, obj, hasValue) && hasValue) { + TAG_LOGW(AAFwkTag::JSNAPI, "%{public}s : undefined", name); + return false; + } + if ((status = env->Object_CallMethodByName_Double( + reinterpret_cast(obj), "unboxed", nullptr, &value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + return true; +} + +bool GetBoolOrUndefined(ani_env *env, ani_object param, const char *name) +{ + ani_ref obj = nullptr; + ani_status status = ANI_ERROR; + ani_boolean res = false; + ani_boolean hasValue = true; + if (GetPropertyRef(env, param, name, obj, hasValue) && hasValue) { + TAG_LOGW(AAFwkTag::JSNAPI, "%{public}s : undefined", name); + return false; + } + if ((status = env->Object_CallMethodByName_Boolean(reinterpret_cast(obj), "unboxed", ":Z", &res)) != + ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return res; + } + return res; +} + +bool GetStringOrUndefined(ani_env *env, ani_object param, const char *name, std::string &res) +{ + ani_ref obj = nullptr; + ani_boolean hasValue = true; + if (GetPropertyRef(env, param, name, obj, hasValue) && hasValue) { + TAG_LOGW(AAFwkTag::JSNAPI, "%{public}s : undefined", name); + return false; + } + if (!GetStdString(env, reinterpret_cast(obj), res)) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetStdString failed"); + return false; + } + return true; +} + +bool GetFixedStringArrayOrUndefined(ani_env *env, ani_object param, const char *name, std::vector &res) +{ + ani_ref obj = nullptr; + ani_status status; + ani_size size = 0; + ani_size i; + ani_ref ref; + std::string str; + ani_boolean hasValue = true; + if (GetPropertyRef(env, param, name, obj, hasValue) && hasValue) { + TAG_LOGW(AAFwkTag::JSNAPI, "%{public}s : undefined", name); + return false; + } + if ((status = env->Array_GetLength(reinterpret_cast(obj), &size)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + for (i = 0; i < size; i++) { + if ((status = env->Array_Get_Ref(reinterpret_cast(obj), i, &ref)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d, index: %{public}zu", status, i); + return false; + } + + str = ""; + if (!GetStdString(env, reinterpret_cast(ref), str)) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetStdString failed, index: %{public}zu", i); + return false; + } + + res.push_back(str); + } + + return true; +} + +bool SetFieldFixedArrayString(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, + const std::vector &values) +{ + ani_field field = nullptr; + ani_array_ref array = nullptr; + ani_class stringCls = nullptr; + ani_string string = nullptr; + ani_ref undefinedRef = nullptr; + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + status = env->FindClass(CLASSNAME_STRING, &stringCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + status = env->GetUndefined(&undefinedRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + status = env->Array_New_Ref(stringCls, values.size(), undefinedRef, &array); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + for (size_t i = 0; i < values.size(); ++i) { + string = nullptr; + status = env->String_NewUTF8(values[i].c_str(), values[i].size(), &string); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + status = env->Array_Set_Ref(array, i, string); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + } + status = env->Object_SetField_Ref(object, field, array); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + return true; +} + +bool GetStringArrayOrUndefined(ani_env *env, ani_object param, const char *name, std::vector &res) +{ + ani_ref arrayObj = nullptr; + ani_boolean isUndefined = true; + ani_status status; + ani_double length; + std::string str; + + if ((status = env->Object_GetFieldByName_Ref(param, name, &arrayObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(arrayObj, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + if (isUndefined) { + TAG_LOGW(AAFwkTag::JSNAPI, "%{public}s : undefined", name); + return false; + } + + status = env->Object_GetPropertyByName_Double(reinterpret_cast(arrayObj), "length", &length); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + for (int i = 0; i < static_cast(length); i++) { + ani_ref stringEntryRef; + status = env->Object_CallMethodByName_Ref(reinterpret_cast(arrayObj), + "$_get", "I:Lstd/core/Object;", &stringEntryRef, (ani_int)i); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d, index: %{public}d", status, i); + return false; + } + + str = ""; + if (!GetStdString(env, reinterpret_cast(stringEntryRef), str)) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetStdString failed, index: %{public}d", i); + return false; + } + + res.push_back(str); + TAG_LOGI(AAFwkTag::JSNAPI, "GetStdString index: %{public}d %{public}s", i, str.c_str()); + } + + return true; +} + + +bool SetFieldArrayString(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, + const std::vector &values) +{ + ani_field field = nullptr; + ani_class arrayCls = nullptr; + ani_method arrayCtor; + ani_object arrayObj; + ani_string string = nullptr; + + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + status = env->FindClass(CLASSNAME_ARRAY, &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, values.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + for (size_t i = 0; i < values.size(); i++) { + string = nullptr; + status = env->String_NewUTF8(values[i].c_str(), values[i].size(), &string); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", i, string); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + } + status = env->Object_SetField_Ref(object, field, arrayObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + return true; +} + +bool GetStdString(ani_env *env, ani_string str, std::string &res) +{ + ani_size sz {}; + ani_status status = ANI_ERROR; + if ((status = env->String_GetUTF8Size(str, &sz)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + res.resize(sz + 1); + if ((status = env->String_GetUTF8SubString(str, 0, sz, res.data(), res.size(), &sz)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + res.resize(sz); + return true; +} + +ani_string GetAniString(ani_env *env, const std::string &str) +{ + ani_string aniStr = nullptr; + ani_status status = env->String_NewUTF8(str.c_str(), str.size(), &aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + return aniStr; +} + +bool GetRefFieldByName(ani_env *env, ani_object param, const char *name, ani_ref &ref) +{ + ani_status status = ANI_ERROR; + if ((status = env->Object_GetFieldByName_Ref(param, name, &ref)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "Object_GetFieldByName_Ref failed, status : %{public}d", status); + return false; + } + + ani_boolean isUndefined = true; + if ((status = env->Reference_IsUndefined(ref, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "Reference_IsUndefined failed, status : %{public}d", status); + return false; + } + if (isUndefined) { + TAG_LOGW(AAFwkTag::JSNAPI, "wantParams is undefined"); + return false; + } + return true; +} + +ani_object createDouble(ani_env *env, ani_double value) +{ + ani_class persion_cls; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(CLASSNAME_DOUBLE, &persion_cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + ani_method personInfoCtor; + if ((status = env->Class_FindMethod(persion_cls, "", "D:V", &personInfoCtor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + ani_object personInfoObj; + if ((status = env->Object_New(persion_cls, personInfoCtor, &personInfoObj, value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + return personInfoObj; +} + +ani_object createBoolean(ani_env *env, ani_boolean value) +{ + ani_class persion_cls; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(CLASSNAME_BOOLEAN, &persion_cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + ani_method personInfoCtor; + if ((status = env->Class_FindMethod(persion_cls, "", "Z:V", &personInfoCtor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + ani_object personInfoObj; + if ((status = env->Object_New(persion_cls, personInfoCtor, &personInfoObj, value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + return personInfoObj; +} + +ani_object createInt(ani_env *env, ani_int value) +{ + ani_class cls; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(CLASSNAME_INT, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "FindClass status : %{public}d", status); + return nullptr; + } + ani_method ctor; + if ((status = env->Class_FindMethod(cls, "", "I:V", &ctor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "Class_FindMethod status : %{public}d", status); + return nullptr; + } + ani_object object; + if ((status = env->Object_New(cls, ctor, &object, value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "Object_New status : %{public}d", status); + return nullptr; + } + return object; +} + +ani_object createLong(ani_env *env, ani_long value) +{ + ani_class persion_cls; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(CLASSNAME_LONG, &persion_cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + ani_method personInfoCtor; + if ((status = env->Class_FindMethod(persion_cls, "", "J:V", &personInfoCtor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + ani_object personInfoObj; + if ((status = env->Object_New(persion_cls, personInfoCtor, &personInfoObj, value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + return personInfoObj; +} + +bool SetFieldString(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, + const std::string &value) +{ + ani_field field = nullptr; + ani_string string = nullptr; + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + + TAG_LOGI(AAFwkTag::JSNAPI, "fieldName : %{public}s", fieldName.c_str()); + + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + if (value.empty()) { + ani_ref nullRef = nullptr; + if ((status = env->GetNull(&nullRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + if ((status = env->Object_SetField_Ref(object, field, nullRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + return true; + } + + if ((status = env->String_NewUTF8(value.c_str(), value.size(), &string)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + if ((status = env->Object_SetField_Ref(object, field, string)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + return true; +} + +bool SetStringProperty(ani_env *env, ani_object param, const char *name, const std::string &value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null env"); + return false; + } + ani_string string = nullptr; + ani_status status; + if (value.empty()) { + ani_ref nullRef = nullptr; + if ((status = env->GetNull(&nullRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + if ((status = env->Object_SetPropertyByName_Ref(param, name, nullRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + return true; + } + if ((status = env->String_NewUTF8(value.c_str(), value.size(), &string)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + if ((status = env->Object_SetPropertyByName_Ref(param, name, string)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + return true; +} + +bool SetFieldBoolean(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, bool value) +{ + ani_field field = nullptr; + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + status = env->Object_SetField_Boolean(object, field, value); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + return true; +} + +bool SetFieldInt(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, int value) +{ + ani_field field = nullptr; + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}s", fieldName.c_str()); + return false; + } + status = env->Object_SetField_Int(object, field, value); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}s", fieldName.c_str()); + return false; + } + return true; +} + +bool SetOptionalFieldInt(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, int value) +{ + ani_field field = nullptr; + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK || field == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "Class_FindField failed or null field, status=%{public}d, fieldName=%{public}s", + status, fieldName.c_str()); + return false; + } + ani_object intObj = createInt(env, value); + if (intObj == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null intObj"); + return false; + } + status = env->Object_SetField_Ref(object, field, intObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "Object_SetField_Ref failed, status=%{public}d, fieldName=%{public}s", + status, fieldName.c_str()); + return false; + } + return true; +} + +bool SetFieldRef(ani_env *env, ani_class cls, ani_object object, const std::string &fieldName, ani_ref value) +{ + ani_field field = nullptr; + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "FindField %{public}s failed, status: %{public}d", fieldName.c_str(), status); + return false; + } + status = env->Object_SetField_Ref(object, field, value); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "SetField_Ref %{public}s failed, status: %{public}d", fieldName.c_str(), status); + return false; + } + return true; +} + +bool AniStringToStdString(ani_env *env, ani_string aniString, std::string &stdString) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "env is nullptr"); + return false; + } + ani_size sz {}; + ani_status status = ANI_ERROR; + if ((status = env->String_GetUTF8Size(aniString, &sz)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "String_ToUTF8Size failed, status: %{public}d", status); + return false; + } + stdString.resize(sz + 1); + if ((status = env->String_GetUTF8SubString(aniString, 0, sz, stdString.data(), stdString.size(), &sz)) + != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "String_GetUTF8SubString failed status: %{public}d", status); + return false; + } + return true; +} + +bool GetPropertyRef(ani_env *env, ani_object obj, const char *name, ani_ref &ref, ani_boolean &isUndefined) +{ + ani_status status = env->Object_GetPropertyByName_Ref(obj, name, &ref); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "Failed to get property '%{public}s', status: %{public}d", name, status); + return false; + } + status = env->Reference_IsUndefined(ref, &isUndefined); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "Failed to check undefined for '%{public}s', status: %{public}d", name, status); + return false; + } + return true; +} + +bool GetFieldRef(ani_env *env, ani_object obj, const char *name, ani_ref &ref, ani_boolean &isUndefined) +{ + ani_status status = env->Object_GetFieldByName_Ref(obj, name, &ref); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "Failed to get field '%{public}s', status: %{public}d", name, status); + return false; + } + status = env->Reference_IsUndefined(ref, &isUndefined); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "Failed to check undefined for '%{public}s', status: %{public}d", name, status); + return false; + } + return true; +} + +bool AsyncCallback(ani_env *env, ani_object call, ani_object error, ani_object result) +{ + ani_status status = ANI_ERROR; + ani_class clsCall {}; + + if ((status = env->FindClass(CLASSNAME_ASYNC_CALLBACK_WRAPPER, &clsCall)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + ani_method method {}; + if ((status = env->Class_FindMethod( + clsCall, "invoke", "L@ohos/base/BusinessError;Lstd/core/Object;:V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + if (result == nullptr) { + ani_ref nullRef = nullptr; + env->GetNull(&nullRef); + result = reinterpret_cast(nullRef); + } + if ((status = env->Object_CallMethod_Void(call, method, error, result)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + return true; +} + +ani_object GetPropertyValueByName(ani_env *env, ani_object param, const char *propertyName) +{ + ani_boolean isUndefined = true; + ani_ref valueRef = nullptr; + if (!AppExecFwk::GetFieldRef(env, param, propertyName, valueRef, isUndefined)) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetFieldRef failed"); + return nullptr; + } + + if (isUndefined) { + TAG_LOGE(AAFwkTag::JSNAPI, "propertyName isUndefined: %{public}s ", propertyName); + return nullptr; + } + + if (valueRef == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetPropertyValueRef is nullptr "); + return nullptr; + } + return reinterpret_cast(valueRef); +} + +bool IsExistsProperty(ani_env *env, ani_object param, const char *name) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null env"); + return false; + } + + ani_ref resRef = nullptr; + ani_status status; + ani_boolean isUndefined = true; + + if ((status = env->Object_GetPropertyByName_Ref(param, name, &resRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(resRef, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + if (isUndefined) { + return false; + } + return true; +} + +bool GetStringProperty(ani_env *env, ani_object param, const char *name, std::string &value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null env"); + return false; + } + + ani_ref obj = nullptr; + ani_boolean isUndefined = true; + ani_status status = ANI_ERROR; + + if ((status = env->Object_GetPropertyByName_Ref(param, name, &obj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(obj, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + if (isUndefined) { + TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s : undefined", name); + return false; + } + if (!GetStdString(env, reinterpret_cast(obj), value)) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetStdString failed"); + return false; + } + return true; +} + +bool GetStringArrayProperty(ani_env *env, ani_object param, const char *name, std::vector &value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null env"); + return false; + } + + ani_ref arrayObj = nullptr; + ani_boolean isUndefined = true; + ani_status status; + ani_double length; + std::string str; + + if ((status = env->Object_GetPropertyByName_Ref(param, name, &arrayObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(arrayObj, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + if (isUndefined) { + TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s : undefined", name); + return false; + } + + status = env->Object_GetPropertyByName_Double(reinterpret_cast(arrayObj), "length", &length); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + + for (int i = 0; i < static_cast(length); i++) { + ani_ref stringEntryRef; + status = env->Object_CallMethodByName_Ref(reinterpret_cast(arrayObj), + "$_get", "I:Lstd/core/Object;", &stringEntryRef, (ani_int)i); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d, index: %{public}d", status, i); + return false; + } + + str = ""; + if (!GetStdString(env, reinterpret_cast(stringEntryRef), str)) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetStdString failed, index: %{public}d", i); + return false; + } + + value.push_back(str); + TAG_LOGI(AAFwkTag::JSNAPI, "GetStdString index: %{public}d %{public}s", i, str.c_str()); + } + + return true; +} + +bool GetDoublePropertyObject(ani_env *env, ani_object param, const char *name, double &value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null env"); + return false; + } + + ani_ref obj = nullptr; + ani_status status = ANI_ERROR; + ani_boolean hasValue = true; + if (GetPropertyRef(env, param, name, obj, hasValue) && hasValue) { + TAG_LOGW(AAFwkTag::JSNAPI, "%{public}s : undefined", name); + return false; + } + if ((status = env->Object_CallMethodByName_Double( + reinterpret_cast(obj), "unboxed", nullptr, &value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + return true; +} +bool GetDoublePropertyValue(ani_env *env, ani_object param, const char *name, double &value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null env"); + return false; + } + + ani_status status = ANI_ERROR; + ani_double res; + if ((status = env->Object_GetPropertyByName_Double(param, name, &res)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + value = static_cast(res); + return true; +} + +bool GetRefProperty(ani_env *env, ani_object param, const char *name, ani_ref &value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null env"); + return false; + } + + ani_status status; + ani_boolean isUndefined = true; + + if ((status = env->Object_GetPropertyByName_Ref(param, name, &value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(value, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + if (isUndefined) { + return false; + } + return true; +} + +bool SetDoublePropertyObject(ani_env *env, ani_object param, const char *name, double value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null env"); + return false; + } + + ani_object obj = createDouble(env, static_cast(value)); + if (obj == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null obj"); + return false; + } + + ani_status status = ANI_ERROR; + if ((status = env->Object_SetPropertyByName_Ref(param, name, obj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + return true; +} + +bool SetDoublePropertyValue(ani_env *env, ani_object param, const char *name, double value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null env"); + return false; + } + + ani_status status = ANI_ERROR; + if ((status = env->Object_SetPropertyByName_Double(param, name, value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + return true; +} + +bool SetStringArrayProperty(ani_env *env, ani_object param, const char *name, const std::vector &values) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null env"); + return false; + } + + ani_class arrayCls = nullptr; + ani_method arrayCtor; + ani_object arrayObj; + ani_string string = nullptr; + + ani_status status = env->FindClass("Lescompat/Array;", &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + + status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, values.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + + for (size_t i = 0; i < values.size(); i++) { + string = nullptr; + status = env->String_NewUTF8(values[i].c_str(), values[i].size(), &string); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", i, string); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + } + status = env->Object_SetPropertyByName_Ref(param, name, arrayObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + + return true; +} + +bool SetRefProperty(ani_env *env, ani_object param, const char *name, ani_ref value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null env"); + return false; + } + + ani_status status; + if ((status = env->Object_SetPropertyByName_Ref(param, name, value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + return true; +} + +bool WrapArrayString(ani_env *env, ani_object &arrayObj, const std::vector &values) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "env null or arrayObj null"); + return false; + } + ani_class arrayCls = nullptr; + ani_method arrayCtor; + ani_string aniStr = nullptr; + ani_status status = ANI_ERROR; + status = env->FindClass(CLASSNAME_ARRAY, &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + status = env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, values.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + + for (size_t i = 0; i < values.size(); i++) { + aniStr = nullptr; + status = env->String_NewUTF8(values[i].c_str(), values[i].size(), &aniStr); + if (aniStr == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null aniStr"); + return false; + } + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", SET_OBJECT_VOID_SIGNATURE, i, aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + } + return true; +} + +bool UnwrapArrayString(ani_env *env, const ani_object &arrayObj, std::vector &stringList) +{ + if (env == nullptr || arrayObj == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "env null or arrayObj null"); + return false; + } + stringList.clear(); + ani_size size = 0; + ani_status status = ANI_ERROR; + if ((status = env->Array_GetLength(reinterpret_cast(arrayObj), &size)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "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::JSNAPI, "status : %{public}d, index: %{public}zu", status, idx); + return false; + } + if (ref == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null ref"); + return false; + } + std::string str = ""; + if (!OHOS::AppExecFwk::GetStdString(env, reinterpret_cast(ref), str)) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetStdString failed, index: %{public}zu", idx); + return false; + } + stringList.push_back(str); + } + return true; +} +} // 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 new file mode 100644 index 0000000000000000000000000000000000000000..81e684d9b69e25bff426c68b58f2b3ed5307f1fe --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/ani_common_want.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 "ani_common_want.h" + +#include "array_wrapper.h" +#include "bool_wrapper.h" +#include "byte_wrapper.h" +#include "double_wrapper.h" +#include "float_wrapper.h" +#include "hilog_tag_wrapper.h" +#include "int_wrapper.h" +#include "ipc_skeleton.h" +#include "long_wrapper.h" +#include "short_wrapper.h" +#include "string_wrapper.h" +#include "want_params_wrapper.h" +#include "zchar_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +namespace { +constexpr const char* WANT_CLASS_NAME = "L@ohos/app/ability/Want/Want;"; +constexpr const char* RECORD_SERIALIZE_TOOL_CLASS_NAME = "L@ohos/app/ability/Want/RecordSerializeTool;"; +constexpr const char* ABILITY_RESULT_INNER_CLASS_NAME = "Lability/abilityResult/AbilityResultInner;"; + +bool InnerWrapWantParams(ani_env* env, ani_class wantCls, ani_object wantObject, const AAFwk::WantParams& wantParams) +{ + ani_ref wantParamRef = WrapWantParams(env, wantParams); + if (wantParamRef == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "failed to WrapWantParams"); + return false; + } + return SetFieldRef(env, wantCls, wantObject, "parameters", wantParamRef); +} + +bool InnerUnwrapWantParams(ani_env* env, ani_object wantObject, AAFwk::WantParams& wantParams) +{ + ani_ref wantParamRef = nullptr; + if (!GetRefFieldByName(env, wantObject, "parameters", wantParamRef)) { + TAG_LOGE(AAFwkTag::JSNAPI, "failed to get want parameter"); + return false; + } + return UnwrapWantParams(env, wantParamRef, wantParams); +} +} + +ani_object WrapWant(ani_env *env, const AAFwk::Want &want) +{ + TAG_LOGI(AAFwkTag::JSNAPI, "WrapWant"); + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object object = nullptr; + if ((status = env->FindClass(WANT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null wantCls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null object"); + return nullptr; + } + + auto elementName = want.GetElement(); + env->Object_SetFieldByName_Ref(object, "deviceId", GetAniString(env, elementName.GetDeviceID())); + env->Object_SetFieldByName_Ref(object, "bundleName", GetAniString(env, elementName.GetBundleName())); + env->Object_SetFieldByName_Ref(object, "abilityName", GetAniString(env, elementName.GetAbilityName())); + env->Object_SetFieldByName_Ref(object, "moduleName", GetAniString(env, elementName.GetModuleName())); + env->Object_SetFieldByName_Ref(object, "uri", GetAniString(env, want.GetUriString())); + env->Object_SetFieldByName_Ref(object, "type", GetAniString(env, want.GetType())); + env->Object_SetFieldByName_Ref(object, "flags", createDouble(env, want.GetFlags())); + env->Object_SetFieldByName_Ref(object, "action", GetAniString(env, want.GetAction())); + InnerWrapWantParams(env, cls, object, want.GetParams()); + SetFieldArrayString(env, cls, object, "entities", want.GetEntities()); + return object; +} + +ani_ref WrapWantParams(ani_env *env, const AAFwk::WantParams &wantParams) +{ + ani_status status = ANI_ERROR; + ani_class cls = nullptr; + if ((status = env->FindClass(RECORD_SERIALIZE_TOOL_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "FindClass RecordSerializeTool failed, status : %{public}d", status); + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "RecordSerializeTool class null"); + return nullptr; + } + ani_static_method parseNoThrowMethod = nullptr; + status = env->Class_FindStaticMethod(cls, "parseNoThrow", nullptr, &parseNoThrowMethod); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "failed to get parseNoThrow method, status : %{public}d", status); + return nullptr; + } + + nlohmann::json wantParamsJson = wantParams; + std::string wantParamsString = wantParamsJson.dump(); + ani_string wantParamsAniString; + status = env->String_NewUTF8(wantParamsString.c_str(), wantParamsString.length(), &wantParamsAniString); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "String_NewUTF8 wantParamsString failed, status : %{public}d", status); + return nullptr; + } + + ani_ref wantParamsRef = nullptr; + status = env->Class_CallStaticMethod_Ref(cls, parseNoThrowMethod, &wantParamsRef, wantParamsAniString); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "failed to call parseNoThrow method, status : %{public}d", status); + return nullptr; + } + return wantParamsRef; +} + +ani_object WrapElementName(ani_env *env, const AppExecFwk::ElementName &elementNameParam) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "WrapElementName"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "null env"); + return nullptr; + } + ani_class elementNameObj = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_object object = {}; + static const char *className = "LbundleManager/ElementNameInner/ElementNameInner;"; + if ((status = env->FindClass(className, &elementNameObj)) != ANI_OK || elementNameObj == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "FindClass status : %{public}d or null elementNameObj", status); + return nullptr; + } + if ((status = env->Class_FindMethod(elementNameObj, "", ":V", &method)) != ANI_OK || method == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Class_FindMethod status : %{public}d or null method", status); + return nullptr; + } + if ((status = env->Object_New(elementNameObj, method, &object)) != ANI_OK || object == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Object_New status : %{public}d or null object", status); + return nullptr; + } + return WrapElementNameInner(env, elementNameObj, object, elementNameParam); +} + +ani_object WrapElementNameInner(ani_env *env, ani_class elementNameObj, ani_object object, + const AppExecFwk::ElementName &elementNameParam) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "WrapElementNameInner"); + if (env == nullptr || elementNameObj == nullptr || object == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid args"); + return nullptr; + } + if (!SetFieldString(env, elementNameObj, object, "bundleName", elementNameParam.GetBundleName())) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set bundleName failed"); + return nullptr; + } + if (!SetFieldString(env, elementNameObj, object, "abilityName", elementNameParam.GetAbilityName())) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set abilityName failed"); + return nullptr; + } + if (!SetStringProperty(env, object, "deviceId", elementNameParam.GetDeviceID())) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set deviceId failed"); + } + if (!SetStringProperty(env, object, "moduleName", elementNameParam.GetModuleName())) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set moduleName failed"); + } + if (!SetStringProperty(env, object, "uri", elementNameParam.GetURI())) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "set uri failed"); + } + return object; +} + +bool UnwrapElementName(ani_env *env, ani_object param, ElementName &elementName) +{ + std::string deviceId; + if (GetStringOrUndefined(env, param, "deviceId", deviceId)) { + elementName.SetDeviceID(deviceId); + } + + std::string bundleName; + if (GetStringOrUndefined(env, param, "bundleName", bundleName)) { + elementName.SetBundleName(bundleName); + } + + std::string abilityName; + if (GetStringOrUndefined(env, param, "abilityName", abilityName)) { + elementName.SetAbilityName(abilityName); + } + + std::string moduleName; + if (GetStringOrUndefined(env, param, "moduleName", moduleName)) { + elementName.SetModuleName(moduleName); + } + return true; +} + +bool UnwrapWant(ani_env *env, ani_object param, AAFwk::Want &want) +{ + TAG_LOGI(AAFwkTag::JSNAPI, "UnwrapWant"); + std::string action; + if (GetStringOrUndefined(env, param, "action", action)) { + TAG_LOGI(AAFwkTag::UIABILITY, "action %{public}s", action.c_str()); + want.SetAction(action); + } + + std::string uri = ""; + if (GetStringOrUndefined(env, param, "uri", uri)) { + TAG_LOGI(AAFwkTag::UIABILITY, "uri %{public}s", uri.c_str()); + want.SetUri(uri); + } + + ani_double flags = 0.0; + if (GetDoubleOrUndefined(env, param, "flags", flags)) { + TAG_LOGI(AAFwkTag::UIABILITY, "flags %{public}f", flags); + want.SetFlags(static_cast(flags)); + } + + std::string type = ""; + if (GetStringOrUndefined(env, param, "type", type)) { + TAG_LOGI(AAFwkTag::UIABILITY, "type %{public}s", type.c_str()); + want.SetType(type); + } + + ElementName natElementName; + UnwrapElementName(env, param, natElementName); + want.SetElementName(natElementName.GetDeviceID(), natElementName.GetBundleName(), natElementName.GetAbilityName(), + natElementName.GetModuleName()); + + std::vector valueStringList; + if (GetStringArrayOrUndefined(env, param, "entities", valueStringList)) { + for (size_t i = 0; i < valueStringList.size(); i++) { + want.AddEntity(valueStringList[i]); + } + } + + TAG_LOGD(AAFwkTag::UIABILITY, + "DeviceID %{public}s, BundleName %{public}s, AbilityName %{public}s, ModuleName %{public}s", + natElementName.GetDeviceID().c_str(), natElementName.GetBundleName().c_str(), + natElementName.GetAbilityName().c_str(), natElementName.GetModuleName().c_str()); + + AAFwk::WantParams wantParams; + if (InnerUnwrapWantParams(env, param, wantParams)) { + want.SetParams(wantParams); + } + return true; +} + +bool UnwrapWantParams(ani_env *env, ani_ref param, AAFwk::WantParams &wantParams) +{ + ani_status status = ANI_ERROR; + ani_class cls = nullptr; + if ((status = env->FindClass(RECORD_SERIALIZE_TOOL_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "FindClass RecordSerializeTool failed, status : %{public}d", status); + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "RecordSerializeTool class null"); + return false; + } + + ani_static_method stringifyMethod = nullptr; + status = env->Class_FindStaticMethod(cls, "stringifyNoThrow", nullptr, &stringifyMethod); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "failed to get stringifyNoThrow method, status : %{public}d", status); + return false; + } + ani_ref wantParamsAniString; + status = env->Class_CallStaticMethod_Ref(cls, stringifyMethod, &wantParamsAniString, param); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "failed to call stringifyNoThrow method, status : %{public}d", status); + return false; + } + + std::string wantParamsString; + if (!GetStdString(env, reinterpret_cast(wantParamsAniString), wantParamsString)) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetStdString failed"); + return false; + } + if (wantParamsString.empty()) { + TAG_LOGE(AAFwkTag::JSNAPI, "wantParamsString empty"); + return false; + } + nlohmann::json wantParamsJson = nlohmann::json::parse(wantParamsString, nullptr, false); + if (wantParamsJson.is_discarded()) { + TAG_LOGE(AAFwkTag::JSNAPI, "Failed to parse json string"); + return false; + } + from_json(wantParamsJson, wantParams); + return true; +} + +bool GetAbilityResultClass(ani_env *env, ani_class &cls) +{ + ani_status status = env->FindClass(ABILITY_RESULT_INNER_CLASS_NAME, &cls); + if (status != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + return true; +} + +bool GetResultCode(ani_env *env, ani_object param, ani_class cls, int &resultCode) +{ + ani_method method {}; + ani_status status = env->Class_FindMethod(cls, "resultCode", nullptr, &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + ani_double dResultCode = 0.0; + status = env->Object_CallMethod_Double(param, method, &dResultCode); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + resultCode = static_cast(dResultCode); + return true; +} + +bool GetWantReference(ani_env *env, ani_object param, ani_class cls, ani_ref &wantRef) +{ + ani_method method {}; + ani_status status = env->Class_FindMethod(cls, "want", nullptr, &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + status = env->Object_CallMethod_Ref(param, method, &wantRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + ani_boolean isUndefined = true; + status = env->Reference_IsUndefined(wantRef, &isUndefined); + if (status != ANI_OK || isUndefined) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + return true; +} + +bool UnWrapAbilityResult(ani_env *env, ani_object param, int &resultCode, AAFwk::Want &want) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "env is null"); + return false; + } + ani_class cls {}; + if (!GetAbilityResultClass(env, cls)) { + return false; + } + if (!GetResultCode(env, param, cls, resultCode)) { + return false; + } + ani_ref wantRef = nullptr; + if (!GetWantReference(env, param, cls, wantRef)) { + return false; + } + return UnwrapWant(env, reinterpret_cast(wantRef), want); +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/frameworks/ets/ani/ani_wantagent_common/BUILD.gn b/frameworks/ets/ani/ani_wantagent_common/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..a2c56476a19aedf647e6c05477f22cec1bd4303e --- /dev/null +++ b/frameworks/ets/ani/ani_wantagent_common/BUILD.gn @@ -0,0 +1,50 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +config("ani_wantagent_common_public_config") { + include_dirs = [ "./" ] +} + +ohos_shared_library("ani_wantagent_common") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + branch_protector_ret = "pac_ret" + + public_configs = [ ":ani_wantagent_common_public_config" ] + + sources = [ "ani_common_want_agent.cpp" ] + + deps = [ + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_innerkits_path}/wantagent:wantagent_innerkits", + ] + + external_deps = [ + "hilog:libhilog", + "runtime_core:ani", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/ani_wantagent_common/ani_common_want_agent.cpp b/frameworks/ets/ani/ani_wantagent_common/ani_common_want_agent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3776fcab0a33b69821faa678eae8049241cb48c3 --- /dev/null +++ b/frameworks/ets/ani/ani_wantagent_common/ani_common_want_agent.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_common_want_agent.h" + +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +namespace { +constexpr const char* LONG_CLASS = "Lstd/core/Long;"; + +ani_object createLong(ani_env *env, ani_long value) +{ + ani_class persion_cls; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(LONG_CLASS, &persion_cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + ani_method personInfoCtor; + if ((status = env->Class_FindMethod(persion_cls, "", "J:V", &personInfoCtor)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + ani_object personInfoObj; + if ((status = env->Object_New(persion_cls, personInfoCtor, &personInfoObj, value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + return personInfoObj; +} +} // namespace + +ani_object WrapWantAgent(ani_env *env, WantAgent *wantAgent) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "env null"); + return nullptr; + } + if (wantAgent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "wantAgent null"); + return nullptr; + } + ani_long pWantAgent = reinterpret_cast(wantAgent); + ani_object longObj = createLong(env, pWantAgent); + if (longObj == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null object"); + return nullptr; + } + return longObj; +} + +void UnwrapWantAgent(ani_env *env, ani_object agent, void** result) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "env null"); + return; + } + if (agent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "agent null"); + return; + } + ani_long param_value; + ani_status status = ANI_ERROR; + ani_class cls {}; + ani_method method {}; + if ((status = env->FindClass(LONG_CLASS, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "FindClass failed status: %{public}d", status); + return; + } + if ((status = env->Class_FindMethod(cls, "unboxed", nullptr, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Class_FindMethod failed status: %{public}d", status); + return; + } + if ((status = env->Object_CallMethod_Long(agent, method, ¶m_value)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Object_CallMethod_Long failed status: %{public}d", status); + return; + } + *result = reinterpret_cast(param_value); +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/frameworks/ets/ani/ani_wantagent_common/ani_common_want_agent.h b/frameworks/ets/ani/ani_wantagent_common/ani_common_want_agent.h new file mode 100644 index 0000000000000000000000000000000000000000..701f012ae9876c241c01e4e896a5163b0420c347 --- /dev/null +++ b/frameworks/ets/ani/ani_wantagent_common/ani_common_want_agent.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_COMMON_WANT_AGENT_H +#define OHOS_ABILITY_RUNTIME_ANI_COMMON_WANT_AGENT_H + +#include "ani.h" +#include "want_agent.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace OHOS::AbilityRuntime::WantAgent; + +ani_object WrapWantAgent(ani_env *env, WantAgent *wantAgent); +void UnwrapWantAgent(ani_env *env, ani_object agent, void** result); + +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANI_COMMON_WANT_AGENT_H diff --git a/frameworks/ets/ani/app/ability_stage_context/BUILD.gn b/frameworks/ets/ani/app/ability_stage_context/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..3f30441af4f1c5b28cd9851f51d73c68fc3469dc --- /dev/null +++ b/frameworks/ets/ani/app/ability_stage_context/BUILD.gn @@ -0,0 +1,66 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("ability_stage_context_ani_kit") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/interfaces/inner_api", + "${ability_runtime_path}/interfaces/kits/native/appkit", + "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", + ] + + configs = [] + + public_configs = [] + + sources = [ "./src/ets_ability_stage_context_module.cpp" ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/ani_base_context:ani_base_context", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_native_path}/appkit:app_context_utils", + "${ability_runtime_native_path}/appkit:appkit_native", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "napi:ace_napi", + "runtime_core:ani", + "runtime_core:ani_helpers", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/app/ability_stage_context/include/ets_ability_stage_context_module.h b/frameworks/ets/ani/app/ability_stage_context/include/ets_ability_stage_context_module.h new file mode 100755 index 0000000000000000000000000000000000000000..e98ff1d986445f163f78172d28d8595b2a2b0ac3 --- /dev/null +++ b/frameworks/ets/ani/app/ability_stage_context/include/ets_ability_stage_context_module.h @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_ABILITY_STAGE_CONTEXT_MODULE_H +#define OHOS_ABILITY_RUNTIME_ETS_ABILITY_STAGE_CONTEXT_MODULE_H + +#include +#include "ani.h" +#include "ability_stage_context.h" +#include "native_engine/native_engine.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsAbilityStageContextModule { +public: + EtsAbilityStageContextModule() = default; + ~EtsAbilityStageContextModule() = default; + + EtsAbilityStageContextModule(const EtsAbilityStageContextModule&) = delete; + EtsAbilityStageContextModule(EtsAbilityStageContextModule&&) = delete; + EtsAbilityStageContextModule& operator=(const EtsAbilityStageContextModule&) = delete; + EtsAbilityStageContextModule& operator=(EtsAbilityStageContextModule&&) = delete; + + static ani_object NativeTransferStatic(ani_env *aniEnv, ani_object aniObj, ani_object input); + static ani_object NativeTransferDynamic(ani_env *aniEnv, ani_object aniObj, ani_object input); + +private: + static bool IsInstanceOf(ani_env *aniEnv, ani_object aniObj); + static std::unique_ptr GetOrCreateNativeReference(napi_env napiEnv, + std::shared_ptr abilityStageContext); + static std::unique_ptr CreateNativeReference(napi_env napiEnv, + std::shared_ptr abilityStageContext); +}; + +void EtsAbilityStageContextModuleInit(ani_env *aniEnv); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_STAGE_CONTEXT_MODULE_H diff --git a/frameworks/ets/ani/app/ability_stage_context/src/ets_ability_stage_context_module.cpp b/frameworks/ets/ani/app/ability_stage_context/src/ets_ability_stage_context_module.cpp new file mode 100755 index 0000000000000000000000000000000000000000..6f20b20784544df89ad1713f4dfa6a123eebfb1d --- /dev/null +++ b/frameworks/ets/ani/app/ability_stage_context/src/ets_ability_stage_context_module.cpp @@ -0,0 +1,284 @@ +/* + * 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_stage_context_module.h" + +#include +#include +#include +#include "ability_stage_context.h" +#include "ani_base_context.h" +#include "hilog_tag_wrapper.h" +#include "interop_js/arkts_esvalue.h" +#include "interop_js/hybridgref_ani.h" +#include "interop_js/hybridgref_napi.h" +#include "js_ability_stage_context.h" +#include "js_runtime_utils.h" +#include "native_engine/native_engine.h" +#include "sts_ability_stage_context.h" +#include "sts_error_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char *ETS_ABILITY_STAGE_CONTEXT_CLASS_NAME = "Lapplication/AbilityStageContext/AbilityStageContext;"; +} // namespace + +ani_object EtsAbilityStageContextModule::NativeTransferStatic(ani_env *aniEnv, ani_object, ani_object input) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "transfer static AbilityStageContext"); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null aniEnv"); + return nullptr; + } + + void *unwrapResult = nullptr; + bool success = arkts_esvalue_unwrap(aniEnv, input, &unwrapResult); + if (!success) { + TAG_LOGE(AAFwkTag::CONTEXT, "failed to unwrap"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + if (unwrapResult == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null unwrapResult"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + auto context = reinterpret_cast *>(unwrapResult)->lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null AbilityStageContext"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + auto abilityStageContext = Context::ConvertTo(context); + if (abilityStageContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "invalid abilityStageContext"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + auto &bindingObj = abilityStageContext->GetBindingObject(); + if (bindingObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null bindingObj"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + auto staticContext = bindingObj->Get(); + if (staticContext != nullptr) { + TAG_LOGI(AAFwkTag::CONTEXT, "there exist a staticContext"); + return reinterpret_cast(*staticContext); + } + + // if not exist, create a new one + auto newContext = STSAbilityStageContext::CreateStsAbilityStageContext(aniEnv, abilityStageContext); + if (newContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "create abilityStageContext failed"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + return newContext; +} + +std::unique_ptr EtsAbilityStageContextModule::CreateNativeReference(napi_env napiEnv, + std::shared_ptr abilityStageContext) +{ + if (napiEnv == nullptr || abilityStageContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null param"); + return nullptr; + } + + auto value = CreateJsAbilityStageContext(napiEnv, abilityStageContext); + auto systemModule = JsRuntime::LoadSystemModuleByEngine(napiEnv, "application.AbilityStageContext", &value, 1); + if (systemModule == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null systemModule"); + return nullptr; + } + + napi_value object = systemModule->GetNapiValue(); + if (!CheckTypeForNapiValue(napiEnv, object, napi_object)) { + TAG_LOGE(AAFwkTag::CONTEXT, "check type failed"); + return nullptr; + } + + auto workContext = new (std::nothrow) std::weak_ptr(abilityStageContext); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null workContext"); + return nullptr; + } + auto status = napi_coerce_to_native_binding_object(napiEnv, object, DetachCallbackFunc, AttachAbilityStageContext, + workContext, nullptr); + if (status != napi_ok) { + TAG_LOGE(AAFwkTag::CONTEXT, "coerce AbilityStageContext failed: %{public}d", status); + delete workContext; + return nullptr; + } + + status = napi_wrap(napiEnv, object, workContext, + [](napi_env, void *data, void *) { + TAG_LOGD(AAFwkTag::CONTEXT, "finalizer for weak_ptr AbilityStageContext"); + delete static_cast *>(data); + }, nullptr, nullptr); + if (status != napi_ok) { + TAG_LOGE(AAFwkTag::CONTEXT, "wrap failed: %{public}d", status); + delete workContext; + return nullptr; + } + + return systemModule; +} + +std::unique_ptr EtsAbilityStageContextModule::GetOrCreateNativeReference(napi_env napiEnv, + std::shared_ptr abilityStageContext) +{ + if (napiEnv == nullptr || abilityStageContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null param"); + return nullptr; + } + + // if sub-thread, create a new abilityStageContext and return + if (getpid() != syscall(SYS_gettid)) { + return CreateNativeReference(napiEnv, abilityStageContext); + } + + // if main-thread, get bindingObj firstly + auto &bindingObj = abilityStageContext->GetBindingObject(); + if (bindingObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null bindingObj"); + return nullptr; + } + + // if main-thread bindingObj exist, return it directly + auto dynamicContext = bindingObj->Get(); + if (dynamicContext != nullptr) { + TAG_LOGI(AAFwkTag::UIABILITY, "there exist a dynamicContext"); + return std::unique_ptr(dynamicContext); + } + + // if main-thread bindingObj didn't exist, create and bind + auto nativeRef = CreateNativeReference(napiEnv, abilityStageContext); + if (nativeRef == nullptr) { + return nullptr; + } + + abilityStageContext->Bind(nativeRef.get()); + return nativeRef; +} + +ani_object EtsAbilityStageContextModule::NativeTransferDynamic(ani_env *aniEnv, ani_object, ani_object input) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "transfer dynamic AbilityStageContext"); + if (!IsInstanceOf(aniEnv, input)) { + TAG_LOGE(AAFwkTag::CONTEXT, "not AbilityStageContext"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + auto context = AbilityRuntime::GetStageModeContext(aniEnv, input); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + auto abilityStageContext = Context::ConvertTo(context); + if (abilityStageContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "invalid abilityStageContext"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + // Not support yet + ThrowStsTransferClassError(aniEnv); + return nullptr; +} + +bool EtsAbilityStageContextModule::IsInstanceOf(ani_env *aniEnv, ani_object aniObj) +{ + ani_class cls {}; + ani_status status = ANI_ERROR; + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null aniEnv"); + return false; + } + if ((status = aniEnv->FindClass(ETS_ABILITY_STAGE_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "FindClass status: %{public}d", status); + return false; + } + ani_boolean isInstanceOf = false; + if ((status = aniEnv->Object_InstanceOf(aniObj, cls, &isInstanceOf)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "Object_InstanceOf status: %{public}d", status); + return false; + } + return isInstanceOf; +} + +void EtsAbilityStageContextModuleInit(ani_env *aniEnv) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "Init AbilityStageContext kit"); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null ani env"); + return; + } + + ani_class abilityStageContextCls = nullptr; + auto status = aniEnv->FindClass(ETS_ABILITY_STAGE_CONTEXT_CLASS_NAME, &abilityStageContextCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "FindClass AbilityStageContext failed status: %{public}d", status); + return; + } + + std::array nativeFuncs = { + ani_native_function { "nativeTransferStatic", "Lstd/interop/ESValue;:Lstd/core/Object;", + reinterpret_cast(EtsAbilityStageContextModule::NativeTransferStatic) }, + ani_native_function { "nativeTransferDynamic", "Lstd/core/Object;:Lstd/interop/ESValue;", + reinterpret_cast(EtsAbilityStageContextModule::NativeTransferDynamic) }, + }; + status = aniEnv->Class_BindNativeMethods(abilityStageContextCls, nativeFuncs.data(), nativeFuncs.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_BindNativeMethods failed status: %{public}d", status); + return; + } + + TAG_LOGD(AAFwkTag::CONTEXT, "Init AbilityStageContext kit end"); +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "ANI_Constructor"); + if (vm == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null vm"); + return ANI_ERROR; + } + + ani_env *aniEnv = nullptr; + ani_status status = vm->GetEnv(ANI_VERSION_1, &aniEnv); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "GetEnv failed status: %{public}d", status); + return ANI_NOT_FOUND; + } + + EtsAbilityStageContextModuleInit(aniEnv); + *result = ANI_VERSION_1; + TAG_LOGD(AAFwkTag::CONTEXT, "ANI_Constructor finish"); + return ANI_OK; +} +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/app/application_context/BUILD.gn b/frameworks/ets/ani/app/application_context/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..6517cd9775b5057e3654be1017f6ac9560f2eabd --- /dev/null +++ b/frameworks/ets/ani/app/application_context/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("application_context_ani_kit") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_napi_path}/ability_auto_startup_callback", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", + ] + + configs = [] + + public_configs = [] + + sources = [ "./src/ets_application_context_module.cpp" ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/ani_base_context:ani_base_context", + "${ability_runtime_innerkits_path}/error_utils:ability_runtime_error_util", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_napi_path}/inner/napi_common:napi_common", + "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_native_path}/appkit:app_context_utils", + "${ability_runtime_native_path}/appkit:application_context_manager", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "napi:ace_napi", + "runtime_core:ani", + "runtime_core:ani_helpers", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/app/application_context/include/ets_application_context_module.h b/frameworks/ets/ani/app/application_context/include/ets_application_context_module.h new file mode 100755 index 0000000000000000000000000000000000000000..5955f66d16edef2baff3bbce971db393646421ec --- /dev/null +++ b/frameworks/ets/ani/app/application_context/include/ets_application_context_module.h @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_APPLICATION_CONTEXT_MODULE_H +#define OHOS_ABILITY_RUNTIME_ETS_APPLICATION_CONTEXT_MODULE_H + +#include +#include "ani.h" +#include "application_context.h" +#include "native_engine/native_engine.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsApplicationContextModule { +public: + EtsApplicationContextModule() = default; + ~EtsApplicationContextModule() = default; + + EtsApplicationContextModule(const EtsApplicationContextModule&) = delete; + EtsApplicationContextModule(EtsApplicationContextModule&&) = delete; + EtsApplicationContextModule& operator=(const EtsApplicationContextModule&) = delete; + EtsApplicationContextModule& operator=(EtsApplicationContextModule&&) = delete; + + static ani_object NativeTransferStatic(ani_env *aniEnv, ani_object aniObj, ani_object input); + static ani_object NativeTransferDynamic(ani_env *aniEnv, ani_object aniObj, ani_object input); + +private: + static bool IsInstanceOf(ani_env *aniEnv, ani_object aniObj); + static std::unique_ptr GetOrCreateNativeReference(napi_env napiEnv, + std::shared_ptr applicationContext); + static std::unique_ptr CreateNativeReference(napi_env napiEnv, + std::shared_ptr applicationContext); +}; + +void EtsApplicationContextModuleInit(ani_env *aniEnv); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_APPLICATION_CONTEXT_MODULE_H diff --git a/frameworks/ets/ani/app/application_context/src/ets_application_context_module.cpp b/frameworks/ets/ani/app/application_context/src/ets_application_context_module.cpp new file mode 100755 index 0000000000000000000000000000000000000000..958ed653ce867b5a8bbde5b414f8e2b090b286ab --- /dev/null +++ b/frameworks/ets/ani/app/application_context/src/ets_application_context_module.cpp @@ -0,0 +1,286 @@ +/* + * 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_context_module.h" + +#include +#include +#include +#include "ani_base_context.h" +#include "application_context_manager.h" +#include "ets_application_context_utils.h" +#include "hilog_tag_wrapper.h" +#include "interop_js/arkts_esvalue.h" +#include "interop_js/hybridgref_ani.h" +#include "interop_js/hybridgref_napi.h" +#include "js_application_context_utils.h" +#include "js_context_utils.h" +#include "js_runtime_utils.h" +#include "native_engine/native_engine.h" +#include "sts_error_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char *ETS_APPLICATION_CONTEXT_CLASS_NAME = "Lapplication/ApplicationContext/ApplicationContext;"; +} // namespace + +ani_object EtsApplicationContextModule::NativeTransferStatic(ani_env *aniEnv, ani_object, ani_object input) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "transfer static ApplicationContext"); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null aniEnv"); + return nullptr; + } + + void *unwrapResult = nullptr; + bool success = arkts_esvalue_unwrap(aniEnv, input, &unwrapResult); + if (!success) { + TAG_LOGE(AAFwkTag::CONTEXT, "failed to unwrap"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + if (unwrapResult == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null unwrapResult"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + auto context = reinterpret_cast *>(unwrapResult)->lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null application context"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + auto applicationContext = Context::ConvertTo(context); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null ApplicationContext"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + auto &bindingObj = applicationContext->GetBindingObject(); + if (bindingObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null bindingObj"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + // get binding obj + auto staticContext = bindingObj->Get(); + if (staticContext != nullptr) { + TAG_LOGI(AAFwkTag::CONTEXT, "got an exist staticContext"); + return reinterpret_cast(*staticContext); + } + + // create a new one + EtsApplicationContextUtils::CreateEtsApplicationContext(aniEnv); + auto appContextObj = ApplicationContextManager::GetApplicationContextManager().GetEtsGlobalObject(); + if (appContextObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "appContextObj is nullptr"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + return appContextObj->aniObj; +} + +std::unique_ptr EtsApplicationContextModule::CreateNativeReference(napi_env napiEnv, + std::shared_ptr applicationContext) +{ + if (napiEnv == nullptr || applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null param"); + return nullptr; + } + + auto value = JsApplicationContextUtils::CreateJsApplicationContext(napiEnv); + auto systemModule = JsRuntime::LoadSystemModuleByEngine(napiEnv, "application.ApplicationContext", &value, 1); + if (systemModule == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null system module"); + return nullptr; + } + + napi_value object = systemModule->GetNapiValue(); + if (!CheckTypeForNapiValue(napiEnv, object, napi_object)) { + TAG_LOGE(AAFwkTag::CONTEXT, "check type failed"); + return nullptr; + } + + auto workContext = new (std::nothrow) std::weak_ptr(applicationContext); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null workContext"); + return nullptr; + } + auto status = napi_coerce_to_native_binding_object(napiEnv, object, DetachCallbackFunc, AttachApplicationContext, + workContext, nullptr); + if (status != napi_ok) { + TAG_LOGE(AAFwkTag::CONTEXT, "coerce applicationContext failed: %{public}d", status); + delete workContext; + return nullptr; + } + + status = napi_wrap(napiEnv, object, workContext, + [](napi_env, void *data, void *) { + TAG_LOGD(AAFwkTag::CONTEXT, "finalizer for weak_ptr applicationContext"); + delete static_cast *>(data); + }, nullptr, nullptr); + if (status != napi_ok) { + TAG_LOGE(AAFwkTag::CONTEXT, "wrap failed: %{public}d", status); + delete workContext; + return nullptr; + } + + return systemModule; +} + +std::unique_ptr EtsApplicationContextModule::GetOrCreateNativeReference(napi_env napiEnv, + std::shared_ptr applicationContext) +{ + if (napiEnv == nullptr || applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null param"); + return nullptr; + } + + // if sub-thread, create a new applicationContext and return + if (getpid() != syscall(SYS_gettid)) { + return CreateNativeReference(napiEnv, applicationContext); + } + + // if main-thread, get bindingObj firstly + auto &bindingObj = applicationContext->GetBindingObject(); + if (bindingObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null bindingObj"); + return nullptr; + } + + // if main-thread bindingObj exist, return it directly + auto dynamicContext = bindingObj->Get(); + if (dynamicContext != nullptr) { + TAG_LOGI(AAFwkTag::UIABILITY, "there exist a dynamicContext"); + return std::unique_ptr(dynamicContext); + } + + // if main-thread bindingObj didn't exist, create and bind + auto nativeRef = CreateNativeReference(napiEnv, applicationContext); + if (nativeRef == nullptr) { + return nullptr; + } + + applicationContext->Bind(nativeRef.get()); + return nativeRef; +} + +ani_object EtsApplicationContextModule::NativeTransferDynamic(ani_env *aniEnv, ani_object, ani_object input) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "transfer dynamic ApplicationContext"); + if (!IsInstanceOf(aniEnv, input)) { + TAG_LOGE(AAFwkTag::CONTEXT, "not AbilityStageContext"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + auto context = AbilityRuntime::GetStageModeContext(aniEnv, input); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + auto applicationContext = Context::ConvertTo(context); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "invalid applicationContext"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + // Not support yet + ThrowStsTransferClassError(aniEnv); + return nullptr; +} + +bool EtsApplicationContextModule::IsInstanceOf(ani_env *aniEnv, ani_object aniObj) +{ + ani_class cls {}; + ani_status status = ANI_ERROR; + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null aniEnv"); + return false; + } + if ((status = aniEnv->FindClass(ETS_APPLICATION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "FindClass status: %{public}d", status); + return false; + } + ani_boolean isInstanceOf = false; + if ((status = aniEnv->Object_InstanceOf(aniObj, cls, &isInstanceOf)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "Object_InstanceOf status: %{public}d", status); + return false; + } + return isInstanceOf; +} + +void EtsApplicationContextModuleInit(ani_env *aniEnv) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "Init application context kit"); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null ani env"); + return; + } + + ani_class applicationContextCls = nullptr; + auto status = aniEnv->FindClass(ETS_APPLICATION_CONTEXT_CLASS_NAME, &applicationContextCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "FindClass ApplicationContext failed status: %{public}d", status); + return; + } + + std::array nativeFuncs = { + ani_native_function { "nativeTransferStatic", "Lstd/interop/ESValue;:Lstd/core/Object;", + reinterpret_cast(EtsApplicationContextModule::NativeTransferStatic) }, + ani_native_function { "nativeTransferDynamic", "Lstd/core/Object;:Lstd/interop/ESValue;", + reinterpret_cast(EtsApplicationContextModule::NativeTransferDynamic) }, + }; + status = aniEnv->Class_BindNativeMethods(applicationContextCls, nativeFuncs.data(), nativeFuncs.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "Class_BindNativeMethods failed status: %{public}d", status); + return; + } + + TAG_LOGD(AAFwkTag::CONTEXT, "Init application context kit end"); +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "ANI_Constructor"); + if (vm == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null vm"); + return ANI_ERROR; + } + + ani_env *aniEnv = nullptr; + ani_status status = vm->GetEnv(ANI_VERSION_1, &aniEnv); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "GetEnv failed status: %{public}d", status); + return ANI_NOT_FOUND; + } + + EtsApplicationContextModuleInit(aniEnv); + *result = ANI_VERSION_1; + TAG_LOGD(AAFwkTag::CONTEXT, "ANI_Constructor finish"); + return ANI_OK; +} +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/app/context/BUILD.gn b/frameworks/ets/ani/app/context/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..d3313f4645a4a0b9acdf4bac1542c3daae7f6889 --- /dev/null +++ b/frameworks/ets/ani/app/context/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("context_ani_kit") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_napi_path}/ability_auto_startup_callback", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", + ] + + configs = [] + + public_configs = [] + + sources = [ "./src/ets_context_module.cpp" ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/ani_base_context:ani_base_context", + "${ability_runtime_innerkits_path}/error_utils:ability_runtime_error_util", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_napi_path}/inner/napi_common:napi_common", + "${ability_runtime_native_path}/ability/native:ability_business_error", + "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_native_path}/appkit:app_context_utils", + "${ability_runtime_native_path}/appkit:appkit_native", + "${ability_runtime_native_path}/appkit:application_context_manager", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "napi:ace_napi", + "runtime_core:ani", + "runtime_core:ani_helpers", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/app/context/include/ets_context_module.h b/frameworks/ets/ani/app/context/include/ets_context_module.h new file mode 100755 index 0000000000000000000000000000000000000000..b4c60fc6705e980e1a516ded7d723d9d3e4325bc --- /dev/null +++ b/frameworks/ets/ani/app/context/include/ets_context_module.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_CONTEXT_MODULE_H +#define OHOS_ABILITY_RUNTIME_ETS_CONTEXT_MODULE_H + +#include +#include "ani.h" +#include "ability_stage_context.h" +#include "application_context.h" +#include "native_engine/native_engine.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsContextModule { +public: + EtsContextModule() = default; + ~EtsContextModule() = default; + + EtsContextModule(const EtsContextModule&) = delete; + EtsContextModule(EtsContextModule&&) = delete; + EtsContextModule& operator=(const EtsContextModule&) = delete; + EtsContextModule& operator=(EtsContextModule&&) = delete; + + static ani_object NativeTransferStatic(ani_env *env, ani_object aniObj, ani_object input); + static ani_object NativeTransferDynamic(ani_env *env, ani_object aniObj, ani_object input); + +private: + static ani_object GetOrCreateAniObject(ani_env *aniEnv, std::shared_ptr context); + static std::unique_ptr GetOrCreateNativeReference(napi_env napiEnv, + std::shared_ptr context); + static std::unique_ptr CreateNativeReference(napi_env napiEnv, + std::shared_ptr context); + static std::unique_ptr CreateApplicationNativeReference(napi_env napiEnv, + std::shared_ptr applicationContext); + static std::unique_ptr CreateAbilityStageNativeReference(napi_env napiEnv, + std::shared_ptr abilityStageContext); +}; + +void EtsContextModuleInit(ani_env *aniEnv); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_CONTEXT_MODULE_H diff --git a/frameworks/ets/ani/app/context/src/ets_context_module.cpp b/frameworks/ets/ani/app/context/src/ets_context_module.cpp new file mode 100755 index 0000000000000000000000000000000000000000..28f76587ffee16c7f4f0595b83912672b2ed31d3 --- /dev/null +++ b/frameworks/ets/ani/app/context/src/ets_context_module.cpp @@ -0,0 +1,395 @@ +/* + * 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_context_module.h" + +#include +#include +#include +#include "ani_base_context.h" +#include "application_context_manager.h" +#include "ets_application_context_utils.h" +#include "hilog_tag_wrapper.h" +#include "interop_js/arkts_esvalue.h" +#include "interop_js/hybridgref_ani.h" +#include "interop_js/hybridgref_napi.h" +#include "js_ability_stage_context.h" +#include "js_application_context_utils.h" +#include "js_context_utils.h" +#include "js_runtime_utils.h" +#include "native_engine/native_engine.h" +#include "sts_ability_stage_context.h" +#include "sts_error_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char *ETS_CONTEXT_CLASS_NAME = "Lapplication/Context/Context;"; +} // namespace + +ani_object EtsContextModule::NativeTransferStatic(ani_env *aniEnv, ani_object, ani_object input) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "transfer static Context"); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null aniEnv"); + return nullptr; + } + void *unwrapResult = nullptr; + bool success = arkts_esvalue_unwrap(aniEnv, input, &unwrapResult); + if (!success) { + TAG_LOGE(AAFwkTag::CONTEXT, "failed to unwrap"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + if (unwrapResult == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null unwrapResult"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + auto context = reinterpret_cast *>(unwrapResult)->lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null Context"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + auto &bindingObj = context->GetBindingObject(); + if (bindingObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null bindingObj"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + auto staticContext = bindingObj->Get(); + if (staticContext != nullptr) { + TAG_LOGI(AAFwkTag::CONTEXT, "there exist a staticContext"); + return reinterpret_cast(*staticContext); + } + + auto contextObj = GetOrCreateAniObject(aniEnv, context); + if (contextObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "contextObj invalid"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + return contextObj; +} + +ani_object EtsContextModule::GetOrCreateAniObject(ani_env *aniEnv, std::shared_ptr context) +{ + // If context is UIAbilityContext, then the bindingObj->Get will not nullptr, + // So check ApplicationContext and AbilityStageContext. + auto appContext = Context::ConvertTo(context); + if (appContext != nullptr) { + TAG_LOGI(AAFwkTag::CONTEXT, "Context is ApplicationContext"); + EtsApplicationContextUtils::CreateEtsApplicationContext(aniEnv); + auto appContextObj = ApplicationContextManager::GetApplicationContextManager().GetEtsGlobalObject(); + if (appContextObj != nullptr) { + TAG_LOGI(AAFwkTag::CONTEXT, "appContextObj is valid"); + return appContextObj->aniObj; + } + } + + auto abilityStageContext = Context::ConvertTo(context); + if (abilityStageContext != nullptr) { + TAG_LOGI(AAFwkTag::CONTEXT, "Context is AbilityStageContext"); + auto newContext = STSAbilityStageContext::CreateStsAbilityStageContext(aniEnv, abilityStageContext); + if (newContext != nullptr) { + TAG_LOGI(AAFwkTag::CONTEXT, "newContext is valid"); + return newContext; + } + } + + return nullptr; +} + +std::unique_ptr EtsContextModule::CreateNativeReference(napi_env napiEnv, + std::shared_ptr context) +{ + if (napiEnv == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null param"); + return nullptr; + } + + auto value = CreateJsBaseContext(napiEnv, context); + auto systemModule = JsRuntime::LoadSystemModuleByEngine(napiEnv, "application.Context", &value, 1); + if (systemModule == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null system module"); + return nullptr; + } + + napi_value object = systemModule->GetNapiValue(); + if (!CheckTypeForNapiValue(napiEnv, object, napi_object)) { + TAG_LOGE(AAFwkTag::CONTEXT, "check type failed"); + return nullptr; + } + + auto workContext = new (std::nothrow) std::weak_ptr(context); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null workContext"); + return nullptr; + } + auto status = napi_coerce_to_native_binding_object(napiEnv, object, DetachCallbackFunc, AttachBaseContext, + workContext, nullptr); + if (status != napi_ok) { + TAG_LOGE(AAFwkTag::CONTEXT, "coerce context failed: %{public}d", status); + delete workContext; + return nullptr; + } + + status = napi_wrap(napiEnv, object, workContext, + [](napi_env, void *data, void *) { + TAG_LOGD(AAFwkTag::CONTEXT, "finalizer for weak_ptr context"); + delete static_cast *>(data); + }, nullptr, nullptr); + if (status != napi_ok) { + TAG_LOGE(AAFwkTag::CONTEXT, "wrap failed: %{public}d", status); + delete workContext; + return nullptr; + } + + return systemModule; +} + +std::unique_ptr EtsContextModule::CreateApplicationNativeReference(napi_env napiEnv, + std::shared_ptr applicationContext) +{ + if (napiEnv == nullptr || applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null param"); + return nullptr; + } + + auto value = JsApplicationContextUtils::CreateJsApplicationContext(napiEnv); + auto systemModule = JsRuntime::LoadSystemModuleByEngine(napiEnv, "application.ApplicationContext", &value, 1); + if (systemModule == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null system module"); + return nullptr; + } + + napi_value object = systemModule->GetNapiValue(); + if (!CheckTypeForNapiValue(napiEnv, object, napi_object)) { + TAG_LOGE(AAFwkTag::CONTEXT, "check type failed"); + return nullptr; + } + + auto workContext = new (std::nothrow) std::weak_ptr(applicationContext); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null workContext"); + return nullptr; + } + auto status = napi_coerce_to_native_binding_object(napiEnv, object, DetachCallbackFunc, AttachApplicationContext, + workContext, nullptr); + if (status != napi_ok) { + TAG_LOGE(AAFwkTag::CONTEXT, "coerce applicationContext failed: %{public}d", status); + delete workContext; + return nullptr; + } + + status = napi_wrap(napiEnv, object, workContext, + [](napi_env, void *data, void *) { + TAG_LOGD(AAFwkTag::CONTEXT, "finalizer for weak_ptr applicationContext"); + delete static_cast *>(data); + }, nullptr, nullptr); + if (status != napi_ok) { + TAG_LOGE(AAFwkTag::CONTEXT, "wrap failed: %{public}d", status); + delete workContext; + return nullptr; + } + + return systemModule; +} + +std::unique_ptr EtsContextModule::CreateAbilityStageNativeReference(napi_env napiEnv, + std::shared_ptr abilityStageContext) +{ + if (napiEnv == nullptr || abilityStageContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null param"); + return nullptr; + } + + auto value = CreateJsAbilityStageContext(napiEnv, abilityStageContext); + auto systemModule = JsRuntime::LoadSystemModuleByEngine(napiEnv, "application.AbilityStageContext", &value, 1); + if (systemModule == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null systemModule"); + return nullptr; + } + + napi_value object = systemModule->GetNapiValue(); + if (!CheckTypeForNapiValue(napiEnv, object, napi_object)) { + TAG_LOGE(AAFwkTag::CONTEXT, "check type failed"); + return nullptr; + } + + auto workContext = new (std::nothrow) std::weak_ptr(abilityStageContext); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null workContext"); + return nullptr; + } + auto status = napi_coerce_to_native_binding_object(napiEnv, object, DetachCallbackFunc, AttachAbilityStageContext, + workContext, nullptr); + if (status != napi_ok) { + TAG_LOGE(AAFwkTag::CONTEXT, "coerce AbilityStageContext failed: %{public}d", status); + delete workContext; + return nullptr; + } + + status = napi_wrap(napiEnv, object, workContext, + [](napi_env, void *data, void *) { + TAG_LOGD(AAFwkTag::CONTEXT, "finalizer for weak_ptr AbilityStageContext"); + delete static_cast *>(data); + }, nullptr, nullptr); + if (status != napi_ok) { + TAG_LOGE(AAFwkTag::CONTEXT, "wrap failed: %{public}d", status); + delete workContext; + return nullptr; + } + + return systemModule; +} + +std::unique_ptr EtsContextModule::GetOrCreateNativeReference(napi_env napiEnv, + std::shared_ptr context) +{ + if (napiEnv == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null param"); + return nullptr; + } + + // if sub-thread, create a new context and return + if (getpid() != syscall(SYS_gettid)) { + return CreateNativeReference(napiEnv, context); + } + + // if main-thread, get bindingObj firstly + auto &bindingObj = context->GetBindingObject(); + if (bindingObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null bindingObj"); + return nullptr; + } + + // if main-thread bindingObj exist, return it directly + auto dynamicContext = bindingObj->Get(); + if (dynamicContext != nullptr) { + TAG_LOGI(AAFwkTag::UIABILITY, "there exist a dynamicContext"); + return std::unique_ptr(dynamicContext); + } + + // If context is UIAbilityContext, then the bindingObj->Get() will not nullptr, + // So check ApplicationContext and AbilityStageContext. + std::unique_ptr nativeRef; + auto appContext = Context::ConvertTo(context); + if (appContext != nullptr) { + TAG_LOGI(AAFwkTag::CONTEXT, "Context is ApplicationContext"); + nativeRef = CreateApplicationNativeReference(napiEnv, appContext); + } + + auto abilityStageContext = Context::ConvertTo(context); + if (abilityStageContext != nullptr) { + TAG_LOGI(AAFwkTag::CONTEXT, "Context is AbilityStageContext"); + nativeRef = CreateAbilityStageNativeReference(napiEnv, abilityStageContext); + } + + // if main-thread bindingObj didn't exist, create and bind + if (nativeRef == nullptr) { + return nullptr; + } + + context->Bind(nativeRef.get()); + return nativeRef; +} + +ani_object EtsContextModule::NativeTransferDynamic(ani_env *aniEnv, ani_object, ani_object input) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "transfer dynamic Context"); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null aniEnv"); + return nullptr; + } + + auto context = AbilityRuntime::GetStageModeContext(aniEnv, input); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + auto contextPtr = Context::ConvertTo(context); + if (contextPtr == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "invalid Context"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + // Not support yet + ThrowStsTransferClassError(aniEnv); + return nullptr; +} + +void EtsContextModuleInit(ani_env *aniEnv) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "Init Context kit"); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null ani env"); + return; + } + + ani_class contextCls = nullptr; + auto status = aniEnv->FindClass(ETS_CONTEXT_CLASS_NAME, &contextCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "FindClass Context failed status: %{public}d", status); + return; + } + + std::array nativeFuncs = { + ani_native_function { "nativeTransferStatic", "Lstd/interop/ESValue;:Lstd/core/Object;", + reinterpret_cast(EtsContextModule::NativeTransferStatic) }, + ani_native_function { "nativeTransferDynamic", "Lstd/core/Object;:Lstd/interop/ESValue;", + reinterpret_cast(EtsContextModule::NativeTransferDynamic) }, + }; + status = aniEnv->Class_BindNativeMethods(contextCls, nativeFuncs.data(), nativeFuncs.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "Class_BindNativeMethods failed status: %{public}d", status); + return; + } + + TAG_LOGD(AAFwkTag::CONTEXT, "Init Context kit end"); +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "ANI_Constructor"); + if (vm == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null vm"); + return ANI_ERROR; + } + + ani_env *aniEnv = nullptr; + ani_status status = vm->GetEnv(ANI_VERSION_1, &aniEnv); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "GetEnv failed status: %{public}d", status); + return ANI_NOT_FOUND; + } + + EtsContextModuleInit(aniEnv); + *result = ANI_VERSION_1; + TAG_LOGD(AAFwkTag::CONTEXT, "ANI_Constructor finish"); + return ANI_OK; +} +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/app_manager/BUILD.gn b/frameworks/ets/ani/app_manager/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..0e46637799e14550f053e041af235c5e8511e35c --- /dev/null +++ b/frameworks/ets/ani/app_manager/BUILD.gn @@ -0,0 +1,80 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("ability_app_manager_ani_kit") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", + "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", + "${ability_runtime_path}/interfaces/kits/native/ability/native", + "${ability_runtime_path}/interfaces/inner_api/runtime/include", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", + ] + + configs = [] + + public_configs = [] + + sources = [ + "./src/sts_app_manager.cpp", + "./src/sts_app_manager_utils.cpp", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/app_manager:app_manager", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] + + external_deps = [ + "ability_base:base", + "ability_base:configuration", + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "ipc:ipc_core", + "ipc:ipc_napi", + "napi:ace_napi", + "runtime_core:ani", + "samgr:samgr_proxy", + ] + + if (ability_runtime_graphics) { + external_deps += [ "access_token:libtokenid_sdk" ] + defines = [ "SUPPORT_SCREEN" ] + } + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/app_manager/include/sts_app_manager.h b/frameworks/ets/ani/app_manager/include/sts_app_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..6b1225841212171d58cc9337bf880fdfbd1e263c --- /dev/null +++ b/frameworks/ets/ani/app_manager/include/sts_app_manager.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_STS_APP_MANAGER_H +#define OHOS_ABILITY_RUNTIME_STS_APP_MANAGER_H + +#include "sts_runtime.h" + +namespace OHOS { +namespace AppManagerSts { +void StsAppManagerRegistryInit(ani_env *env); +} // namespace AppManagerSts +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_APP_MANAGER_H diff --git a/frameworks/ets/ani/app_manager/include/sts_app_manager_utils.h b/frameworks/ets/ani/app_manager/include/sts_app_manager_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..a3af678cbddae15c1e4c326e1ed1e07ec1542d72 --- /dev/null +++ b/frameworks/ets/ani/app_manager/include/sts_app_manager_utils.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_STS_APP_MANAGER_UTILS_H +#define OHOS_ABILITY_RUNTIME_STS_APP_MANAGER_UTILS_H + +#include "sts_runtime.h" +#include +#include "running_process_info.h" +#include "app_state_data.h" +#include "running_multi_info.h" +#include "process_data.h" +#include "keep_alive_info.h" + +namespace OHOS { +namespace AppManagerSts { +ani_object NewArrayClass(ani_env *env, const std::vector& data); +ani_object WrapAppStateData(ani_env *env, const AppExecFwk::AppStateData &appStateData); +bool SetAppStateData(ani_env *env, ani_object object, const AppExecFwk::AppStateData &appStateData); +bool SetProcessInformation(ani_env *env, ani_object object, const AppExecFwk::RunningProcessInfo &processInfo); +ani_object WrapProcessInformation(ani_env *env, const AppExecFwk::RunningProcessInfo &processInfo); +ani_object CreateRunningProcessInfoArray (ani_env *env, std::vector infos); +ani_object CreateAppStateDataArray (ani_env *env, std::vector data); +ani_object CreateRunningMultiInstanceInfoArray(ani_env *env, + std::vector infos); +ani_object CreateRunningAppCloneArray(ani_env *env, std::vector infos); +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); +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 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); +bool UnWrapArrayDouble(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); +} // namespace AppManagerSts +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_APP_MANAGER_UTILS_H diff --git a/frameworks/ets/ani/app_manager/src/sts_app_manager.cpp b/frameworks/ets/ani/app_manager/src/sts_app_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c97d602c19fdf81a116556493ef46d7104c86d0 --- /dev/null +++ b/frameworks/ets/ani/app_manager/src/sts_app_manager.cpp @@ -0,0 +1,1000 @@ +/* + * 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 "sts_app_manager.h" +#include "hilog_tag_wrapper.h" +#include "ability_manager_client.h" +#include "ability_manager_interface.h" +#include "app_mgr_constants.h" +#include "app_mgr_interface.h" +#include "ipc_skeleton.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "sts_error_utils.h" +#include "ani_common_util.h" +#include "ani_enum_convert.h" +#include "sts_error_utils.h" +#include "sts_app_manager_utils.h" +#ifdef SUPPORT_GRAPHICS +#ifdef SUPPORT_SCREEN +#include "tokenid_kit.h" +#endif +#endif + +namespace OHOS { +namespace AppManagerSts { + +constexpr int32_t ERR_FAILURE = -1; + +static const char* ON_SIGNATURE_FIRST + = "Lstd/core/String;Lapplication/ApplicationStateObserver/ApplicationStateObserver;Lescompat/Array;:D"; +static const char* ON_SIGNATURE_SECOND + = "Lstd/core/String;Lapplication/ApplicationStateObserver/ApplicationStateObserver;:D"; + + +static const char* OFF_SIGNATURE_FIRST + = "Lstd/core/String;DLutils/AbilityUtils/AsyncCallbackWrapper;:V"; +class StsAppManager final { +public: + static OHOS::sptr GetAppManagerInstance() + { + OHOS::sptr systemAbilityManager = + OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + OHOS::sptr appObject = systemAbilityManager->GetSystemAbility(OHOS::APP_MGR_SERVICE_ID); + return OHOS::iface_cast(appObject); + } + + static OHOS::sptr GetAbilityManagerInstance() + { + OHOS::sptr systemAbilityManager = + OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + OHOS::sptr abilityObject = + systemAbilityManager->GetSystemAbility(OHOS::ABILITY_MGR_SERVICE_ID); + return OHOS::iface_cast(abilityObject); + } + +#ifdef SUPPORT_SCREEN + static bool CheckCallerIsSystemApp() + { + auto selfToken = IPCSkeleton::GetSelfTokenID(); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { + return false; + } + return true; + } +#endif + static void PreloadApplication(ani_env *env, ani_object callback, ani_string stsBundleName, + ani_double stsUserId, ani_enum_item stsMode, ani_object stsAppIndex) + { + TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env is null"); + return; + } + std::string bundleName; + if (!OHOS::AppExecFwk::GetStdString(env, stsBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "param bundlename err"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM)), nullptr); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication userId:%{public}f, bundleName %{public}s", + stsUserId, bundleName.c_str()); + int32_t userId = static_cast(stsUserId); + + ani_int mode; + if (!AAFwk::AniEnumConvertUtil::EnumConvertStsToNative(env, stsMode, mode)) { + TAG_LOGE(AAFwkTag::APPMGR, "param mode err"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM)), nullptr); + return; + } + ani_status status = ANI_OK; + int32_t appIndex = 0; + ani_boolean isUndefined = false; + if ((status = env->Reference_IsUndefined(stsAppIndex, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to check undefined status : %{public}d", status); + return; + } + ani_double dval = 0.0; + if (!isUndefined) { + if ((status = env->Object_CallMethodByName_Double(stsAppIndex, + "toDouble", nullptr, &dval)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_CallMethodByName_Double status : %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "stsAppIndex: %{public}f", dval); + appIndex = static_cast(dval); + } + TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication userId:%{public}d, mode:%{public}d, appIndex:%{public}d", + userId, mode, appIndex); + + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), nullptr); + return; + } + auto ret = appMgr->PreloadApplication(bundleName, userId, static_cast(mode), + appIndex); + TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication ret %{public}d", ret); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), nullptr); + TAG_LOGD(AAFwkTag::APPMGR, "PreloadApplication END"); + } + + static void GetRunningProcessInformation(ani_env *env, ani_object callback) + { + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInformation called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_object emptyArray = CreateEmptyAniArray(env); + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + return; + } + std::vector infos; + auto ret = appMgr->GetAllRunningProcesses(infos); + TAG_LOGD(AAFwkTag::APPMGR, "GetAllRunningProcesses ret:%{public}d, size:%{public}zu", ret, infos.size()); + if (ret != ERR_OK) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), emptyArray); + return; + } + ani_object aniInfosRef = CreateRunningProcessInfoArray(env, infos); + if (aniInfosRef == nullptr) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + } else { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), aniInfosRef); + } + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInformation finished"); + } + + static void GetForegroundApplications(ani_env *env, ani_object callback) + { + TAG_LOGD(AAFwkTag::APPMGR, "GetForegroundApplications called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_object emptyArray = CreateEmptyAniArray(env); + auto appManager = GetAppManagerInstance(); + if (appManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + return; + } + std::vector appStateData; + int32_t ret = appManager->GetForegroundApplications(appStateData); + TAG_LOGD(AAFwkTag::APPMGR, "GetForegroundApplications ret:%{public}d, size:%{public}zu", + ret, appStateData.size()); + if (ret != ERR_OK) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), emptyArray); + return; + } + ani_object appStateDataObj = CreateAppStateDataArray(env, appStateData); + if (appStateDataObj == nullptr) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + } else { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), appStateDataObj); + } + TAG_LOGD(AAFwkTag::APPMGR, "GetForegroundApplications end"); + } + + static void GetRunningMultiAppInfo(ani_env *env, ani_string stsBundleName, ani_object callback) + { + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningMultiAppInfo called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_object emtpyMultiAppInfo = CreateEmptyMultiAppInfo(env); + #ifdef SUPPORT_SCREEN + if (!CheckCallerIsSystemApp()) { + TAG_LOGE(AAFwkTag::APPMGR, "Non-system app"); + AppExecFwk::AsyncCallback(env, callback, OHOS::AbilityRuntime::CreateStsError(env, + AbilityRuntime::AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP), emtpyMultiAppInfo); + return; + } + #endif + std::string bundleName; + if (!OHOS::AppExecFwk::GetStdString(env, stsBundleName, bundleName) || bundleName.empty()) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsError(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + "Parse param bundleName failed, must be a string."), emtpyMultiAppInfo); + return; + } + auto appManager = GetAppManagerInstance(); + if (appManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager nullptr"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emtpyMultiAppInfo); + return; + } + AppExecFwk::RunningMultiAppInfo info; + int32_t innerErrorCode = ERR_OK; + innerErrorCode = appManager->GetRunningMultiAppInfoByBundleName(bundleName, info); + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningMultiAppInfoByBundleName ret: %{public}d", innerErrorCode); + if (innerErrorCode != ERR_OK) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, innerErrorCode), emtpyMultiAppInfo); + return; + } + ani_object appinfoObj = WrapRunningMultiAppInfo(env, info); + if (appinfoObj == nullptr) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emtpyMultiAppInfo); + } else { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, innerErrorCode), appinfoObj); + } + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningMultiAppInfo end"); + } + + static void GetRunningProcessInfoByBundleNameAndUserId(ani_env *env, ani_string stsBundleName, + ani_int stsUserId, ani_object callback) + { + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInfoByBundleNameAndUserId called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return; + } + ani_object emptyArray = CreateEmptyAniArray(env); + if (stsBundleName == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "stsBundleName null ptr"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM)), emptyArray); + return; + } + std::string bundleName; + if (!OHOS::AppExecFwk::GetStdString(env, stsBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM)), emptyArray); + return; + } + int userId = IPCSkeleton::GetCallingUid() / AppExecFwk::Constants::BASE_USER_RANGE; + if (stsUserId != AppExecFwk::Constants::INVALID_UID) { + userId = static_cast(stsUserId); + } + auto appManager = GetAppManagerInstance(); + if (appManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager nullptr"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + return; + } + std::vector infos; + int32_t ret = appManager->GetRunningProcessInformation(bundleName, userId, infos); + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInformation ret: %{public}d, size:%{public}zu", + ret, infos.size()); + if (ret != ERR_OK) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), emptyArray); + return; + } + ani_object aniInfos = CreateRunningProcessInfoArray(env, infos); + if (aniInfos == nullptr) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + } else { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), aniInfos); + } + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInfoByBundleNameAndUserId finished"); + } + + static void GetRunningProcessInfoByBundleName(ani_env *env, ani_string stsBundleName, + ani_object callback) + { + GetRunningProcessInfoByBundleNameAndUserId(env, stsBundleName, AppExecFwk::Constants::INVALID_UID, callback); + } + +static ani_double OnOnApplicationStateInner(ani_env *env, ani_string type, + ani_object observer, ani_object stsBundleNameList) +{ + TAG_LOGD(AAFwkTag::APPMGR, "OnOnApplicationStateInner called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + return ANI_ERROR; + } + std::string strType; + if (!OHOS::AppExecFwk::GetStdString(env, type, strType)) { + TAG_LOGE(AAFwkTag::APPMGR, "env null ptr"); + AbilityRuntime::ThrowStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM)); + return ANI_ERROR; + } + auto appManager = GetAppManagerInstance(); + if (appManager == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null appManager"); + AbilityRuntime::ThrowStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return ANI_ERROR; + } + + std::vector bundleNameList; + if (stsBundleNameList != nullptr) { + UnWrapArrayString(env, stsBundleNameList, bundleNameList); + } + return ANI_OK; +} + + static ani_double OnOnApplicationStateFirst(ani_env *env, ani_string type, + ani_object observer, ani_object stsBundleNameList) + { + return OnOnApplicationStateInner(env, type, observer, stsBundleNameList); + } + + static ani_double OnOnApplicationStateSecond(ani_env *env, ani_string type, ani_object observer) + { + return OnOnApplicationStateInner(env, type, observer, nullptr); + } + +static void OnOff(ani_env *env, [[maybe_unused]]ani_class aniClss) +{ +} + static void 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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), + AppExecFwk::createDouble(env, ERR_FAILURE)); + return; + } + int32_t memorySize = abilityManager->GetAppMemorySize(); + TAG_LOGD(AAFwkTag::APPMGR, "memorySize:%{public}d", memorySize); + + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ERR_OK)), + AppExecFwk::createDouble(env, static_cast(memorySize))); + TAG_LOGD(AAFwkTag::APPMGR, "GetAppMemorySize end"); + } + + static void 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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ERR_OK)), + AppExecFwk::createBoolean(env, static_cast(ret))); + TAG_LOGD(AAFwkTag::APPMGR, "IsRamConstrainedDevice end"); + } + + static void 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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ERR_OK)), + AppExecFwk::createBoolean(env, static_cast(ret))); + TAG_LOGD(AAFwkTag::APPMGR, "IsRunningInStabilityTest end"); + } + + static void 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)); + } + + static void NativeKillProcessesByBundleName(ani_env *env, ani_object callback, ani_string bundleName, + ani_boolean clearPageStack, ani_object stsAppIndex) + { + KillProcessesByBundleNameInner(env, callback, bundleName, clearPageStack, stsAppIndex); + } + + static void KillProcessesByBundleNameInner(ani_env *env, ani_object callback, ani_string stsBundleName, + ani_boolean clearPageStack, ani_object stsAppIndex) + { + 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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), nullptr); + return; + } + ani_status status = ANI_OK; + std::string bundleName; + if (!OHOS::AppExecFwk::GetStdString(env, stsBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Parse param bundleName failed, must be a string."); + return; + } + int32_t appIndex = 0; + ani_boolean isUndefined = false; + if ((status = env->Reference_IsUndefined(stsAppIndex, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Failed to check undefined status : %{public}d", status); + return; + } + ani_double dval = 0.0; + if (!isUndefined) { + if ((status = env->Object_CallMethodByName_Double(stsAppIndex, + "toDouble", nullptr, &dval)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_CallMethodByName_Double status : %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "stsAppIndex: %{public}f", dval); + appIndex = static_cast(dval); + } + auto ret = abilityManager->KillProcess(bundleName, clearPageStack, appIndex); + TAG_LOGD(AAFwkTag::APPMGR, "KillProcess ret: %{public}d", ret); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), nullptr); + TAG_LOGD(AAFwkTag::APPMGR, "KillProcessesByBundleNameInner end"); + } + + static void NativeKillProcessWithAccountSync(ani_env *env, ani_string aniBundleName, ani_double 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)); + } + + static void NativeKillProcessWithAccount(ani_env *env, ani_object callback, ani_string aniBundleName, + ani_double aniAccountId, ani_boolean clearPageStack, ani_object aniAppIndex) + { + KillProcessWithAccountInner(env, callback, aniBundleName, aniAccountId, + clearPageStack, aniAppIndex); + } + + static void KillProcessWithAccountInner(ani_env *env, ani_object callback, ani_string aniBundleName, + ani_double 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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), nullptr); + return; + } + std::string bundleName; + if (!OHOS::AppExecFwk::GetStdString(env, aniBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Parse param bundleName failed, must be a string."); + return; + } + + TAG_LOGD(AAFwkTag::APPMGR, "KillProcessWithAccount accountId:%{public}f", aniAccountId); + int32_t accountId = static_cast(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; + } + ani_double dval = 0.0; + if (!isUndefined) { + if ((status = env->Object_CallMethodByName_Double(aniAppIndex, + "toDouble", nullptr, &dval)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_CallMethodByName_Double status : %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "stsAppIndex: %{public}f", dval); + appIndex = static_cast(dval); + } + auto ret = appMgr->GetAmsMgr()->KillProcessWithAccount(bundleName, accountId, clearPageStack, appIndex); + TAG_LOGD(AAFwkTag::APPMGR, "KillProcessWithAccount ret: %{public}d", ret); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), nullptr); + TAG_LOGD(AAFwkTag::APPMGR, "KillProcessWithAccount end"); + } + + static void NativeGetProcessMemoryByPid(ani_env *env, ani_double 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}f", aniPid); + int32_t pid = static_cast(aniPid); + + sptr appMgr = GetAppManagerInstance(); + if (appMgr == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "appManager null ptr"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), + AppExecFwk::createDouble(env, ERR_FAILURE)); + return; + } + int32_t memSize = 0; + int32_t ret = appMgr->GetProcessMemoryByPid(pid, memSize); + TAG_LOGD(AAFwkTag::APPMGR, "NativeGetProcessMemoryByPid memSize: %{public}d, ret:%{public}d", memSize, ret); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), + AppExecFwk::createDouble(env, static_cast(memSize))); + TAG_LOGD(AAFwkTag::APPMGR, "NativeGetProcessMemoryByPid end"); + } + + static void 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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + return; + } + ani_int bundleType; + if (!AAFwk::AniEnumConvertUtil::EnumConvertStsToNative(env, aniBundleType, bundleType)) { + TAG_LOGE(AAFwkTag::APPMGR, "param aniBundleType err"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Parse param bundleType failed, must be a BundleType."); + 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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), emptyArray); + return; + } + ani_object aniInfosRef = CreateRunningProcessInfoArray(env, infos); + if (aniInfosRef == nullptr) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + } else { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), aniInfosRef); + } + TAG_LOGD(AAFwkTag::APPMGR, "GetRunningProcessInformationByBundleType end"); + } + + static void NativeIsSharedBundleRunning(ani_env *env, ani_string aniBundleName, + ani_double 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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), + AppExecFwk::createBoolean(env, false)); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "NativeGetProcessMemoryByPid pid:%{public}f", aniVersionCode); + int32_t versionCode = static_cast(aniVersionCode); + + std::string bundleName; + if (!OHOS::AppExecFwk::GetStdString(env, aniBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Parse param bundleName failed, must be a string."); + return; + } + bool ret = appMgr->IsSharedBundleRunning(bundleName, versionCode); + TAG_LOGD(AAFwkTag::APPMGR, "NativeIsSharedBundleRunning ret :%{public}d", ret); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ERR_OK)), + AppExecFwk::createBoolean(env, static_cast(ret))); + TAG_LOGD(AAFwkTag::APPMGR, "NativeIsSharedBundleRunning end"); + } + + static void 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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + return; + } + std::string bundleName; + if (!OHOS::AppExecFwk::GetStdString(env, aniBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Parse param bundleName failed, must be a string."); + 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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), emptyArray); + return; + } + ani_object arrayObj = CreateDoubleAniArray(env, list); + if (arrayObj == nullptr) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + } else { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), arrayObj); + } + TAG_LOGD(AAFwkTag::APPMGR, "NativeGetSupportedProcessCachePids end"); + } + + static void 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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), nullptr); + return; + } + std::vector pidList; + if (!UnWrapArrayDouble(env, pids, pidList)) { + TAG_LOGE(AAFwkTag::APPMGR, "Parse pids failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Parse param pids failed, must be array of numbers."); + return; + } + int32_t innerErrorCode = appMgr->GetAmsMgr()->KillProcessesInBatch(pidList); + TAG_LOGD(AAFwkTag::APPMGR, "NativeKillProcessesInBatch ret:%{public}d", innerErrorCode); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(innerErrorCode)), nullptr); + TAG_LOGD(AAFwkTag::APPMGR, "NativeKillProcessesInBatch end"); + } + + static void 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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), + AppExecFwk::createBoolean(env, false)); + return; + } + std::string bundleName; + if (!OHOS::AppExecFwk::GetStdString(env, aniBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Parse param bundleName failed, must be a string."); + 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; + } + ani_double dval = 0.0; + if (!isUndefined) { + if ((status = env->Object_CallMethodByName_Double(aniAppCloneIndex, + "toDouble", nullptr, &dval)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_CallMethodByName_Double status : %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "aniAppCloneIndex: %{public}f", dval); + appCloneIndex = static_cast(dval); + } + 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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(innerErrorCode)), + AppExecFwk::createBoolean(env, isRunnig)); + } else { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(innerErrorCode)), + AppExecFwk::createBoolean(env, false)); + } + TAG_LOGD(AAFwkTag::APPMGR, "NativeIsAppRunning end"); + } + + static void NativeSetKeepAliveForBundle(ani_env *env, ani_string aniBundleName, + ani_double 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"); + OHOS::AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + std::string bundleName; + if (!OHOS::AppExecFwk::GetStdString(env, aniBundleName, bundleName)) { + TAG_LOGE(AAFwkTag::APPMGR, "GetStdString Failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Parse param bundleName failed, must be a string."); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "KillProcessWithAccount aniUserId:%{public}f", aniUserId); + int32_t userId = static_cast(aniUserId); + int32_t innerErrCode = abilityManager->SetApplicationKeepAlive(bundleName, userId, enable); + TAG_LOGD(AAFwkTag::APPMGR, "innerErrCode:%{public}d", innerErrCode); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(innerErrCode)), nullptr); + TAG_LOGD(AAFwkTag::APPMGR, "NativeSetKeepAliveForBundle end"); + } + + static void 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"); + OHOS::AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + return; + } + ani_int appType = 0; + if (!AAFwk::AniEnumConvertUtil::EnumConvertStsToNative(env, aniType, appType)) { + TAG_LOGE(AAFwkTag::APPMGR, "param mode err"); + OHOS::AbilityRuntime::ThrowStsInvalidParamError(env, "Parse param appType failed, must be a number."); + 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; + } + ani_double dval = 0.0; + if (!isUndefined) { + if ((status = env->Object_CallMethodByName_Double(aniUserId, + "toDouble", nullptr, &dval)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_CallMethodByName_Double status : %{public}d", status); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "stsAppIndex: %{public}f", dval); + userId = static_cast(dval); + } + 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, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(innerErrCode)), emptyArray); + return; + } + ani_object arrayObj = CreateKeepAliveInfoArray(env, infoList); + if (arrayObj == nullptr) { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)), emptyArray); + } else { + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(innerErrCode)), arrayObj); + } + TAG_LOGD(AAFwkTag::APPMGR, "NativeGetKeepAliveBundles end"); + } +}; //StsAppManager + +void StsAppManagerRegistryInit(ani_env *env) +{ + TAG_LOGD(AAFwkTag::APPMGR, "StsAppManagerRegistryInit call"); + ani_status status = ANI_ERROR; + if (env->ResetError() != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "ResetError failed"); + } + ani_namespace ns; + status = env->FindNamespace("L@ohos/app/ability/appManager/appManager;", &ns); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "FindNamespace appManager failed status : %{public}d", status); + return; + } + std::array kitFunctions = { + ani_native_function {"nativePreloadApplication", nullptr, + reinterpret_cast(StsAppManager::PreloadApplication)}, + ani_native_function {"nativeGetRunningProcessInformation", nullptr, + reinterpret_cast(StsAppManager::GetRunningProcessInformation)}, + ani_native_function {"nativeGetForegroundApplications", nullptr, + reinterpret_cast(StsAppManager::GetForegroundApplications)}, + ani_native_function {"nativeGetRunningMultiAppInfo", nullptr, + reinterpret_cast(StsAppManager::GetRunningMultiAppInfo)}, + ani_native_function {"nativeGetRunningProcessInfoByBundleName", nullptr, + reinterpret_cast(StsAppManager::GetRunningProcessInfoByBundleName)}, + ani_native_function {"nativeGetRunningProcessInfoByBundleNameAndUserId", nullptr, + reinterpret_cast(StsAppManager::GetRunningProcessInfoByBundleNameAndUserId)}, + ani_native_function {"nativeOn", ON_SIGNATURE_FIRST, + reinterpret_cast(StsAppManager::OnOnApplicationStateFirst)}, + ani_native_function {"nativeOn", ON_SIGNATURE_SECOND, + reinterpret_cast(StsAppManager::OnOnApplicationStateSecond)}, + ani_native_function {"nativeOff", OFF_SIGNATURE_FIRST, + reinterpret_cast(StsAppManager::OnOff)}, + ani_native_function {"nativeGetAppMemorySize", nullptr, + reinterpret_cast(StsAppManager::GetAppMemorySize)}, + ani_native_function {"nativeIsRamConstrainedDevice", nullptr, + reinterpret_cast(StsAppManager::IsRamConstrainedDevice)}, + ani_native_function {"nativeIsRunningInStabilityTest", nullptr, + reinterpret_cast(StsAppManager::IsRunningInStabilityTest)}, + ani_native_function {"nativeKillProcessesByBundleNameSync", nullptr, + reinterpret_cast(StsAppManager::NativeKillProcessesByBundleNameSync)}, + ani_native_function {"nativeKillProcessesByBundleName", nullptr, + reinterpret_cast(StsAppManager::NativeKillProcessesByBundleName)}, + ani_native_function {"nativeKillProcessWithAccountSync", nullptr, + reinterpret_cast(StsAppManager::NativeKillProcessWithAccountSync)}, + ani_native_function {"nativeKillProcessWithAccount", nullptr, + reinterpret_cast(StsAppManager::NativeKillProcessWithAccount)}, + ani_native_function {"nativeGetProcessMemoryByPid", nullptr, + reinterpret_cast(StsAppManager::NativeGetProcessMemoryByPid)}, + ani_native_function {"nativeGetRunningProcessInformationByBundleType", nullptr, + reinterpret_cast(StsAppManager::GetRunningProcessInformationByBundleType)}, + ani_native_function {"nativeIsSharedBundleRunning", nullptr, + reinterpret_cast(StsAppManager::NativeIsSharedBundleRunning)}, + ani_native_function {"nativeGetSupportedProcessCachePids", nullptr, + reinterpret_cast(StsAppManager::NativeGetSupportedProcessCachePids)}, + ani_native_function {"nativeKillProcessesInBatch", nullptr, + reinterpret_cast(StsAppManager::NativeKillProcessesInBatch)}, + ani_native_function {"nativeIsAppRunning", nullptr, + reinterpret_cast(StsAppManager::NativeIsAppRunning)}, + ani_native_function {"nativeSetKeepAliveForBundle", nullptr, + reinterpret_cast(StsAppManager::NativeSetKeepAliveForBundle)}, + ani_native_function {"nativeGetKeepAliveBundles", nullptr, + reinterpret_cast(StsAppManager::NativeGetKeepAliveBundles)} + }; + + status = env->Namespace_BindNativeFunctions(ns, kitFunctions.data(), kitFunctions.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Namespace_BindNativeFunctions failed status : %{public}d", status); + } + if (env->ResetError() != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "ResetError failed"); + } + TAG_LOGD(AAFwkTag::APPMGR, "StsAppManagerRegistryInit end"); +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::APPMGR, "in AppManagerEts.ANI_Constructor"); + if (vm == nullptr || result == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null vm or result"); + return ANI_INVALID_ARGS; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "GetEnv failed, status=%{public}d", status); + return ANI_NOT_FOUND; + } + StsAppManagerRegistryInit(env); + *result = ANI_VERSION_1; + TAG_LOGD(AAFwkTag::APPMGR, "AppManagerSts.ANI_Constructor finished"); + return ANI_OK; +} +} // extern "C" +} // namespace AppManagerSts +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/app_manager/src/sts_app_manager_utils.cpp b/frameworks/ets/ani/app_manager/src/sts_app_manager_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e0a239871b58fe95a7d2c9d92ff3d89ef2b8d511 --- /dev/null +++ b/frameworks/ets/ani/app_manager/src/sts_app_manager_utils.cpp @@ -0,0 +1,989 @@ +/* + * 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 "sts_app_manager_utils.h" +#include +#include +#include "hilog_tag_wrapper.h" +#include "sts_error_utils.h" +#include "ani_common_util.h" +#include "ani_enum_convert.h" + +namespace OHOS { +namespace AppManagerSts { +ani_object WrapAppStateData(ani_env *env, const AppExecFwk::AppStateData &appStateData) +{ + 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("Lapplication/AppStateData/AppStateData;", &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 AppStateData failed status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + if (!SetAppStateData(env, object, appStateData)) { + TAG_LOGE(AAFwkTag::APPMGR, "SetAppStateData failed"); + return nullptr; + } + return object; +} + +bool SetAppStateData(ani_env *env, ani_object object, const AppExecFwk::AppStateData &appStateData) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return false; + } + ani_status status = ANI_OK; + status = env->Object_SetFieldByName_Ref(object, "bundleName", + OHOS::AppExecFwk::GetAniString(env, appStateData.bundleName)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "bundleName failed status:%{public}d", status); + return false; + } + status = env->Object_SetFieldByName_Double(object, "uid", static_cast(appStateData.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(appStateData.state)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "state failed status:%{public}d", status); + return false; + } + status = env->Object_SetFieldByName_Boolean(object, "isSplitScreenMode", appStateData.isSplitScreenMode); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "isSplitScreenMode failed status:%{public}d", status); + return false; + } + status = env->Object_SetFieldByName_Boolean(object, "isFloatingWindowMode", appStateData.isFloatingWindowMode); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "isFloatingWindowMode failed status:%{public}d", status); + return false; + } + return true; +} + +ani_object CreateAppStateDataArray(ani_env *env, std::vector data) +{ + ani_class arrayCls = nullptr; + ani_status status = ANI_OK; + status = env->FindClass("Lescompat/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, data.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_New failed status : %{public}d", status); + return arrayObj; + } + + ani_size index = 0; + for (auto &appStateData : data) { + ani_ref ani_info = WrapAppStateData(env, appStateData); + if (ani_info == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null ani_info"); + break; + } + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, ani_info); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + break; + } + index++; + } + return arrayObj; +} + +ani_object NewArrayClass(ani_env *env, const std::vector& data) +{ + ani_class arrayCls = nullptr; + ani_status status = ANI_OK; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + status = env->FindClass("Lescompat/Array;", &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "find calss 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, data.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_New array failed status : %{public}d", status); + return arrayObj; + } + + ani_size index = 0; + for (auto &item : data) { + ani_string ani_str; + status = env->String_NewUTF8(item.c_str(), item.size(), &ani_str); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "String_NewUTF8 failed status : %{public}d", status); + break; + } + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, ani_str); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_CallMethodByName_Void failed status : %{public}d", status); + break; + } + index++; + } + return arrayObj; +} + +bool SetProcessInformation(ani_env *env, ani_object object, const AppExecFwk::RunningProcessInfo &processInfo) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return false; + } + ani_status status = ANI_OK; + if ((status = env->Object_SetPropertyByName_Double(object, "pid", processInfo.pid_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "pid failed status:%{public}d", status); + return false; + } + if ((status = env->Object_SetPropertyByName_Double(object, "uid", processInfo.uid_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "uid failed status:%{public}d", status); + return false; + } + status = env->Object_SetPropertyByName_Ref(object, "processName", + OHOS::AppExecFwk::GetAniString(env, processInfo.processName_)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "processName failed status:%{public}d", status); + return false; + } + status = env->Object_SetPropertyByName_Ref(object, "bundleNames", NewArrayClass(env, processInfo.bundleNames)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "bundleNames failed status:%{public}d", status); + return false; + } + ani_enum_item stateItem {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvertNativeToSts(env, + "L@ohos/app/ability/appManager/appManager/ProcessState;", processInfo.state_, stateItem); + if ((status = env->Object_SetPropertyByName_Ref(object, "state", stateItem)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "state failed status:%{public}d", status); + return false; + } + ani_enum_item bundleTypeItem {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvertNativeToSts(env, + "L@ohos/bundle/bundleManager/bundleManager/BundleType;", + processInfo.bundleType, bundleTypeItem); + if ((status = env->Object_SetPropertyByName_Ref(object, "bundleType", bundleTypeItem)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "bundleType failed status:%{public}d", status); + return false; + } + status = env->Object_SetPropertyByName_Ref(object, "appCloneIndex", + AppExecFwk::createDouble(env, processInfo.appCloneIndex)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "appCloneIndex failed status:%{public}d", status); + return false; + } + return true; +} + +ani_object WrapProcessInformation(ani_env *env, const AppExecFwk::RunningProcessInfo &processInfo) +{ + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method {}; + ani_object object = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + if ((status = env->FindClass("Lapplication/ProcessInformation/ProcessInformationInner;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "FindClass failed status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "find ctor failed status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_New ProcessInformationInner failed status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + if (!SetProcessInformation(env, object, processInfo)) { + TAG_LOGE(AAFwkTag::APPMGR, "SetProcessInformation failed"); + return nullptr; + } + return object; +} + +ani_object CreateRunningProcessInfoArray(ani_env *env, std::vector infos) +{ + ani_class arrayCls = nullptr; + ani_status status = ANI_OK; + + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + + status = env->FindClass("Lescompat/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 &processInfo : infos) { + ani_object ani_info = WrapProcessInformation(env, processInfo); + 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; +} + +ani_object CreateEmptyAniArray(ani_env *env) +{ + ani_class arrayCls = nullptr; + ani_status status = ANI_OK; + + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + + status = env->FindClass("Lescompat/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, "", ":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); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_New array failed status : %{public}d", status); + return arrayObj; + } + return arrayObj; +} + +ani_object CreateEmptyMultiAppInfo(ani_env *env) +{ + ani_class cls {}; + 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("Lapplication/RunningMultiAppInfo/RunningMultiAppInfoInner;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "FindClass failed status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "find ctor failed status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_New failed status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + return object; +} + +ani_object CreateRunningMultiInstanceInfoArray(ani_env *env, 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("Lescompat/Array;", &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "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, "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, "status : %{public}d", status); + return arrayObj; + } + + ani_size index = 0; + for (auto &instanceInfo : infos) { + ani_ref ani_info = WrapRunningMultiInstanceInfo(env, instanceInfo); + if (ani_info == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null ani_info"); + break; + } + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, ani_info); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + break; + } + index++; + } + return arrayObj; +} + +ani_object CreateRunningAppCloneArray(ani_env *env, 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("Lescompat/Array;", &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "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, "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, "status : %{public}d", status); + return arrayObj; + } + + ani_size index = 0; + for (auto &runningAppclone : infos) { + ani_ref ani_info = WrapRunningAppClone(env, runningAppclone); + if (ani_info == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null ani_info"); + break; + } + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, ani_info); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + break; + } + index++; + } + return arrayObj; +} + +bool SetRunningMultiAppInfo(ani_env *env, ani_object object, + const AppExecFwk::RunningMultiAppInfo &runningMultiAppInfo) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return false; + } + ani_status status = env->Object_SetPropertyByName_Ref(object, "bundleName", + OHOS::AppExecFwk::GetAniString(env, runningMultiAppInfo.bundleName)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "bundleName failed status:%{public}d", status); + return false; + } + ani_enum_item modeItem {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvertNativeToSts(env, + "Lapplication/MultiAppMode/MultiAppMode;", runningMultiAppInfo.mode, modeItem); + status = env->Object_SetPropertyByName_Ref(object, "mode", modeItem); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "mode failed status:%{public}d", status); + return false; + } + status = env->Object_SetPropertyByName_Ref(object, "runningMultiInstances", + CreateRunningMultiInstanceInfoArray(env, runningMultiAppInfo.runningMultiIntanceInfos)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "runningMultiInstances failed status:%{public}d", status); + return false; + } + status = env->Object_SetPropertyByName_Ref(object, "runningAppClones", + CreateRunningAppCloneArray(env, runningMultiAppInfo.runningAppClones)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "runningAppClones failed status:%{public}d", status); + return false; + } + return true; +} + +ani_object WrapRunningMultiAppInfo(ani_env *env, const AppExecFwk::RunningMultiAppInfo &runningMultiAppInfo) +{ + 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("Lapplication/RunningMultiAppInfo/RunningMultiAppInfoInner;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "FindClass failed status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "find ctor failed status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_New failed status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + if (!SetRunningMultiAppInfo(env, object, runningMultiAppInfo)) { + TAG_LOGE(AAFwkTag::APPMGR, "SetRunningMultiAppInfo failed"); + return nullptr; + } + return object; +} + +ani_object WrapRunningMultiInstanceInfo(ani_env *env, const AppExecFwk::RunningMultiInstanceInfo &instanceInfo) +{ + 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("Lapplication/RunningMultiAppInfo/RunningMultiInstanceInfoInner;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + if (!SetRunningMultiInstanceInfo(env, object, instanceInfo)) { + TAG_LOGE(AAFwkTag::APPMGR, "SetRunningMultiInstanceInfo failed"); + return nullptr; + } + return object; +} + +bool SetRunningMultiInstanceInfo(ani_env *env, ani_object object, + const AppExecFwk::RunningMultiInstanceInfo &instanceInfo) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return false; + } + ani_status status = env->Object_SetPropertyByName_Ref(object, "instanceKey", + OHOS::AppExecFwk::GetAniString(env, instanceInfo.instanceKey)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "failed status:%{public}d", status); + return false; + } + return true; +} + +ani_object WrapRunningAppClone(ani_env *env, const AppExecFwk::RunningAppClone &runningAppClone) +{ + 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("Lapplication/RunningMultiAppInfo/RunningAppCloneInner;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + if (!SetRunningAppClone(env, object, runningAppClone)) { + TAG_LOGE(AAFwkTag::APPMGR, "SetRunningAppClone failed"); + return nullptr; + } + return object; +} + +bool SetRunningAppClone(ani_env *env, ani_object object, const AppExecFwk::RunningAppClone &runningAppClone) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return false; + } + ani_status status = env->Object_SetPropertyByName_Double(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); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "uid failed status:%{public}d", status); + return false; + } + ani_class arrayCls = nullptr; + status = env->FindClass("Lescompat/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, runningAppClone.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 : runningAppClone.pids) { + status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ID;:V", index, pid); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "set failed status : %{public}d", status); + return false; + } + index++; + } + status = env->Object_SetPropertyByName_Ref(object, "pids", arrayObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "pids failed status:%{public}d", status); + return false; + } + return true; +} + +ani_object WrapProcessData(ani_env *env, const AppExecFwk::ProcessData &processData) +{ + 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("Lapplication/ProcessData/ProcessData;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null object"); + return nullptr; + } + if (!SetProcessData(env, object, processData)) { + TAG_LOGE(AAFwkTag::APPMGR, "SetProcessData failed"); + return nullptr; + } + return object; +} + +bool SetProcessData(ani_env* env, ani_object object, const AppExecFwk::ProcessData &processData) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return false; + } + ani_status status = env->Object_SetFieldByName_Ref(object, "bundleName", + OHOS::AppExecFwk::GetAniString(env, processData.bundleName)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "bundleName failed status:%{public}d", status); + return false; + } + status = env->Object_SetFieldByName_Double(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); + 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)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "state failed status:%{public}d", status); + return false; + } + status = env->Object_SetFieldByName_Boolean(object, "isContinuousTask", processData.isContinuousTask); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "isContinuousTask failed status:%{public}d", status); + return false; + } + status = env->Object_SetFieldByName_Boolean(object, "isKeepAlive", processData.isKeepAlive); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "isKeepAlive failed status:%{public}d", status); + return false; + } + return true; +} + +bool UnWrapArrayString(ani_env *env, ani_object arrayObj, std::vector&stringList) +{ + if (env == nullptr || arrayObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env null or arrayObj null"); + return false; + } + stringList.clear(); + ani_size size = 0; + ani_status status = ANI_ERROR; + if ((status = env->Array_GetLength(reinterpret_cast(arrayObj), &size)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return false; + } + ani_ref ref; + 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; + } + std::string str = ""; + if (!OHOS::AppExecFwk::GetStdString(env, reinterpret_cast(ref), str)) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetStdString failed, index: %{public}zu", idx); + return false; + } + stringList.push_back(str); + } + return true; +} + +ani_object CreateDoubleAniArray(ani_env * env, const std::vector &dataArry) +{ + ani_class arrayCls = nullptr; + ani_status status = ANI_OK; + + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "null env"); + return nullptr; + } + + status = env->FindClass("Lescompat/Array;", &arrayCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "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, "status : %{public}d", status); + return nullptr; + } + + ani_object arrayObj; + status = env->Object_New(arrayCls, arrayCtor, &arrayObj, dataArry.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return arrayObj; + } + + for (size_t i = 0; i < dataArry.size(); i++) { + ani_object intObj = AppExecFwk::createDouble(env, static_cast(dataArry[i])); + if (intObj == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "intObj nullptr"); + return nullptr; + } + ani_status status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", i, intObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "status : %{public}d", status); + return nullptr; + } + } + return arrayObj; +} + +bool UnWrapArrayDouble(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_double dval = 0.0; + if ((status = env->Object_CallMethodByName_Double(static_cast(ref), + "unboxed", nullptr, &dval)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_CallMethodByName_Double status : %{public}d", status); + return false; + } + list.push_back(static_cast(dval)); + } + 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("L@ohos/app/ability/appManager/appManager/KeepAliveBundleInfoInner;", &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 ((env->Object_SetFieldByName_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::EnumConvertNativeToSts(env, + "L@ohos/app/ability/appManager/appManager/KeepAliveAppType;", 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::EnumConvertNativeToSts(env, + "L@ohos/app/ability/appManager/appManager/KeepAliveSetter;", 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("Lescompat/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; +} + +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/application/BUILD.gn b/frameworks/ets/ani/application/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..da507884d1e540129bab607a3195e42eec2b0ef2 --- /dev/null +++ b/frameworks/ets/ani/application/BUILD.gn @@ -0,0 +1,64 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("application_ani") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/interfaces/inner_api/runtime/include", + "${ability_runtime_path}/interfaces/inner_api/error_utils/include", + "${ability_runtime_path}/interfaces/kits/native/ability/native", + ] + + sources = [ "./src/ets_application.cpp" ] + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/ani_base_context:ani_base_context", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_native_path}/appkit:app_context_utils", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_native_path}/appkit:application_context_manager", + "${ability_runtime_services_path}/common:perm_verification", + ] + + external_deps = [ + "ability_base:configuration", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_core", + "hilog:libhilog", + "jsoncpp:jsoncpp", + "ipc:ipc_core", + "napi:ace_napi", + "runtime_core:ani", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/application/include/ets_application.h b/frameworks/ets/ani/application/include/ets_application.h new file mode 100644 index 0000000000000000000000000000000000000000..202e42a3a200e014e9ee4353a61a66fbfded9360 --- /dev/null +++ b/frameworks/ets/ani/application/include/ets_application.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_APPLICATION_H +#define OHOS_ABILITY_RUNTIME_ETS_APPLICATION_H + +#include "ani.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsApplication { +public: + static void CreateModuleContext([[maybe_unused]] ani_env *env, + ani_object contextObj, ani_string bundleName, ani_string moduleName, ani_object callback); + static void CreateBundleContext([[maybe_unused]] 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 +} // namespace OHOS +#endif //OHOS_ABILITY_RUNTIME_ETS_APPLICATION_H \ No newline at end of file diff --git a/frameworks/ets/ani/application/src/ets_application.cpp b/frameworks/ets/ani/application/src/ets_application.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d3c75e90d8255f566a110b8a58d89397699a550d --- /dev/null +++ b/frameworks/ets/ani/application/src/ets_application.cpp @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ets_application.h" + +#include "accesstoken_kit.h" +#include "ani_base_context.h" +#include "ani_common_util.h" +#include "application_context.h" +#include "application_context_manager.h" +#include "context_impl.h" +#include "ets_application_context_utils.h" +#include "hilog_tag_wrapper.h" +#include "ipc_skeleton.h" +#include "permission_verification.h" +#include "sts_context_utils.h" +#include "sts_error_utils.h" +#include "tokenid_kit.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* PERMISSION_GET_BUNDLE_INFO = "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED"; +} + +ani_object CreateEmptyObject(ani_env *env) +{ + ani_class cls = nullptr; + ani_status status = env->FindClass("Lapplication/Context/Context;", &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "find Context failed status: %{public}d", status); + return nullptr; + } + ani_method method = nullptr; + status = env->Class_FindMethod(cls, "", ":V", &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_FindMethod ctor failed status: %{public}d", status); + return nullptr; + } + ani_object objValue = nullptr; + if (env->Object_New(cls, method, &objValue) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_New failed status: %{public}d", status); + return nullptr; + } + return objValue; +} + +bool CheckIsSystemAppOrPermisson(ani_env *env, ani_object callback) +{ + auto emptyObject = CreateEmptyObject(env); + if (!AAFwk::PermissionVerification::GetInstance()->IsSystemAppCall()) { + TAG_LOGE(AAFwkTag::APPKIT, "no system app"); + AppExecFwk::AsyncCallback(env, callback, CreateStsError(env, + static_cast(AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP), + "The application is not system-app, can not use system-api."), emptyObject); + return false; + } + if (!AAFwk::PermissionVerification::GetInstance()->VerifyGetBundleInfoPrivilegedPermission()) { + TAG_LOGE(AAFwkTag::APPKIT, "no permission"); + AppExecFwk::AsyncCallback(env, callback, + CreateStsNoPermissionError(env, PERMISSION_GET_BUNDLE_INFO), emptyObject); + return false; + } + return true; +} + +bool SetNativeContextLong(ani_env *env, std::shared_ptr context, ani_class& cls, ani_object& contextObj) +{ + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "env or context is null"); + return false; + } + ani_status status = ANI_ERROR; + ani_method method {}; + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + return false; + } + if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + return false; + } + ani_field field = nullptr; + if ((status = env->Class_FindField(cls, "nativeContext", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + return false; + } + auto workContext = new (std::nothrow) std::weak_ptr(context); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "workContext nullptr"); + return false; + } + ani_long nativeContextLong = (ani_long)workContext; + if ((status = env->Object_SetField_Long(contextObj, field, nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + delete workContext; + workContext = nullptr; + return false; + } + return true; +} + +void SetCreateCompleteCallback(ani_env *env, std::shared_ptr> contextPtr, ani_object callback) +{ + if (env == nullptr || contextPtr == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "env or contextPtr is nullptr"); + return; + } + auto context = *contextPtr; + if (!context) { + TAG_LOGE(AAFwkTag::APPKIT, "failed to create context"); + auto emptyObject = CreateEmptyObject(env); + AppExecFwk::AsyncCallback(env, callback, CreateStsError(env, + AbilityErrorCode::ERROR_CODE_INVALID_PARAM), emptyObject); + return; + } + ani_class cls {}; + ani_status status = ANI_ERROR; + if ((status = env->FindClass("Lapplication/Context/Context;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + return; + } + ani_object contextObj = nullptr; + if (!SetNativeContextLong(env, context, cls, contextObj)) { + TAG_LOGE(AAFwkTag::APPKIT, "set nativeContextLong failed"); + return; + } + ContextUtil::StsCreatContext(env, cls, contextObj, context); + AppExecFwk::AsyncCallback(env, callback, CreateStsError(env, AbilityErrorCode::ERROR_OK), contextObj); +} + +std::shared_ptr GetStageModeContext(ani_env *env, ani_object &contextObj, + ani_object callback, ani_object emptyObject) +{ + ani_boolean stageMode = false; + ani_status status = IsStageContext(env, contextObj, stageMode); + if (status != ANI_OK || !stageMode) { + TAG_LOGE(AAFwkTag::APPKIT, "not stageMode"); + AppExecFwk::AsyncCallback(env, callback, CreateStsInvalidParamError(env, + "Parse param context failed, must be a context of stageMode."), emptyObject); + return nullptr; + } + auto context = GetStageModeContext(env, contextObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + AppExecFwk::AsyncCallback(env, callback, CreateStsInvalidParamError(env, + "Parse param context failed, must not be nullptr."), emptyObject); + return nullptr; + } + return context; +} + +void EtsApplication::CreateModuleContext([[maybe_unused]] ani_env *env, + ani_object contextObj, ani_string bundleName, ani_string moduleName, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "CreateModuleContext Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + ani_object emptyObject = CreateEmptyObject(env); + std::string stdBundleName = ""; + std::string stdModuleName = ""; + AppExecFwk::GetStdString(env, bundleName, stdBundleName); + AppExecFwk::GetStdString(env, moduleName, stdModuleName); + auto context = GetStageModeContext(env, contextObj, callback, emptyObject); + if (context == nullptr) { + return; + } + auto inputContextPtr = Context::ConvertTo(context); + if (inputContextPtr == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "Convert to context failed"); + AppExecFwk::AsyncCallback(env, callback, CreateStsInvalidParamError(env, + "Parse param context failed, must be a context."), emptyObject); + return; + } + std::shared_ptr> moduleContext = std::make_shared>(); + std::shared_ptr contextImpl = std::make_shared(); + if (contextImpl == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null contextImpl"); + AppExecFwk::AsyncCallback(env, callback, CreateStsInvalidParamError(env, + "create context failed."), emptyObject); + return; + } + contextImpl->SetProcessName(context->GetProcessName()); + if (stdBundleName.empty()) { + *moduleContext = contextImpl->CreateModuleContext(stdModuleName, inputContextPtr); + } else { + if (!CheckIsSystemAppOrPermisson(env, callback)) { + TAG_LOGE(AAFwkTag::APPKIT, "CheckCaller failed"); + } + *moduleContext = contextImpl->CreateModuleContext(stdBundleName, stdModuleName, inputContextPtr); + } + SetCreateCompleteCallback(env, moduleContext, callback); +} + +void EtsApplication::CreateBundleContext([[maybe_unused]] ani_env *env, + ani_object contextObj, ani_string bundleName, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "CreateBundleContext Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + ani_object emptyObject = CreateEmptyObject(env); + if (!CheckIsSystemAppOrPermisson(env, callback)) { + TAG_LOGE(AAFwkTag::APPKIT, "CheckCaller failed"); + return; + } + std::string stdBundleName = ""; + AppExecFwk::GetStdString(env, bundleName, stdBundleName); + ani_boolean stageMode = false; + ani_status status = OHOS::AbilityRuntime::IsStageContext(env, contextObj, stageMode); + if (status != ANI_OK || !stageMode) { + TAG_LOGE(AAFwkTag::APPKIT, "not stageMode"); + AppExecFwk::AsyncCallback(env, callback, CreateStsInvalidParamError(env, + "Parse param context failed, must be a context of stageMode."), emptyObject); + return; + } + auto context = OHOS::AbilityRuntime::GetStageModeContext(env, contextObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + AppExecFwk::AsyncCallback(env, callback, CreateStsInvalidParamError(env, + "Parse param context failed, must not be nullptr."), emptyObject); + return; + } + auto inputContextPtr = Context::ConvertTo(context); + if (inputContextPtr == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "Convert to context failed"); + AppExecFwk::AsyncCallback(env, callback, CreateStsInvalidParamError(env, + "Parse param context failed, must be a context."), emptyObject); + return; + } + auto bundleContext = std::make_shared>(); + std::shared_ptr contextImpl = std::make_shared(); + if (contextImpl == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null contextImpl"); + AppExecFwk::AsyncCallback(env, callback, CreateStsInvalidParamError(env, + "create context failed."), emptyObject); + return; + } + contextImpl->SetProcessName(context->GetProcessName()); + contextImpl->CreateBundleContext(*bundleContext, stdBundleName, inputContextPtr); + 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 {}; + } + auto stsReference = + AbilityRuntime::ApplicationContextManager::GetApplicationContextManager().GetEtsGlobalObject(); + if (stsReference == nullptr || stsReference->aniObj == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContextObject"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + ani_ref result = nullptr; + env->GetNull(&result); + return static_cast(result); + } + return stsReference->aniObj; +} + +void ApplicationInit(ani_env *env) +{ + TAG_LOGD(AAFwkTag::APPKIT, "ApplicationInit Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + ani_status status = ANI_ERROR; + ani_namespace ns; + status = env->FindNamespace("L@ohos/app/ability/application/application;", &ns); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "FindNamespace application failed status: %{public}d", status); + return; + } + std::array methods = { + ani_native_function { + "nativeCreateModuleContext", + "Lapplication/Context/Context;Lstd/core/String;Lstd/core/String;" + "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplication::CreateModuleContext) + }, + ani_native_function { + "nativeCreateBundleContext", + "Lapplication/Context/Context;Lstd/core/String;" + "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplication::CreateBundleContext) + }, + ani_native_function { + "nativeGetApplicationContext", + ":Lapplication/ApplicationContext/ApplicationContext;", + reinterpret_cast(EtsApplication::GetApplicationContext) + }, + }; + status = env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Namespace_BindNativeFunctions failed status: %{public}d", status); + } +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::APPKIT, "in ApplicationETS.ANI_Constructor"); + if (vm == nullptr || result == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null vm or result"); + return ANI_INVALID_ARGS; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed, status: %{public}d", status); + return ANI_NOT_FOUND; + } + ApplicationInit(env); + *result = ANI_VERSION_1; + TAG_LOGD(AAFwkTag::APPKIT, "AbilityManagerSts.ANI_Constructor finished"); + return ANI_OK; +} +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/enum_convert/ani_enum_convert.h b/frameworks/ets/ani/enum_convert/ani_enum_convert.h new file mode 100644 index 0000000000000000000000000000000000000000..1d18ef52956c915fc1d85bebcfc0cedd8b02644c --- /dev/null +++ b/frameworks/ets/ani/enum_convert/ani_enum_convert.h @@ -0,0 +1,107 @@ +/* + * 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_BASE_ANI_ENUM_CONVERT_UTILS_H +#define OHOS_ABILITY_BASE_ANI_ENUM_CONVERT_UTILS_H +#include +#include "hilog_tag_wrapper.h" +#include "ani.h" +namespace OHOS { +namespace AAFwk { + +namespace AniEnumConvertUtil { +//enum convert +[[maybe_unused]] static bool GetStdString(ani_env *env, ani_string str, std::string &res) +{ + ani_size sz {}; + ani_status status = ANI_ERROR; + if ((status = env->String_GetUTF8Size(str, &sz)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + res.resize(sz + 1); + if ((status = env->String_GetUTF8SubString(str, 0, sz, res.data(), res.size(), &sz)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return false; + } + res.resize(sz); + return true; +} + +template +static bool EnumConvertStsToNative(ani_env *env, ani_enum_item enumItem, T &result) +{ + ani_status status = ANI_ERROR; + if constexpr (std::is_enum::value || std::is_integral::value) { + ani_int intValue{}; + status = env->EnumItem_GetValue_Int(enumItem, &intValue); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "EnumConvertStsToNative failed, status : %{public}d", status); + return false; + } + result = static_cast(intValue); + return true; + } else if constexpr (std::is_same::value) { + ani_string strValue{}; + status = env->EnumItem_GetValue_String(enumItem, &strValue); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "EnumItem_GetValue_String failed, status : %{public}d", status); + return false; + } + return GetStdString(env, strValue, result); + } else { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Enum convert failed: type not supported"); + return false; + } +} + +template +static bool EnumConvertStsToNative(ani_env *env, ani_object enumItem, T &result) +{ + return EnumConvertStsToNative(env, static_cast(enumItem), result); +} + +template +static bool EnumConvertNativeToSts(ani_env *env, const char *enumName, const T enumValue, ani_enum_item &result) +{ + ani_enum aniEnum{}; + ani_status status = env->FindEnum(enumName, &aniEnum); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Enum convert FindEnum failed: %{public}s status: %{public}d", enumName, status); + return false; + } + constexpr int32_t loopMaxNum = 1000; + for (int32_t index = 0U; index < loopMaxNum; index++) { + ani_enum_item enumItem{}; + status = env->Enum_GetEnumItemByIndex(aniEnum, index, &enumItem); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::STSRUNTIME, + "Enum convert Enum_GetEnumItemByIndex failed: enumName:%{public}s index:%{public}d status:%{public}d", + enumName, index, status); + return false; + } + // compare value + T tmpValue{}; + if (EnumConvertStsToNative(env, enumItem, tmpValue) && tmpValue == enumValue) { + result = enumItem; + return true; + } + } + TAG_LOGE(AAFwkTag::STSRUNTIME, "EnumConvertNativeToSts failed enumName: %{public}s", enumName); + return false; +} +} +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_ABILITY_BASE_ANI_ENUM_CONVERT_UTILS_H diff --git a/frameworks/ets/ani/form_extension_ability/BUILD.gn b/frameworks/ets/ani/form_extension_ability/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..94439d9bfbfac7bd2995fe0ff8bd3be0e8fdb80a --- /dev/null +++ b/frameworks/ets/ani/form_extension_ability/BUILD.gn @@ -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. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") + +generate_static_abc("form_extension_ability_ani") { + base_url = "./ets" + files = [ + "./ets/@ohos.app.form.FormExtensionAbility.ets", + "./ets/application/FormExtensionContext.ets", + ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/form_extension_ability_ani.abc" +} + +ohos_prebuilt_etc("form_extension_ability_etc") { + source = "$target_out_dir/form_extension_ability_ani.abc" + deps = [ ":form_extension_ability_ani" ] + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/form_extension_ability/ets/@ohos.app.form.FormExtensionAbility.ets b/frameworks/ets/ani/form_extension_ability/ets/@ohos.app.form.FormExtensionAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..ec46ff210576719525afd72e6dab0d844fd6c75a --- /dev/null +++ b/frameworks/ets/ani/form_extension_ability/ets/@ohos.app.form.FormExtensionAbility.ets @@ -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. + */ + +import formBindingData from '@ohos.app.form.formBindingData'; +import FormExtensionContext from './application/FormExtensionContext'; +import Want from '@ohos.app.ability.Want'; + +type OnStopFn = () => void; + +export default class FormExtensionAbility { + public context: FormExtensionContext = new FormExtensionContext(); + + onAddForm(want: Want): formBindingData.FormBindingData { + console.log('FormExtensionAbility onAddForm'); + let dataObj1: Record = { + 'temperature': '11c', + 'time': '11:00' + }; + + let obj1: formBindingData.FormBindingData = formBindingData.createFormBindingData(dataObj1); + return obj1; + } + + onCastToNormalForm(formId: string): void { + console.log(`FormExtensionAbility onCastToNormalForm, formId: ${formId}`); + } + + onUpdateForm(formId: string, wantParams?: Record): void { + console.log(`FormExtensionAbility onUpdateForm, formId: ${formId}, + wantPara: ${wantParams?.['ohos.extra.param.key.host_bg_inverse_color']}`); + } + + onChangeFormVisibility(newStatus: Record): void { + console.log(`FormExtensionAbility onChangeFormVisibility, newStatus: ${newStatus}`); + } + + onFormEvent(formId: string, message: string): void { + console.log(`FormExtensionAbility onFormEvent, formId: ${formId}, message: ${message}`); + } + + onRemoveForm(formId: string): void { + console.log(`FormExtensionAbility onRemoveForm, formId: ${formId}`); + } + + public onStop?: OnStopFn; +} \ No newline at end of file diff --git a/frameworks/ets/ani/form_extension_ability/ets/application/ApplicationContext.ets b/frameworks/ets/ani/form_extension_ability/ets/application/ApplicationContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..62767df3bea4f0415438a518e62877a9ca0496dc --- /dev/null +++ b/frameworks/ets/ani/form_extension_ability/ets/application/ApplicationContext.ets @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Context } from './Context' + +export default class ApplicationContext extends Context { + public native setSupportedProcessCacheSync(isSupported: boolean): void; + + setSupportedProcessCache(isSupported: boolean): void { + taskpool.execute((): void => { + this.setSupportedProcessCacheSync(isSupported); + }); + } +} \ No newline at end of file diff --git a/frameworks/ets/ani/form_extension_ability/ets/application/BaseContext.ets b/frameworks/ets/ani/form_extension_ability/ets/application/BaseContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..b5b76c11b849df7b9fb9cd5d25ce5e9c62840595 --- /dev/null +++ b/frameworks/ets/ani/form_extension_ability/ets/application/BaseContext.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default class BaseContext { + public stageMode: boolean; +} \ No newline at end of file diff --git a/frameworks/ets/ani/form_extension_ability/ets/application/Context.ets b/frameworks/ets/ani/form_extension_ability/ets/application/Context.ets new file mode 100644 index 0000000000000000000000000000000000000000..eb29c4b66b91d5bf952ce193c283287973b345b6 --- /dev/null +++ b/frameworks/ets/ani/form_extension_ability/ets/application/Context.ets @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import BaseContext from './BaseContext.ets' +import ApplicationContext from './ApplicationContext' + +export class Context extends BaseContext { + area: int = 0; + filesDir: string = ""; + tempDir: string = ""; + private applicationContext?: ApplicationContext; + + getApplicationContext(): ApplicationContext | undefined { + return this.applicationContext; + } +} \ No newline at end of file diff --git a/frameworks/ets/ani/form_extension_ability/ets/application/ExtensionContext.ets b/frameworks/ets/ani/form_extension_ability/ets/application/ExtensionContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..e0be18107546166cacb93883d738f6a0311cf60b --- /dev/null +++ b/frameworks/ets/ani/form_extension_ability/ets/application/ExtensionContext.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Context } from './Context' + +export default class ExtensionContext extends Context { + +} \ No newline at end of file diff --git a/frameworks/ets/ani/form_extension_ability/ets/application/FormExtensionContext.ets b/frameworks/ets/ani/form_extension_ability/ets/application/FormExtensionContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..63fcfbf217efef67388aabe9fc2599deea196200 --- /dev/null +++ b/frameworks/ets/ani/form_extension_ability/ets/application/FormExtensionContext.ets @@ -0,0 +1,20 @@ +/* + * 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 ExtensionContext from './ExtensionContext'; + +export default class FormExtensionContext extends ExtensionContext { + +} \ No newline at end of file diff --git a/frameworks/ets/ani/form_extension_ability/include/sts_form_extension.h b/frameworks/ets/ani/form_extension_ability/include/sts_form_extension.h new file mode 100644 index 0000000000000000000000000000000000000000..31b5cf3671eb87249b564d3c97cc21bb744d3de3 --- /dev/null +++ b/frameworks/ets/ani/form_extension_ability/include/sts_form_extension.h @@ -0,0 +1,82 @@ +/* + * 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_STS_FORM_EXTENSION_H +#define OHOS_ABILITY_RUNTIME_STS_FORM_EXTENSION_H + +#include "ani.h" +#include "form_extension.h" +#include "sts_runtime.h" + +class NativeReference; +class STSNativeReference; +namespace OHOS { +namespace AbilityRuntime { +class FormExtension; +class STSRuntime; + +class STSFormExtension : public FormExtension { +public: + static STSFormExtension *Create(const std::unique_ptr &runtime); + const STSRuntime &GetSTSRuntime(); + explicit STSFormExtension(STSRuntime &stsRuntime); + ~STSFormExtension() override; + + void Init(const std::shared_ptr &record, + const std::shared_ptr &application, + std::shared_ptr &handler, const sptr &token) override; + OHOS::AppExecFwk::FormProviderInfo OnCreate(const OHOS::AAFwk::Want &want) override; + + void OnDestroy(const int64_t formId) override; + + void OnEvent(const int64_t formId, const std::string &message) override; + + void OnUpdate(const int64_t formId, const AAFwk::WantParams &wantParams) override; + + void OnCastToNormal(const int64_t formId) override; + + void OnVisibilityChange(const std::map &formEventsMap) override; + + sptr OnConnect(const OHOS::AAFwk::Want &want) override; + + void OnStop() override; +private: + void BindContext(std::shared_ptr &abilityInfo, std::shared_ptr want, + const std::string &moduleName, const std::string &srcPath); + + void UpdateFormExtensionObj( + std::shared_ptr &abilityInfo, const std::string &moduleName, const std::string &srcPath); + + void GetSrcPath(std::string &srcPath); + + bool CreateAndFillRecordObject( + ani_env *env, const std::map &formEventsMap, ani_object &recordObject); + + bool CallNativeFormMethod(ani_env *env, ani_object aniWant, ani_ref &nativeResult); + + bool ExtractFormData(ani_env *env, ani_ref nativeResult, AppExecFwk::FormProviderData &formData, + std::vector &formDataProxies); + + bool ConvertFromDataProxies(ani_env *env, ani_object arrayValue, std::vector &formDataProxies); + std::string ANIUtils_ANIStringToStdString(ani_env *env, ani_string ani_str); + ani_status ANIUtils_FormIdToAniString(ani_env *env, int64_t formId, ani_string &formIdStr); + std::unique_ptr stsObj_; + std::shared_ptr stsAbilityObj_; + STSRuntime &stsRuntime_; + sptr providerRemoteObject_ = nullptr; +}; // namespace AbilityRuntime +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_SIMULATOR_STS_ABILITY_CONTEXT_H \ No newline at end of file diff --git a/frameworks/ets/ani/form_extension_ability/include/sts_form_extension_context.h b/frameworks/ets/ani/form_extension_ability/include/sts_form_extension_context.h new file mode 100644 index 0000000000000000000000000000000000000000..d8462fe08295d1d175a2571ae5799a4cf8ef2cdb --- /dev/null +++ b/frameworks/ets/ani/form_extension_ability/include/sts_form_extension_context.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_STS_FORM_EXTENSION_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_STS_FORM_EXTENSION_CONTEXT_H + +#include "ani.h" +#include "form_extension_context.h" + +namespace OHOS { +namespace AbilityRuntime { +ani_ref CreateStsFormExtensionContext(ani_env *env, std::shared_ptr &context); + +class STSFormExtensionContext { +public: + static ani_ref CreateStsExtensionContext(ani_env *env, const std::shared_ptr &context, + std::shared_ptr &abilityInfo); + + static ani_object SetFormExtensionContext(ani_env *env, const std::shared_ptr &context); +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_FORM_EXTENSION_CONTEXT_H \ No newline at end of file diff --git a/frameworks/ets/ani/form_extension_ability/src/sts_form_extension.cpp b/frameworks/ets/ani/form_extension_ability/src/sts_form_extension.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c8ccbbadf8420d5179a79b3dbd0f76b6d3046fb7 --- /dev/null +++ b/frameworks/ets/ani/form_extension_ability/src/sts_form_extension.cpp @@ -0,0 +1,659 @@ +/* + * 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 "sts_form_extension.h" + +#include +#include + +#include "ability_info.h" +#include "ani.h" +#include "ani_common_want.h" +#include "form_provider_data.h" +#include "form_runtime/form_extension_provider_client.h" +#include "hilog_tag_wrapper.h" +#include "sts_form_extension_context.h" +#include "connection_manager.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* FORM_BINDING_DATA_CLASS_NAME = + "L@ohos/app/form/formBindingData/formBindingData/FormBindingDataInner;"; +constexpr const char* RECORD_CLASS_NAME = "Lescompat/Record;"; +} + +STSFormExtension *STSFormExtension::Create(const std::unique_ptr &runtime) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "call___%{public}d", runtime->GetLanguage()); + return new STSFormExtension(static_cast(*runtime)); +} + +const STSRuntime &STSFormExtension::GetSTSRuntime() +{ + return stsRuntime_; +} + +STSFormExtension::STSFormExtension(STSRuntime &stsRuntime) : stsRuntime_(stsRuntime) {} + +STSFormExtension::~STSFormExtension() +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "destructor"); + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "env null"); + return; + } + if (stsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "stsAbilityObj_ null"); + return; + } + if (stsAbilityObj_->aniRef) { + env->GlobalReference_Delete(stsAbilityObj_->aniRef); + } +} + +void STSFormExtension::Init(const std::shared_ptr &record, + const std::shared_ptr &application, std::shared_ptr &handler, + const sptr &token) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "Init call"); + if (record == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "null localAbilityRecord"); + return; + } + auto abilityInfo = record->GetAbilityInfo(); + if (abilityInfo == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "null abilityInfo"); + return; + } + FormExtension::Init(record, application, handler, token); + + std::string srcPath; + GetSrcPath(srcPath); + + std::string moduleName(Extension::abilityInfo_->moduleName); + moduleName.append("::").append(abilityInfo_->name); + TAG_LOGD(AAFwkTag::FORM_EXT, + "moduleName:%{public}s,srcPath:%{public}s," + "compileMode :%{public}d", + moduleName.c_str(), srcPath.c_str(), abilityInfo_->compileMode); + + BindContext(abilityInfo, record->GetWant(), moduleName, srcPath); + TAG_LOGI(AAFwkTag::FORM_EXT, "Init End"); +} + +void STSFormExtension::GetSrcPath(std::string &srcPath) +{ + if (!Extension::abilityInfo_->isModuleJson) { + srcPath.append(Extension::abilityInfo_->package); + srcPath.append("/assets/js/"); + if (!Extension::abilityInfo_->srcPath.empty()) { + srcPath.append(Extension::abilityInfo_->srcPath); + } + srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc"); + return; + } + + if (!Extension::abilityInfo_->srcEntrance.empty()) { + srcPath.append(Extension::abilityInfo_->moduleName + "/"); + srcPath.append(Extension::abilityInfo_->srcEntrance); + auto pos = srcPath.rfind("."); + if (pos != std::string::npos) { + srcPath.erase(pos); + srcPath.append(".abc"); + } + } +} + +void STSFormExtension::UpdateFormExtensionObj( + std::shared_ptr &abilityInfo, const std::string &moduleName, const std::string &srcPath) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "UpdateFormExtensionObj call"); + stsAbilityObj_ = stsRuntime_.LoadModule(moduleName, srcPath, abilityInfo->hapPath, + abilityInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE, false, abilityInfo_->srcEntrance); + if (stsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "null stsAbilityObj_"); + return; + } + TAG_LOGI(AAFwkTag::FORM_EXT, "UpdateFormExtensionObj End"); +} + +void STSFormExtension::BindContext(std::shared_ptr &abilityInfo, std::shared_ptr want, + const std::string &moduleName, const std::string &srcPath) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "BindContext call"); + + UpdateFormExtensionObj(abilityInfo, moduleName, srcPath); + + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "env null"); + return; + } + if (stsAbilityObj_ == nullptr || want == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "null stsAbilityObj_ or abilityContext_ or want"); + return; + } + + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "get context error"); + return; + } + ani_ref contextObj = CreateStsFormExtensionContext(env, context); + if (contextObj == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Create context obj error"); + return; + } + ani_ref contextGlobalRef = nullptr; + ani_field field = nullptr; + ani_status status = ANI_ERROR; + + if ((status = env->GlobalReference_Create(contextObj, &contextGlobalRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "status : %{public}d", status); + } + if ((status = env->Class_FindField(stsAbilityObj_->aniCls, "context", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "status : %{public}d", status); + } + + if ((status = env->Object_SetField_Ref(stsAbilityObj_->aniObj, field, contextGlobalRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "status : %{public}d", status); + } + + TAG_LOGI(AAFwkTag::FORM_EXT, "BindContext End"); +} + +std::string STSFormExtension::ANIUtils_ANIStringToStdString(ani_env *env, ani_string ani_str) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "ANIUtils_ANIStringToStdString Call"); + ani_size strSize; + if (ANI_OK != env->String_GetUTF8Size(ani_str, &strSize)) { + TAG_LOGE(AAFwkTag::FORM_EXT, "String_GetUTF8Size Failed"); + return ""; + } + + std::vector buffer(strSize + 1); + char *utf8_buffer = buffer.data(); + + ani_size bytes_written = 0; + if (ANI_OK != env->String_GetUTF8(ani_str, utf8_buffer, strSize + 1, &bytes_written)) { + TAG_LOGE(AAFwkTag::FORM_EXT, "String_GetUTF8 Failed"); + return ""; + } + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + TAG_LOGI(AAFwkTag::FORM_EXT, "ANIUtils_ANIStringToStdString End"); + return content; +} + +bool STSFormExtension::ConvertFromDataProxies( + ani_env *env, ani_object arrayValue, std::vector &formDataProxies) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "ConvertFromDataProxies Call"); + ani_status status = ANI_OK; + if (arrayValue == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "arrayValue null"); + return false; + } + + ani_double length; + if (ANI_OK != env->Object_GetPropertyByName_Double(arrayValue, "length", &length)) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_GetPropertyByName_Double length Failed"); + return false; + } + + int proxyLength = int(length); + for (int i = 0; i < proxyLength; i++) { + FormDataProxy formDataProxy("", ""); + ani_ref stringEntryRef; + if (ANI_OK != + env->Object_CallMethodByName_Ref(arrayValue, "$_get", "I:Lstd/core/Object;", &stringEntryRef, (ani_int)i)) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_CallMethodByName_Ref _get Failed"); + return false; + } + + ani_field key; + if ((status = env->Class_FindField(stsAbilityObj_->aniCls, "key", &key)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Class_FindField status : %{public}d", status); + return false; + } + + ani_ref keyRef; + if ((status = env->Object_GetField_Ref(static_cast(stringEntryRef), key, &keyRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_GetField_Ref status : %{public}d", status); + return false; + } + + formDataProxy.key = ANIUtils_ANIStringToStdString(env, static_cast(keyRef)); + + ani_field subscriberId; + if ((status = env->Class_FindField(stsAbilityObj_->aniCls, "subscriberId", &subscriberId)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Class_FindField status : %{public}d", status); + return false; + } + + ani_ref subscriberIdRef; + status = env->Object_GetField_Ref(static_cast(stringEntryRef), subscriberId, &subscriberIdRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_GetField_Ref status : %{public}d", status); + return false; + } + + formDataProxy.subscribeId = ANIUtils_ANIStringToStdString(env, static_cast(subscriberIdRef)); + formDataProxies.push_back(formDataProxy); + } + TAG_LOGI(AAFwkTag::FORM_EXT, "ConvertFromDataProxies End"); + return true; +} + +sptr STSFormExtension::OnConnect(const OHOS::AAFwk::Want &want) +{ + TAG_LOGD(AAFwkTag::FORM_EXT, "call"); + Extension::OnConnect(want); + if (providerRemoteObject_ == nullptr) { + TAG_LOGD(AAFwkTag::FORM_EXT, "null providerRemoteObject"); + sptr providerClient = new (std::nothrow) FormExtensionProviderClient(); + std::shared_ptr formExtension = + std::static_pointer_cast(shared_from_this()); + providerClient->SetOwner(formExtension); + providerRemoteObject_ = providerClient->AsObject(); + } + return providerRemoteObject_; +} + +OHOS::AppExecFwk::FormProviderInfo STSFormExtension::OnCreate(const OHOS::AAFwk::Want &want) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "OnCreate call"); + + OHOS::AppExecFwk::FormProviderInfo formProviderInfo; + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "env null"); + return formProviderInfo; + } + + ani_object aniWant = OHOS::AppExecFwk::WrapWant(env, want); + if (aniWant == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "null aniWant"); + return formProviderInfo; + } + + ani_ref nativeResult; + if (!CallNativeFormMethod(env, aniWant, nativeResult)) { + return formProviderInfo; + } + + AppExecFwk::FormProviderData formData; + std::vector formDataProxies; + if (ExtractFormData(env, nativeResult, formData, formDataProxies)) { + formProviderInfo.SetFormData(formData); + if (!formDataProxies.empty()) { + formProviderInfo.SetFormDataProxies(formDataProxies); + } + } + + TAG_LOGI(AAFwkTag::FORM_EXT, "OnCreate End"); + return formProviderInfo; +} + +bool STSFormExtension::CallNativeFormMethod(ani_env *env, ani_object aniWant, ani_ref &nativeResult) +{ + ani_status status = ANI_OK; + + ani_method function; + if ((status = env->Class_FindMethod(stsAbilityObj_->aniCls, "onAddForm", + "L@ohos/app/ability/Want/Want;:L@ohos/app/form/formBindingData/formBindingData/FormBindingData;", + &function))) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Class_FindMethod status: %{public}d", status); + return false; + } + + status = env->Object_CallMethod_Ref(stsAbilityObj_->aniObj, function, &nativeResult, aniWant); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_CallMethod_Ref status: %{public}d", status); + return false; + } + + return true; +} + +bool STSFormExtension::ExtractFormData(ani_env *env, ani_ref nativeResult, AppExecFwk::FormProviderData &formData, + std::vector &formDataProxies) +{ + ani_status status = ANI_OK; + + ani_class cls{}; + status = env->FindClass(FORM_BINDING_DATA_CLASS_NAME, &cls); + if (status != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "FindClass status: %{public}d", status); + return false; + } + + ani_method data{}; + status = env->Class_FindMethod(cls, "data", nullptr, &data); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Class_FindMethod data status: %{public}d", status); + return false; + } + + ani_ref dataRef; + status = env->Object_CallMethod_Ref(static_cast(nativeResult), data, &dataRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_CallMethod_Ref data status: %{public}d", status); + return false; + } + + std::string dataStr = ANIUtils_ANIStringToStdString(env, static_cast(dataRef)); + formData = AppExecFwk::FormProviderData(dataStr); + + ani_method proxies; + status = env->Class_FindMethod(cls, "proxies", nullptr, &proxies); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Class_FindMethod proxies status: %{public}d", status); + return true; + } + + ani_ref proxiesRef; + status = env->Object_CallMethod_Ref(static_cast(nativeResult), proxies, &proxiesRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_CallMethod_Ref proxies status: %{public}d", status); + return true; + } + + ani_boolean isUndefined = true; + if ((status = env->Reference_IsUndefined(proxiesRef, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Reference_IsUndefined status: %{public}d", status); + } + + if (!isUndefined && proxiesRef != nullptr) { + ConvertFromDataProxies(env, static_cast(proxiesRef), formDataProxies); + } + + return true; +} + +ani_status STSFormExtension::ANIUtils_FormIdToAniString(ani_env *env, int64_t formId, ani_string &formIdStr) +{ + ani_status status = ANI_OK; + std::string str = std::to_string(formId); + ani_string formIdStrTmp; + if ((status = env->String_NewUTF8(str.c_str(), str.size(), &formIdStrTmp))) { + TAG_LOGE(AAFwkTag::FORM_EXT, "String_NewUTF8 status : %{public}d", status); + return status; + } + formIdStr = formIdStrTmp; + return status; +} + +void STSFormExtension::OnDestroy(const int64_t formId) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "OnDestroy formId: %{public}" PRId64, formId); + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "env null"); + return; + } + ani_status status = ANI_OK; + + ani_string formIdStr; + if (ANIUtils_FormIdToAniString(env, formId, formIdStr) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "formId change failed."); + return; + } + + ani_method function; + if ((status = env->Class_FindMethod(stsAbilityObj_->aniCls, "onRemoveForm", "Lstd/core/String;:V", &function))) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Class_FindMethod status : %{public}d", status); + return; + } + + status = env->Object_CallMethod_Void(stsAbilityObj_->aniObj, function, formIdStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_New status : %{public}d", status); + return; + } + TAG_LOGI(AAFwkTag::FORM_EXT, "OnDestroy End"); +} + +void STSFormExtension::OnEvent(const int64_t formId, const std::string &message) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "OnEvent formId: %{public}" PRId64, formId); + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "env null"); + return; + } + ani_status status = ANI_OK; + + ani_string formIdStr; + if (ANIUtils_FormIdToAniString(env, formId, formIdStr) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "formId change failed."); + return; + } + ani_string aniMessage; + if ((status = env->String_NewUTF8(message.c_str(), message.size(), &aniMessage))) { + TAG_LOGE(AAFwkTag::FORM_EXT, "String_NewUTF8 status : %{public}d", status); + return; + } + ani_method function; + if ((status = env->Class_FindMethod( + stsAbilityObj_->aniCls, "onFormEvent", "Lstd/core/String;Lstd/core/String;:V", &function))) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Class_FindMethod status : %{public}d", status); + return; + } + + status = env->Object_CallMethod_Void(stsAbilityObj_->aniObj, function, formIdStr, aniMessage); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_New status : %{public}d", status); + return; + } + TAG_LOGI(AAFwkTag::FORM_EXT, "OnEvent End"); +} + +void STSFormExtension::OnUpdate(const int64_t formId, const AAFwk::WantParams &wantParams) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "OnUpdate formId: %{public}" PRId64, formId); + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "env null"); + return; + } + ani_status status = ANI_OK; + + ani_string formIdStr; + if (ANIUtils_FormIdToAniString(env, formId, formIdStr) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "formId change failed."); + return; + } + + ani_ref aniWantParams = OHOS::AppExecFwk::WrapWantParams(env, wantParams); + + ani_method function; + if ((status = env->Class_FindMethod( + stsAbilityObj_->aniCls, "onUpdateForm", "Lstd/core/String;Lescompat/Record;:V", &function))) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Class_FindMethod status : %{public}d", status); + return; + } + status = env->Object_CallMethod_Void( + stsAbilityObj_->aniObj, function, formIdStr, static_cast(aniWantParams)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_New status : %{public}d", status); + return; + } + TAG_LOGI(AAFwkTag::FORM_EXT, "OnUpdate End"); +} + +void STSFormExtension::OnCastToNormal(const int64_t formId) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "OnCastToNormal formId: %{public}" PRId64, formId); + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "env null"); + return; + } + ani_status status = ANI_OK; + + ani_string formIdStr; + if (ANIUtils_FormIdToAniString(env, formId, formIdStr) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "formId change failed."); + return; + } + + ani_method function; + if ((status = env->Class_FindMethod( + stsAbilityObj_->aniCls, "onCastToNormalForm", "Lstd/core/String;:V", &function))) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Class_FindMethod status : %{public}d", status); + return; + } + + status = env->Object_CallMethod_Void(stsAbilityObj_->aniObj, function, formIdStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_New status : %{public}d", status); + return; + } + TAG_LOGI(AAFwkTag::FORM_EXT, "OnCastToNormal End"); +} + +void STSFormExtension::OnVisibilityChange(const std::map &formEventsMap) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "OnVisibilityChange call"); + + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "env null"); + return; + } + + ani_method function; + ani_status status = + env->Class_FindMethod(stsAbilityObj_->aniCls, "onChangeFormVisibility", "Lescompat/Record;:V", &function); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Class_FindMethod status: %{public}d", status); + return; + } + + ani_object recordObject = {}; + if (!CreateAndFillRecordObject(env, formEventsMap, recordObject)) { + TAG_LOGW(AAFwkTag::FORM_EXT, "formEventsMap empty"); + } + + status = env->Object_CallMethod_Void(stsAbilityObj_->aniObj, function, recordObject); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_CallMethod_Void status: %{public}d", status); + return; + } + + TAG_LOGI(AAFwkTag::FORM_EXT, "OnVisibilityChange End"); +} + +bool STSFormExtension::CreateAndFillRecordObject(ani_env *env, const std::map &formEventsMap, + ani_object &recordObject) +{ + ani_status status = ANI_OK; + + ani_class recordCls; + status = env->FindClass(RECORD_CLASS_NAME, &recordCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "FindClass failed status: %{public}d", status); + return false; + } + + ani_method objectMethod; + if ((status = env->Class_FindMethod(recordCls, "", ":V", &objectMethod)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Class_FindMethod constructor failed: %{public}d", status); + return false; + } + + if ((status = env->Object_New(recordCls, objectMethod, &recordObject)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_New failed: %{public}d", status); + return false; + } + + ani_method recordSetMethod; + status = env->Class_FindMethod(recordCls, "$_set", "Lstd/core/Object;Lstd/core/Object;:V", &recordSetMethod); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Class_FindMethod set failed: %{public}d", status); + return false; + } + + for (auto iter = formEventsMap.begin(); iter != formEventsMap.end(); ++iter) { + std::string key = std::to_string(iter->first); + ani_string ani_key; + ani_int ani_value = iter->second; + + if ((status = env->String_NewUTF8(key.c_str(), key.length(), &ani_key)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "String_NewUTF8 key failed status : %{public}d", status); + return false; + } + + static const char *className = "Lstd/core/Int;"; + ani_class persion_cls; + if (ANI_OK != env->FindClass(className, &persion_cls)) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Not found "); + return false; + } + ani_method personInfoCtor; + env->Class_FindMethod(persion_cls, "", "I:V", &personInfoCtor); + ani_object personInfoObj; + env->Object_New(persion_cls, personInfoCtor, &personInfoObj, ani_value); + + if ((status = env->Object_CallMethod_Void(recordObject, recordSetMethod, ani_key, personInfoObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_CallMethod_Void failed status : %{public}d", status); + return false; + } + } + + return true; +} + +void STSFormExtension::OnStop() +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "OnStop begin"); + + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "env null"); + return; + } + + ani_ref nameRef; + ani_status status = env->Object_GetFieldByName_Ref( + static_cast(stsAbilityObj_->aniRef), "onStop", &nameRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "Object_GetFieldByName status: %{public}d, %{public}p, %{public}p", + status, stsAbilityObj_->aniRef, stsAbilityObj_->aniObj); + return; + } + + ani_ref result; + status = env->FunctionalObject_Call(static_cast(nameRef), 0, nullptr, &result); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "FunctionalObject_Call status: %{public}d", status); + return; + } + + bool ret = ConnectionManager::GetInstance().DisconnectCaller(GetContext()->GetToken()); + if (ret) { + ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid()); + TAG_LOGI(AAFwkTag::FORM_EXT, "disconnected failed"); + return; + } + + TAG_LOGI(AAFwkTag::FORM_EXT, "OnStop End"); +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/form_extension_ability/src/sts_form_extension_context.cpp b/frameworks/ets/ani/form_extension_ability/src/sts_form_extension_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b919ad62cdaa784a747b150a1ef415c111833f48 --- /dev/null +++ b/frameworks/ets/ani/form_extension_ability/src/sts_form_extension_context.cpp @@ -0,0 +1,98 @@ +/* + * 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 "sts_form_extension_context.h" + +#include +#include + +#include "ani_common_configuration.h" +#include "form_extension_context.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* FORM_EXTENSION_CONTEXT_CLASS_NAME = "Lapplication/FormExtensionContext/FormExtensionContext;"; +} + +ani_object STSFormExtensionContext::SetFormExtensionContext( + ani_env *env, const std::shared_ptr &context) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "SetFormExtensionContext call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "env null"); + return nullptr; + } + ani_long nativeContextLong = (ani_long)context.get(); + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_object contextObj = nullptr; + ani_method method = nullptr; + ani_field field = nullptr; + + if ((status = env->FindClass(FORM_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "status : %{public}d", status); + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "status : %{public}d", status); + } + if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "status : %{public}d", status); + } + if ((status = env->Class_FindField(cls, "nativeContext", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "status : %{public}d", status); + } + if ((status = env->Object_SetField_Long(contextObj, field, nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "status : %{public}d", status); + } + TAG_LOGI(AAFwkTag::FORM_EXT, "SetFormExtensionContext end"); + return contextObj; +} + +ani_ref STSFormExtensionContext::CreateStsExtensionContext(ani_env *env, + const std::shared_ptr &context, std::shared_ptr &abilityInfo) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "CreateStsExtensionContext call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::FORM_EXT, "env null"); + return nullptr; + } + + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + + status = env->FindClass(FORM_EXTENSION_CONTEXT_CLASS_NAME, &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "status : %{public}d", status); + return nullptr; + } + + ani_object contextObj = STSFormExtensionContext::SetFormExtensionContext(env, context); + + TAG_LOGI(AAFwkTag::FORM_EXT, "CreateStsExtensionContext end"); + return contextObj; +} + +ani_ref CreateStsFormExtensionContext(ani_env *env, std::shared_ptr &context) +{ + TAG_LOGI(AAFwkTag::FORM_EXT, "CreateStsFormExtensionContext call"); + auto abilityInfo = context->GetAbilityInfo(); + ani_ref object = STSFormExtensionContext::CreateStsExtensionContext(env, context, abilityInfo); + TAG_LOGI(AAFwkTag::FORM_EXT, "CreateStsFormExtensionContext end"); + return object; +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/insight_intent/insight_intent_driver/BUILD.gn b/frameworks/ets/ani/insight_intent/insight_intent_driver/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..29e9f83ce0c30befe61ce5c7c8f7800533793f64 --- /dev/null +++ b/frameworks/ets/ani/insight_intent/insight_intent_driver/BUILD.gn @@ -0,0 +1,70 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("insight_intent_driver_ani_kit") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", + "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/interfaces/kits/native/ability/native", + "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", + "${ability_runtime_path}/interfaces/inner_api/runtime/include", + ] + + configs = [] + + public_configs = [] + + sources = [ + "./src/ets_insight_intent_driver.cpp", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_native_path}/ability/native:abilitykit_native", + "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] + + external_deps = [ + "ability_base:want", + "bundle_framework:appexecfwk_base", + "c_utils:utils", + "hilog:libhilog", + "json:nlohmann_json_static", + "napi:ace_napi", + "runtime_core:ani", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} \ No newline at end of file diff --git a/frameworks/ets/ani/insight_intent/insight_intent_driver/include/ets_insight_intent_driver.h b/frameworks/ets/ani/insight_intent/insight_intent_driver/include/ets_insight_intent_driver.h new file mode 100644 index 0000000000000000000000000000000000000000..045b2ca04084cd494716809ec7fd2f01def14655 --- /dev/null +++ b/frameworks/ets/ani/insight_intent/insight_intent_driver/include/ets_insight_intent_driver.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_DRIVER_H +#define OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_DRIVER_H + +#include "ani.h" + +namespace OHOS { +namespace AbilityRuntime { +void EtsInsightIntentDriverInit(ani_env *env, [[maybe_unused]]ani_class aniClass, + ani_object exparam, ani_object callback, ani_boolean isCallback); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_DRIVER_H diff --git a/frameworks/ets/ani/insight_intent/insight_intent_driver/src/ets_insight_intent_driver.cpp b/frameworks/ets/ani/insight_intent/insight_intent_driver/src/ets_insight_intent_driver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f6b724d2403106b5df26444907ac365f0069665 --- /dev/null +++ b/frameworks/ets/ani/insight_intent/insight_intent_driver/src/ets_insight_intent_driver.cpp @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ets_insight_intent_driver.h" + +#include "ability_business_error.h" +#include "ability_manager_client.h" +#include "event_handler.h" +#include "event_runner.h" +#include "hilog_tag_wrapper.h" +#include "insight_intent_callback_interface.h" +#include "insight_intent_host_client.h" +#include "insight_intent_execute_result.h" +#include +#include "ani_common_execute_param.h" +#include "ani_common_execute_result.h" +#include "ani_common_util.h" +#include "sts_error_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +using namespace OHOS::AppExecFwk; +class EtsInsightIntentExecuteCallbackClient : public InsightIntentExecuteCallbackInterface, + public std::enable_shared_from_this { +public: + EtsInsightIntentExecuteCallbackClient(ani_vm *vm, ani_ref callbackRef, ani_ref promiseRef) + : vm_(vm), callbackRef_(callbackRef), promiseRef_(promiseRef) {} + + virtual ~EtsInsightIntentExecuteCallbackClient() + { + ani_env *env = AttachCurrentThread(); + if (env != nullptr) { + if (promiseRef_) { + env->GlobalReference_Delete(promiseRef_); + promiseRef_ = nullptr; + } + if (callbackRef_) { + env->GlobalReference_Delete(callbackRef_); + callbackRef_ = nullptr; + } + DetachCurrentThread(); + } + } + + void ProcessInsightIntentExecute(int32_t resultCode, + AppExecFwk::InsightIntentExecuteResult executeResult) override + { + ani_env *env = AttachCurrentThread(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "GetEnv failed"); + return; + } + + ani_object error; + ani_object result; + if (resultCode != 0) { + error = CreateStsErrorByNativeErr(env, resultCode); + result = CreateNullExecuteResult(env); + } else { + error = CreateStsError(env, AbilityErrorCode::ERROR_OK); + result = WrapExecuteResult(env, executeResult); + } + if (callbackRef_) { + AsyncCallback(env, static_cast(callbackRef_), error, result); + } + if (promiseRef_) { + AsyncCallback(env, static_cast(promiseRef_), error, result); + } + DetachCurrentThread(); + } + + ani_env *AttachCurrentThread() + { + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if ((status = vm_->GetEnv(ANI_VERSION_1, &env)) == ANI_OK) { + return env; + } + + ani_option interopEnabled { "--interop=disable", nullptr }; + ani_options aniArgs { 1, &interopEnabled }; + if ((status = vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + isAttachThread_ = true; + return env; + } + + void DetachCurrentThread() + { + if (isAttachThread_) { + vm_->DetachCurrentThread(); + isAttachThread_ = false; + } + } + +private: + ani_vm *vm_ = nullptr; + ani_ref callbackRef_ = nullptr; + ani_ref promiseRef_ = nullptr; + bool isAttachThread_ = false; +}; + +class EtsInsightIntentDriver { +public: + EtsInsightIntentDriver() = default; + ~EtsInsightIntentDriver() = default; + + static void OnExecute(ani_env *env, ani_object exparam, ani_object callback, ani_boolean isCallback) + { + TAG_LOGD(AAFwkTag::INTENT, "OnExecute called"); + ani_object error; + if (exparam == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "invalid param"); + error = CreateStsInvalidParamError(env, "invalid param"); + AsyncCallback(env, callback, error, CreateNullExecuteResult(env)); + return; + } + + InsightIntentExecuteParam param; + if (!UnwrapExecuteParam(env, exparam, param)) { + TAG_LOGE(AAFwkTag::INTENT, "parse execute param failed"); + error = CreateStsInvalidParamError(env, + "Parameter error: Parse param failed, param must be a ExecuteParam."); + AsyncCallback(env, callback, error, CreateNullExecuteResult(env)); + return; + } + + ani_ref callbackRef = nullptr; + if (env->GlobalReference_Create(callback, &callbackRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "GlobalReference_Create failed"); + error = CreateStsErrorByNativeErr(env, static_cast(AbilityErrorCode::ERROR_CODE_INNER)); + AsyncCallback(env, callback, error, CreateNullExecuteResult(env)); + return; + } + + ani_vm *vm = nullptr; + if (env->GetVM(&vm) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "GetVM failed"); + error = CreateStsErrorByNativeErr(env, static_cast(AbilityErrorCode::ERROR_CODE_INNER)); + AsyncCallback(env, callback, error, CreateNullExecuteResult(env)); + return; + } + + std::shared_ptr client; + if (isCallback) { + client = std::make_shared(vm, callbackRef, nullptr); + } else { + client = std::make_shared(vm, nullptr, callbackRef); + } + uint64_t key = InsightIntentHostClient::GetInstance()->AddInsightIntentExecute(client); + auto err = AbilityManagerClient::GetInstance()->ExecuteIntent(key, + InsightIntentHostClient::GetInstance(), param); + if (err != 0) { + error = CreateStsErrorByNativeErr(env, err); + AsyncCallback(env, callback, error, CreateNullExecuteResult(env)); + InsightIntentHostClient::GetInstance()->RemoveInsightIntentExecute(key); + } + return; + } +}; + +void EtsInsightIntentDriverInit(ani_env *env) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentDriverInit called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return; + } + + ani_namespace ns; + ani_status status = env->FindNamespace("L@ohos/app/ability/insightIntentDriver/insightIntentDriver;", &ns); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "FindNamespace insightIntentDriver failed status: %{public}d", status); + return; + } + + std::array kitFunctions = { + ani_native_function {"nativeExecuteSync", nullptr, + reinterpret_cast(EtsInsightIntentDriver::OnExecute)}, + }; + + status = env->Namespace_BindNativeFunctions(ns, kitFunctions.data(), kitFunctions.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "bind nativeExecuteSync failed status: %{public}d", status); + } +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::INTENT, "ANI_Constructor"); + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGD(AAFwkTag::INTENT, "GetEnv failed status: %{public}d", status); + return ANI_NOT_FOUND; + } + + EtsInsightIntentDriverInit(env); + *result = ANI_VERSION_1; + TAG_LOGD(AAFwkTag::INTENT, "ANI_Constructor finish"); + return ANI_OK; +} +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/native_constructor/BUILD.gn b/frameworks/ets/ani/native_constructor/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3637f8a2acd409fa39b8bda960235366e6c93312 --- /dev/null +++ b/frameworks/ets/ani/native_constructor/BUILD.gn @@ -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("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("context_ani") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + sources = [ + "context_native_constructor.cpp", + ] + + include_dirs = [ + "${ability_runtime_services_path}/common/include", + ] + + external_deps = [ + "hilog:libhilog", + "runtime_core:ani", + ] + subsystem_name = "ability" + part_name = "ability_runtime" + output_extension = "so" +} diff --git a/frameworks/ets/ani/native_constructor/context_native_constructor.cpp b/frameworks/ets/ani/native_constructor/context_native_constructor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b402dad70d58335e188783889c763d4955ab3219 --- /dev/null +++ b/frameworks/ets/ani/native_constructor/context_native_constructor.cpp @@ -0,0 +1,115 @@ +/* + * 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 +#include +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +void ContextConstructor() +{ +} + +void AbilityStageContextConstructor() +{ +} + +void ExtensionContextConstructor() +{ +} + +void UIAbilityContextConstructor() +{ +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (vm == nullptr || result == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Illegal VM or result"); + return ANI_ERROR; + } + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Unsupported ANI_VERSION_1"); + return ANI_ERROR; + } + // class Context + ani_class contextClass; + static const char *contextClassName = "Lapplication/Context/Context;"; + if (ANI_OK != env->FindClass(contextClassName, &contextClass)) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Not found class %{public}s.", contextClassName); + return ANI_NOT_FOUND; + } + std::array classMethods_context = { + ani_native_function {"", ":V", reinterpret_cast(ContextConstructor)}, + }; + if (ANI_OK != env->Class_BindNativeMethods(contextClass, classMethods_context.data(), + classMethods_context.size())) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Cannot bind native ctor to class %{public}s.", contextClassName); + return ANI_ERROR; + }; + // class ExtensionContext + ani_class extensionContextClass; + static const char *extensionContextClassName = "Lapplication/ExtensionContext/ExtensionContext;"; + if (ANI_OK != env->FindClass(extensionContextClassName, &extensionContextClass)) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Not found class %{public}s.", extensionContextClassName); + return ANI_NOT_FOUND; + } + std::array classMethods_extensionContext = { + ani_native_function {"", ":V", reinterpret_cast(ExtensionContextConstructor)}, + }; + if (ANI_OK != env->Class_BindNativeMethods(extensionContextClass, classMethods_extensionContext.data(), + classMethods_extensionContext.size())) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Cannot bind native ctor to class %{public}s.", extensionContextClassName); + return ANI_ERROR; + }; + // class UIAbilityContext + ani_class uiAbilityClass; + static const char *uiAbilityClassName = "Lapplication/UIAbilityContext/UIAbilityContext;"; + if (ANI_OK != env->FindClass(uiAbilityClassName, &uiAbilityClass)) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Not found class %{public}s.", uiAbilityClassName); + return ANI_NOT_FOUND; + } + std::array classMethods_uiAbility = { + ani_native_function {"", ":V", reinterpret_cast(UIAbilityContextConstructor)}, + }; + if (ANI_OK != env->Class_BindNativeMethods(uiAbilityClass, classMethods_uiAbility.data(), + classMethods_uiAbility.size())) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Cannot bind native ctor to class %{public}s.", uiAbilityClassName); + return ANI_ERROR; + }; + // class AbilityStageContext + ani_class abilityStageContextClass; + static const char *abilityStageContextClassName = "Lapplication/AbilityStageContext/AbilityStageContext;"; + if (ANI_OK != env->FindClass(abilityStageContextClassName, &abilityStageContextClass)) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Not found class %{public}s.", abilityStageContextClassName); + return ANI_NOT_FOUND; + } + std::array classMethods_abilityStage = { + ani_native_function {"", ":V", reinterpret_cast(AbilityStageContextConstructor)}, + }; + if (ANI_OK != env->Class_BindNativeMethods(abilityStageContextClass, classMethods_abilityStage.data(), + classMethods_abilityStage.size())) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Cannot bind native ctor to class %{public}s.", abilityStageContextClassName); + return ANI_ERROR; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/service_extension_ability/include/sts_service_extension.h b/frameworks/ets/ani/service_extension_ability/include/sts_service_extension.h new file mode 100644 index 0000000000000000000000000000000000000000..de9f9aaabd69816a60cdd6acd5f8833ef80e20a2 --- /dev/null +++ b/frameworks/ets/ani/service_extension_ability/include/sts_service_extension.h @@ -0,0 +1,230 @@ +/* + * 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_STS_SERVICE_EXTENSION_H +#define OHOS_ABILITY_RUNTIME_STS_SERVICE_EXTENSION_H + +#include "configuration.h" +#include "insight_intent_execute_param.h" +#include "insight_intent_execute_result.h" +#include "insight_intent_executor_info.h" +#ifdef SUPPORT_GRAPHICS +#include "display_manager.h" +#include "system_ability_status_change_stub.h" +#include "window_manager.h" +#endif +#include "service_extension.h" +#include "sts_runtime.h" +class STSNativeReference; + +namespace OHOS { +namespace AbilityRuntime { +class ServiceExtension; +class STSRuntime; +[[maybe_unused]] static void DisconnectPromiseCallback(ani_env* env, ani_object aniObj); +/** + * @brief Basic service components. + */ +class StsServiceExtension : public ServiceExtension { +public: + explicit StsServiceExtension(STSRuntime& stsRuntime); + virtual ~StsServiceExtension() override; + + /** + * @brief Create StsServiceExtension. + * + * @param runtime The runtime. + * @return The StsServiceExtension instance. + */ + static StsServiceExtension* Create(const std::unique_ptr& runtime); + /** + * @brief Init the extension. + * + * @param record the extension record. + * @param application the application info. + * @param handler the extension handler. + * @param token the remote token. + */ + virtual void Init(const std::shared_ptr &record, + const std::shared_ptr &application, + std::shared_ptr &handler, + const sptr &token) override; + + /** + * @brief Called when this extension is started. You must override this function if you want to perform some + * initialization operations during extension startup. + * + * This function can be called only once in the entire lifecycle of an extension. + * @param Want Indicates the {@link Want} structure containing startup information about the extension. + */ + virtual void OnStart(const AAFwk::Want &want) override; + + /** + * @brief Called when this Service extension is connected for the first time. + * + * You can override this function to implement your own processing logic. + * + * @param want Indicates the {@link Want} structure containing connection information about the Service extension. + * @return Returns a pointer to the sid of the connected Service extension. + */ + virtual sptr OnConnect(const AAFwk::Want &want) override; + + /** + * @brief Called when this Service extension is connected for the first time. + * + * You can override this function to implement your own processing logic. + * + * @param want Indicates the {@link Want} structure containing connection information about the Service extension. + * @param callbackInfo Indicates the lifecycle transaction callback information + * @param isAsyncCallback Indicates whether it is an asynchronous lifecycle callback + * @return Returns a pointer to the sid of the connected Service extension. + */ + virtual sptr OnConnect(const AAFwk::Want &want, + AppExecFwk::AbilityTransactionCallbackInfo> *callbackInfo, + bool &isAsyncCallback) override; + /** + * @brief Called when all abilities connected to this Service extension are disconnected. + * + * You can override this function to implement your own processing logic. + * + */ + virtual void OnDisconnect(const AAFwk::Want &want) override; + + /** + * @brief Called when all abilities connected to this Service extension are disconnected. + * + * You can override this function to implement your own processing logic. + * @param callbackInfo Indicates the lifecycle transaction callback information + * @param isAsyncCallback Indicates whether it is an asynchronous lifecycle callback + */ + void OnDisconnect(const AAFwk::Want &want, AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, + bool &isAsyncCallback) override; + + /** + * @brief Called back when Service is started. + * This method can be called only by Service. You can use the StartAbility(ohos.aafwk.content.Want) method to start + * Service. Then the system calls back the current method to use the transferred want parameter to execute its own + * logic. + * + * @param want Indicates the want of Service to start. + * @param restart Indicates the startup mode. The value true indicates that Service is restarted after being + * destroyed, and the value false indicates a normal startup. + * @param startId Indicates the number of times the Service extension has been started. The startId is incremented + * by 1 every time the extension is started. For example, if the extension has been started for six times, the + * value of startId is 6. + */ + virtual void OnCommand(const AAFwk::Want &want, bool restart, int startId) override; + + bool HandleInsightIntent(const AAFwk::Want &want) override; + + /** + * @brief Called when this extension enters the STATE_STOP state. + * + * The extension in the STATE_STOP is being destroyed. + * You can override this function to implement your own processing logic. + */ + virtual void OnStop() 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 configuration changed, including system configuration and window configuration. + * + */ + void ConfigurationUpdated(); + + /** + * @brief Called when extension need dump info. + * + * @param params The params from service. + * @param info The dump info to show. + */ + virtual void Dump(const std::vector ¶ms, std::vector &info) override; + + void ResetEnv(ani_env* env); + +private: + ani_ref CallObjectMethod(bool withResult, const char* name, const char* signature, ...); + + void BindContext(ani_env *env, std::shared_ptr want); + ani_object CreateSTSContext(ani_env *env, std::shared_ptr context, int32_t screenMode); + + void GetSrcPath(std::string &srcPath); + + napi_value CallOnConnect(const AAFwk::Want &want); + + napi_value CallOnDisconnect(const AAFwk::Want &want, bool withResult = false); + + bool CheckPromise(napi_value result); + + bool CallPromise(napi_value result, AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo); + + void ListenWMS(); + + STSRuntime& stsRuntime_; + std::unique_ptr stsObj_; + std::shared_ptr shellContextRef_ = nullptr; + std::shared_ptr handler_ = nullptr; +#ifdef SUPPORT_GRAPHICS +protected: + class StsServiceExtensionDisplayListener : public Rosen::IDisplayInfoChangedListener { + public: + explicit StsServiceExtensionDisplayListener(const std::weak_ptr& stsServiceExtension) + { + stsServiceExtension_ = stsServiceExtension; + } + + void OnDisplayInfoChange(const sptr& token, Rosen::DisplayId displayId, float density, + Rosen::DisplayOrientation orientation) override + { + auto sptr = stsServiceExtension_.lock(); + if (sptr != nullptr) { + sptr->OnDisplayInfoChange(token, displayId, density, orientation); + } + } + + private: + std::weak_ptr stsServiceExtension_; + }; + + void OnCreate(Rosen::DisplayId displayId); + void OnDestroy(Rosen::DisplayId displayId); + void OnChange(Rosen::DisplayId displayId); + void OnDisplayInfoChange(const sptr& token, Rosen::DisplayId displayId, float density, + Rosen::DisplayOrientation orientation); + +private: + class SystemAbilityStatusChangeListener : public OHOS::SystemAbilityStatusChangeStub { + public: + SystemAbilityStatusChangeListener(sptr displayListener, + const sptr & token): tmpDisplayListener_(displayListener), token_(token) {}; + virtual void OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override; + virtual void OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override {} + + private: + sptr tmpDisplayListener_ = nullptr; + sptr token_ = nullptr; + }; + + sptr displayListener_ = nullptr; + sptr saStatusChangeListener_ = nullptr; +#endif +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_SERVICE_EXTENSION_H \ No newline at end of file diff --git a/frameworks/ets/ani/service_extension_ability/include/sts_service_extension_context.h b/frameworks/ets/ani/service_extension_ability/include/sts_service_extension_context.h new file mode 100644 index 0000000000000000000000000000000000000000..61f416c05b9664e81e39946367c4b0f68c3e86a8 --- /dev/null +++ b/frameworks/ets/ani/service_extension_ability/include/sts_service_extension_context.h @@ -0,0 +1,70 @@ +/* + * 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_STS_UI_EXTENSION_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_STS_UI_EXTENSION_CONTEXT_H + +#include "sts_runtime.h" +#include +#include +#include +#include "service_extension.h" +#include "service_extension_context.h" +#include "hilog_tag_wrapper.h" +#include "hitrace_meter.h" +#include "ohos_application.h" +#include "sts_free_install_observer.h" + +namespace OHOS { +namespace AbilityRuntime { +bool BindNativeMethods(ani_env *env, ani_class &cls); +[[maybe_unused]] static void TerminateSelfSync([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, + [[maybe_unused]] ani_object callback); +[[maybe_unused]] static void StartAbility([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + ani_object wantObj, ani_object call); +[[maybe_unused]] static void StartAbilityWithOption([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + ani_object wantObj, ani_object opt, ani_object call); +[[maybe_unused]] static void StartServiceExtensionAbilitySync([[maybe_unused]] ani_env *env, + [[maybe_unused]] ani_object obj, [[maybe_unused]] ani_object wantObj, [[maybe_unused]] ani_object callbackobj); +[[maybe_unused]] static void StopServiceExtensionAbilitySync(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callbackobj); +ani_object CreateStsServiceExtensionContext(ani_env *env, std::shared_ptr context); + +void StsCreatExtensionContext(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context); + +void BindExtensionInfo(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context, std::shared_ptr abilityInfo); + +void UpdateContextConfiguration(ani_env *env, std::unique_ptr& stsObj, + ani_object aniConfiguration); + +class StsServiceExtensionContext final { +public: + static StsServiceExtensionContext &GetInstance() + { + static StsServiceExtensionContext instance; + return instance; + } + void StartAbilityInner([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + ani_object wantObj, ani_object opt, ani_object call); + static ServiceExtensionContext* GetAbilityContext(ani_env *env, ani_object obj); + void AddFreeInstallObserver(ani_env *env, const AAFwk::Want &want, ani_object callback, + ServiceExtensionContext* context); +private: + sptr freeInstallObserver_ = nullptr; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_UI_EXTENSION_CONTEXT_H \ No newline at end of file diff --git a/frameworks/ets/ani/service_extension_ability/src/sts_service_extension.cpp b/frameworks/ets/ani/service_extension_ability/src/sts_service_extension.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0db37ff0df1031ddf4498196cb8ddabccc5c318c --- /dev/null +++ b/frameworks/ets/ani/service_extension_ability/src/sts_service_extension.cpp @@ -0,0 +1,594 @@ +/* +* 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 "sts_service_extension.h" +#include "ability_business_error.h" +#include "ability_info.h" +#include "ability_manager_client.h" +#include "ani_common_configuration.h" +#include "ani_common_want.h" +#include "ani_remote_object.h" +#include "configuration_utils.h" +#include "hitrace_meter.h" +#include "hilog_tag_wrapper.h" +#include "insight_intent_execute_param.h" +#include "insight_intent_execute_result.h" +#include "insight_intent_executor_info.h" +#include "insight_intent_executor_mgr.h" +#include "js_service_extension_context.h" +#include "sts_service_extension_context.h" + +#ifdef SUPPORT_GRAPHICS +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "window_scene.h" +#endif + +namespace OHOS { +namespace AbilityRuntime { + +void DisconnectPromiseCallback(ani_env* env, ani_object aniObj) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "DisconnectPromiseCallback"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return; + } + ani_long disconnectCallbackPoint = 0; + ani_status status = ANI_ERROR; + if ((status = env->Object_GetFieldByName_Long(aniObj, "disconnectCallbackPoint", + &disconnectCallbackPoint)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status : %{public}d", status); + return; + } + auto *callbackInfo = + reinterpret_cast *>(disconnectCallbackPoint); + if (callbackInfo == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null callbackInfo"); + return; + } + callbackInfo->Call(); + AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo); +} + +void ConnectPromiseCallback(ani_env* env, ani_object aniObj, ani_object obj) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "PromiseCallback"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return; + } + ani_long connectCallbackPoint = 0; + ani_status status = ANI_ERROR; + if ((status = env->Object_GetFieldByName_Long(aniObj, "connectCallbackPoint", &connectCallbackPoint)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status : %{public}d", status); + return; + } + auto remoteObject = AniGetNativeRemoteObject(env, obj); + if (remoteObject == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null remoteObject"); + } + auto *callbackInfo = + reinterpret_cast>*>(connectCallbackPoint); + if (callbackInfo == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null callbackInfo"); + return; + } + + callbackInfo->Call(remoteObject); + AppExecFwk::AbilityTransactionCallbackInfo>::Destroy(callbackInfo); +} + +using namespace OHOS::AppExecFwk; + +StsServiceExtension* StsServiceExtension::Create(const std::unique_ptr& runtime) +{ + return new StsServiceExtension(static_cast(*runtime)); +} + +StsServiceExtension::StsServiceExtension(STSRuntime& stsRuntime) : stsRuntime_(stsRuntime) {} +StsServiceExtension::~StsServiceExtension() +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "called"); +} + +void StsServiceExtension::Init(const std::shared_ptr &record, + const std::shared_ptr &application, std::shared_ptr &handler, + const sptr &token) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "StsServiceExtension init"); + if (record == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "record null"); + return; + } + ServiceExtension::Init(record, application, handler, token); + if (Extension::abilityInfo_ == nullptr || Extension::abilityInfo_->srcEntrance.empty()) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "StsServiceExtension Init abilityInfo error"); + return; + } + std::string srcPath(Extension::abilityInfo_->moduleName + "/"); + srcPath.append(Extension::abilityInfo_->srcEntrance); + auto pos = srcPath.rfind("."); + if (pos != std::string::npos) { + srcPath.erase(pos); + srcPath.append(".abc"); + } + std::string moduleName(Extension::abilityInfo_->moduleName); + moduleName.append("::").append(abilityInfo_->name); + stsObj_ = stsRuntime_.LoadModule( + moduleName, srcPath, abilityInfo_->hapPath, abilityInfo_->compileMode == AppExecFwk::CompileMode::ES_MODULE, + false, abilityInfo_->srcEntrance); + if (stsObj_ == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to get stsObj"); + return; + } + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return; + } + std::array functions = { + ani_native_function { "nativeOnDisconnectCallback", ":V", reinterpret_cast(DisconnectPromiseCallback) }, + ani_native_function { "nativeOnConnectCallback", nullptr, reinterpret_cast(ConnectPromiseCallback) }, + }; + + ani_status status = env->Class_BindNativeMethods(stsObj_->aniCls, functions.data(), functions.size()); + if (ANI_OK != status) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Class_BindNativeMethods is fail %{public}d", status); + }; + BindContext(env, record->GetWant()); + return; +} +#ifdef SUPPORT_GRAPHICS +void StsServiceExtension::SystemAbilityStatusChangeListener::OnAddSystemAbility(int32_t systemAbilityId, + const std::string& deviceId) +{ +} +#endif //SUPPORT_GRAPHICS + +ani_object StsServiceExtension::CreateSTSContext(ani_env* env, std::shared_ptr context, + int32_t screenMode) +{ + TAG_LOGI(AAFwkTag::SERVICE_EXT, "CreateSTSContext"); + ani_object obj = CreateStsServiceExtensionContext(env, context); + return obj; +} + +void StsServiceExtension::BindContext(ani_env*env, std::shared_ptr want) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "StsServiceExtension BindContext Call"); + if (env == nullptr || want == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Want info is null or env is null"); + return; + } + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Failed to get context"); + return; + } + int32_t screenMode = want->GetIntParam(AAFwk::SCREEN_MODE_KEY, AAFwk::IDLE_SCREEN_MODE); + ani_object contextObj = CreateSTSContext(env, context, screenMode); + if (contextObj == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null contextObj"); + return; + } + //bind StsServiceExtension + ani_field contextField; + auto status = env->Class_FindField(stsObj_->aniCls, "context", &contextField); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Class_GetField context failed"); + ResetEnv(env); + return; + } + ani_ref contextRef = nullptr; + if (env->GlobalReference_Create(contextObj, &contextRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "GlobalReference_Create contextObj failed"); + return; + } + if (env->Object_SetField_Ref(stsObj_->aniObj, contextField, contextRef) != ANI_OK) { + TAG_LOGI(AAFwkTag::SERVICE_EXT, "Object_SetField_Ref contextObj failed"); + ResetEnv(env); + } + TAG_LOGD(AAFwkTag::SERVICE_EXT, "BindContext end"); +} + +void StsServiceExtension::ResetEnv(ani_env* env) +{ + env->DescribeError(); // 打印异常信息 + env->ResetError(); // 清除异常,避免影响后续 ANI 调用 +} + +void StsServiceExtension::OnStart(const AAFwk::Want &want) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::SERVICE_EXT, "called"); + + auto env = stsRuntime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "env not found Ability.sts"); + return; + } + + ani_ref wantRef = OHOS::AppExecFwk::WrapWant(env, want); + if (wantRef == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null wantRef"); + return; + } + + const char* signature = "L@ohos/app/ability/Want/Want;:V"; + CallObjectMethod(false, "onCreate", signature, wantRef); + TAG_LOGD(AAFwkTag::SERVICE_EXT, "end"); +} + +void StsServiceExtension::OnStop() +{ + ServiceExtension::OnStop(); + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::SERVICE_EXT, "called"); + const char* signature = ":V"; + CallObjectMethod(false, "onDestroy", signature); + TAG_LOGD(AAFwkTag::SERVICE_EXT, "end"); +} + +sptr StsServiceExtension::OnConnect(const AAFwk::Want &want) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::SERVICE_EXT, "called"); + auto env = stsRuntime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "env not found Ability.sts"); + return nullptr; + } + ani_ref wantRef = OHOS::AppExecFwk::WrapWant(env, want); + if (wantRef == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null wantRef"); + return nullptr; + } + const char* signature = "L@ohos/app/ability/Want/Want;:L@ohos/rpc/rpc/RemoteObject;"; + ani_ref result = CallObjectMethod(true, "onConnect", signature, wantRef); + auto obj = reinterpret_cast(result); + auto remoteObj = AniGetNativeRemoteObject(env, obj); + if (remoteObj == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "remoteObj null"); + return nullptr; + } + TAG_LOGD(AAFwkTag::SERVICE_EXT, "end"); + return remoteObj; +} + +sptr StsServiceExtension::OnConnect(const AAFwk::Want &want, + AppExecFwk::AbilityTransactionCallbackInfo> *callbackInfo, bool &isAsyncCallback) +{ + auto env = stsRuntime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "env not found"); + return nullptr; + } + ani_ref wantRef = OHOS::AppExecFwk::WrapWant(env, want); + if (wantRef == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null wantRef"); + return nullptr; + } + if (callbackInfo == nullptr) { + isAsyncCallback = false; + return OnConnect(want); + } + ani_long connectCallbackPoint = (ani_long)callbackInfo; + ani_status status = ANI_ERROR; + ani_field field = nullptr; + if ((status = env->Class_FindField(stsObj_->aniCls, "connectCallbackPoint", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + } + if ((status = env->Object_SetField_Long(stsObj_->aniObj, field, connectCallbackPoint)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + } + ani_ref result = + CallObjectMethod(true, "callOnConnect", "L@ohos/app/ability/Want/Want;:L@ohos/rpc/rpc/RemoteObject;", wantRef); + auto obj = reinterpret_cast(result); + auto remoteObj = AniGetNativeRemoteObject(env, obj); + if (remoteObj == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "remoteObj null"); + return nullptr; + } + return remoteObj; +} + +void StsServiceExtension::OnDisconnect(const AAFwk::Want &want) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::SERVICE_EXT, "called"); + auto env = stsRuntime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "env not found Ability.sts"); + return; + } + ani_ref wantRef = OHOS::AppExecFwk::WrapWant(env, want); + if (wantRef == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null wantRef"); + return; + } + const char* signature = "L@ohos/app/ability/Want/Want;:V"; + CallObjectMethod(false, "onDisconnect", signature, wantRef); + TAG_LOGD(AAFwkTag::SERVICE_EXT, "end"); +} + +void StsServiceExtension::OnDisconnect(const AAFwk::Want &want, + AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback) +{ + auto env = stsRuntime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "env not found"); + return; + } + ani_ref wantRef = OHOS::AppExecFwk::WrapWant(env, want); + if (wantRef == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null wantRef"); + return; + } + if (callbackInfo == nullptr) { + isAsyncCallback = false; + OnDisconnect(want); + return; + } + ani_long disconnectCallbackPoint = (ani_long)callbackInfo; + ani_status status = ANI_ERROR; + ani_field field = nullptr; + if ((status = env->Class_FindField(stsObj_->aniCls, "disconnectCallbackPoint", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return; + } + if ((status = env->Object_SetField_Long(stsObj_->aniObj, field, disconnectCallbackPoint)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return; + } + CallObjectMethod(false, "callOnDisconnect", "L@ohos/app/ability/Want/Want;:V", wantRef); +} + +void StsServiceExtension::OnCommand(const AAFwk::Want &want, bool restart, int startId) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::SERVICE_EXT, "called"); + auto env = stsRuntime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "env not found Ability.sts"); + return; + } + ani_ref wantRef = OHOS::AppExecFwk::WrapWant(env, want); + if (wantRef == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null wantRef"); + } + ani_int iStartId = static_cast(startId); + const char* signature = "L@ohos/app/ability/Want/Want;D:V"; + CallObjectMethod(false, "onRequest", signature, wantRef, iStartId); + TAG_LOGD(AAFwkTag::SERVICE_EXT, "end"); + return; +} + +bool StsServiceExtension::HandleInsightIntent(const AAFwk::Want &want) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "HandleInsightIntent called"); + auto callback = std::make_unique(); + callback.reset(InsightIntentExecutorAsyncCallback::Create()); + if (callback == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null callback"); + return false; + } + auto executeParam = std::make_shared(); + bool ret = AppExecFwk::InsightIntentExecuteParam::GenerateFromWant(want, *executeParam); + if (!ret) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Generate execute param failed"); + InsightIntentExecutorMgr::TriggerCallbackInner(std::move(callback), + static_cast(AbilityErrorCode::ERROR_CODE_INVALID_PARAM)); + return false; + } + TAG_LOGD(AAFwkTag::SERVICE_EXT, "Insight bundleName: %{public}s, moduleName: %{public}s, abilityName: %{public}s" + "insightIntentName: %{public}s, executeMode: %{public}d, intentId: %{public}" PRIu64 "", + executeParam->bundleName_.c_str(), executeParam->moduleName_.c_str(), executeParam->abilityName_.c_str(), + executeParam->insightIntentName_.c_str(), executeParam->executeMode_, executeParam->insightIntentId_); + auto asyncCallback = [weak = weak_from_this(), intentId = executeParam->insightIntentId_] + (AppExecFwk::InsightIntentExecuteResult result) { + TAG_LOGD(AAFwkTag::SERVICE_EXT, "intentId %{public}" PRIu64"", intentId); + auto extension = weak.lock(); + if (extension == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null extension"); + return; + } + auto ret = extension->OnInsightIntentExecuteDone(intentId, result); + if (!ret) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "OnInsightIntentExecuteDone failed"); + } + }; + callback->Push(asyncCallback); + InsightIntentExecutorInfo executorInfo; + ret = GetInsightIntentExecutorInfo(want, executeParam, executorInfo); + if (!ret) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Get Intent executor failed"); + InsightIntentExecutorMgr::TriggerCallbackInner(std::move(callback), + static_cast(AbilityErrorCode::ERROR_CODE_INVALID_PARAM)); + return false; + } + ret = DelayedSingleton::GetInstance()->ExecuteInsightIntent( + stsRuntime_, executorInfo, std::move(callback)); + if (!ret) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Execute insight intent failed"); + return false; + } + return true; +} + +ani_ref StsServiceExtension::CallObjectMethod(bool withResult, const char* name, const char* signature, ...) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name); + ani_status status = ANI_ERROR; + ani_method method = nullptr; + auto env = stsRuntime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return nullptr; + } + if ((status = env->Class_FindMethod(stsObj_->aniCls, name, signature, &method)) != ANI_OK) { + return nullptr; + } + if (method == nullptr) { + return nullptr; + } + ani_ref res = nullptr; + va_list args; + if (withResult) { + va_start(args, signature); + if ((status = env->Object_CallMethod_Ref_V(stsObj_->aniObj, method, &res, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status : %{public}d", status); + } + va_end(args); + return res; + } + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(stsObj_->aniObj, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status : %{public}d", status); + } + va_end(args); + return nullptr; +} +void StsServiceExtension::OnConfigurationUpdated(const AppExecFwk::Configuration& configuration) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "call"); + ServiceExtension::OnConfigurationUpdated(configuration); + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); + return; + } + auto contextConfig = context->GetConfiguration(); + if (contextConfig != nullptr) { + TAG_LOGD(AAFwkTag::SERVICE_EXT, "Config dump: %{public}s", contextConfig->GetName().c_str()); + std::vector changeKeyV; + contextConfig->CompareDifferent(changeKeyV, configuration); + if (!changeKeyV.empty()) { + contextConfig->Merge(changeKeyV, configuration); + } + TAG_LOGD(AAFwkTag::SERVICE_EXT, "Config dump after merge: %{public}s", contextConfig->GetName().c_str()); + } + ConfigurationUpdated(); +} + +void StsServiceExtension::ConfigurationUpdated() +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "called"); + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "env nullptr"); + return; + } + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); + return; + } + auto fullConfig = context->GetConfiguration(); + if (!fullConfig) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null configuration"); + return; + } + + ani_object aniConfiguration = OHOS::AppExecFwk::WrapConfiguration(env, *fullConfig); + ani_method method = nullptr; + ani_status status = env->Class_FindMethod(stsObj_->aniCls, + "onConfigurationUpdate", "L@ohos/app/ability/Configuration/Configuration;:V", &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "Class_FindMethod failed, status: %{public}d", status); + ResetEnv(env); + return; + } + status = env->Object_CallMethod_Void(stsObj_->aniObj, method, aniConfiguration); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "CALL Object_CallMethod failed, status: %{public}d", status); + ResetEnv(env); + return; + } + UpdateContextConfiguration(env, stsObj_, aniConfiguration); +} + +void StsServiceExtension::Dump(const std::vector ¶ms, std::vector &info) +{ + Extension::Dump(params, info); + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "env nullptr"); + return; + } + ani_object arrayObj = nullptr; + if (!WrapArrayString(env, arrayObj, params)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "WrapArrayString failed"); + arrayObj = nullptr; + return; + } + if (stsObj_ == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null stsObj_"); + return; + } + if (stsObj_->aniObj == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Not found ServiceExtension Obj"); + return; + } + if (stsObj_->aniCls == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Not found ServiceExtension class"); + return; + } + + ani_status status = ANI_ERROR; + ani_method method = nullptr; + if ((status = env->Class_FindMethod(stsObj_->aniCls, "onDump", nullptr, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Class_FindMethod FAILED: %{public}d", status); + return; + } + ani_ref dumpInfoRef; + if ((status = env->Object_CallMethod_Ref(stsObj_->aniObj, method, &dumpInfoRef, arrayObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Object_CallMethod_Ref FAILED: %{public}d", status); + return; + } + std::vector dumpInfoStrArray; + ani_object dumpInfoObj = reinterpret_cast(dumpInfoRef); + if (!UnwrapArrayString(env, dumpInfoObj, dumpInfoStrArray)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "UnwrapArrayString failed"); + return; + } + for (auto dumpInfoStr:dumpInfoStrArray) { + info.push_back(dumpInfoStr); + } + TAG_LOGD(AAFwkTag::SERVICE_EXT, "Dump info size: %{public}zu", info.size()); +} + +#ifdef SUPPORT_GRAPHICS +void StsServiceExtension::OnCreate(Rosen::DisplayId displayId) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "enter"); +} + +void StsServiceExtension::OnDestroy(Rosen::DisplayId displayId) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "exit"); +} + +void StsServiceExtension::OnDisplayInfoChange(const sptr& token, Rosen::DisplayId displayId, + float density, Rosen::DisplayOrientation orientation) +{ +} + +void StsServiceExtension::OnChange(Rosen::DisplayId displayId) +{ +} +#endif +} // AbilityRuntime +} // OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/service_extension_ability/src/sts_service_extension_context.cpp b/frameworks/ets/ani/service_extension_ability/src/sts_service_extension_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9fd5f6f8159dc9790015a8bba66065e6cdb46da2 --- /dev/null +++ b/frameworks/ets/ani/service_extension_ability/src/sts_service_extension_context.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 "common_fun_ani.h" +#include "ani_common_want.h" +#include "ability_manager_client.h" +#include "sts_context_utils.h" +#include "sts_error_utils.h" +#include "sts_service_extension_context.h" +#include "ani_common_start_options.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* SERVICE_EXTENSION_CONTEXT_CLASS_NAME = + "Lapplication/ServiceExtensionContext/ServiceExtensionContext;"; +} + +const char *INVOKE_METHOD_NAME = "invoke"; +static void TerminateSelfSync([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, + [[maybe_unused]] ani_object callback) +{ + TAG_LOGE(AAFwkTag::SERVICE_EXT, "terminateSelfSync call"); + ani_object aniObject = nullptr; + ErrCode ret = ERR_INVALID_VALUE; + auto context = StsServiceExtensionContext::GetAbilityContext(env, obj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "GetAbilityContext is nullptr"); + ret = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = CreateStsError(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); + return; + } + ret = context->TerminateAbility(); + AppExecFwk::AsyncCallback(env, callback, + CreateStsErrorByNativeErr(env, static_cast(ret)), nullptr); +} + +static void StartServiceExtensionAbilitySync([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + [[maybe_unused]] ani_object wantObj, [[maybe_unused]] ani_object callbackobj) +{ + TAG_LOGE(AAFwkTag::SERVICE_EXT, "call"); + ani_object aniObject = nullptr; + ErrCode ret = ERR_OK; + auto context = StsServiceExtensionContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "GetAbilityContext is nullptr"); + ret = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = CreateStsError(env, static_cast< AbilityErrorCode>(ret)); + AppExecFwk::AsyncCallback(env, callbackobj, aniObject, nullptr); + return; + } + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "UnwrapWant failed"); + aniObject = CreateStsInvalidParamError(env, "UnwrapWant failed"); + AppExecFwk::AsyncCallback(env, callbackobj, aniObject, nullptr); + return; + } + ret = context->StartServiceExtensionAbility(want); + if (ret == ERR_OK) { + aniObject = CreateStsError(env, static_cast< AbilityErrorCode>(ret)); + } else { + aniObject = CreateStsErrorByNativeErr(env, static_cast(ret)); + } + AppExecFwk::AsyncCallback(env, callbackobj, aniObject, nullptr); +} + +static void StartAbility([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + ani_object wantObj, ani_object call) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "StartAbility called"); + StsServiceExtensionContext::GetInstance().StartAbilityInner(env, aniObj, wantObj, nullptr, call); +} + +static void StartAbilityWithOption([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + ani_object wantObj, ani_object opt, ani_object call) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "StartAbilityWithOption called"); + StsServiceExtensionContext::GetInstance().StartAbilityInner(env, aniObj, wantObj, opt, call); +} + +static void StopServiceExtensionAbilitySync(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object callbackobj) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "StopServiceExtensionAbilitySync"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "env is nullptr"); + return; + } + ani_object aniObject = nullptr; + ErrCode ret = ERR_OK; + auto context = StsServiceExtensionContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "GetAbilityContext is nullptr"); + ret = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = CreateStsError(env, static_cast< AbilityErrorCode>(ret)); + AppExecFwk::AsyncCallback(env, callbackobj, aniObject, nullptr); + return; + } + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "UnwrapWant failed"); + aniObject = CreateStsInvalidParamError(env, "UnwrapWant failed"); + AppExecFwk::AsyncCallback(env, callbackobj, aniObject, nullptr); + return; + } + ret = context->StopServiceExtensionAbility(want); + aniObject = CreateStsErrorByNativeErr(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callbackobj, aniObject, nullptr); +} + +ServiceExtensionContext* StsServiceExtensionContext::GetAbilityContext(ani_env *env, + ani_object obj) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "GetAbilityContext start"); + ani_class cls = nullptr; + ani_long nativeContextLong; + ani_field contextField = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return nullptr; + } + if ((status = env->FindClass(SERVICE_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "terminateSelfSync find class status : %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeServiceExtensionContext", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "terminateSelfSync find field status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_GetField_Long(obj, contextField, &nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "terminateSelfSync get filed status : %{public}d", status); + return nullptr; + } + return (ServiceExtensionContext*)nativeContextLong; +} + +void UpdateContextConfiguration(ani_env *env, std::unique_ptr& stsObj, + ani_object aniConfiguration) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "GetAbilityContext start"); + ani_field contextField = nullptr; + ani_ref contextRef = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->Class_FindField(stsObj->aniCls, "context", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "terminateSelfSync find field status : %{public}d", status); + return; + } + if ((status = env->Object_GetField_Ref(stsObj->aniObj, contextField, &contextRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "terminateSelfSync get filed status : %{public}d", status); + return; + } + ani_class cls = nullptr; + ani_field configField = nullptr; + + if ((status = env->FindClass(SERVICE_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "terminateSelfSync find class status : %{public}d", status); + return; + } + if ((status = env->Class_FindField(cls, "config", &configField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "terminateSelfSync find field status : %{public}d", status); + return; + } + if ((status = env->Object_SetField_Ref(reinterpret_cast(contextRef), + configField, aniConfiguration)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "terminateSelfSync get filed status : %{public}d", status); + return; + } +} + +void StsServiceExtensionContext::AddFreeInstallObserver(ani_env *env, const AAFwk::Want &want, + ani_object callback, ServiceExtensionContext* context) +{ + // adapter free install async return install and start result + TAG_LOGD(AAFwkTag::SERVICE_EXT, "called"); + int ret = 0; + if (!context) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); + return; + } + if (!env) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return; + } + if (freeInstallObserver_ == nullptr) { + ani_vm *etsVm = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GetVM(&etsVm)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "status : %{public}d", status); + } + freeInstallObserver_ = new StsFreeInstallObserver(etsVm); + ret = context->AddFreeInstallObserver(freeInstallObserver_); + } + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "addFreeInstallObserver error"); + } + std::string startTime = want.GetStringParam(AAFwk::Want::PARAM_RESV_START_TIME); + TAG_LOGI(AAFwkTag::SERVICE_EXT, "addStsObserver"); + std::string bundleName = want.GetElement().GetBundleName(); + std::string abilityName = want.GetElement().GetAbilityName(); + freeInstallObserver_->AddStsObserverObject( + env, bundleName, abilityName, startTime, callback); +} + +void StsServiceExtensionContext::StartAbilityInner([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + ani_object wantObj, ani_object opt, ani_object call) +{ + ani_object aniObject = nullptr; + AAFwk::Want want; + ErrCode innerErrCode = ERR_OK; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + aniObject = CreateStsInvalidParamError(env, "UnwrapWant filed"); + AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + return; + } + auto context = StsServiceExtensionContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "GetAbilityContext is nullptr"); + innerErrCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = CreateStsError(env, static_cast(innerErrCode)); + AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + return; + } + if ((want.GetFlags() & AAFwk::Want::FLAG_INSTALL_ON_DEMAND) == AAFwk::Want::FLAG_INSTALL_ON_DEMAND) { + std::string startTime = std::to_string(std::chrono::duration_cast(std::chrono:: + system_clock::now().time_since_epoch()).count()); + want.SetParam(AAFwk::Want::PARAM_RESV_START_TIME, startTime); + AddFreeInstallObserver(env, want, call, context); + } + if (opt != nullptr) { + AAFwk::StartOptions startOptions; + if (!AppExecFwk::UnwrapStartOptionsWithProcessOption(env, opt, startOptions)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "UnwrapStartOptions filed"); + aniObject = CreateStsInvalidParamError(env, "UnwrapWant filed"); + AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + return; + } + innerErrCode = context->StartAbility(want, startOptions); + } else { + innerErrCode = context->StartAbility(want); + } + aniObject = CreateStsError(env, AbilityErrorCode::ERROR_OK); + if (innerErrCode != ERR_OK) { + aniObject = CreateStsErrorByNativeErr(env, innerErrCode); + } + if ((want.GetFlags() & AAFwk::Want::FLAG_INSTALL_ON_DEMAND) == AAFwk::Want::FLAG_INSTALL_ON_DEMAND) { + if (innerErrCode != ERR_OK && freeInstallObserver_ != nullptr) { + std::string bundleName = want.GetElement().GetBundleName(); + std::string abilityName = want.GetElement().GetAbilityName(); + std::string startTime = want.GetStringParam(AAFwk::Want::PARAM_RESV_START_TIME); + freeInstallObserver_->OnInstallFinished(bundleName, abilityName, startTime, innerErrCode); + } + } else { + AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + } +} + +void BindExtensionInfo(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context, std::shared_ptr abilityInfo) +{ + TAG_LOGI(AAFwkTag::APPKIT, "BindExtensionInfo"); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return; + } + auto hapModuleInfo = context->GetHapModuleInfo(); + ani_status status = ANI_OK; + if (abilityInfo && hapModuleInfo) { + auto isExist = [&abilityInfo](const AppExecFwk::ExtensionAbilityInfo& info) { + TAG_LOGD(AAFwkTag::CONTEXT, "%{public}s, %{public}s", info.bundleName.c_str(), info.name.c_str()); + return info.bundleName == abilityInfo->bundleName && info.name == abilityInfo->name; + }; + auto infoIter = std::find_if( + hapModuleInfo->extensionInfos.begin(), hapModuleInfo->extensionInfos.end(), isExist); + if (infoIter == hapModuleInfo->extensionInfos.end()) { + TAG_LOGE(AAFwkTag::CONTEXT, "set extensionAbilityInfo fail"); + return; + } + ani_field extensionAbilityInfoField; + status = aniEnv->Class_FindField(contextClass, "extensionAbilityInfo", &extensionAbilityInfoField); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "find extensionAbilityInfo failed status: %{public}d", status); + return; + } + ani_object extAbilityInfoObj = AppExecFwk::CommonFunAni::ConvertExtensionInfo(aniEnv, *infoIter); + status = aniEnv->Object_SetField_Ref(contextObj, extensionAbilityInfoField, + reinterpret_cast(extAbilityInfoObj)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_SetField_Ref failed status: %{public}d", status); + return; + } + } +} + +void StsCreatExtensionContext(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context) +{ + ContextUtil::StsCreatContext(aniEnv, contextClass, contextObj, context); + BindExtensionInfo(aniEnv, contextClass, contextObj, context, context->GetAbilityInfo()); +} + +bool BindNativeMethods(ani_env *env, ani_class &cls) +{ + ani_status status = ANI_ERROR; + std::array functions = { + ani_native_function { "nativeTerminateSelfSync", nullptr, reinterpret_cast(TerminateSelfSync) }, + ani_native_function { "nativeStartAbilitySync", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(StartAbility) }, + ani_native_function { "nativeStartAbilitySync", + "L@ohos/app/ability/Want/Want;L@ohos/app/ability/StartOptions/StartOptions;Lutils/AbilityUtils/" + "AsyncCallbackWrapper;:V", + reinterpret_cast(StartAbilityWithOption) }, + ani_native_function { "nativeStartServiceExtensionAbilitySync", nullptr, + reinterpret_cast(StartServiceExtensionAbilitySync) }, + ani_native_function { "nativeStopServiceExtensionAbility", nullptr, + reinterpret_cast(StopServiceExtensionAbilitySync) }, + }; + if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "bind method status : %{public}d", status); + return false; + } + return true; +} + +ani_object CreateStsServiceExtensionContext(ani_env *env, std::shared_ptr context) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env"); + return nullptr; + } + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_field field = nullptr; + ani_object contextObj = nullptr; + if ((env->FindClass(SERVICE_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "find class status : %{public}d", status); + return nullptr; + } + if (!BindNativeMethods(env, cls)) { + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "find method status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "new object status : %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeServiceExtensionContext", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "find field status : %{public}d", status); + return nullptr; + } + ani_long nativeContextLong = (ani_long)context.get(); + if ((status = env->Object_SetField_Long(contextObj, field, nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "set filed status : %{public}d", status); + return nullptr; + } + StsCreatExtensionContext(env, cls, contextObj, context); + return contextObj; +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ui_extension_ability/include/sts_ui_extension.h b/frameworks/ets/ani/ui_extension_ability/include/sts_ui_extension.h new file mode 100644 index 0000000000000000000000000000000000000000..7c73cd984f84438d6b6e5f5bc7260db058051aa8 --- /dev/null +++ b/frameworks/ets/ani/ui_extension_ability/include/sts_ui_extension.h @@ -0,0 +1,246 @@ +/* + * 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_STS_UI_EXTENSION_H +#define OHOS_ABILITY_RUNTIME_STS_UI_EXTENSION_H + +#include "ability_handler.h" +#include "configuration.h" +#ifdef SUPPORT_GRAPHICS +#include "display_manager.h" +#include "window_manager.h" +#endif // SUPPORT_GRAPHICS +#include "insight_intent_executor_info.h" +#include "ui_extension.h" +#include "ui_extension_context.h" +#include +#include "sts_runtime.h" +#include "sts_ui_extension_content_session.h" + +class STSNativeReference; + +namespace OHOS { +namespace AbilityRuntime { +class UIExtension; +class UIExtensionContext; +class JsRuntime; + +/** + * @brief Basic ui extension components. + */ +class StsUIExtension : public UIExtension { +public: + explicit StsUIExtension(STSRuntime& stsRuntime); + virtual ~StsUIExtension() override; + + /** + * @brief Create StsUIExtension. + * + * @param runtime The runtime. + * @return The StsUIExtension instance. + */ + static StsUIExtension* Create(const std::unique_ptr& stsRuntime); + + /** + * @brief Init the ui extension. + * + * @param record the ui extension record. + * @param application the application info. + * @param handler the ui extension handler. + * @param token the remote token. + */ + virtual void Init(const std::shared_ptr &record, + const std::shared_ptr &application, + std::shared_ptr &handler, + const sptr &token) override; + + /** + * @brief Called when this ui extension is started. You must override this function if you want to perform some + * initialization operations during ui extension startup. + * + * This function can be called only once in the entire lifecycle of an ui extension. + * + * @param Want Indicates the {@link Want} structure containing startup information about the ui extension. + * @param sessionInfo The session info of the ability. + */ + virtual void OnStart(const AAFwk::Want &want, sptr sessionInfo) override; + + /** + * @brief Called when this ui extension is connected for the first time. + * + * You can override this function to implement your own processing logic. + * + * @param want Indicates the {@link Want} structure containing connection information about the ui extension. + * @return Returns a pointer to the sid of the connected ui extension. + */ + virtual sptr OnConnect(const AAFwk::Want &want) override; + + /** + * @brief Called when all abilities connected to this ui extension are disconnected. + * + * You can override this function to implement your own processing logic. + * + */ + virtual void OnDisconnect(const AAFwk::Want &want) override; + + /** + * @brief Called back when ui extension is started. + * + * This method can be called only by ui extension. You can use the StartAbility(Want) method to start + * ui extension. Then the system calls back the current method to use the transferred want parameter to + * execute its own logic. + * + * @param want Indicates the want of ui extension to start. + * @param restart Indicates the startup mode. The value true indicates that ui extension is restarted after being + * destroyed, and the value false indicates a normal startup. + * @param startId Indicates the number of times the ui extension has been started. The startId is incremented + * by 1 every time the ui extension is started. For example, if the ui extension has been started for six times, the + * value of startId is 6. + */ + virtual void OnCommand(const AAFwk::Want &want, bool restart, int startId) override; + + /** + * @brief Called when this ui extension enters the STATE_STOP state. + * + * The ui extension in the STATE_STOP is being destroyed. + * You can override this function to implement your own processing logic. + */ + virtual void OnStop() override; + virtual void OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback) override; + /** + * @brief The callback of OnStop. + */ + 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. + * + * + * The extension in the STATE_FOREGROUND state is visible. + * You can override this function to implement your own processing logic. + */ + virtual void OnForeground(const Want &want, sptr sessionInfo) override; + + /** + * @brief Called when this extension enters the STATE_BACKGROUND state. + * + * + * The extension in the STATE_BACKGROUND state is invisible. + * You can override this function to implement your own processing logic. + */ + virtual void OnBackground() override; + + /** + * @brief Called when ui extension need dump info. + * + * @param params The params from ui extension. + * @param info The dump info to show. + */ + virtual void Dump(const std::vector ¶ms, std::vector &info) override; + + /** + * @brief Called when startAbilityForResult(ohos.aafwk.content.Want,int) is called to start an extension ability + * and the result is returned. + * @param requestCode Indicates the request code returned after the ability is started. You can define the request + * code to identify the results returned by abilities. The value ranges from 0 to 65535. + * @param resultCode Indicates the result code returned after the ability is started. You can define the result + * code to identify an error. + * @param resultData Indicates the data returned after the ability is started. You can define the data returned. The + * value can be null. + */ + void OnAbilityResult(int requestCode, int resultCode, const Want &resultData) override; + + /** + * @brief Called when configuration changed, including system configuration and window configuration. + */ + void ConfigurationUpdated(); + + void ResetEnv(ani_env* env); + +private: + virtual void BindContext(ani_env *env, std::shared_ptr want); + ani_object CreateSTSContext(ani_env *env, std::shared_ptr context, int32_t screenMode); + bool CallObjectMethod(bool withResult, const char* name, const char* signature, ...); + ani_status CallOnDisconnect(const AAFwk::Want &want, bool withResult = false); + ani_object CreateStsLaunchParam(ani_env* env, const AAFwk::LaunchParam& param); + std::shared_ptr LoadModule(ani_env *env); + + void ForegroundWindow(const AAFwk::Want &want, const sptr &sessionInfo) override; + void BackgroundWindow(const sptr &sessionInfo) override; + void DestroyWindow(const sptr &sessionInfo) override; + bool ForegroundWindowInitInsightIntentExecutorInfo(const AAFwk::Want &want, + const sptr &sessionInfo, InsightIntentExecutorInfo &executorInfo); + bool ForegroundWindowWithInsightIntent(const AAFwk::Want &want, const sptr &sessionInfo, + bool needForeground) override; + bool HandleSessionCreate(const AAFwk::Want &want, const sptr &sessionInfo); + void PostInsightIntentExecuted(const sptr &sessionInfo, + const AppExecFwk::InsightIntentExecuteResult &result, bool needForeground); + std::unique_ptr CreateAppWindowStage(sptr uiWindow, + sptr sessionInfo); + sptr CreateUIWindow(const std::shared_ptr context, + const sptr &sessionInfo); + void ExecuteInsightIntentDone(uint64_t intentId, const InsightIntentExecuteResult &result); + + STSRuntime& stsRuntime_; + std::shared_ptr stsObj_ = nullptr; + std::shared_ptr shellContextRef_ = nullptr; + std::map> contentSessions_; + int32_t screenMode_ = AAFwk::IDLE_SCREEN_MODE; + std::shared_ptr screenModePtr_; + sptr token_ = nullptr; + std::shared_ptr handler_ = nullptr; + std::shared_ptr abilityResultListeners_ = nullptr; + ani_ref contentSession_ = nullptr; + std::shared_ptr stsUiExtContentSession_; + +#ifdef SUPPORT_GRAPHICS + class StsUIExtensionAbilityDisplayListener : public OHOS::Rosen::IDisplayInfoChangedListener { + public: + explicit StsUIExtensionAbilityDisplayListener(const std::weak_ptr &StsUIExtension) + { + StsUIExtension_ = StsUIExtension; + } + + void OnDisplayInfoChange(const sptr &token, Rosen::DisplayId displayId, float density, + Rosen::DisplayOrientation orientation) override + { + auto sptr = StsUIExtension_.lock(); + if (sptr != nullptr) { + sptr->OnDisplayInfoChange(token, displayId, density, orientation); + } + } + + private: + std::weak_ptr StsUIExtension_; + }; + + void RegisterDisplayInfoChangedListener(); + void UnregisterDisplayInfoChangedListener(); + void OnDisplayInfoChange(const sptr &token, Rosen::DisplayId displayId, float density, + Rosen::DisplayOrientation orientation); + + sptr StsUIExtensionAbilityDisplayListener_ = nullptr; +#endif +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_UI_EXTENSION_H diff --git a/frameworks/ets/ani/ui_extension_ability/include/sts_ui_extension_content_session.h b/frameworks/ets/ani/ui_extension_ability/include/sts_ui_extension_content_session.h new file mode 100644 index 0000000000000000000000000000000000000000..99cac035eb583e31c271b533b487ef470982a6f1 --- /dev/null +++ b/frameworks/ets/ani/ui_extension_ability/include/sts_ui_extension_content_session.h @@ -0,0 +1,113 @@ +/* +* 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_STS_UI_EXTENSION_CONTENT_SESSION_H +#define OHOS_ABILITY_RUNTIME_STS_UI_EXTENSION_CONTENT_SESSION_H + +#include "session_info.h" +#include "start_options.h" +#include "window.h" +#include "sts_runtime.h" + +namespace OHOS { +namespace AbilityRuntime { +[[maybe_unused]] static void NativeSendData(ani_env* env, ani_object obj, ani_object data); +[[maybe_unused]] static void NativeLoadContent(ani_env* env, ani_object obj, ani_string path, ani_object storage); +[[maybe_unused]] static void NativeTerminateSelf(ani_env* env, ani_object obj, [[maybe_unused]] ani_object callback); +[[maybe_unused]] static void NativeSetWindowBackgroundColor(ani_env* env, ani_object obj, ani_string color); +[[maybe_unused]] static int NativeTerminateSelfWithResult(ani_env* env, ani_object obj, + [[maybe_unused]] ani_object abilityResult, [[maybe_unused]] ani_object callback); +[[maybe_unused]] static void NativeSetReceiveDataCallback(ani_env* env, ani_object clsObj, ani_object funcObj); +[[maybe_unused]] static void NativeSetReceiveDataForResultCallback(ani_env* env, ani_object clsObj, ani_object funcObj); + +using RuntimeTask = std::function; + +class StsAbilityResultListener { +public: + StsAbilityResultListener() = default; + virtual ~StsAbilityResultListener() = default; + virtual void OnAbilityResult(int requestCode, int resultCode, const AAFwk::Want &resultData) = 0; + virtual bool IsMatch(int requestCode) = 0; +}; + +class StsAbilityResultListeners { +public: + StsAbilityResultListeners() = default; + virtual ~StsAbilityResultListeners() = default; + void AddListener(const uint64_t &uiExtensionComponentId, std::shared_ptr listener) {} + void RemoveListener(const uint64_t &uiExtensionComponentId) {} + void OnAbilityResult(int requestCode, int resultCode, const AAFwk::Want &resultData) {} +private: + std::map> listeners_; +}; + +class StsUISessionAbilityResultListener : public StsAbilityResultListener { +public: + StsUISessionAbilityResultListener() = default; + virtual ~StsUISessionAbilityResultListener() = default; + virtual void OnAbilityResult(int requestCode, int resultCode, const AAFwk::Want &resultData) {} + virtual bool IsMatch(int requestCode) {return true;} + void OnAbilityResultInner(int requestCode, int resultCode, const AAFwk::Want &resultData) {} + void SaveResultCallbacks(int requestCode, RuntimeTask&& task) {} +private: + std::map resultCallbacks_; +}; + +class StsUIExtensionContentSession { +private: + class CallbackWrapper; +public: + StsUIExtensionContentSession(sptr sessionInfo, + sptr uiWindow, std::weak_ptr& context, + std::shared_ptr& abilityResultListeners); + StsUIExtensionContentSession(sptr sessionInfo, + sptr uiWindow); + virtual ~StsUIExtensionContentSession() = default; + static ani_object CreateStsUIExtensionContentSession(ani_env* env, + sptr sessionInfo, sptr uiWindow, + std::weak_ptr context, + std::shared_ptr& abilityResultListeners, + std::shared_ptr contentSessionPtr); + 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); + void TerminateSelf(); + int32_t TerminateSelfWithResult(); + void SetWindowBackgroundColor(ani_env* env, ani_string color); + ani_object GetUIExtensionHostWindowProxy(ani_env* env, ani_object object); + void SetReceiveDataCallback(ani_env* env, ani_object functionObj); + static void CallReceiveDataCallback(ani_vm* vm, ani_ref callbackRef, const AAFwk::WantParams& wantParams); + void SetReceiveDataForResultCallback(ani_env* env, ani_object object); + static void CallReceiveDataCallbackForResult(ani_vm* vm, ani_ref callbackRef, + const AAFwk::WantParams& wantParams, AAFwk::WantParams& retWantParams); + +private: + bool SetReceiveDataCallbackUnRegist(ani_env* env, ani_object functionObj); + bool SetReceiveDataForResultCallbackUnRegist(ani_env* env, ani_object funcObj); + + sptr sessionInfo_; + sptr uiWindow_; + std::weak_ptr context_; + ani_ref receiveDataCallback_ = nullptr; + bool isRegistered_ = false; + ani_ref receiveDataForResultCallback_ = nullptr; + bool isSyncRegistered_ = false; + std::shared_ptr listener_; + bool isFirstTriggerBindModal_ = true; +}; + +StsUIExtensionContentSession* GetStsContentSession(ani_env* env, ani_object obj); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_UI_EXTENSION_CONTENT_SESSION_H diff --git a/frameworks/ets/ani/ui_extension_ability/include/sts_ui_extension_context.h b/frameworks/ets/ani/ui_extension_ability/include/sts_ui_extension_context.h new file mode 100644 index 0000000000000000000000000000000000000000..95d68fc2ac7f7c9e7a9de4dbf58641af6f4b906c --- /dev/null +++ b/frameworks/ets/ani/ui_extension_ability/include/sts_ui_extension_context.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_ABILITY_RUNTIME_STS_UI_EXTENSION_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_STS_UI_EXTENSION_CONTEXT_H + +#include "sts_runtime.h" +#include +#include +#include +#include "ui_extension_context.h" +#include "hilog_tag_wrapper.h" +#include "hitrace_meter.h" +#include "ohos_application.h" +#include "sts_free_install_observer.h" +namespace OHOS { +namespace AbilityRuntime { + +[[maybe_unused]] static void TerminateSelfSync([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, + [[maybe_unused]] ani_object callback); +[[maybe_unused]] static void TerminateSelfWithResultSync([[maybe_unused]] ani_env *env, + [[maybe_unused]] ani_object obj, [[maybe_unused]] ani_object abilityResult, [[maybe_unused]] ani_object callback); +ani_object CreateStsUIExtensionContext(ani_env *env, std::shared_ptr context); + +bool BindNativeMethods(ani_env *env, ani_class &cls); + +class StsUIExtensionContext final { +public: + static StsUIExtensionContext &GetInstance() + { + static StsUIExtensionContext instance; + return instance; + } + void StartAbilityInner([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + ani_object wantObj, ani_object opt, ani_object call); + static UIExtensionContext* GetAbilityContext(ani_env *env, ani_object obj); + void AddFreeInstallObserver(ani_env *env, const AAFwk::Want &want, + ani_object callback, UIExtensionContext* context); + static void NativeSetColorMode(ani_env *env, ani_object aniCls, ani_enum_item aniColorMode); + static void NativeReportDrawnCompleted(ani_env *env, ani_object aniCls, ani_object callback); +private: + sptr freeInstallObserver_ = nullptr; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_UI_EXTENSION_CONTEXT_H \ No newline at end of file diff --git a/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension.cpp b/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c6edf16f575d5b1ced41e202e0b3e7f9841db854 --- /dev/null +++ b/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension.cpp @@ -0,0 +1,804 @@ +/* + * 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 "sts_ui_extension.h" +#include "ability_context.h" +#include "ability_delegator_registry.h" +#include "ability_info.h" +#include "ability_manager_client.h" +#include "ability_start_setting.h" +#include "array_wrapper.h" +#include "configuration_utils.h" +#include "connection_manager.h" +#include "context.h" +#include "hitrace_meter.h" +#include "hilog_tag_wrapper.h" +#include "insight_intent_executor_info.h" +#include "insight_intent_executor_mgr.h" +#include "int_wrapper.h" +#include "sts_runtime.h" +#include "ani_common_want.h" +#include "ui_extension_window_command.h" +#include "want_params_wrapper.h" +#include "sts_data_struct_converter.h" +#include "sts_ui_extension_context.h" +#include "string_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +using namespace OHOS::AppExecFwk; + +static constexpr char UIEXTENSION_CLASS_NAME[] = "L@ohos/app/ability/UIExtensionAbility/UIExtensionAbility;"; + +StsUIExtension* StsUIExtension::Create(const std::unique_ptr& runtime) +{ + return new (std::nothrow) StsUIExtension(static_cast(*runtime)); +} + +StsUIExtension::StsUIExtension(STSRuntime &stsRuntime) : stsRuntime_(stsRuntime) +{ +} + +StsUIExtension::~StsUIExtension() +{ + auto context = GetContext(); + if (context) { + context->Unbind(); + } + contentSessions_.clear(); +} + +void StsUIExtension::ResetEnv(ani_env* env) +{ + env->DescribeError(); + env->ResetError(); +} + +static void PromiseCallback(ani_env* env, ani_object aniObj) +{ + if (env == nullptr || aniObj == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env or null aniObj"); + return; + } + 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); + return; + } + auto *callbackInfo = reinterpret_cast *>(destroyCallbackPoint); + if (callbackInfo == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null callbackInfo"); + return; + } + callbackInfo->Call(); + AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo); + + if ((status = env->Object_SetFieldByName_Long(aniObj, "destroyCallbackPoint", + static_cast(0))) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status : %{public}d", status); + return; + } +} + +void StsUIExtension::Init(const std::shared_ptr &record, + const std::shared_ptr &application, std::shared_ptr &handler, + const sptr &token) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (record == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "record null"); + return; + } + UIExtension::Init(record, application, handler, token); + if (Extension::abilityInfo_ == nullptr || Extension::abilityInfo_->srcEntrance.empty()) { + TAG_LOGE(AAFwkTag::UI_EXT, "StsUIExtension Init abilityInfo error"); + return; + } + + if (record != nullptr) { + token_ = record->GetToken(); + } + std::string srcPath(Extension::abilityInfo_->moduleName + "/"); + srcPath.append(Extension::abilityInfo_->srcEntrance); + auto pos = srcPath.rfind("."); + if (pos != std::string::npos) { + srcPath.erase(pos); + srcPath.append(".abc"); + } + std::string moduleName(Extension::abilityInfo_->moduleName); + moduleName.append("::").append(abilityInfo_->name); + + stsObj_ = stsRuntime_.LoadModule( + moduleName, srcPath, abilityInfo_->hapPath, abilityInfo_->compileMode == AppExecFwk::CompileMode::ES_MODULE, + false, abilityInfo_->srcEntrance); + if (stsObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "stsObj_ null"); + return; + } + + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + std::array functions = { + ani_native_function { "nativeOnDestroyCallback", ":V", reinterpret_cast(PromiseCallback) }, + }; + ani_status status = ANI_ERROR; + if ((status = env->Class_BindNativeMethods(stsObj_->aniCls, functions.data(), functions.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + } + BindContext(env, record->GetWant()); + RegisterDisplayInfoChangedListener(); +} + +std::shared_ptr StsUIExtension::LoadModule(ani_env *env) +{ + std::shared_ptr stsNativeReference = std::make_shared(); + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(UIEXTENSION_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + } + + ani_method entryMethod = nullptr; + if ((status = env->Class_FindMethod(cls, "", ":V", &entryMethod)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + } + + ani_object entryObject = nullptr; + if ((status = env->Object_New(cls, entryMethod, &entryObject)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + } + + ani_ref entryObjectRef = nullptr; + if ((status = env->GlobalReference_Create(entryObject, &entryObjectRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + } + stsNativeReference->aniCls = cls; + stsNativeReference->aniObj = entryObject; + stsNativeReference->aniRef = entryObjectRef; + return stsNativeReference; +} + +ani_object StsUIExtension::CreateSTSContext(ani_env* env, std::shared_ptr context, + int32_t screenMode) +{ + ani_object obj = CreateStsUIExtensionContext(env, context); + return obj; +} + +void StsUIExtension::BindContext(ani_env*env, std::shared_ptr want) +{ + if (env == nullptr || want == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "Want info is null or env is null"); + return; + } + + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "context null"); + return; + } + + int32_t screenMode = want->GetIntParam(AAFwk::SCREEN_MODE_KEY, AAFwk::IDLE_SCREEN_MODE); + ani_object contextObj = CreateSTSContext(env, context, screenMode); + if (contextObj == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null contextObj"); + return; + } + + ani_field contextField; + auto status = env->Class_FindField(stsObj_->aniCls, "context", &contextField); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + ResetEnv(env); + return; + } + + ani_ref contextRef = nullptr; + if ((status = env->GlobalReference_Create(contextObj, &contextRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + return; + } + + if ((status = env->Object_SetField_Ref(stsObj_->aniObj, contextField, contextRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + ResetEnv(env); + } +} + +ani_object StsUIExtension::CreateStsLaunchParam(ani_env* env, const AAFwk::LaunchParam& param) +{ + ani_object obj = nullptr; + return obj; +} + +void StsUIExtension::OnStart(const AAFwk::Want &want, sptr sessionInfo) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + auto context = GetContext(); +#ifdef SUPPORT_GRAPHICS + if (context != nullptr && sessionInfo != nullptr) { + auto configUtils = std::make_shared(); + configUtils->InitDisplayConfig(context->GetConfiguration(), context->GetResourceManager(), + sessionInfo->displayId, sessionInfo->density, sessionInfo->orientation); + } +#endif // SUPPORT_GRAPHICS + + auto env = stsRuntime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::UI_EXT, "env not found Ability.sts"); + return; + } + const char *signature = + "L@ohos/app/ability/AbilityConstant/AbilityConstant/LaunchParam;:V"; + auto launchParam = Extension::GetLaunchParam(); + if (InsightIntentExecuteParam::IsInsightIntentExecute(want)) { + launchParam.launchReason = AAFwk::LaunchReason::LAUNCHREASON_INSIGHT_INTENT; + } + ani_object launchParamRef = CreateStsLaunchParam(env, launchParam); + CallObjectMethod(false, "onCreate", signature, launchParamRef); +} + +void StsUIExtension::OnStop() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + CallObjectMethod(false, "onDestroy", nullptr); +#ifdef SUPPORT_GRAPHICS + UnregisterDisplayInfoChangedListener(); +#endif // SUPPORT_GRAPHICS + OnStopCallBack(); +} + +void StsUIExtension::OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback) +{ + if (callbackInfo == nullptr) { + isAsyncCallback = false; + OnStop(); + return; + } + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + UIExtension::OnStop(); +#ifdef SUPPORT_GRAPHICS + UnregisterDisplayInfoChangedListener(); +#endif // SUPPORT_GRAPHICS + + std::weak_ptr weakPtr = shared_from_this(); + auto asyncCallback = [extensionWeakPtr = weakPtr]() { + auto stsUIExtension = extensionWeakPtr.lock(); + if (stsUIExtension == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "stsUIExtension null"); + return; + } + stsUIExtension->OnStopCallBack(); + }; + callbackInfo->Push(asyncCallback); + ani_long destroyCallbackPoint = (ani_long)callbackInfo; + ani_status status = ANI_ERROR; + ani_field field = nullptr; + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr || stsObj_ == nullptr) { + isAsyncCallback = false; + OnStop(); + return; + } + if ((status = env->Class_FindField(stsObj_->aniCls, "destroyCallbackPoint", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + } + if ((status = env->Object_SetField_Long(stsObj_->aniObj, field, destroyCallbackPoint)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + } + + isAsyncCallback = CallObjectMethod(true, "callOnDestroy", ":Z"); + if (!isAsyncCallback) { + OnStopCallBack(); + return; + } +} + +void StsUIExtension::OnStopCallBack() +{ + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "context null"); + return; + } + bool ret = ConnectionManager::GetInstance().DisconnectCaller(context->GetToken()); + if (ret) { + ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid()); + } +} + +sptr StsUIExtension::OnConnect(const AAFwk::Want &want) +{ + sptr remoteObj = nullptr; + return remoteObj; +} + +void StsUIExtension::OnDisconnect(const AAFwk::Want &want) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + Extension::OnDisconnect(want); +} + +ani_status StsUIExtension::CallOnDisconnect(const AAFwk::Want &want, bool withResult) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "called"); + return ANI_OK; +} + +bool StsUIExtension::ForegroundWindowInitInsightIntentExecutorInfo(const AAFwk::Want &want, + const sptr &sessionInfo, InsightIntentExecutorInfo &executorInfo) +{ + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + return false; + } + if (sessionInfo == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null sessionInfo"); + return false; + } + std::shared_ptr abilityInfo = context->GetAbilityInfo(); + if (abilityInfo != nullptr) { + executorInfo.hapPath = abilityInfo->hapPath; + executorInfo.windowMode = abilityInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE; + } + executorInfo.token = context->GetToken(); + executorInfo.pageLoader = contentSessions_[sessionInfo->uiExtensionComponentId]; + executorInfo.executeParam = std::make_shared(); + InsightIntentExecuteParam::GenerateFromWant(want, *executorInfo.executeParam); + executorInfo.executeParam->executeMode_ = UI_EXTENSION_ABILITY; + executorInfo.srcEntry = want.GetStringParam(INSIGHT_INTENT_SRC_ENTRY); + TAG_LOGD(AAFwkTag::UI_EXT, "executorInfo, insightIntentId: %{public}" PRIu64, + executorInfo.executeParam->insightIntentId_); + return true; +} + +bool StsUIExtension::ForegroundWindowWithInsightIntent(const AAFwk::Want &want, + const sptr &sessionInfo, bool needForeground) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (!HandleSessionCreate(want, sessionInfo)) { + TAG_LOGE(AAFwkTag::UI_EXT, "HandleSessionCreate failed"); + return false; + } + + std::unique_ptr executorCallback = nullptr; + executorCallback.reset(InsightIntentExecutorAsyncCallback::Create()); + if (executorCallback == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "Create async callback failed"); + return false; + } + + auto uiExtension = std::static_pointer_cast(shared_from_this()); + executorCallback->Push( + [uiExtension, sessionInfo, needForeground, want](AppExecFwk::InsightIntentExecuteResult result) { + TAG_LOGI(AAFwkTag::UI_EXT, "Execute post insightintent"); + if (uiExtension == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null uiExtension"); + return; + } + + InsightIntentExecuteParam executeParam; + InsightIntentExecuteParam::GenerateFromWant(want, executeParam); + if (result.uris.size() > 0) { + uiExtension->ExecuteInsightIntentDone(executeParam.insightIntentId_, result); + } + uiExtension->PostInsightIntentExecuted(sessionInfo, result, needForeground); + }); + + InsightIntentExecutorInfo executorInfo; + if (!ForegroundWindowInitInsightIntentExecutorInfo(want, sessionInfo, executorInfo)) { + return false; + } + + int32_t ret = DelayedSingleton::GetInstance()->ExecuteInsightIntent( + stsRuntime_, executorInfo, std::move(executorCallback)); + if (!ret) { + TAG_LOGE(AAFwkTag::UI_EXT, "Execute insight intent failed"); + } + return true; +} + +void StsUIExtension::ExecuteInsightIntentDone(uint64_t intentId, const InsightIntentExecuteResult &result) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "intentId %{public}" PRIu64"", intentId); + auto ret = AAFwk::AbilityManagerClient::GetInstance()->ExecuteInsightIntentDone(token_, intentId, result); + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "notify execute done failed"); + } +} + +void StsUIExtension::PostInsightIntentExecuted(const sptr &sessionInfo, + const AppExecFwk::InsightIntentExecuteResult &result, bool needForeground) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (needForeground) { + // If uiextensionability is started for the first time or need move background to foreground. + CallObjectMethod(false, "onForeground", nullptr); + } + + OnInsightIntentExecuteDone(sessionInfo, result); + + if (needForeground) { + // If need foreground, that means triggered by onForeground. + AAFwk::PacMap restoreData; + AAFwk::AbilityManagerClient::GetInstance()->AbilityTransitionDone(token_, AAFwk::ABILITY_STATE_FOREGROUND_NEW, + restoreData); + } else { + // If uiextensionability has displayed in the foreground. + OnCommandWindowDone(sessionInfo, AAFwk::WIN_CMD_FOREGROUND); + } +} + +void StsUIExtension::OnCommand(const AAFwk::Want &want, bool restart, int startId) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "called"); +} + +void StsUIExtension::OnForeground(const Want &want, sptr sessionInfo) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (sessionInfo == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "sessionInfo nullptr"); + return; + } + Extension::OnForeground(want, sessionInfo); + + if (InsightIntentExecuteParam::IsInsightIntentExecute(want)) { + bool finish = ForegroundWindowWithInsightIntent(want, sessionInfo, true); + if (finish) { + return; + } + } + ForegroundWindow(want, sessionInfo); + CallObjectMethod(false, "onForeground", nullptr); +} + +void StsUIExtension::OnBackground() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + CallObjectMethod(false, "onBackground", nullptr); + Extension::OnBackground(); +} + +bool StsUIExtension::HandleSessionCreate(const AAFwk::Want &want, const sptr &sessionInfo) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (sessionInfo == nullptr || sessionInfo->uiExtensionComponentId == 0) { + TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo"); + return false; + } + std::lock_guard lock(uiWindowMutex_); + auto compId = sessionInfo->uiExtensionComponentId; + if (uiWindowMap_.find(compId) == uiWindowMap_.end()) { + auto context = GetContext(); + auto uiWindow = CreateUIWindow(context, sessionInfo); + if (uiWindow == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "create ui window error"); + return false; + } + auto env = stsRuntime_.GetAniEnv(); + ani_ref wantObj = OHOS::AppExecFwk::WrapWant(env, want); + if (wantObj == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null wantObj"); + return false; + } + ani_ref wantRef = nullptr; + ani_status status = ANI_OK; + if ((status = env->GlobalReference_Create(wantObj, &wantRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + } + std::weak_ptr wkctx = context; + stsUiExtContentSession_ = std::make_shared(sessionInfo, uiWindow, + wkctx, abilityResultListeners_); + ani_object sessonObj = StsUIExtensionContentSession::CreateStsUIExtensionContentSession(env, + sessionInfo, uiWindow, context, abilityResultListeners_, stsUiExtContentSession_); + if ((status = env->GlobalReference_Create(sessonObj, &contentSession_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + } + std::shared_ptr etsNativeRef = std::make_shared(); + etsNativeRef->ref_ = std::make_shared(); + etsNativeRef->ref_->aniObj = sessonObj; + etsNativeRef->ref_->aniRef = contentSession_; + contentSessions_.insert_or_assign(compId, etsNativeRef); + int32_t screenMode = want.GetIntParam(AAFwk::SCREEN_MODE_KEY, AAFwk::IDLE_SCREEN_MODE); + if (screenMode == AAFwk::EMBEDDED_FULL_SCREEN_MODE) { + screenMode_ = AAFwk::EMBEDDED_FULL_SCREEN_MODE; + auto jsAppWindowStage = CreateAppWindowStage(uiWindow, sessionInfo); + if (jsAppWindowStage == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "JsAppWindowStage is nullptr"); + return false; + } + } else { + CallObjectMethod(false, "onSessionCreate", nullptr, wantObj, sessonObj); + } + uiWindowMap_[compId] = uiWindow; +#ifdef SUPPORT_GRAPHICS + if (context && context->GetWindow() == nullptr) { + context->SetWindow(uiWindow); + } +#endif // SUPPORT_GRAPHICS + } + return true; +} + +sptr StsUIExtension::CreateUIWindow(const std::shared_ptr context, + const sptr &sessionInfo) +{ + if (context == nullptr || context->GetAbilityInfo() == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "context null"); + return nullptr; + } + auto option = sptr::MakeSptr(); + if (option == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "option null"); + return nullptr; + } + option->SetWindowName(context->GetBundleName() + context->GetAbilityInfo()->name); + option->SetWindowType(Rosen::WindowType::WINDOW_TYPE_UI_EXTENSION); + option->SetWindowSessionType(Rosen::WindowSessionType::EXTENSION_SESSION); + option->SetParentId(sessionInfo->hostWindowId); + option->SetRealParentId(sessionInfo->realHostWindowId); + option->SetParentWindowType(static_cast(sessionInfo->parentWindowType)); + option->SetUIExtensionUsage(static_cast(sessionInfo->uiExtensionUsage)); + HITRACE_METER_NAME(HITRACE_TAG_APP, "Rosen::Window::Create"); + return Rosen::Window::Create(option, GetContext(), sessionInfo->sessionToken); +} + +std::unique_ptr StsUIExtension::CreateAppWindowStage(sptr uiWindow, + sptr sessionInfo) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "called"); + return std::make_unique(); +} + +void StsUIExtension::ForegroundWindow(const AAFwk::Want &want, const sptr &sessionInfo) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "called"); + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (!HandleSessionCreate(want, sessionInfo)) { + TAG_LOGE(AAFwkTag::UI_EXT, "HandleSessionCreate failed"); + return; + } + std::lock_guard lock(uiWindowMutex_); + auto componentId = sessionInfo->uiExtensionComponentId; + auto& uiWindow = uiWindowMap_[componentId]; + if (uiWindow) { + HITRACE_METER_NAME(HITRACE_TAG_APP, "Rosen::Window::show"); + uiWindow->Show(); + foregroundWindows_.emplace(componentId); + } +} + +void StsUIExtension::BackgroundWindow(const sptr &sessionInfo) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (sessionInfo == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo"); + return; + } + std::lock_guard lock(uiWindowMutex_); + auto componentId = sessionInfo->uiExtensionComponentId; + if (uiWindowMap_.find(componentId) == uiWindowMap_.end()) { + TAG_LOGE(AAFwkTag::UI_EXT, "Fail to find uiWindow"); + return; + } + auto& uiWindow = uiWindowMap_[componentId]; + if (uiWindow) { + uiWindow->Hide(); + foregroundWindows_.erase(componentId); + } +} + +void StsUIExtension::DestroyWindow(const sptr &sessionInfo) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (sessionInfo == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo"); + return; + } + std::lock_guard lock(uiWindowMutex_); + auto componentId = sessionInfo->uiExtensionComponentId; + if (uiWindowMap_.find(componentId) == uiWindowMap_.end()) { + TAG_LOGE(AAFwkTag::UI_EXT, "Wrong to find uiWindow"); + return; + } + ani_object contenSessionObj = static_cast(contentSession_); + if (contenSessionObj == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "contenSessionObj null ptr"); + } else { + CallObjectMethod(false, "onSessionDestroy", nullptr, contenSessionObj); + } + auto uiWindow = uiWindowMap_[componentId]; + if (uiWindow) { + uiWindow->Destroy(); + } + uiWindowMap_.erase(componentId); +#ifdef SUPPORT_GRAPHICS + auto context = GetContext(); + if (context != nullptr && context->GetWindow() == uiWindow) { + context->SetWindow(nullptr); + for (auto it : uiWindowMap_) { + context->SetWindow(it.second); + break; + } + } +#endif // SUPPORT_GRAPHICS + foregroundWindows_.erase(componentId); + contentSessions_.erase(componentId); + if (abilityResultListeners_) { + abilityResultListeners_->RemoveListener(componentId); + } +} + +bool StsUIExtension::CallObjectMethod(bool withResult, const char *name, const char *signature, ...) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name); + if (stsObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "stsObj_ nullptr"); + return false; + } + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return false; + } + ResetEnv(env); + ani_status status = ANI_OK; + ani_method method = nullptr; + if ((status = env->Class_FindMethod(stsObj_->aniCls, name, signature, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return false; + } + env->ResetError(); + if (withResult) { + ani_boolean res = 0; + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Boolean(stsObj_->aniObj, method, &res, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + stsRuntime_.HandleUncaughtError(); + } + va_end(args); + return res; + } + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(stsObj_->aniObj, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + stsRuntime_.HandleUncaughtError(); + return false; + } + va_end(args); + return false; +} + +void StsUIExtension::OnConfigurationUpdated(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()); + ConfigurationUpdated(); +} + +void StsUIExtension::Dump(const std::vector ¶ms, std::vector &info) +{ + Extension::Dump(params, info); + TAG_LOGD(AAFwkTag::UI_EXT, "called"); +} + +void StsUIExtension::OnAbilityResult(int requestCode, int resultCode, const Want &resultData) +{ + Extension::OnAbilityResult(requestCode, resultCode, resultData); + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "context null"); + return; + } + context->OnAbilityResult(requestCode, resultCode, resultData); + if (abilityResultListeners_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "abilityResultListensers null"); + return; + } + abilityResultListeners_->OnAbilityResult(requestCode, resultCode, resultData); +} + +void StsUIExtension::ConfigurationUpdated() +{ + ani_env* env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "env null"); + return; + } + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "context null"); + return; + } + + auto fullConfig = context->GetConfiguration(); + if (fullConfig == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "fullConfig null"); + return; + } +} + +#ifdef SUPPORT_GRAPHICS +void StsUIExtension::OnDisplayInfoChange( + const sptr &token, Rosen::DisplayId displayId, float density, Rosen::DisplayOrientation orientation) +{ + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "Context null"); + return; + } + + auto contextConfig = context->GetConfiguration(); + if (contextConfig == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "Configuration null"); + return; + } + + auto configUtils = std::make_shared(); + auto result = + configUtils->UpdateDisplayConfig(contextConfig, context->GetResourceManager(), displayId, density, orientation); + if (result) { + auto stsUiExtension = std::static_pointer_cast(shared_from_this()); + auto task = [stsUiExtension]() { + if (stsUiExtension) { + stsUiExtension->ConfigurationUpdated(); + } + }; + if (handler_ != nullptr) { + handler_->PostTask(task, "StsUIExtension:OnChange"); + } + } +} + +void StsUIExtension::RegisterDisplayInfoChangedListener() +{ + auto context = GetContext(); + if (context == nullptr || context->GetToken() == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "Param is invalid"); + return; + } + Rosen::WindowManager::GetInstance().RegisterDisplayInfoChangedListener( + context->GetToken(), StsUIExtensionAbilityDisplayListener_); +} + +void StsUIExtension::UnregisterDisplayInfoChangedListener() +{ + auto context = GetContext(); + if (context == nullptr || context->GetToken() == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "Param is invalid"); + return; + } + Rosen::WindowManager::GetInstance().UnregisterDisplayInfoChangedListener( + context->GetToken(), StsUIExtensionAbilityDisplayListener_); +} +#endif // SUPPORT_GRAPHICS +} // AbilityRuntime +} // OHOS diff --git a/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension_content_session.cpp b/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension_content_session.cpp new file mode 100644 index 0000000000000000000000000000000000000000..324463e6762b01696877b388f9ad174085eedda2 --- /dev/null +++ b/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension_content_session.cpp @@ -0,0 +1,568 @@ +/* + * 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 +#include "sts_ui_extension_content_session.h" +#include "sts_ui_extension_context.h" +#include "hilog_tag_wrapper.h" +#ifdef SUPPORT_SCREEN +#include "ui_content.h" +#endif // SUPPORT_SCREEN +#include "want.h" +#include "window.h" +#include "ability_manager_client.h" + +#include "ani_common_want.h" +#include "ani_common_util.h" +#include "ani_extension_window.h" +#include "hilog_tag_wrapper.h" +#include "ipc_skeleton.h" +#include "remote_object_wrapper.h" +#include "tokenid_kit.h" +#include "want_params_wrapper.h" +#include "sts_error_utils.h" +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* UI_SESSION_CLASS_NAME = + "L@ohos/app/ability/UIExtensionContentSession/UIExtensionContentSession;"; +} + +StsUIExtensionContentSession* GetStsContentSession(ani_env* env, ani_object obj) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + ThrowStsInvalidParamError(env, "context null"); + return nullptr; + } + ani_class cls; + ani_status status = ANI_ERROR; + status = env->FindClass(UI_SESSION_CLASS_NAME, &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + ThrowStsInvalidParamError(env, "findClass fail"); + return nullptr; + } + StsUIExtensionContentSession *stsContentSession = nullptr; + ani_field stsContentSessionField; + status = env->Class_FindField(cls, "nativeContextSession", &stsContentSessionField); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + ThrowStsInvalidParamError(env, "class find field fail"); + return nullptr; + } + status = env->Object_GetField_Long(obj, stsContentSessionField, reinterpret_cast(&stsContentSession)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + ThrowStsInvalidParamError(env, "object get field Long fail"); + return nullptr; + } + if (stsContentSession == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "stsContentSession null"); + ThrowStsInvalidParamError(env, "stsContentSession null"); + return nullptr; + } + return stsContentSession; +} + +void NativeSetReceiveDataCallback(ani_env* env, ani_object clsObj, ani_object funcObj) +{ + auto stsContentSession = GetStsContentSession(env, clsObj); + if (stsContentSession != nullptr) { + stsContentSession->SetReceiveDataCallback(env, funcObj); + } +} + +void NativeSetReceiveDataForResultCallback(ani_env* env, ani_object clsObj, ani_object funcObj) +{ + auto stsContentSession = GetStsContentSession(env, clsObj); + if (stsContentSession != nullptr) { + stsContentSession->SetReceiveDataForResultCallback(env, funcObj); + } +} + +void NativeSendData(ani_env* env, ani_object obj, ani_object data) +{ + auto stsContentSession = GetStsContentSession(env, obj); + if (stsContentSession != nullptr) { + stsContentSession->SendData(env, obj, data); + } +} + +void NativeLoadContent(ani_env* env, ani_object obj, ani_string path, ani_object storage) +{ + auto stsContentSession = GetStsContentSession(env, obj); + if (stsContentSession != nullptr) { + stsContentSession->LoadContent(env, obj, path, storage); + } +} + +void NativeTerminateSelf(ani_env* env, ani_object obj, [[maybe_unused]] ani_object callback) +{ + auto stsContentSession = GetStsContentSession(env, obj); + if (stsContentSession != nullptr) { + int32_t resultCode = stsContentSession->TerminateSelfWithResult(); + OHOS::AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(resultCode)), nullptr); + } +} + +int NativeTerminateSelfWithResult(ani_env* env, ani_object obj, [[maybe_unused]] ani_object abilityResult, + [[maybe_unused]] ani_object callback) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "NativeTerminateSelfWithResult called"); + int ret = 0; + auto stsContentSession = GetStsContentSession(env, obj); + if (stsContentSession != nullptr) { + ret = stsContentSession->TerminateSelfWithResult(); + OHOS::AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, static_cast(ret)), nullptr); + } + return ret; +} + +void NativeSetWindowBackgroundColor(ani_env* env, ani_object obj, ani_string color) +{ + auto stsContentSession = GetStsContentSession(env, obj); + if (stsContentSession != nullptr) { + stsContentSession->SetWindowBackgroundColor(env, color); + } +} + +ani_object NativeGetUIExtensionHostWindowProxy(ani_env* env, ani_object obj) +{ + auto stsContentSession = GetStsContentSession(env, obj); + ani_object object = nullptr; + if (stsContentSession != nullptr) { + object = stsContentSession->GetUIExtensionHostWindowProxy(env, obj); + } + return object; +} + +StsUIExtensionContentSession::StsUIExtensionContentSession( + sptr sessionInfo, sptr uiWindow, + std::weak_ptr &context, + std::shared_ptr& abilityResultListeners) + : sessionInfo_(sessionInfo), uiWindow_(uiWindow), context_(context) +{ + listener_ = std::make_shared(); + if (abilityResultListeners == nullptr || sessionInfo == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null params"); + } else { + abilityResultListeners->AddListener(sessionInfo->uiExtensionComponentId, listener_); + } +} + +StsUIExtensionContentSession::StsUIExtensionContentSession(sptr sessionInfo, + sptr uiWindow) : sessionInfo_(sessionInfo), uiWindow_(uiWindow) +{ +} + +ani_object StsUIExtensionContentSession::CreateStsUIExtensionContentSession(ani_env* env, + sptr sessionInfo, sptr uiWindow, + std::weak_ptr context, + std::shared_ptr& abilityResultListeners, + std::shared_ptr contentSessionPtr) +{ + ani_object object = nullptr; + ani_method method = nullptr; + ani_class cls; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(UI_SESSION_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + return nullptr; + } + status = env->Object_New(cls, method, &object); + if ((status != ANI_OK) || (object == nullptr)) { + return nullptr; + } + std::array methods = { + ani_native_function {"terminateSelfSync", nullptr, + reinterpret_cast(OHOS::AbilityRuntime::NativeTerminateSelf)}, + ani_native_function {"nativeSendData", nullptr, + reinterpret_cast(OHOS::AbilityRuntime::NativeSendData)}, + ani_native_function {"loadContent", nullptr, + reinterpret_cast(OHOS::AbilityRuntime::NativeLoadContent)}, + ani_native_function {"terminateSelfWithResultSync", nullptr, + reinterpret_cast(OHOS::AbilityRuntime::NativeTerminateSelfWithResult)}, + ani_native_function {"setWindowBackgroundColor", nullptr, + reinterpret_cast(OHOS::AbilityRuntime::NativeSetWindowBackgroundColor)}, + ani_native_function {"getUIExtensionHostWindowProxy", nullptr, + reinterpret_cast(OHOS::AbilityRuntime::NativeGetUIExtensionHostWindowProxy)}, + ani_native_function {"nativeSetReceiveDataCallback", nullptr, + reinterpret_cast(OHOS::AbilityRuntime::NativeSetReceiveDataCallback)}, + ani_native_function {"nativeSetReceiveDataForResultCallback", nullptr, + reinterpret_cast(OHOS::AbilityRuntime::NativeSetReceiveDataForResultCallback)} + }; + if ((status = env->Class_BindNativeMethods(cls, methods.data(), methods.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return nullptr; + } + ani_field nativeField = nullptr; + if ((status = env->Class_FindField(cls, "nativeContextSession", &nativeField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return nullptr; + } + status = env->Object_SetField_Long(object, nativeField, reinterpret_cast(contentSessionPtr.get())); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return nullptr; + } + return object; +} + +void StsUIExtensionContentSession::SendData(ani_env* env, ani_object object, ani_object data) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "called"); + AAFwk::WantParams params; + AppExecFwk::UnwrapWantParams(env, reinterpret_cast(data), params); + if (uiWindow_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null uiWindow_"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + return; + } + + Rosen::WMError ret = uiWindow_->TransferExtensionData(params); + if (ret == Rosen::WMError::WM_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "TransferExtensionData success"); + } else { + TAG_LOGE(AAFwkTag::UI_EXT, "TransferExtensionData failed, ret=%{public}d", ret); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + return; + } +} + +void StsUIExtensionContentSession::LoadContent(ani_env* env, ani_object object, ani_string path, ani_object storage) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "LoadContent called"); + std::string contextPath; + if (!OHOS::AppExecFwk::GetStdString(env, path, contextPath)) { + TAG_LOGE(AAFwkTag::UI_EXT, "invalid param"); + ThrowStsInvalidParamError(env, "Parameter error: Path must be a string."); + return; + } + TAG_LOGD(AAFwkTag::UI_EXT, "contextPath: %{public}s", contextPath.c_str()); + if (uiWindow_ == nullptr || sessionInfo_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "uiWindow_ or sessionInfo_ is nullptr"); + ThrowStsErrorByNativeErr(env, static_cast(AbilityErrorCode::ERROR_CODE_INNER)); + return; + } + if (sessionInfo_->isAsyncModalBinding && isFirstTriggerBindModal_) { + TAG_LOGD(AAFwkTag::UI_EXT, "Trigger binding UIExtension modal window"); + uiWindow_->TriggerBindModalUIExtension(); + isFirstTriggerBindModal_ = false; + } + sptr parentToken = sessionInfo_->parentToken; + Rosen::WMError ret = uiWindow_->NapiSetUIContent(contextPath, env, storage, + Rosen::BackupAndRestoreType::NONE, parentToken); + if (ret != Rosen::WMError::WM_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "AniSetUIContent failed, ret=%{public}d", ret); + ThrowStsErrorByNativeErr(env, static_cast(AbilityErrorCode::ERROR_CODE_INNER)); + } else { + TAG_LOGD(AAFwkTag::UI_EXT, "AniSetUIContent success"); + } + TAG_LOGD(AAFwkTag::UI_EXT, "LoadContent end"); + return; +} + +void StsUIExtensionContentSession::TerminateSelf() +{ + TAG_LOGD(AAFwkTag::UI_EXT, "TerminateSelf call"); + AAFwk::AbilityManagerClient::GetInstance()->TerminateUIExtensionAbility(sessionInfo_); +} + +int32_t StsUIExtensionContentSession::TerminateSelfWithResult() +{ + TAG_LOGD(AAFwkTag::UI_EXT, "TerminateSelfWithResult call"); + return AAFwk::AbilityManagerClient::GetInstance()->TerminateUIExtensionAbility(sessionInfo_); +} + +void StsUIExtensionContentSession::SetWindowBackgroundColor(ani_env* env, ani_string color) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "SetWindowBackgroundColor call"); + std::string strColor; + ani_size sz {}; + env->String_GetUTF8Size(color, &sz); + strColor.resize(sz + 1); + env->String_GetUTF8SubString(color, 0, sz, strColor.data(), strColor.size(), &sz); + if (uiWindow_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "uiWindow_ is nullptr"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + return; + } + Rosen::WMError ret = uiWindow_->SetBackgroundColor(strColor); + if (ret != Rosen::WMError::WM_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "SetBackgroundColor failed, ret=%{public}d", ret); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + } +} + +ani_object StsUIExtensionContentSession::GetUIExtensionHostWindowProxy(ani_env* env, ani_object object) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "called"); + if (sessionInfo_ == nullptr) { + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + return nullptr; + } + ani_object stsExtensionWindow = nullptr; + stsExtensionWindow = + Rosen::AniExtensionWindow::CreateAniExtensionWindow(env, uiWindow_, sessionInfo_->hostWindowId); + if (stsExtensionWindow == nullptr) { + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + return nullptr; + } + ani_ref resultRef = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GlobalReference_Create(stsExtensionWindow, &resultRef)) != ANI_OK) { + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + return nullptr; + } + return reinterpret_cast(resultRef); +} + +void StsUIExtensionContentSession::SetReceiveDataCallback(ani_env* env, ani_object functionObj) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "SetReceiveDataCallback call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "env null"); + AbilityRuntime::ThrowStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM)); + return; + } + if (!isRegistered_) { + if (!SetReceiveDataCallbackUnRegist(env, functionObj)) { + return; + } + } else { + if (receiveDataCallback_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null receiveDataCallback_"); + AbilityRuntime::ThrowStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return; + } + ani_status status = ANI_OK; + if ((status = env->GlobalReference_Delete(receiveDataCallback_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GlobalReference_Delete failed status = %{public}d", status); + AbilityRuntime::ThrowStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return; + } + receiveDataCallback_ = nullptr; + if ((status = env->GlobalReference_Create(functionObj, &receiveDataCallback_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GlobalReference_Create failed status:%{public}d", status); + AbilityRuntime::ThrowStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return; + } + } + TAG_LOGD(AAFwkTag::UI_EXT, "SetReceiveDataCallback end"); +} + +bool StsUIExtensionContentSession::SetReceiveDataCallbackUnRegist(ani_env* env, ani_object functionObj) +{ + if (uiWindow_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "uiWindow_ is nullptr"); + AbilityRuntime::ThrowStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return false; + } + ani_status status = ANI_OK; + if (receiveDataCallback_ == nullptr) { + if ((status = env->GlobalReference_Create(functionObj, &receiveDataCallback_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GlobalReference_Create receiveDataCallback_ failed status:%{public}d", + status); + AbilityRuntime::ThrowStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return false; + } + } + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "get aniVM failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Get aniVm failed."); + return false; + } + auto callbackRef = receiveDataCallback_; + auto handler = std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); + uiWindow_->RegisterTransferComponentDataListener([aniVM, handler, callbackRef] ( + const AAFwk::WantParams& wantParams) { + if (handler) { + handler->PostTask([aniVM, callbackRef, wantParams]() { + StsUIExtensionContentSession::CallReceiveDataCallback(aniVM, callbackRef, wantParams); + }, "StsUIExtensionContentSession:OnSetReceiveDataCallback"); + } + }); + isRegistered_ = true; + return true; +} + +void StsUIExtensionContentSession::CallReceiveDataCallback(ani_vm* vm, ani_ref callbackRef, + const AAFwk::WantParams& wantParams) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "CallReceiveDataCallback call"); + if (vm == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "vm is nullptr"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_OK; + if ((status = vm->GetEnv(ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetEnv failed status: %{public}d", status); + return; + } + if (callbackRef == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "callbackPtr is nullptr"); + return; + } + ani_object callbackObj = static_cast(callbackRef); + ani_fn_object callbackFunc = reinterpret_cast(callbackObj); + if (callbackFunc == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "callbackFunc is nullptr"); + return; + } + ani_ref wantObj = AppExecFwk::WrapWantParams(env, wantParams); + if (wantObj == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "wantObj is nullptr"); + return; + } + ani_ref argv[] = {wantObj}; + ani_ref result; + if ((status = env->FunctionalObject_Call(callbackFunc, 1, argv, &result)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "FunctionalObjectCall FAILED staus %{public}d", status); + } + TAG_LOGD(AAFwkTag::UI_EXT, "CallReceiveDataCallback end"); +} + +void StsUIExtensionContentSession::SetReceiveDataForResultCallback(ani_env* env, ani_object funcObj) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "SetReceiveDataForResultCallback call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "env null"); + AbilityRuntime::ThrowStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_PARAM)); + return; + } + if (!isSyncRegistered_) { + if (!SetReceiveDataForResultCallbackUnRegist(env, funcObj)) { + return; + } + } else { + if (receiveDataForResultCallback_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null receiveDataForResultCallback_"); + AbilityRuntime::ThrowStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return; + } + ani_status status = ANI_OK; + if ((status = env->GlobalReference_Delete(receiveDataForResultCallback_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GlobalReference_Delete failed status = %{public}d", status); + AbilityRuntime::ThrowStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return; + } + receiveDataForResultCallback_ = nullptr; + if ((status = env->GlobalReference_Create(funcObj, &receiveDataForResultCallback_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GlobalReference_Create failed status:%{public}d", status); + AbilityRuntime::ThrowStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return; + } + } + TAG_LOGD(AAFwkTag::UI_EXT, "SetReceiveDataForResultCallback end"); +} + +bool StsUIExtensionContentSession::SetReceiveDataForResultCallbackUnRegist(ani_env* env, ani_object funcObj) +{ + if (uiWindow_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null uiWindow_"); + AbilityRuntime::ThrowStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return false; + } + if (receiveDataForResultCallback_ == nullptr) { + if (env->GlobalReference_Create(funcObj, &receiveDataForResultCallback_) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GlobalReference_Create receiveDataForResultCallback_ failed"); + AbilityRuntime::ThrowStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER)); + return false; + } + } + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "get aniVM failed"); + AbilityRuntime::ThrowStsInvalidParamError(env, "Get aniVm failed."); + return false; + } + auto callbackRef = receiveDataForResultCallback_; + auto handler = std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); + uiWindow_->RegisterTransferComponentDataForResultListener([aniVM, handler, callbackRef] ( + const AAFwk::WantParams& wantParams) -> AAFwk::WantParams { + AAFwk::WantParams retWantParams; + if (handler) { + handler->PostSyncTask([aniVM, callbackRef, wantParams, &retWantParams]() { + StsUIExtensionContentSession::CallReceiveDataCallbackForResult(aniVM, callbackRef, + wantParams, retWantParams); + }, "StsUIExtensionContentSession:OnSetReceiveDataForResultCallback"); + } + return retWantParams; + }); + isSyncRegistered_ = true; + return true; +} + +void StsUIExtensionContentSession::CallReceiveDataCallbackForResult(ani_vm* vm, ani_ref callbackRef, + const AAFwk::WantParams& wantParams, AAFwk::WantParams& retWantParams) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "CallReceiveDataCallbackForResult call"); + if (vm == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "vm is nullptr"); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_OK; + if ((status = vm->GetEnv(ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetEnv failed status: %{public}d", status); + return; + } + if (callbackRef == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "callback is nullptr"); + return; + } + ani_object callbackObj = static_cast(callbackRef); + ani_fn_object callbackFunc = reinterpret_cast(callbackObj); + if (callbackFunc == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "callbackFunc is nullptr"); + return; + } + ani_ref wantObj = AppExecFwk::WrapWantParams(env, wantParams); + if (wantObj == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "wantObj is nullptr"); + return; + } + ani_ref argv[] = {wantObj}; + ani_ref result; + if ((status = env->FunctionalObject_Call(callbackFunc, 1, argv, &result)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "FunctionalObjectCall FAILED staus %{public}d", status); + return; + } + if (!AppExecFwk::UnwrapWantParams(env, result, retWantParams)) { + TAG_LOGE(AAFwkTag::UI_EXT, "UnwrapWantParams failed"); + } + TAG_LOGD(AAFwkTag::UI_EXT, "CallReceiveDataCallbackForResult end"); +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension_context.cpp b/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d652b15eaad374b8f206deb58daba9ea6473457 --- /dev/null +++ b/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension_context.cpp @@ -0,0 +1,337 @@ +/* + * 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 "common_fun_ani.h" +#include "sts_ui_extension_context.h" +#include "ui_extension_context.h" +#include "ani_common_want.h" +#include "ability_manager_client.h" +#include "sts_context_utils.h" +#include "sts_error_utils.h" +#include "ets_extension_context.h" +#include "ani_common_start_options.h" +#include "ani_common_util.h" +#include "ani_enum_convert.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* UI_CONTEXT_CLASS_NAME = "Lapplication/UIExtensionContext/UIExtensionContext;"; +} + +static void TerminateSelfSync([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, + [[maybe_unused]] ani_object callback) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "TerminateSelfSync"); + ani_class cls = nullptr; + ani_long nativeContextLong; + ani_field contextField = nullptr; + ani_status status = ANI_ERROR; + ErrCode ret = ERR_INVALID_VALUE; + if ((status = env->FindClass(UI_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return; + } + if ((status = env->Class_FindField(cls, "nativeContext", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return; + } + if ((status = env->Object_GetField_Long(obj, contextField, &nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return; + } + ret = ((UIExtensionContext*)nativeContextLong)->TerminateSelf(); + AppExecFwk::AsyncCallback(env, callback, + CreateStsErrorByNativeErr(env, static_cast(ret)), nullptr); +} +static void TerminateSelfWithResultSync([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, + [[maybe_unused]] ani_object abilityResult, [[maybe_unused]] ani_object callback) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "TerminateSelfWithResultSync"); + ani_class cls = nullptr; + ani_long nativeContextLong; + ani_field contextField = nullptr; + ani_status status = ANI_ERROR; + ErrCode ret = ERR_INVALID_VALUE; + if ((status = env->FindClass(UI_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return; + } + if ((status = env->Class_FindField(cls, "nativeContext", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return; + } + if ((status = env->Object_GetField_Long(obj, contextField, &nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return; + } + auto context = ((UIExtensionContext*)nativeContextLong); + if (!context) { + TAG_LOGE(AAFwkTag::UI_EXT, "context is released"); + return; + } + + AAFwk::Want want; + int resultCode = 0; + AppExecFwk::UnWrapAbilityResult(env, abilityResult, resultCode, want); + auto token = context->GetToken(); + AAFwk::AbilityManagerClient::GetInstance()->TransferAbilityResultForExtension(token, resultCode, want); + ret = context->TerminateSelf(); + if (ret != 0) { + TAG_LOGE(AAFwkTag::UI_EXT, "TerminateSelf failed, errorCode is %{public}d", ret); + return; + } + AppExecFwk::AsyncCallback(env, callback, + CreateStsErrorByNativeErr(env, static_cast(ret)), nullptr); +} + +static void StartAbility([[maybe_unused]] ani_env *env, + [[maybe_unused]] ani_object aniObj, ani_object wantObj, ani_object call) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "StartAbility"); + StsUIExtensionContext::GetInstance().StartAbilityInner(env, aniObj, wantObj, nullptr, call); +} + +static void StartAbilityWithOption([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + ani_object wantObj, ani_object opt, ani_object call) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "StartAbilityWithOption"); + StsUIExtensionContext::GetInstance().StartAbilityInner(env, aniObj, wantObj, opt, call); +} + +UIExtensionContext* StsUIExtensionContext::GetAbilityContext(ani_env *env, ani_object obj) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "GetAbilityContext start"); + ani_class cls = nullptr; + ani_long nativeContextLong; + ani_field contextField = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return nullptr; + } + if ((status = env->FindClass(UI_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetAbilityContext find class status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeContext", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetAbilityContext find field status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_GetField_Long(obj, contextField, &nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetAbilityContext get filed status: %{public}d", status); + return nullptr; + } + return (UIExtensionContext*)nativeContextLong; +} + +void StsUIExtensionContext::AddFreeInstallObserver(ani_env *env, const AAFwk::Want &want, + ani_object callback, UIExtensionContext*context) +{ + // adapter free install async return install and start result + TAG_LOGD(AAFwkTag::UI_EXT, "AddFreeInstallObserver"); + int ret = 0; + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + return; + } + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + if (freeInstallObserver_ == nullptr) { + ani_vm *etsVm = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GetVM(&etsVm)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + } + freeInstallObserver_ = new StsFreeInstallObserver(etsVm); + ret = context->AddFreeInstallObserver(freeInstallObserver_); + } + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "addFreeInstallObserver error"); + } + std::string startTime = want.GetStringParam(AAFwk::Want::PARAM_RESV_START_TIME); + TAG_LOGI(AAFwkTag::UI_EXT, "addStsObserver"); + std::string bundleName = want.GetElement().GetBundleName(); + std::string abilityName = want.GetElement().GetAbilityName(); + freeInstallObserver_->AddStsObserverObject( + env, bundleName, abilityName, startTime, callback); +} + +void StsUIExtensionContext::StartAbilityInner([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + ani_object wantObj, ani_object opt, ani_object call) +{ + ani_object aniObject = nullptr; + AAFwk::Want want; + ErrCode innerErrCode = ERR_OK; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + aniObject = CreateStsInvalidParamError(env, "UnwrapWant filed"); + AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + return; + } + auto context = StsUIExtensionContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetAbilityContext is nullptr"); + innerErrCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = CreateStsError(env, static_cast(innerErrCode)); + AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + return; + } + if ((want.GetFlags() & AAFwk::Want::FLAG_INSTALL_ON_DEMAND) == AAFwk::Want::FLAG_INSTALL_ON_DEMAND) { + std::string startTime = std::to_string(std::chrono::duration_cast(std::chrono:: + system_clock::now().time_since_epoch()).count()); + want.SetParam(AAFwk::Want::PARAM_RESV_START_TIME, startTime); + AddFreeInstallObserver(env, want, call, context); + } + if (opt != nullptr) { + AAFwk::StartOptions startOptions; + if (!AppExecFwk::UnwrapStartOptionsWithProcessOption(env, opt, startOptions)) { + TAG_LOGE(AAFwkTag::UI_EXT, "UnwrapStartOptions filed"); + aniObject = CreateStsInvalidParamError(env, "UnwrapWant filed"); + AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + return; + } + innerErrCode = context->StartAbility(want, startOptions); + } else { + innerErrCode = context->StartAbility(want); + } + aniObject = CreateStsError(env, AbilityErrorCode::ERROR_OK); + if (innerErrCode != ERR_OK) { + aniObject = CreateStsErrorByNativeErr(env, innerErrCode); + } + if ((want.GetFlags() & AAFwk::Want::FLAG_INSTALL_ON_DEMAND) == AAFwk::Want::FLAG_INSTALL_ON_DEMAND) { + if (innerErrCode != ERR_OK && freeInstallObserver_ != nullptr) { + std::string bundleName = want.GetElement().GetBundleName(); + std::string abilityName = want.GetElement().GetAbilityName(); + std::string startTime = want.GetStringParam(AAFwk::Want::PARAM_RESV_START_TIME); + freeInstallObserver_->OnInstallFinished(bundleName, abilityName, startTime, innerErrCode); + } + } else { + AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + } +} + +void StsUIExtensionContext::NativeSetColorMode(ani_env *env, ani_object aniContext, ani_enum_item aniColorMode) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "NativeSetColorMode called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + ani_int colorMode = 0; + if (!AAFwk::AniEnumConvertUtil::EnumConvertStsToNative(env, aniColorMode, colorMode)) { + TAG_LOGE(AAFwkTag::UI_EXT, "param aniColorMode err"); + ThrowStsInvalidParamError(env, "Parse param colorMode failed, colorMode must be number."); + return; + } + auto context = StsUIExtensionContext::GetAbilityContext(env, aniContext); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetAbilityContext is nullptr"); + ThrowStsError(env, static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)); + return; + } + context->SetAbilityColorMode(colorMode); + TAG_LOGD(AAFwkTag::UI_EXT, "NativeSetColorMode end"); +} + +void StsUIExtensionContext::NativeReportDrawnCompleted(ani_env* env, ani_object aniCls, ani_object callback) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "NativeReportDrawnCompleted called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return; + } + auto context = StsUIExtensionContext::GetAbilityContext(env, aniCls); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetAbilityContext is nullptr"); + AppExecFwk::AsyncCallback(env, callback, + CreateStsErrorByNativeErr(env, static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)), + nullptr); + return; + } + int32_t innerErrorCode = context->ReportDrawnCompleted(); + AppExecFwk::AsyncCallback(env, callback, CreateStsErrorByNativeErr(env, + static_cast(innerErrorCode)), nullptr); + TAG_LOGD(AAFwkTag::UI_EXT, "NativeReportDrawnCompleted end"); +} + +bool BindNativeMethods(ani_env *env, ani_class &cls) +{ + ani_status status = ANI_ERROR; + std::array functions = { + ani_native_function { "terminateSelfSync", nullptr, reinterpret_cast(TerminateSelfSync) }, + ani_native_function { "terminateSelfWithResultSync", nullptr, + reinterpret_cast(TerminateSelfWithResultSync) }, + ani_native_function { "nativeStartAbilitySync", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(StartAbility) }, + ani_native_function { "nativeStartAbilitySync", + "L@ohos/app/ability/Want/Want;L@ohos/app/ability/StartOptions/StartOptions;Lutils/AbilityUtils/" + "AsyncCallbackWrapper;:V", + reinterpret_cast(StartAbilityWithOption) }, + ani_native_function { "setColorMode", nullptr, + reinterpret_cast(StsUIExtensionContext::NativeSetColorMode)}, + ani_native_function { "nativeReportDrawnCompleted", nullptr, + reinterpret_cast(StsUIExtensionContext::NativeReportDrawnCompleted)} + }; + if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return false; + } + return true; +} + +ani_object CreateStsUIExtensionContext(ani_env *env, std::shared_ptr context) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "CreateStsUIExtensionContext"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null env"); + return nullptr; + } + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; + ani_field field = nullptr; + ani_object contextObj = nullptr; + if ((env->FindClass(UI_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return nullptr; + } + if (!BindNativeMethods(env, cls)) { + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeContext", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return nullptr; + } + ani_long nativeContextLong = (ani_long)context.get(); + if ((status = env->Object_SetField_Long(contextObj, field, nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return nullptr; + } + OHOS::AbilityRuntime::ContextUtil::StsCreatContext(env, cls, contextObj, context); + OHOS::AbilityRuntime::CreatEtsExtensionContext(env, cls, contextObj, context, context->GetAbilityInfo()); + return contextObj; +} +} // AbilityRuntime +} // OHOS diff --git a/frameworks/ets/ani/uri_permission_manager/BUILD.gn b/frameworks/ets/ani/uri_permission_manager/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..45039ec05ed7f5b6dc3377d95a1ca637a48829d1 --- /dev/null +++ b/frameworks/ets/ani/uri_permission_manager/BUILD.gn @@ -0,0 +1,105 @@ +# 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("uri_permission_manager_ani_kit") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", + "${ability_runtime_path}/frameworks/js/napi/uri_permission", + "${ability_runtime_path}/interfaces/kits/native/ability/native", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/ability_delegator/include", + "${ability_runtime_services_path}/common/include", + ] + configs = [] + + public_configs = [] + + sources = [ "./src/sts_uri_perm_mgr.cpp" ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", + "${ability_runtime_innerkits_path}/ability_manager:ability_start_options", + "${ability_runtime_innerkits_path}/error_utils:ability_runtime_error_util", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_innerkits_path}/uri_permission:uri_permission_mgr", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_napi_path}/inner/napi_common:napi_common", + "${ability_runtime_native_path}/ability/native:abilitykit_native", + "${ability_runtime_native_path}/ability/native:ability_business_error", + "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_native_path}/appkit:appkit_delegator", + "${ability_runtime_native_path}/appkit:delegator_mgmt", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "eventhandler:libeventhandler", + "hilog:libhilog", + "init:libbegetutil", + "ipc:ipc_core", + "ipc:ipc_napi", + "json:nlohmann_json_static", + "napi:ace_napi", + "runtime_core:ani", + ] + + public_external_deps = [ "ability_base:configuration" ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} + +generate_static_abc("uri_permission_manager_abc") { + base_url = "./ets" + + files = [ "./ets/@ohos.application.uriPermissionManager.ets" ] + + dst_file = "$target_out_dir/uri_permission_manager.abc" + out_puts = [ "$target_out_dir/uri_permission_manager.abc" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/uri_permission_manager.abc" +} + +ohos_prebuilt_etc("uri_permission_manager_abc_etc") { + source = "$target_out_dir/uri_permission_manager.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":uri_permission_manager_abc" ] +} \ No newline at end of file diff --git a/frameworks/ets/ani/uri_permission_manager/ets/@ohos.application.uriPermissionManager.ets b/frameworks/ets/ani/uri_permission_manager/ets/@ohos.application.uriPermissionManager.ets new file mode 100644 index 0000000000000000000000000000000000000000..c586a2cca3900d702063c47e1a321be6b1c72e6f --- /dev/null +++ b/frameworks/ets/ani/uri_permission_manager/ets/@ohos.application.uriPermissionManager.ets @@ -0,0 +1,119 @@ +/* + * 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 wantConstant from '@ohos.app.ability.wantConstant'; +import { BusinessError, AsyncCallback } from '@ohos.base'; + +export class AsyncCallbackWrapper { + myFun_:AsyncCallback = (err: BusinessError, data: T) => {} + + constructor(myFun:AsyncCallback){ + this.myFun_ = myFun; + } + + invoke(err: BusinessError, data: T) : void { + this.myFun_(err, data); + } +} + +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, + callback: AsyncCallbackWrapper): void; + + export function grantUriPermission(uri: string, flag: wantConstant.Flags, targetBundleName: string): Promise { + let p:Promise = new Promise((resolve: (data: number)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: number)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + uriPermissionManager.grantUriPermissionCallbackSync(uri, flag, targetBundleName, 0, myCall); + }); + }); + return p; + } + + export function grantUriPermission(uri: string, flag: wantConstant.Flags, targetBundleName: string, + appCloneIndex: number): Promise { + let p:Promise = new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: number)=>{ + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + uriPermissionManager.grantUriPermissionCallbackSync(uri, + flag, targetBundleName, appCloneIndex, myCall); + }); + }); + return p; + } + + export function grantUriPermission(uri: string, flag: wantConstant.Flags, targetBundleName: string, + callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + uriPermissionManager.grantUriPermissionCallbackSync(uri, flag, targetBundleName, 0, myCall); + }) + } + + export function revokeUriPermission(uri: string, targetBundleName: string): Promise { + let p:Promise = new Promise((resolve: (data: number)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: number)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + uriPermissionManager.revokeUriPermissionCallbackSync(uri, targetBundleName, 0, myCall); + }); + }); + return p; + } + + export function revokeUriPermission(uri: string, targetBundleName: string, appCloneIndex: number): Promise { + let p:Promise = new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: number)=>{ + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + uriPermissionManager.revokeUriPermissionCallbackSync(uri, targetBundleName, appCloneIndex, myCall); + }); + }); + return p; + } + + export function revokeUriPermission(uri: string, targetBundleName: string, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + uriPermissionManager.revokeUriPermissionCallbackSync(uri, targetBundleName, 0, myCall); + }) + } +} \ No newline at end of file diff --git a/frameworks/ets/ani/uri_permission_manager/include/sts_uri_perm_mgr.h b/frameworks/ets/ani/uri_permission_manager/include/sts_uri_perm_mgr.h new file mode 100644 index 0000000000000000000000000000000000000000..0972a72bb5a4b47f34cda5951885d4ce9f1cc8db --- /dev/null +++ b/frameworks/ets/ani/uri_permission_manager/include/sts_uri_perm_mgr.h @@ -0,0 +1,36 @@ +/* + * 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_STS_URI_PERM_MGR_H +#define OHOS_ABILITY_RUNTIME_STS_URI_PERM_MGR_H + +#include "sts_runtime.h" + +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); +static void revokeUriPermissionCallbackSync([[maybe_unused]]ani_env *env, + ani_string uri, ani_string targetName, ani_double 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); +ani_object WrapError(ani_env *env, const std::string &msg); +ani_string GetAniString(ani_env *env, const std::string &str); +ani_object createDouble(ani_env *env, int32_t res); +std::string GetErrMsg(int32_t err, const std::string &permission = ""); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_URI_PERM_MGR_H \ No newline at end of file diff --git a/frameworks/ets/ani/uri_permission_manager/src/sts_uri_perm_mgr.cpp b/frameworks/ets/ani/uri_permission_manager/src/sts_uri_perm_mgr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..638650677fb2b7c6e57b637d2d2612bccad40551 --- /dev/null +++ b/frameworks/ets/ani/uri_permission_manager/src/sts_uri_perm_mgr.cpp @@ -0,0 +1,298 @@ +/* + * 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 "sts_uri_perm_mgr.h" + +#include "ability_business_error.h" +#include "ability_manager_errors.h" +#include "ability_runtime_error_util.h" +#include "ani_enum_convert.h" +#include "hilog_tag_wrapper.h" +#include "ipc_skeleton.h" +#include "js_error_utils.h" +#include "js_runtime_utils.h" +#include "napi_common_util.h" +#include "parameters.h" +#include "tokenid_kit.h" +#include "uri.h" +#include "uri_permission_manager_client.h" +#include "sts_runtime.h" +#include "sts_error_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* WRAPPER_CLASS_NAME = "Lutils/AbilityUtils/AsyncCallbackWrapper;"; +constexpr const char* ERROR_CLASS_NAME = "Lescompat/Error;"; +constexpr const char* BUSINESS_ERROR_CLASS_NAME = "L@ohos/base/BusinessError;"; +} +const char *INVOKE_METHOD_NAME = "invoke"; +const int32_t ERR_OK = 0; +const int32_t ERR_FAILURE = -1; +constexpr const char* NOT_SYSTEM_APP = "The application is not system-app, can not use system-api."; + +static std::string GetStdString(ani_env* env, ani_string str) +{ + std::string result; + ani_size sz {}; + env->String_GetUTF8Size(str, &sz); + result.resize(sz + 1); + env->String_GetUTF8SubString(str, 0, sz, result.data(), result.size(), &sz); + result.resize(sz); + return result; +} + +static void grantUriPermissionCallbackSync([[maybe_unused]]ani_env *env, + ani_string uri, ani_enum_item flagEnum, ani_string targetName, ani_double appCloneIndex, ani_object callback) +{ + TAG_LOGI(AAFwkTag::URIPERMMGR, "grantUriPermissionCallbackSync run"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "env null"); + return; + } + auto selfToken = IPCSkeleton::GetSelfTokenID(); + ani_object stsErrCode = CreateStsError(env, AbilityErrorCode::ERROR_OK); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "app not system-app"); + stsErrCode = CreateStsError(env, static_cast(AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP), + NOT_SYSTEM_APP); + AsyncCallback(env, callback, stsErrCode, createDouble(env, ERR_FAILURE)); + return; + } + std::string uriStr = GetStdString(env, uri); + Uri uriVec(uriStr); + ani_int flag = 0; + AAFwk::AniEnumConvertUtil::EnumConvertStsToNative(env, flagEnum, flag); + int32_t flagId = static_cast(flag); + std::string targetBundleName = GetStdString(env, targetName); + int32_t appCloneIndexId = static_cast(appCloneIndex); + int32_t errCode = ERR_OK; + int32_t result = ERR_OK; + errCode = AAFwk::UriPermissionManagerClient::GetInstance().GrantUriPermission(uriVec, flagId, + targetBundleName, appCloneIndexId); + if (errCode != ERR_OK) { + result = ERR_FAILURE; + stsErrCode = CreateStsErrorByNativeErr(env, errCode); + } + + AsyncCallback(env, callback, stsErrCode, createDouble(env, result)); +} + +static void revokeUriPermissionCallbackSync([[maybe_unused]]ani_env *env, + ani_string uri, ani_string targetName, ani_double appCloneIndex, ani_object callback) +{ + TAG_LOGI(AAFwkTag::URIPERMMGR, "revokeUriPermissionCallbackSync run"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "env null"); + return; + } + auto selfToken = IPCSkeleton::GetSelfTokenID(); + ani_object stsErrCode = CreateStsError(env, AbilityErrorCode::ERROR_OK); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "app not system-app"); + stsErrCode = CreateStsError(env, static_cast(AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP), + NOT_SYSTEM_APP); + AsyncCallback(env, callback, stsErrCode, createDouble(env, ERR_FAILURE)); + return; + } + std::string uriStr = GetStdString(env, uri); + Uri uriVec(uriStr); + std::string targetBundleName = GetStdString(env, targetName); + int32_t errCode = ERR_OK; + int32_t result = ERR_OK; + errCode = AAFwk::UriPermissionManagerClient::GetInstance().RevokeUriPermissionManually(uriVec, + targetBundleName, appCloneIndex); + if (errCode != ERR_OK) { + result = ERR_FAILURE; + stsErrCode = CreateStsErrorByNativeErr(env, errCode); + } + AsyncCallback(env, callback, stsErrCode, createDouble(env, result)); +} + +ani_object createDouble(ani_env *env, int32_t res) +{ +static const char *className = "Lstd/core/Double;"; +ani_class persion_cls; +if (ANI_OK != env->FindClass(className, &persion_cls)) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "create double error"); + return nullptr; +} +ani_method persionInfoCtor; +env->Class_FindMethod(persion_cls, "", "D:V", &persionInfoCtor); +ani_object persionInfoObj; +env->Object_New(persion_cls, persionInfoCtor, &persionInfoObj, ani_double(res)); +return persionInfoObj; +} + +void StsUriPermissionManagerInit(ani_env *env) +{ + TAG_LOGI(AAFwkTag::URIPERMMGR, "StsUriPermissionManagerInit call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "Invalid param"); + } + ani_namespace ns; + const char* targetNamespace = "L@ohos/application/uriPermissionManager/uriPermissionManager;"; + if (env->FindNamespace(targetNamespace, &ns) != ANI_OK) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "FindNamespace failed"); + } + std::array functions = { + ani_native_function { + "grantUriPermissionCallbackSync", + "Lstd/core/String;L@ohos/app/ability/wantConstant/wantConstant/Flags;Lstd/core/String;D" + "L@ohos/application/uriPermissionManager/AsyncCallbackWrapper;:V", + reinterpret_cast(grantUriPermissionCallbackSync) + }, + ani_native_function { + "revokeUriPermissionCallbackSync", + "Lstd/core/String;Lstd/core/String;D" + "L@ohos/application/uriPermissionManager/AsyncCallbackWrapper;:V", + reinterpret_cast(revokeUriPermissionCallbackSync) + }, + }; + TAG_LOGI(AAFwkTag::URIPERMMGR, "StsUriPermissionManagerInit bind functions"); + if (env->Namespace_BindNativeFunctions(ns, functions.data(), functions.size()) != ANI_OK) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "Namespace_BindNativeFunctions failed"); + }; + TAG_LOGI(AAFwkTag::URIPERMMGR, "StsUriPermissionManagerInit success"); +} + +extern "C"{ +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGI(AAFwkTag::URIPERMMGR, "ANI_Constructor"); + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGI(AAFwkTag::URIPERMMGR, "GetEnv failed status: %{public}d", status); + return ANI_NOT_FOUND; + } + + StsUriPermissionManagerInit(env); + *result = ANI_VERSION_1; + TAG_LOGI(AAFwkTag::URIPERMMGR, "ANI_Constructor finish"); + return ANI_OK; +} +} + +bool AsyncCallback(ani_env *env, ani_object call, ani_object error, ani_object result) +{ + ani_status status = ANI_ERROR; + ani_class clsCall {}; + + if ((status = env->FindClass(WRAPPER_CLASS_NAME, &clsCall)) != ANI_OK) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "status: %{public}d", status); + return false; + } + ani_method method = {}; + if ((status = env->Class_FindMethod( + clsCall, INVOKE_METHOD_NAME, "L@ohos/base/BusinessError;Lstd/core/Object;:V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "status: %{public}d", status); + return false; + } + if (result == nullptr) { + ani_ref nullRef = nullptr; + env->GetNull(&nullRef); + result = reinterpret_cast(nullRef); + } + if ((status = env->Object_CallMethod_Void(call, method, error, result)) != ANI_OK) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "status: %{public}d", status); + return false; + } + return true; +} + +ani_object WrapError(ani_env *env, const std::string &msg) +{ + ani_class cls {}; + ani_method method {}; + ani_object obj = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "null env"); + return nullptr; + } + ani_string aniMsg = GetAniString(env, msg); + ani_ref undefRef; + env->GetUndefined(&undefRef); + if ((status = env->FindClass(ERROR_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "statys: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", "Lstd/core/String;Lescompat/ErrorOptions;:V", &method)) != + ANI_OK) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &obj, aniMsg, undefRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::URIPERMMGR, "status: %{public}d", status); + return nullptr; + } + return obj; +} + +ani_string GetAniString(ani_env *env, const std::string &str) +{ + ani_string aniStr = nullptr; + ani_status status = env->String_NewUTF8(str.c_str(), str.size(), &aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status : %{public}d", status); + return nullptr; + } + return aniStr; +} + +ani_object WrapBusinessError(ani_env *env, int32_t code) +{ + ani_class cls {}; + ani_method method {}; + ani_object obj = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return nullptr; + } + if ((status = env->FindClass(BUSINESS_ERROR_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", "DLescompat/Error;:V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return nullptr; + } + ani_object error = WrapError(env, GetErrMsg(code)); + if (error == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "error nulll"); + return nullptr; + } + ani_double dCode(code); + if ((status = env->Object_New(cls, method, &obj, dCode, error)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return nullptr; + } + return obj; +} + +std::string GetErrMsg(int32_t err, const std::string &permission) +{ + auto errCode = GetJsErrorCodeByNativeError(err); + auto errMsg = (errCode == AbilityErrorCode::ERROR_CODE_PERMISSION_DENIED && !permission.empty()) + ? GetNoPermissionErrorMsg(permission) + : GetErrorMsg(errCode); + return errMsg; +} + +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/wantagent/BUILD.gn b/frameworks/ets/ani/wantagent/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..1bf1b8ec940a0fdd720ed9d081f6fc7f9b2c9c95 --- /dev/null +++ b/frameworks/ets/ani/wantagent/BUILD.gn @@ -0,0 +1,61 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("aniwantagent") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime", + ] + + sources = [ "src/ani_want_agent.cpp" ] + + deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_start_options", + "${ability_runtime_innerkits_path}/error_utils:ability_runtime_error_util", + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_innerkits_path}/wantagent:wantagent_innerkits", + "${ability_runtime_native_path}/ability/native:abilitykit_native", + "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_path}/frameworks/ets/ani/ani_wantagent_common:ani_wantagent_common", + ] + + external_deps = [ + "ability_base:want", + "access_token:libtokenid_sdk", + "c_utils:utils", + "hilog:libhilog", + "runtime_core:ani", + ] + + cflags_cc = [] + if (os_dlp_part_enabled) { + cflags_cc += [ "-DWITH_DLP" ] + } + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/frameworks/ets/ani/wantagent/include/ani_want_agent.h b/frameworks/ets/ani/wantagent/include/ani_want_agent.h new file mode 100644 index 0000000000000000000000000000000000000000..94cab407b2ea2382ddcef255962214b9a3781008 --- /dev/null +++ b/frameworks/ets/ani/wantagent/include/ani_want_agent.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ANI_WANT_AGENT_H +#define OHOS_ABILITY_RUNTIME_ANI_WANT_AGENT_H + +#include "ability.h" +#include "completed_callback.h" +#include "context/application_context.h" +#include "sts_error_utils.h" +#include "sts_runtime.h" +#include "trigger_info.h" +#include "want.h" +#include "want_agent.h" +#include "want_agent_constant.h" +#include "want_params.h" + +namespace OHOS { +using namespace OHOS::AppExecFwk; +using namespace OHOS::AbilityRuntime::WantAgent; + +struct CallbackInfo { + std::shared_ptr wantAgent; + ani_vm *vm = nullptr; + ani_ref call = nullptr; +}; + +struct TriggerReceiveDataWorker { + WantAgent* wantAgent; + AAFwk::Want want; + int resultCode; + std::string resultData; + AAFwk::WantParams resultExtras; + ani_vm *vm = nullptr; + ani_ref call = nullptr; +}; + +struct WantAgentWantsParas { + std::vector> wants = {}; + int32_t operationType = -1; + int32_t requestCode = -1; + std::vector wantAgentFlags = {}; + AAFwk::WantParams extraInfo = {}; +}; + +class EtsWantAgent : public std::enable_shared_from_this { +public: + EtsWantAgent() = default; + ~EtsWantAgent() = default; + static EtsWantAgent &GetInstance(); + static void Equal(ani_env *env, ani_object agent, ani_object otherAgent, ani_object call); + static void GetWant(ani_env *env, ani_object agent, ani_object call); + static void GetOperationType(ani_env *env, ani_object agent, ani_object call); + static void GetBundleName(ani_env *env, ani_object agent, ani_object call); + static void GetUid(ani_env *env, ani_object agent, ani_object call); + static void Cancel(ani_env *env, ani_object agent, ani_object call); + static void Trigger(ani_env *env, ani_object agent, ani_object triggerInfoObj, ani_object call); + static void GetWantAgent(ani_env *env, ani_object info, ani_object call); + +private: + void OnEqual(ani_env *env, ani_object agent, ani_object otherAgent, ani_object call); + void OnGetWant(ani_env *env, ani_object agent, ani_object call); + void OnGetOperationType(ani_env *env, ani_object agent, ani_object call); + void OnGetBundleName(ani_env *env, ani_object agent, ani_object call); + void OnGetUid(ani_env *env, ani_object agent, ani_object call); + void OnCancel(ani_env *env, ani_object agent, ani_object call); + void OnTrigger(ani_env *env, ani_object agent, ani_object triggerInfoObj, ani_object call); + void OnGetWantAgent(ani_env *env, ani_object info, ani_object call); + int32_t GetTriggerInfo(ani_env *env, ani_object triggerInfoObj, TriggerInfo &triggerInfo); + int32_t GetWantAgentParam(ani_env *env, ani_object info, WantAgentWantsParas ¶s); +}; + +class TriggerCompleteCallBack : public CompletedCallback { +public: + TriggerCompleteCallBack(); + virtual ~TriggerCompleteCallBack(); + +public: + void OnSendFinished(const AAFwk::Want &want, int resultCode, const std::string &resultData, + const AAFwk::WantParams &resultExtras) override; + void SetCallbackInfo(ani_vm *vm, ani_ref call); + void SetWantAgentInstance(std::shared_ptr wantAgent); + +private: + CallbackInfo triggerCompleteInfo_; +}; +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ANI_WANT_AGENT_H diff --git a/frameworks/ets/ani/wantagent/src/ani_want_agent.cpp b/frameworks/ets/ani/wantagent/src/ani_want_agent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e3c8b3d224b246d782fc73f785798e6cae9ce97 --- /dev/null +++ b/frameworks/ets/ani/wantagent/src/ani_want_agent.cpp @@ -0,0 +1,686 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_want_agent.h" + +#include "ability_runtime_error_util.h" +#include "ani_common_start_options.h" +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "ani_common_want_agent.h" +#include "ani_enum_convert.h" +#include "hilog_tag_wrapper.h" +#include "start_options.h" +#include "want_agent_helper.h" + +using namespace OHOS::AbilityRuntime; +namespace OHOS { +namespace { +constexpr int32_t ERR_NOT_OK = -1; +constexpr int32_t BUSINESS_ERROR_CODE_OK = 0; +constexpr int32_t PARAMETER_ERROR = -1; +constexpr const char* COMPLETE_DATA_IMPL_CLASS_NAME = "L@ohos/app/ability/wantAgent/wantAgent/CompleteDataImpl;"; +constexpr const char* WANT_AGENT_CLASS = "L@ohos/app/ability/wantAgent/wantAgent;"; +} // namespace + +TriggerCompleteCallBack::TriggerCompleteCallBack() +{} + +TriggerCompleteCallBack::~TriggerCompleteCallBack() +{} + +void TriggerCompleteCallBack::SetCallbackInfo(ani_vm *vm, ani_ref call) +{ + triggerCompleteInfo_.vm = vm; + triggerCompleteInfo_.call = call; +} + +void TriggerCompleteCallBack::SetWantAgentInstance(std::shared_ptr wantAgent) +{ + triggerCompleteInfo_.wantAgent = wantAgent; +} + +void OnSendFinishedCallback(TriggerReceiveDataWorker *dataWorker) +{ + if (dataWorker == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "dataWorker null"); + return; + } + ani_vm *etsVm = dataWorker->vm; + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + if (etsVm == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "etsVm null"); + return; + } + if ((status = etsVm->GetEnv(ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetEnv failed status: %{public}d", status); + return; + } + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "env null"); + return; + } + ani_class cls {}; + ani_method method = nullptr; + ani_object object = nullptr; + if ((status = env->FindClass(COMPLETE_DATA_IMPL_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "FindClass failed status: %{public}d", status); + return; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Class_FindMethod failed status: %{public}d", status); + return; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Object_New failed status: %{public}d", status); + return; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null object"); + return; + } + env->Object_SetPropertyByName_Ref(object, "info", WrapWantAgent(env, dataWorker->wantAgent)); + env->Object_SetPropertyByName_Ref(object, "want", AppExecFwk::WrapWant(env, dataWorker->want)); + env->Object_SetPropertyByName_Double(object, "finalCode", static_cast(dataWorker->resultCode)); + env->Object_SetPropertyByName_Ref(object, "finalData", GetAniString(env, dataWorker->resultData)); + env->Object_SetPropertyByName_Ref(object, "extraInfo", AppExecFwk::WrapWantParams(env, dataWorker->resultExtras)); + + ani_object error = CreateStsError(env, AbilityErrorCode::ERROR_OK); + AsyncCallback(env, reinterpret_cast(dataWorker->call), error, object); + env->GlobalReference_Delete(dataWorker->call); +} + +void TriggerCompleteCallBack::OnSendFinished( + const AAFwk::Want &want, int resultCode, const std::string &resultData, const AAFwk::WantParams &resultExtras) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "OnSendFinished"); + if (triggerCompleteInfo_.call == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "CallBack is nullptr"); + return; + } + TriggerReceiveDataWorker* dataWorker = new (std::nothrow) TriggerReceiveDataWorker(); + if (dataWorker == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "dataWorker null"); + return; + } + dataWorker->want = want; + dataWorker->resultCode = resultCode; + dataWorker->resultData = resultData; + dataWorker->resultExtras = resultExtras; + dataWorker->vm = triggerCompleteInfo_.vm; + dataWorker->call = triggerCompleteInfo_.call; + if (triggerCompleteInfo_.wantAgent != nullptr) { + dataWorker->wantAgent = new WantAgent(triggerCompleteInfo_.wantAgent->GetPendingWant()); + } + OnSendFinishedCallback(dataWorker); + if (dataWorker != nullptr) { + delete dataWorker; + dataWorker = nullptr; + } +} + +EtsWantAgent &EtsWantAgent::GetInstance() +{ + static EtsWantAgent instance; + return instance; +} + +void EtsWantAgent::GetBundleName(ani_env *env, ani_object agent, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "called"); + GetInstance().OnGetBundleName(env, agent, call); +}; + +void EtsWantAgent::GetUid(ani_env *env, ani_object agent, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "called"); + GetInstance().OnGetUid(env, agent, call); +}; + +void EtsWantAgent::Cancel(ani_env *env, ani_object agent, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "called"); + GetInstance().OnCancel(env, agent, call); +}; + +void EtsWantAgent::Equal(ani_env *env, ani_object agent, ani_object otherAgent, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "called"); + GetInstance().OnEqual(env, agent, otherAgent, call); +}; + +void EtsWantAgent::GetWant(ani_env *env, ani_object agent, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "called"); + GetInstance().OnGetWant(env, agent, call); +}; + +void EtsWantAgent::GetOperationType(ani_env *env, ani_object agent, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "called"); + GetInstance().OnGetOperationType(env, agent, call); +}; + +void EtsWantAgent::Trigger(ani_env *env, ani_object agent, ani_object triggerInfoObj, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "called"); + GetInstance().OnTrigger(env, agent, triggerInfoObj, call); +}; + +void EtsWantAgent::GetWantAgent(ani_env *env, ani_object info, ani_object call) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "called"); + GetInstance().OnGetWantAgent(env, info, call); +} + +void EtsWantAgent::OnGetBundleName(ani_env *env, ani_object agent, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "env null"); + return; + } + WantAgent* pWantAgent = nullptr; + ErrCode resultCode = ERR_OK; + ani_object aniObject = CreateStsError(env, AbilityErrorCode::ERROR_OK); + UnwrapWantAgent(env, agent, reinterpret_cast(&pWantAgent)); + std::string bundleName = ""; + if (pWantAgent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Parse pWantAgent failed"); + aniObject = CreateStsErrorByNativeErr(env, ERR_NOT_OK); +#ifdef ENABLE_ERRCODE + ThrowStsInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; +#else + AsyncCallback(env, call, aniObject, GetAniString(env, bundleName)); + return; +#endif + } + std::shared_ptr wantAgent = std::make_shared(*pWantAgent); + resultCode = WantAgentHelper::GetBundleName(wantAgent, bundleName); + if (resultCode != ERR_OK) { + aniObject = CreateStsErrorByNativeErr(env, resultCode); + } + ani_string aniBundleName = GetAniString(env, bundleName); + AsyncCallback(env, call, aniObject, reinterpret_cast(aniBundleName)); +} + +void EtsWantAgent::OnGetUid(ani_env *env, ani_object agent, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "env null"); + return; + } + WantAgent* pWantAgent = nullptr; + ErrCode resultCode = ERR_OK; + ani_object aniObject = CreateStsError(env, AbilityErrorCode::ERROR_OK); + UnwrapWantAgent(env, agent, reinterpret_cast(&pWantAgent)); + if (pWantAgent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Parse pWantAgent failed"); + aniObject = CreateStsErrorByNativeErr(env, ERR_NOT_OK); +#ifdef ENABLE_ERRCODE + ThrowStsInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; +#else + AsyncCallback(env, call, aniObject, createDouble(env, ERR_NOT_OK)); + return; +#endif + } + std::shared_ptr wantAgent = std::make_shared(*pWantAgent); + int uid = -1; + resultCode = WantAgentHelper::GetUid(wantAgent, uid); + if (resultCode != ERR_OK) { + aniObject = CreateStsErrorByNativeErr(env, resultCode); + } + AsyncCallback(env, call, aniObject, createDouble(env, static_cast(uid))); +} + +void EtsWantAgent::OnCancel(ani_env *env, ani_object agent, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "env null"); + return; + } + WantAgent* pWantAgent = nullptr; + ErrCode resultCode = ERR_OK; + ani_object aniObject = CreateStsError(env, AbilityErrorCode::ERROR_OK); + UnwrapWantAgent(env, agent, reinterpret_cast(&pWantAgent)); + if (pWantAgent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Parse pWantAgent failed"); + aniObject = CreateStsErrorByNativeErr(env, ERR_NOT_OK); +#ifdef ENABLE_ERRCODE + ThrowStsInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; +#else + AsyncCallback(env, call, aniObject, nullptr); + return; +#endif + } + std::shared_ptr wantAgent = std::make_shared(*pWantAgent); + resultCode = WantAgentHelper::Cancel(wantAgent); + if (resultCode != NO_ERROR) { + aniObject = CreateStsErrorByNativeErr(env, resultCode); + } + AsyncCallback(env, call, aniObject, nullptr); +} + +void EtsWantAgent::OnEqual(ani_env *env, ani_object agent, ani_object otherAgent, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "env null"); + return; + } + WantAgent* pWantAgentFirst = nullptr; + WantAgent* pWantAgentSecond = nullptr; + ErrCode resultCode = ERR_OK; + ani_object aniObject = CreateStsError(env, AbilityErrorCode::ERROR_OK); + UnwrapWantAgent(env, agent, reinterpret_cast(&pWantAgentFirst)); + UnwrapWantAgent(env, otherAgent, reinterpret_cast(&pWantAgentSecond)); + if (pWantAgentFirst == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Parse pWantAgentFirst failed"); + aniObject = CreateStsErrorByNativeErr(env, ERR_NOT_OK); +#ifdef ENABLE_ERRCODE + ThrowStsInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; +#else + AsyncCallback(env, call, aniObject, createBoolean(env, false)); + return; +#endif + } + if (pWantAgentSecond == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Parse pWantAgentSecond failed"); + aniObject = CreateStsErrorByNativeErr(env, ERR_NOT_OK); +#ifdef ENABLE_ERRCODE + ThrowStsInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; +#else + AsyncCallback(env, call, aniObject, createBoolean(env, false)); + return; +#endif + } + std::shared_ptr wantAgentFirst = std::make_shared(*pWantAgentFirst); + std::shared_ptr wantAgentSecond = std::make_shared(*pWantAgentSecond); + resultCode = WantAgentHelper::IsEquals(wantAgentFirst, wantAgentSecond); + bool ret = false; + if (resultCode == ERR_NOT_OK) { + ret = false; + } else if (resultCode == ERR_OK) { + ret = true; + } else { + aniObject = CreateStsErrorByNativeErr(env, resultCode); + } + AsyncCallback(env, call, aniObject, createBoolean(env, static_cast(ret))); +} + +void EtsWantAgent::OnGetWant(ani_env *env, ani_object agent, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "env null"); + return; + } + std::shared_ptr want = std::make_shared(AAFwk::Want()); + ani_object wantAniObj = AppExecFwk::WrapWant(env, *want); + WantAgent* pWantAgent = nullptr; + ani_object aniObject = CreateStsError(env, AbilityErrorCode::ERROR_OK); + UnwrapWantAgent(env, agent, reinterpret_cast(&pWantAgent)); + if (pWantAgent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Parse pWantAgent failed"); + aniObject = CreateStsErrorByNativeErr(env, ERR_NOT_OK); +#ifdef ENABLE_ERRCODE + ThrowStsInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; +#else + AsyncCallback(env, call, aniObject, wantAniObj); + return; +#endif + } + std::shared_ptr wantAgent = std::make_shared(*pWantAgent); + want = WantAgentHelper::GetWant(wantAgent); + if (want == nullptr) { + aniObject = CreateStsError(env, ERR_NOT_OK, "WantAgentHelper::GetWant result nullptr."); + } else { + wantAniObj = AppExecFwk::WrapWant(env, *want); + } + AsyncCallback(env, call, aniObject, wantAniObj); +} + +void EtsWantAgent::OnGetOperationType(ani_env *env, ani_object agent, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "env null"); + return; + } + WantAgent* pWantAgent = nullptr; + ani_object aniObject = CreateStsError(env, AbilityErrorCode::ERROR_OK); + UnwrapWantAgent(env, agent, reinterpret_cast(&pWantAgent)); + if (pWantAgent == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Parse pWantAgent failed"); + aniObject = CreateStsErrorByNativeErr(env, ERR_NOT_OK); +#ifdef ENABLE_ERRCODE + ThrowStsInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; +#else + AsyncCallback(env, call, aniObject, createDouble(env, ERR_NOT_OK)); + return; +#endif + } + std::shared_ptr wantAgent = std::make_shared(*pWantAgent); + auto ret = WantAgentHelper::GetType(wantAgent); + AsyncCallback(env, call, aniObject, createDouble(env, static_cast(ret))); +} + +int32_t EtsWantAgent::GetWantAgentParam(ani_env *env, ani_object info, WantAgentWantsParas ¶s) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "called"); + ani_status status = ANI_ERROR; + ani_ref wantsRef = nullptr; + if ((status = env->Object_GetPropertyByName_Ref(info, "wants", &wantsRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Object_GetPropertyByName_Ref failed status: %{public}d", status); + return PARAMETER_ERROR; + } + if (wantsRef == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "null wantsRef"); + return PARAMETER_ERROR; + } + ani_array_ref wantsArr = reinterpret_cast(wantsRef); + ani_size length = 0; + if ((status = env->Object_GetPropertyByName_Ref(info, "wants", &wantsRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Object_GetPropertyByName_Ref failed status: %{public}d", status); + return PARAMETER_ERROR; + } + if ((status = env->Array_GetLength(wantsArr, &length)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Array_GetLength failed status: %{public}d", status); + return PARAMETER_ERROR; + } + for (size_t i = 0; i < length; i++) { + ani_ref wantRef = nullptr; + std::shared_ptr want = std::make_shared(); + if ((status = env->Array_Get_Ref(wantsArr, i, &wantRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Array_Get_Ref failed status: %{public}d", status); + return PARAMETER_ERROR; + } + if (!AppExecFwk::UnwrapWant(env, reinterpret_cast(wantRef), *want)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "UnwrapWant failed"); + return PARAMETER_ERROR; + } + paras.wants.emplace_back(want); + } + + ani_boolean isUndefined = true; + ani_ref actionTypeRef = nullptr; + if (!AppExecFwk::GetPropertyRef(env, info, "actionType", actionTypeRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return PARAMETER_ERROR; + } + if (!isUndefined) { + AAFwk::AniEnumConvertUtil::EnumConvertStsToNative( + env, reinterpret_cast(actionTypeRef), paras.operationType); + } + + ani_double dRequestCode = 0.0; + if ((status = env->Object_GetPropertyByName_Double(info, "requestCode", &dRequestCode)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Object_GetPropertyByName_Double failed status: %{public}d", status); + return PARAMETER_ERROR; + } + paras.requestCode = dRequestCode; + + ani_ref actionFlagsRef = nullptr; + if (!AppExecFwk::GetPropertyRef(env, info, "actionFlags", actionFlagsRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return PARAMETER_ERROR; + } + ani_array_ref actionFlagsArr = reinterpret_cast(actionFlagsRef); + if (!isUndefined) { + ani_size actionFlagsLen = 0; + if ((status = env->Array_GetLength(actionFlagsArr, &actionFlagsLen)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Array_GetLength failed status: %{public}d", status); + return PARAMETER_ERROR; + } + for (size_t i = 0; i < actionFlagsLen; i++) { + ani_ref actionFlagRef = nullptr; + int32_t actionFlag = 0; + if ((status = env->Array_Get_Ref(actionFlagsArr, i, &actionFlagRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Array_Get_Ref failed status: %{public}d", status); + return PARAMETER_ERROR; + } + AAFwk::AniEnumConvertUtil::EnumConvertStsToNative( + env, reinterpret_cast(actionFlagRef), actionFlag); + paras.wantAgentFlags.emplace_back(static_cast(actionFlag)); + } + } + + ani_ref extraInfoRef = nullptr; + if (!AppExecFwk::GetPropertyRef(env, info, "extraInfos", extraInfoRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return PARAMETER_ERROR; + } + if (isUndefined) { + if (!AppExecFwk::GetPropertyRef(env, info, "extraInfo", extraInfoRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return PARAMETER_ERROR; + } + } + if (!isUndefined) { + if (!UnwrapWantParams(env, extraInfoRef, paras.extraInfo)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Convert extraInfo failed"); + return PARAMETER_ERROR; + } + } + return BUSINESS_ERROR_CODE_OK; +} + +void EtsWantAgent::OnTrigger(ani_env *env, ani_object agent, ani_object triggerInfoObj, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "env null"); + return; + } + std::shared_ptr wantAgent = nullptr; + WantAgent* pWantAgent = nullptr; + TriggerInfo triggerInfo; + UnwrapWantAgent(env, agent, reinterpret_cast(&pWantAgent)); + if (pWantAgent == nullptr) { + ThrowStsInvalidParamError(env, "Parse pWantAgent failed. Agent must be a WantAgent."); + return; + } + wantAgent = std::make_shared(*pWantAgent); + int32_t ret = GetTriggerInfo(env, triggerInfoObj, triggerInfo); + if (ret != 0) { + ThrowStsInvalidParamError(env, "Get trigger info error. TriggerInfo must be a TriggerInfo."); + return; + } + auto triggerObj = std::make_shared(); + ani_vm *etsVm = nullptr; + ani_ref callbackRef = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GetVM(&etsVm)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetVM failed status: %{public}d", status); + return; + } + ani_boolean isUndefined = true; + if ((status = env->Reference_IsUndefined(call, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Reference_IsUndefined failed status: %{public}d", status); + return; + } + if (!isUndefined) { + if ((status = env->GlobalReference_Create(call, &callbackRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GlobalReference_Create failed status: %{public}d", status); + return; + } + } + triggerObj->SetCallbackInfo(etsVm, callbackRef); + triggerObj->SetWantAgentInstance(std::make_shared(pWantAgent->GetPendingWant())); + WantAgentHelper::TriggerWantAgent(wantAgent, triggerObj, triggerInfo); +} + +int32_t EtsWantAgent::GetTriggerInfo(ani_env *env, ani_object triggerInfoObj, TriggerInfo &triggerInfo) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "called"); + ani_status status = ANI_ERROR; + + ani_double dCode { 0.0 }; + if ((status = env->Object_GetPropertyByName_Double(triggerInfoObj, "code", &dCode)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Object_GetPropertyByName_Double failed status: %{public}d", status); + return PARAMETER_ERROR; + } + const int32_t code = static_cast(dCode); + + std::shared_ptr want = nullptr; + ani_ref wantRef = nullptr; + ani_boolean isUndefined = true; + if (!AppExecFwk::GetPropertyRef(env, triggerInfoObj, "want", wantRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return PARAMETER_ERROR; + } + if (!isUndefined) { + want = std::make_shared(); + if (!AppExecFwk::UnwrapWant(env, reinterpret_cast(wantRef), *want)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "UnwrapWant failed"); + return PARAMETER_ERROR; + } + } + + std::string permission = ""; + AppExecFwk::GetStringOrUndefined(env, triggerInfoObj, "permission", permission); + + std::shared_ptr extraInfo = nullptr; + ani_ref extraInfoRef = nullptr; + if (!AppExecFwk::GetPropertyRef(env, triggerInfoObj, "extraInfos", extraInfoRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return PARAMETER_ERROR; + } + if (isUndefined) { + if (!AppExecFwk::GetPropertyRef(env, triggerInfoObj, "extraInfo", extraInfoRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return PARAMETER_ERROR; + } + } + if (!isUndefined) { + extraInfo = std::make_shared(); + if (!UnwrapWantParams(env, extraInfoRef, *extraInfo)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Convert extraInfo failed"); + return PARAMETER_ERROR; + } + } + + std::shared_ptr startOptions = nullptr; + ani_ref startOptionsRef = nullptr; + if (!AppExecFwk::GetPropertyRef(env, triggerInfoObj, "startOptions", startOptionsRef, isUndefined)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetPropertyRef failed"); + return PARAMETER_ERROR; + } + if (!isUndefined) { + startOptions = std::make_shared(); + if (!UnwrapStartOptionsWithProcessOption(env, reinterpret_cast(startOptionsRef), *startOptions)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "UnwrapStartOptionsWithProcessOption failed"); + return PARAMETER_ERROR; + } + } + + TriggerInfo triggerInfoData(permission, extraInfo, want, startOptions, code); + triggerInfo = triggerInfoData; + return BUSINESS_ERROR_CODE_OK; +} + +void EtsWantAgent::OnGetWantAgent(ani_env *env, ani_object info, ani_object call) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "env null"); + return; + } + std::shared_ptr parasobj = std::make_shared(); + int32_t ret = GetWantAgentParam(env, info, *parasobj); + if (ret != 0) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Failed to get wantAgent parameter. Agent must be a WantAgent."); + ThrowStsInvalidParamError(env, "Failed to get wantAgent parameter. Agent must be a WantAgent."); + return; + } + std::shared_ptr extraInfo = std::make_shared(parasobj->extraInfo); + WantAgentInfo wantAgentInfo(parasobj->requestCode, + static_cast(parasobj->operationType), + parasobj->wantAgentFlags, + parasobj->wants, + extraInfo); + auto context = OHOS::AbilityRuntime::Context::GetApplicationContext(); + std::shared_ptr wantAgent = nullptr; + WantAgentHelper::GetWantAgent(context, wantAgentInfo, wantAgent); + + WantAgent* pWantAgent = nullptr; + ani_object error = CreateStsErrorByNativeErr(env, ERR_NOT_OK); + ani_object retObj = createLong(env, ERR_NOT_OK); + if (wantAgent != nullptr) { + pWantAgent = new (std::nothrow) WantAgent(wantAgent->GetPendingWant()); + error = CreateStsError(env, AbilityErrorCode::ERROR_OK); + retObj = WrapWantAgent(env, pWantAgent); + } + AsyncCallback(env, call, error, retObj); +} + +bool BindNativeFunctions(ani_env *env, ani_namespace &ns) +{ + ani_status status = ANI_ERROR; + if ((status = env->FindNamespace(WANT_AGENT_CLASS, &ns)) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "FindNamespace failed status: %{public}d", status); + return false; + } + std::array functions = { + ani_native_function { "nativeGetBundleName", nullptr, reinterpret_cast(EtsWantAgent::GetBundleName) }, + ani_native_function { "nativeGetUid", nullptr, reinterpret_cast(EtsWantAgent::GetUid) }, + ani_native_function { + "nativeGetOperationType", nullptr, reinterpret_cast(EtsWantAgent::GetOperationType) }, + ani_native_function { "nativeCancel", nullptr, reinterpret_cast(EtsWantAgent::Cancel) }, + ani_native_function { "nativeEqual", nullptr, reinterpret_cast(EtsWantAgent::Equal) }, + ani_native_function { "nativeTrigger", nullptr, reinterpret_cast(EtsWantAgent::Trigger) }, + ani_native_function { "nativeGetWant", nullptr, reinterpret_cast(EtsWantAgent::GetWant) }, + ani_native_function { "nativeGetWantAgent", nullptr, reinterpret_cast(EtsWantAgent::GetWantAgent) }, + }; + if ((status = env->Namespace_BindNativeFunctions(ns, functions.data(), functions.size())) != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "Namespace_BindNativeFunctions failed status: %{public}d", status); + return false; + } + return true; +} + +void EtsWantAgentInit(ani_env *env) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::WANTAGENT, "env null"); + return; + } + ani_namespace ns; + if (!BindNativeFunctions(env, ns)) { + TAG_LOGE(AAFwkTag::WANTAGENT, "BindNativeFunctions failed"); + return; + } +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::WANTAGENT, "ANI_Constructor"); + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::WANTAGENT, "GetEnv failed status: %{public}d", status); + return ANI_NOT_FOUND; + } + + EtsWantAgentInit(env); + *result = ANI_VERSION_1; + return ANI_OK; +} +} +} // namespace OHOS diff --git a/frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets b/frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets new file mode 100644 index 0000000000000000000000000000000000000000..c559189304b6c8b020f62e2d50c315e25544bad7 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace AbilityConstant { + export interface LaunchParam { + launchReason: LaunchReason; + launchReasonMessage?: string; + lastExitReason: LastExitReason; + lastExitMessage: string; + lastExitDetailInfo?: LastExitDetailInfo; + } + export interface LastExitDetailInfo { + pid: number; + processName: string; + uid: number; + exitSubReason: number; + exitMsg: string; + rss: number; + pss: number; + timestamp: number; + } + export enum LaunchReason { + UNKNOWN = 0, + START_ABILITY = 1, + CALL = 2, + CONTINUATION = 3, + APP_RECOVERY = 4, + SHARE = 5, + AUTO_STARTUP = 8, + INSIGHT_INTENT = 9, + PREPARE_CONTINUATION = 10, + } + export enum LastExitReason { + UNKNOWN = 0, + ABILITY_NOT_RESPONDING = 1, + NORMAL = 2, + CPP_CRASH = 3, + JS_ERROR = 4, + APP_FREEZE = 5, + PERFORMANCE_CONTROL = 6, + RESOURCE_CONTROL = 7, + UPGRADE = 8, + USER_REQUEST = 9, + SIGNAL = 10 + } + export enum OnContinueResult { + AGREE = 0, + REJECT = 1, + MISMATCH = 2 + } + export enum MemoryLevel { + MEMORY_LEVEL_MODERATE = 0, + MEMORY_LEVEL_LOW = 1, + MEMORY_LEVEL_CRITICAL = 2 + } + export enum WindowMode { + WINDOW_MODE_UNDEFINED = 0, + WINDOW_MODE_FULLSCREEN = 1, + WINDOW_MODE_SPLIT_PRIMARY = 100, + WINDOW_MODE_SPLIT_SECONDARY = 101, + WINDOW_MODE_FLOATING = 102 + } + export enum OnSaveResult { + ALL_AGREE = 0, + CONTINUATION_REJECT = 1, + CONTINUATION_MISMATCH = 2, + RECOVERY_AGREE = 3, + RECOVERY_REJECT = 4, + ALL_REJECT + } + export enum StateType { + CONTINUATION = 0, + APP_RECOVERY = 1 + } + export enum ContinueState { + ACTIVE = 0, + INACTIVE = 1 + } + export enum CollaborateResult { + ACCEPT = 0, + REJECT = 1, + } + export enum PrepareTermination { + TERMINATE_IMMEDIATELY = 0, + CANCEL = 1 + } +} + +class LaunchParamImpl implements AbilityConstant.LaunchParam { + launchReason: AbilityConstant.LaunchReason = AbilityConstant.LaunchReason.UNKNOWN; + launchReasonMessage?: string | undefined; + lastExitReason: AbilityConstant.LastExitReason = AbilityConstant.LastExitReason.UNKNOWN; + lastExitMessage: string = ''; + lastExitDetailInfo?: AbilityConstant.LastExitDetailInfo = undefined; +} + +class LastExitDetailInfoImpl implements AbilityConstant.LastExitDetailInfo { + pid: number = 0; + processName: string = ''; + uid: number = 0; + exitSubReason: number = 0; + exitMsg: string = ''; + rss: number = 0; + pss: number = 0; + timestamp: number = 0; +} + +export default AbilityConstant; diff --git a/frameworks/ets/ets/@ohos.app.ability.AbilityStage.ets b/frameworks/ets/ets/@ohos.app.ability.AbilityStage.ets new file mode 100644 index 0000000000000000000000000000000000000000..27df91c758a16f67c19e42313692874cd50a4e6d --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.AbilityStage.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. + */ + +import { Configuration } from '@ohos.app.ability.Configuration' +import AbilityStageContext from 'application.AbilityStageContext' + +export default class AbilityStage { + context: AbilityStageContext = new AbilityStageContext(); + + onConfigurationUpdate(newConfig: Configuration): void { + } + + onCreate(): void { + } + + onDestroy(): void { + } +} \ No newline at end of file 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 0000000000000000000000000000000000000000..32585e54e3fee22f8af329b0ea2a92210d5aa8f4 --- /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.Configuration.ets b/frameworks/ets/ets/@ohos.app.ability.Configuration.ets new file mode 100644 index 0000000000000000000000000000000000000000..7546792e520c50f52efb66f8de7fcfa1991ca621 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.Configuration.ets @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant'; + +export interface Configuration { + language?: string; + colorMode?: ConfigurationConstant.ColorMode; + direction?: ConfigurationConstant.Direction; + screenDensity?: ConfigurationConstant.ScreenDensity; + displayId?: number; + hasPointerDevice?: boolean; + fontId?: string; + fontSizeScale?: number; + fontWeightScale?: number; + mcc?: string; + mnc?: string; +} + +class ConfigurationImpl implements Configuration { + language?: string; + colorMode?: ConfigurationConstant.ColorMode; + direction?: ConfigurationConstant.Direction; + screenDensity?: ConfigurationConstant.ScreenDensity; + displayId?: number; + hasPointerDevice?: boolean; + fontId?: string; + fontSizeScale?: number; + fontWeightScale?: number; + mcc?: string; + mnc?: string; +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.ConfigurationConstant.ets b/frameworks/ets/ets/@ohos.app.ability.ConfigurationConstant.ets new file mode 100644 index 0000000000000000000000000000000000000000..acfd8f140503d407bdb690b78ab274e21a792393 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.ConfigurationConstant.ets @@ -0,0 +1,38 @@ +/* + * 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. + */ + +namespace ConfigurationConstant { + export enum ColorMode { + COLOR_MODE_NOT_SET = -1, + COLOR_MODE_DARK = 0, + COLOR_MODE_LIGHT = 1 + } + export enum Direction { + DIRECTION_NOT_SET = -1, + DIRECTION_VERTICAL = 0, + DIRECTION_HORIZONTAL = 1 + } + export enum ScreenDensity { + SCREEN_DENSITY_NOT_SET = 0, + SCREEN_DENSITY_SDPI = 120, + SCREEN_DENSITY_MDPI = 160, + SCREEN_DENSITY_LDPI = 240, + SCREEN_DENSITY_XLDPI = 320, + SCREEN_DENSITY_XXLDPI = 480, + SCREEN_DENSITY_XXXLDPI = 640 + } + } + export default ConfigurationConstant; + \ No newline at end of file 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 0000000000000000000000000000000000000000..908a4f82e0e959746a03fccc64effe5d9e672f51 --- /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.InsightIntentContext.ets b/frameworks/ets/ets/@ohos.app.ability.InsightIntentContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..a8fceeb56bb19f8585e346ab93064edf53243878 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.InsightIntentContext.ets @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BusinessError, AsyncCallback } from '@ohos.base'; +import Want from '@ohos.app.ability.Want'; + +export default class InsightIntentContext { + nativeContext: long; + + public native nativeStartAbilitySync(want: Want): BusinessError; + + startAbility(want: Want, callback: AsyncCallback): void { + let p1 = taskpool.execute((): BusinessError => { + return this.nativeStartAbilitySync(want); + }); + p1.then((e: NullishType) => { + let retError = e as BusinessError; + callback(retError, undefined); + }, (err: Error): void => { + callback(err as BusinessError, undefined); + }); + } + + startAbility(want: Want): Promise { + let p = new Promise((resolve: (v: undefined) => void, reject: (error: BusinessError) => void): void => { + let p1 = taskpool.execute((): BusinessError => { + return this.nativeStartAbilitySync(want); + }); + p1.then((e: NullishType) => { + let retError = e as BusinessError; + if (retError.code === 0) { + resolve(undefined); + } else { + reject(retError); + } + }).catch((err: Error): void => { + reject(err as BusinessError); + }); + }); + return p; + } +} diff --git a/frameworks/ets/ets/@ohos.app.ability.InsightIntentExecutor.ets b/frameworks/ets/ets/@ohos.app.ability.InsightIntentExecutor.ets new file mode 100644 index 0000000000000000000000000000000000000000..dca81b8dad3476ff82f4ebd5a435d3cda997cc7f --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.InsightIntentExecutor.ets @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import window from '@ohos.window'; +import insightIntent from './@ohos.app.ability.insightIntent'; +import InsightIntentContext from '@ohos.app.ability.InsightIntentContext'; +import type UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; + +export default class InsightIntentExecutor { + context: InsightIntentContext = {}; + public nativeExecutor: long = 0; + public isOnExecuteInUIAbilityForegroundModeAsync: boolean = true; + public isOnExecuteInUIAbilityBackgroundModeAsync: boolean = true; + public isOnExecuteInUIExtensionAbilityAsync: boolean = true; + public isOnExecuteInServiceExtensionAbilityAsync: boolean = true; + + public native nativeOnExecuteResult(data: insightIntent.ExecuteResult): void; + + public callOnExecuteInUIAbilityForegroundMode(name: string, param: Record, + pageLoader: window.WindowStage): insightIntent.ExecuteResult { + let p = this.onExecuteInUIAbilityForegroundModeAsync(name, param, pageLoader); + if (this.isOnExecuteInUIAbilityForegroundModeAsync) { + p.then((result: insightIntent.ExecuteResult): void => { + this.nativeOnExecuteResult(result); + }); + let ret: insightIntent.ExecuteResult = {}; + return ret; + } else { + return this.onExecuteInUIAbilityForegroundMode(name, param, pageLoader); + } + } + + public callOnExecuteInUIAbilityBackgroundMode(name: string, param: Record): + insightIntent.ExecuteResult { + let p = this.onExecuteInUIAbilityBackgroundModeAsync(name, param); + if (this.isOnExecuteInUIAbilityBackgroundModeAsync) { + p.then((result: insightIntent.ExecuteResult): void => { + this.nativeOnExecuteResult(result); + }); + let ret: insightIntent.ExecuteResult = {}; + return ret; + } else { + return this.onExecuteInUIAbilityBackgroundMode(name, param); + } + } + + public callOnExecuteInUIExtensionAbility(name: string, param: Record, + pageLoader: UIExtensionContentSession): insightIntent.ExecuteResult { + let p = this.onExecuteInUIExtensionAbilityAsync(name, param, pageLoader); + if (this.isOnExecuteInUIExtensionAbilityAsync) { + p.then((result: insightIntent.ExecuteResult): void => { + this.nativeOnExecuteResult(result); + }); + let ret: insightIntent.ExecuteResult = {}; + return ret; + } else { + return this.onExecuteInUIExtensionAbility(name, param, pageLoader); + } + } + + public callOnExecuteInServiceExtensionAbility(name: string, param: Record): + insightIntent.ExecuteResult { + let p = this.onExecuteInServiceExtensionAbilityAsync(name, param); + if (this.isOnExecuteInServiceExtensionAbilityAsync) { + p.then((result: insightIntent.ExecuteResult): void => { + this.nativeOnExecuteResult(result); + }); + let ret: insightIntent.ExecuteResult = {}; + return ret; + } else { + return this.onExecuteInServiceExtensionAbility(name, param); + } + } + + onExecuteInUIAbilityForegroundMode(name: string, param: Record, pageLoader: window.WindowStage): + insightIntent.ExecuteResult { + let ret: insightIntent.ExecuteResult = {}; + return ret; + } + + onExecuteInUIAbilityForegroundModeAsync(name: string, param: Record, pageLoader: window.WindowStage): + Promise { + this.isOnExecuteInUIAbilityForegroundModeAsync = false; + return new Promise(( + resolve: (a: insightIntent.ExecuteResult) => void, + reject: (err: Error) => void): void => { + }); + } + + onExecuteInUIAbilityBackgroundMode(name: string, param: Record): + insightIntent.ExecuteResult { + let ret: insightIntent.ExecuteResult = {}; + return ret; + } + + onExecuteInUIAbilityBackgroundModeAsync(name: string, param: Record): + Promise { + this.isOnExecuteInUIAbilityBackgroundModeAsync = false; + return new Promise(( + resolve: (a: insightIntent.ExecuteResult) => void, + reject: (err: Error) => void): void => { + }); + } + + onExecuteInUIExtensionAbility(name: string, param: Record, pageLoader: UIExtensionContentSession): + insightIntent.ExecuteResult { + let ret: insightIntent.ExecuteResult = {}; + return ret; + } + + onExecuteInUIExtensionAbilityAsync(name: string, param: Record, + pageLoader: UIExtensionContentSession): + Promise { + this.isOnExecuteInUIExtensionAbilityAsync = false; + return new Promise(( + resolve: (a: insightIntent.ExecuteResult) => void, + reject: (err: Error) => void): void => { + }); + } + + onExecuteInServiceExtensionAbility(name: string, param: Record): + insightIntent.ExecuteResult { + let ret: insightIntent.ExecuteResult = {}; + return ret; + } + + onExecuteInServiceExtensionAbilityAsync(name: string, param: Record): + Promise { + this.isOnExecuteInServiceExtensionAbilityAsync = false; + return new Promise(( + resolve: (a: insightIntent.ExecuteResult) => void, + reject: (err: Error) => void): void => { + }); + } +} diff --git a/frameworks/ets/ets/@ohos.app.ability.OpenLinkOptions.ets b/frameworks/ets/ets/@ohos.app.ability.OpenLinkOptions.ets new file mode 100644 index 0000000000000000000000000000000000000000..b8e04eba7aa93f9c638e0c2b5fe956be7c0612d9 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.OpenLinkOptions.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. + */ +export default interface OpenLinkOptions { + appLinkingOnly?: boolean; + parameters?: Record; +} + +class OpenLinkOptionsImpl implements OpenLinkOptions { + appLinkingOnly?: boolean|undefined; + parameters?: Record|undefined; +} diff --git a/frameworks/ets/ets/@ohos.app.ability.ServiceExtensionAbility.ets b/frameworks/ets/ets/@ohos.app.ability.ServiceExtensionAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..8fccea3f7ade8181ff7f1a169ff3a1c252038e59 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.ServiceExtensionAbility.ets @@ -0,0 +1,104 @@ +/* + * 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 rpc from '@ohos.rpc'; +import Want from '@ohos.app.ability.Want'; +import ServiceExtensionContext from 'application.ServiceExtensionContext'; +import { Configuration } from '@ohos.app.ability.Configuration' + +class MyService extends rpc.RemoteObject { + constructor(descriptor: string) { + super(descriptor); + } + + public onRemoteMessageRequest( + code: number, + data: rpc.MessageSequence, + reply: rpc.MessageSequence, + options: rpc.MessageOption + ): boolean | Promise { + return false; + } + } + +export default class ServiceExtensionAbility { + private isOnConnectAsync: boolean = true; + private connectCallbackPoint: long; + private native nativeOnConnectCallback(service: rpc.RemoteObject): void; + private callOnConnect(want: Want): rpc.RemoteObject { + let p = this.onConnectAsync(want); + if (this.isOnConnectAsync) { + p.then((a:rpc.RemoteObject) => { + this.nativeOnConnectCallback(a); + }); + return new MyService("onConnectAsync") + } else { + return this.onConnect(want); + } + } + + private isOnDisconnectAsync: boolean = true; + private disconnectCallbackPoint: long; + private native nativeOnDisconnectCallback(): void; + private callOnDisconnect(want: Want): void { + let p = this.onDisconnectAsync(want); + if (this.isOnDisconnectAsync) { + p.then((): void => { + this.nativeOnDisconnectCallback(); + }); + } else { + this.onDisconnect(want); + } + } + launchWant: Want = new Want(); + lastRequestWant: Want = new Want(); + context: ServiceExtensionContext = {}; + onCreate(want: Want): void{ + console.log("onCreate"); + } + onDestroy(): void { + console.log("ServiceExtensionAbility onRequest"); + } + onRequest(want: Want, startld: double): void { + console.log("onRequest"); + } + onConnect(want: Want): rpc.RemoteObject { + console.log("onConnect"); + let myService: rpc.RemoteObject = new MyService("onConnect"); + return myService; + } + onConnectAsync(want: Want): Promise { + console.log("onConnectAsync"); + this.isOnConnectAsync = false; + return new Promise((resolve, reject) => { + resolve(new MyService("onConnectAsync")); + }); + } + onDisconnect(want: Want): void { + console.log("onDisconnect"); + } + onDisconnectAsync(want: Want): Promise { + console.log("onDisconnectAsync"); + this.isOnDisconnectAsync = false; + return new Promise((resolve: (a: undefined)=>void, reject: (err: Error)=>void): void => {}); + } + onConfigurationUpdate(newConfig: Configuration): void { + console.log("onConfigurationUpdate"); + } + onDump(params: Array): Array { + console.log("onDump"); + return ['params']; + } +} 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 0000000000000000000000000000000000000000..b238c15ea6a2ee9f02c7459e07fc5f3aac73baa9 --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..a34b28d5dcd7c6cce7cb7101ec9d452e7c086d04 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.StartOptions.ets @@ -0,0 +1,38 @@ +/* + * 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 contextConstant from '@ohos.app.ability.contextConstant'; +import image from '@ohos.multimedia.image'; +import bundleManager from '@ohos.bundle.bundleManager'; + +export default class StartOptions { + windowMode?: number; + displayId?: number; + withAnimation?: boolean; + windowLeft?: number; + windowTop?: number; + windowWidth?: number; + windowHeight?: number; + windowFocused?: boolean; + processMode?: contextConstant.ProcessMode; + startupVisibility?: contextConstant.StartupVisibility; + startWindowBackgroundColor?: string; + startWindowIcon?: image.PixelMap; + supportWindowModes?: Array; + minWindowWidth?: number; + minWindowHeight?: number; + maxWindowWidth?: number; + maxWindowHeight?: number; +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.UIAbility.ets b/frameworks/ets/ets/@ohos.app.ability.UIAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..dee014b5f1c503140220f2769430e63e5f05190c --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.UIAbility.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 AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import UIAbilityContext from 'application.UIAbilityContext'; +import Want from '@ohos.app.ability.Want'; +import rpc from '@ohos.rpc'; +import window from '@ohos.window'; +import { AbilityUtils } from './utils/AbilityUtils'; + +export type OnReleaseCallback = (msg: string) => void; +export type CalleeCallback = (indata: rpc.MessageSequence) => rpc.Parcelable; +export interface Caller { + call(method: string, data: rpc.Parcelable): Promise; + onRelease(callback: OnReleaseCallback): void; + release(): void; +} +export interface Callee { + on(method: string, callback: CalleeCallback): void; +} + +export default class UIAbility { + private destroyCallbackPoint: long; + private native nativeOnDestroyCallback(): void; + private callOnDestroy(): boolean { + const derivedClassType = AbilityUtils.getClassType(this); + if (derivedClassType === undefined) { + this.onDestroy(); + return false; + } + const uiAbilityClassType = AbilityUtils.getClassType(new UIAbility()); + if (uiAbilityClassType === undefined) { + this.onDestroy(); + return false; + } + const isInherited = AbilityUtils.isInherited(derivedClassType, "onDestroyAsync", uiAbilityClassType); + if (isInherited === false) { + this.onDestroyAsync().then(() => this.nativeOnDestroyCallback()); + return true; + } + this.onDestroy(); + return false; + } + + context: UIAbilityContext = new UIAbilityContext(); + launchWant: Want = new Want(); + lastRequestWant: Want = new Want(); + callee: Callee | null = null; + + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {} + onWindowStageCreate(windowStage: window.WindowStage): void {} + onWindowStageWillDestroy(windowStage: window.WindowStage): void {} + onWindowStageDestroy(): void {} + onWindowStageRestore(windowStage: window.WindowStage): void {} + onDestroy(): void {} + onDestroyAsync(): Promise { + return new Promise((resolve: (a: undefined)=>void, reject: (err: Error)=>void): void => {}); + } + onForeground(): void {} + onBackground(): 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 new file mode 100644 index 0000000000000000000000000000000000000000..5c22e51bb92f6a90a70a19fc701545b6f8c006d7 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.UIExtensionAbility.ets @@ -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. + */ + +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import Want from '@ohos.app.ability.Want'; +import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; +import UIExtensionContext from 'application.UIExtensionContext'; + +class ExtensionAbility{} + +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(); + } + return this.isOnDestroyAsync; + } + + context: UIExtensionContext = {}; + + onCreate(launchParam: AbilityConstant.LaunchParam): void {} + + onSessionCreate(want: Want, session: UIExtensionContentSession): void {} + + onSessionDestroy(session: UIExtensionContentSession): void {} + + onForeground(): void {} + + onBackground(): void {} + + onDestroy(): void {} + + onDestroyAsync(): Promise { + this.isOnDestroyAsync = false; + return new Promise((resolve: (a: undefined)=>void, reject: (err: Error)=>void): void => {}); + } +} diff --git a/frameworks/ets/ets/@ohos.app.ability.UIExtensionContentSession.ets b/frameworks/ets/ets/@ohos.app.ability.UIExtensionContentSession.ets new file mode 100644 index 0000000000000000000000000000000000000000..64066274f0fc4b10972509ef3686851fea241597 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.UIExtensionContentSession.ets @@ -0,0 +1,90 @@ +/* + * 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'; +import { AsyncCallback } from '@ohos.base'; +import { BusinessError } from '@ohos.base'; +import uiExtensionHost from '@ohos.uiExtensionHost'; +import { LocalStorage } from '@ohos.arkui.stateManagement'; +import AsyncCallbackWrapper from './utils/AbilityUtils'; +export default class UIExtensionContentSession { + nativeContextSession:long = 0; + native nativeSendData(data: Record): void; + native loadContent(path: string, storage?: LocalStorage): void; + native setWindowBackgroundColor(color: string): void; + native getUIExtensionHostWindowProxy(): uiExtensionHost.UIExtensionHostWindowProxy; + native nativeSetReceiveDataCallback(callback: (data: Record) => void): void; + native nativeSetReceiveDataForResultCallback(callback: (data: Record) => Record): void; + native terminateSelfSync(callback:AsyncCallbackWrapper): void; + native terminateSelfWithResultSync(parameter: AbilityResult, callback:AsyncCallbackWrapper): void; + + sendData(data: Record): void { + this.nativeSendData(data); + } + + setReceiveDataCallback(callback: (data: Record) => void): void { + this.nativeSetReceiveDataCallback(callback); + } + + setReceiveDataForResultCallback(callback: (data: Record) => Record): void { + this.nativeSetReceiveDataForResultCallback(callback); + } + + terminateSelf(callback:AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.terminateSelfSync(myCall); + }); + } + + terminateSelf(): Promise { + let p = new Promise((resolve: (data: undefined) => void, reject:(err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.terminateSelfSync(myCall); + }); + }); + return p; + } + + terminateSelfWithResult(parameter: AbilityResult, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.terminateSelfWithResultSync(parameter, myCall); + }); + } + + terminateSelfWithResult(parameter: AbilityResult): Promise { + let p = new Promise((resolve: (data: undefined) => void, reject:(err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.terminateSelfWithResultSync(parameter, myCall); + }); + }); + return p; + } +} diff --git a/frameworks/ets/ets/@ohos.app.ability.Want.ets b/frameworks/ets/ets/@ohos.app.ability.Want.ets new file mode 100644 index 0000000000000000000000000000000000000000..4c526067919e638d39297cbed4566b0bc4bdcfdf --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.Want.ets @@ -0,0 +1,229 @@ +/* + * 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 valueType = NullishType; + +class RecordWriter { + private buffer = new StringBuilder(); + private store = new Set(); + + public write(obj: Object): String { + this.writeObject(obj); + return this.buffer.toString(); + } + + private writeObject(obj: NullishType): void { + if (obj === null) { + this.buffer.append('null'); + } else if (obj === undefined) { + this.buffer.append('undefined'); + } else if (obj instanceof String) { + this.buffer.append(JSON.stringify(obj as String)); + } else if (this.writeValueType(obj as Object)) { + // nothing to do + } else if (obj instanceof Array) { + this.writeArray(obj as Object as Array); + } else if (obj instanceof Record) { + this.writeRecord(obj as Object as Record); + } else { + const objType = Type.of(obj); + if (objType instanceof ArrayType) { + this.writeBuildArray(obj as Object, Value.of(obj) as ArrayValue); + } else { + this.buffer.append('null'); + } + } + } + + private writeValueType(obj: Object): boolean { + if (obj instanceof Boolean) { + this.buffer.append(JSON.stringify(obj.unboxed())); + return true; + } else if (obj instanceof Byte) { + this.buffer.append(JSON.stringify(obj.unboxed())); + return true; + } else if (obj instanceof Char) { + this.buffer.append(JSON.stringify(obj.unboxed())); + return true; + } else if (obj instanceof Short) { + this.buffer.append(JSON.stringify(obj.unboxed())); + return true; + } else if (obj instanceof Int) { + this.buffer.append(JSON.stringify(obj.unboxed())); + return true; + } else if (obj instanceof Long) { + this.buffer.append(JSON.stringify(obj.unboxed())); + return true; + } else if (obj instanceof Float) { + this.buffer.append(JSON.stringify(obj.unboxed())); + return true; + } else if (obj instanceof Double) { + this.buffer.append(JSON.stringify(obj.unboxed())); + return true; + } else if (obj instanceof BigInt) { + this.buffer.append(JSON.stringify(obj)); + return true; + } else { + return false; + } + } + + private writeArray(arr: Array): void { + this.buffer.append('['); + const length = arr.length as int; + this.checkReferencesCycle(arr); + this.store.add(arr); + for (let idx = 0; idx < length; idx++) { + if (arr[idx] == null) { + this.buffer.append('null'); + } else { + this.writeObject(arr[idx]); + } + if (idx < length - 1) { + this.buffer.append(','); + } + } + this.store.delete(arr); + this.buffer.append(']'); + } + + private writeBuildArray(arr: Object, arrayValue: ArrayValue): void { + this.buffer.append('['); + const length = arrayValue.getLength() as int; + this.checkReferencesCycle(arr); + this.store.add(arr); + for (let idx = 0; idx < length; idx++) { + let member = arrayValue.getElement(idx).getData(); + if (member == null) { + this.buffer.append('null'); + } else { + this.writeObject(member); + } + if (idx < length - 1) { + this.buffer.append(','); + } + } + this.store.delete(arr); + this.buffer.append(']'); + } + + private writeRecord(rec: Record): void { + this.buffer.append('{'); + this.checkReferencesCycle(rec); + this.store.add(rec); + let isFirst = true; + for (let key of rec.keys()) { + if (rec[key] !== undefined) { + if (!isFirst) { + this.buffer.append(','); + } else { + isFirst = false; + } + this.buffer.append(JSON.stringify(key as String)); + this.buffer.append(':'); + this.writeObject(rec[key]); + } + } + this.store.delete(rec); + this.buffer.append('}'); + } + + private checkReferencesCycle(obj: Object): void { + if (this.store.has(obj)) { + throw new TypeError('cyclic object value'); + } + } +} + +export class RecordSerializeTool { + public static stringifyNoThrow(obj: Record): String { + try { + return JSON.stringify(obj as Object as Record); + } catch (err) { + console.log('err: ' + err.toString()); + return ''; + } + } + + public static parseNoThrow(text: string): Record { + try { + return RecordSerializeTool.parse(text) as Object as Record; + } catch (err) { + console.log('err: ' + err.toString()); + return new Record(); + } + } + + public static stringify(obj: Record): String { + return new RecordWriter().write(obj); + } + + public static parse(text: string): Record { + let jsonValue = JSONParser.parse(text); + let res = RecordSerializeTool.jsonValue2Object(jsonValue); + if (!(res instanceof Record)) { + throw new TypeError('RecordSerializeTool parse only used for Record'); + } + return res as Record; + } + + private static jsonValue2Object(value: JSONValue): string | number | boolean | null | + Array | Record { + if (value instanceof JSONString) { + return value.value; + } else if (value instanceof JSONNumber) { + return new Double(value.value); + } else if (value instanceof JSONTrue) { + return new Boolean(true); + } else if (value instanceof JSONFalse) { + return new Boolean(false); + } else if (value instanceof JSONNull) { + return null; + } else if (value instanceof JSONArray) { + let obj = value as JSONArray; + let values = obj.values; + let result: Array = new Array(); + for (let i: int = 0; i < values.length; i++) { + result.push(RecordSerializeTool.jsonValue2Object(values[i])); + } + return result; + } else if (value instanceof JSONObject) { + let obj = value as JSONObject; + let keys: Array = obj.keys_; + let values: Array = obj.values; + let result: Record = new Record(); + for (let i: int = 0; i < keys.length; i++) { + result[keys[i].value] = RecordSerializeTool.jsonValue2Object(values[i]); + } + return result; + } else { + throw new TypeError('unknown JSONValue'); + } + } +} + +export default class Want { + bundleName?: string; + abilityName?: string; + deviceId?: string; + uri?: string; + type?: string; + flags?: number; + action?: string; + parameters?: Record; + entities?: Array; + moduleName?: string; + readonly fds?: Record; +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.abilityDelegatorRegistry.ets b/frameworks/ets/ets/@ohos.app.ability.abilityDelegatorRegistry.ets new file mode 100644 index 0000000000000000000000000000000000000000..878e80402d2baf07cc7a475a933598ecee68f5da --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.abilityDelegatorRegistry.ets @@ -0,0 +1,39 @@ +/* + * 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 { AbilityDelegator as _AbilityDelegator } from 'application.AbilityDelegator'; +import { AbilityDelegatorArgs as _AbilityDelegatorArgs } from 'application.abilityDelegatorArgs'; +import { AbilityMonitor as _AbilityMonitor } from 'application.AbilityMonitor'; +import { ShellCmdResult as _ShellCmdResult } from 'application.shellCmdResult'; + +export default namespace abilityDelegatorRegistry { + loadLibrary("ability_delegator_registry_ani_kit.z") + + export native function getAbilityDelegator(): AbilityDelegator; + + export native function getArguments(): AbilityDelegatorArgs; + + export enum AbilityLifecycleState { + UNINITIALIZED, + CREATE, + FOREGROUND, + BACKGROUND, + DESTROY + } + export type AbilityDelegator = _AbilityDelegator; + export type AbilityDelegatorArgs = _AbilityDelegatorArgs; + export type AbilityMonitor = _AbilityMonitor; + export type ShellCmdResult = _ShellCmdResult; +} diff --git a/frameworks/ets/ets/@ohos.app.ability.abilityManager.ets b/frameworks/ets/ets/@ohos.app.ability.abilityManager.ets new file mode 100644 index 0000000000000000000000000000000000000000..274a24fc0af837e4077fcee9f2a9c1d7ccb4765b --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.abilityManager.ets @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbilityStateData from 'application.AbilityStateData'; +import { ElementName } from 'bundleManager.ElementName' +import { BusinessError, AsyncCallback } from '@ohos.base'; +import AsyncCallbackWrapper from './utils/AbilityUtils'; +import { AbilityRunningInfo as _AbilityRunningInfo } from 'application.AbilityRunningInfo'; +import { ExtensionRunningInfo as _ExtensionRunningInfo } from 'application.ExtensionRunningInfo'; +import _AbilityForegroundStateObserver from 'application.AbilityForegroundStateObserver'; +import _AbilityStateData from 'application.AbilityStateData'; + +export default namespace abilityManager { + loadLibrary("ability_ability_manager_ani_kit.z") + + export native function nativeGetForegroundUIAbilities(): Array; + export native function getForegroundUIAbilitiesCallback(callback:AsyncCallbackWrapper>) : void; + export native function nativeGetTopAbility(callback:AsyncCallbackWrapper) : void; + export native function nativeGetAbilityRunningInfos(callback:AsyncCallbackWrapper>) : void; + + export function getForegroundUIAbilities():Promise> { + let p = new Promise>((resolve: (data: Array) => void, reject: (error: Error) => void): void => { + let executeFunc = (): Array => { + return nativeGetForegroundUIAbilities(); + }; + let p1 = taskpool.execute(executeFunc); + p1.then((e :NullishType)=>{ + let abilities: Array = e as Array; + resolve(abilities); + }, (err: Error): void => { + reject(err); + }); + }); + return p; + } + + export function getForegroundUIAbilities(callback: AsyncCallback, void>): void { + let myCall = new AsyncCallbackWrapper>(callback); + taskpool.execute((): void => { + abilityManager.getForegroundUIAbilitiesCallback(myCall); + }) + } + + export function getTopAbility():Promise { + let p = new Promise((resolve: (data: ElementName)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: ElementName)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + abilityManager.nativeGetTopAbility(myCall); + }); + }); + return p; +} + +export function getTopAbility(callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute( (): void => { + abilityManager.nativeGetTopAbility(myCall); + }); +} + + function getAbilityRunningInfos(): Promise> { + return new Promise>((resolve: (data: Array) => void, + reject: (err: BusinessError) => void): void => { + let syncCall = new AsyncCallbackWrapper>((err: BusinessError, + data: Array) => { + if (err.code == 0) { + resolve(data); + } 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); + }); + } + + 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 ExtensionRunningInfo = _ExtensionRunningInfo; + + 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 new file mode 100644 index 0000000000000000000000000000000000000000..fe4df6bd34b107bc516fa8cc2ec8f0a51c9fa134 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.appManager.ets @@ -0,0 +1,549 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ProcessInformation as _ProcessInformation } from 'application.ProcessInformation'; +import { RunningMultiAppInfo as _RunningMultiAppInfo } from 'application.RunningMultiAppInfo'; +import _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'; + +export default namespace appManager { +loadLibrary("ability_app_manager_ani_kit.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 enum PreloadMode { + PRESS_DOWN +} + +export enum ApplicationState { + STATE_CREATE, + STATE_FOREGROUND, + STATE_ACTIVE, + STATE_BACKGROUND, + STATE_DESTROY +} + +export enum ProcessState { + STATE_CREATE, + STATE_FOREGROUND, + STATE_ACTIVE, + STATE_BACKGROUND, + STATE_DESTROY +} + +export 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: number, + mode: PreloadMode, appIndex?: number): void; +export function preloadApplication(bundleName: string, userId: number, mode: PreloadMode, appIndex?: number): Promise{ + let p:Promise = new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError)=>{ + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativePreloadApplication(myCall, bundleName, userId, mode, appIndex); + }); + }); + return p; +} + +export native function nativeGetRunningProcessInformation(callback: AsyncCallbackWrapper>): void; +export function getRunningProcessInformation(callback: AsyncCallback>): void { + let myCall = new AsyncCallbackWrapper>(callback); + taskpool.execute((): void => { + appManager.nativeGetRunningProcessInformation(myCall); + }); +} + +export function getRunningProcessInformation(): Promise> { + let p = new Promise>((resolve:(data:Array)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper>((err: BusinessError, data: Array)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeGetRunningProcessInformation(myCall); + }); + }); + return p; +} + +export native function nativeGetForegroundApplications(callback:AsyncCallbackWrapper>): void; +export function getForegroundApplications(callback: AsyncCallback>): void { + let myCall = new AsyncCallbackWrapper>(callback); + taskpool.execute((): void => { + appManager.nativeGetForegroundApplications(myCall); + }); +} + +export function getForegroundApplications(): Promise> { + let p = new Promise>((resolve:(data:Array)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper>((err: BusinessError, data: Array)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeGetForegroundApplications(myCall); + }); + }); + return p; +} + +export native function nativeGetRunningMultiAppInfo(bundleName: string, callback: AsyncCallbackWrapper): void; +export function getRunningMultiAppInfo(bundleName: string): Promise { + let p = new Promise((resolve:(data: RunningMultiAppInfo)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: RunningMultiAppInfo)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeGetRunningMultiAppInfo(bundleName, myCall); + }); + }); + return p; +} + +export native function nativeGetRunningProcessInfoByBundleName(bundleName: string, callback:AsyncCallbackWrapper>):void; +export function getRunningProcessInfoByBundleName(bundleName: string, callback: AsyncCallback>): void { + let myCall = new AsyncCallbackWrapper>(callback); + taskpool.execute((): void => { + appManager.nativeGetRunningProcessInfoByBundleName(bundleName, myCall); + }); +} + +export function getRunningProcessInfoByBundleName(bundleName: string): Promise> { + let p = new Promise>((resolve:(data: Array)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper>((err: BusinessError, data: Array)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeGetRunningProcessInfoByBundleName(bundleName, myCall); + }); + }); + return p; +} + +export native function nativeGetRunningProcessInfoByBundleNameAndUserId(bundleName: string, + userId: number, callback:AsyncCallbackWrapper>):void; +export function getRunningProcessInfoByBundleName(bundleName: string, userId: number, callback: AsyncCallback>): void { + let myCall = new AsyncCallbackWrapper>(callback); + taskpool.execute((): void => { + appManager.nativeGetRunningProcessInfoByBundleNameAndUserId(bundleName, userId, myCall); + }); +} + +export function getRunningProcessInfoByBundleName(bundleName: string, userId: number): Promise> { + let p = new Promise>((resolve:(data: Array)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper>((err: BusinessError, data: Array)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeGetRunningProcessInfoByBundleNameAndUserId(bundleName, userId, myCall); + }); + }); + return p; +} + +export native function nativeOn(type: string, observer: ApplicationStateObserver, bundleNameList?: Array) : number; +export native function nativeOn(type: string, observer: ApplicationStateObserver) : number; + +export function on(type: 'applicationState', observer: ApplicationStateObserver): number { + return appManager.nativeOn('applicationState', observer); +} + +export function on(type: 'applicationState', observer: ApplicationStateObserver, bundleNameList: Array): number { + return appManager.nativeOn('applicationState', observer, bundleNameList); +} + +export native function nativeOff(type:string, observerId: number, callback: AsyncCallbackWrapper) : void; +export function off(type: 'applicationState', observerId: number, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + appManager.nativeOff(type, observerId, myCall); + }); +} + +export function off(type: 'applicationState', observerId: number): Promise { + let p:Promise = new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError)=>{ + if (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:number)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: number)=>{ + if (err.code == 0) { + resolve(data); + } 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)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: boolean)=>{ + if (err.code == 0) { + resolve(data); + } 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)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: boolean)=>{ + if (err.code == 0) { + resolve(data); + } 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?: number) : 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)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError)=>{ + if (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?: number): Promise { + let p:Promise = new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError)=>{ + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeKillProcessesByBundleName(myCall, bundleName, clearPageStack, appIndex); + }); + }); + return p; +} + +export native function nativeKillProcessWithAccountSync(bundleName: string, accountId: number, callback: AsyncCallbackWrapper) : void; +export function killProcessWithAccount(bundleName: string, accountId: number, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + appManager.nativeKillProcessWithAccountSync(bundleName, accountId, myCall); + }); +} +export function killProcessWithAccount(bundleName: string, accountId: number): Promise { + let p:Promise = new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError)=>{ + if (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: number, clearPageStack: boolean, appIndex?: number) : void; +export function killProcessWithAccount(bundleName: string, accountId: number, + clearPageStack: boolean, appIndex?: number): Promise +{ + let p:Promise = new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError)=>{ + if (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: number, callback: AsyncCallbackWrapper) : void; +export function getProcessMemoryByPid(pid: number, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + appManager.nativeGetProcessMemoryByPid(pid, myCall); + }); +} +export function getProcessMemoryByPid(pid: number): Promise { + let p = new Promise((resolve:(data:number)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: number)=>{ + if (err.code == 0) { + resolve(data); + } 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, data: Array)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeGetRunningProcessInformationByBundleType(bundleType, myCall); + }); + }); + return p; +} + +export native function nativeIsSharedBundleRunning(bundleName: string, versionCode: number, callback: AsyncCallbackWrapper) : void; +export function isSharedBundleRunning(bundleName: string, versionCode: number, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + appManager.nativeIsSharedBundleRunning(bundleName, versionCode, myCall); + }); +} +export function isSharedBundleRunning(bundleName: string, versionCode: number): Promise { + let p = new Promise((resolve:(data:boolean)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: boolean)=>{ + if (err.code == 0) { + resolve(data); + } 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, data: Array)=>{ + if (err.code == 0) { + resolve(data); + } 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)=>{ + if (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?: number) : void; +export function isAppRunning(bundleName: string, appCloneIndex?: number): Promise { + let p = new Promise((resolve:(data:boolean)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: boolean)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + appManager.nativeIsAppRunning(myCall, bundleName, appCloneIndex); + }); + }); + return p; +} + +export native function nativeSetKeepAliveForBundle(bundleName: string, + userId: number, enable: boolean, callback: AsyncCallbackWrapper) : void; +export function setKeepAliveForBundle(bundleName: string, userId: number, enable: boolean): Promise { + let p:Promise = new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError)=>{ + if (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?: number) : void; +export function getKeepAliveBundles(type: KeepAliveAppType, userId?: number): Promise> { + let p = new Promise>((resolve:(data:Array)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper>((err: BusinessError, data: Array)=>{ + if (err.code == 0) { + resolve(data); + } 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 new file mode 100644 index 0000000000000000000000000000000000000000..f32197999a7d6956bbda34864750b4178633358d --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.application.ets @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 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") + export native function nativeCreateModuleContext(context: Context, bundleName: string, moduleName: string, + callback: AsyncCallbackWrapper): void; + + export native function nativeCreateBundleContext(context: Context, bundleName: string, + callback: AsyncCallbackWrapper): void; + + export 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 => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: Context) => { + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + application.nativeCreateModuleContext(context, "", moduleName, myCall); + }); + }); + return p; + } + + export function createModuleContext(context: Context, bundleName: string, moduleName: string): Promise { + let p = + new Promise((resolve: (data: Context) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: Context) => { + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + application.nativeCreateModuleContext(context, bundleName, moduleName, myCall); + }); + }); + return p; + } + + export function createBundleContext(context: Context, bundleName: string): Promise { + let p = + new Promise((resolve: (data: Context) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: Context) => { + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + application.nativeCreateBundleContext(context, bundleName, myCall); + }); + }); + return p; + } + export function getApplicationContext(): ApplicationContext { + return nativeGetApplicationContext(); + } +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.contextConstant.ets b/frameworks/ets/ets/@ohos.app.ability.contextConstant.ets new file mode 100644 index 0000000000000000000000000000000000000000..bfcb768d98c28c8e23690d2ddcbe5b1c1882d7b4 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.contextConstant.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. + */ + +namespace contextConstant { + export enum AreaMode { + EL1 = 0, + EL2 = 1, + EL3 = 2, + EL4 = 3, + EL5 = 4 + } + + export enum ProcessMode { + NEW_PROCESS_ATTACH_TO_PARENT = 1, + NEW_PROCESS_ATTACH_TO_STATUS_BAR_ITEM = 2, + ATTACH_TO_STATUS_BAR_ITEM = 3 + } + + export enum StartupVisibility { + STARTUP_HIDE = 0, + STARTUP_SHOW = 1 + } +} + +export default contextConstant; diff --git a/frameworks/ets/ets/@ohos.app.ability.insightIntent.ets b/frameworks/ets/ets/@ohos.app.ability.insightIntent.ets new file mode 100644 index 0000000000000000000000000000000000000000..cf3b65fefb5a4448e3de670975c219046c738f03 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.insightIntent.ets @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Want from '@ohos.app.ability.Want'; +import wantConstant from '@ohos.app.ability.wantConstant'; + +namespace insightIntent { + + export enum ExecuteMode { + UI_ABILITY_FOREGROUND = 0, + UI_ABILITY_BACKGROUND = 1, + UI_EXTENSION_ABILITY = 2, + SERVICE_EXTENSION_ABILITY = 3, + } + + export interface ExecuteResult { + code: number; + result?: Record; + uris?: Array; + flags?: number; + } + + export class ExecuteResultInner implements ExecuteResult{ + code: number; + result?: Record; + uris?: Array; + flags?: number; + } +} + +export default insightIntent; \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.insightIntentDriver.ets b/frameworks/ets/ets/@ohos.app.ability.insightIntentDriver.ets new file mode 100644 index 0000000000000000000000000000000000000000..2d897c008b8d682e2d91feb2a2c7348d5163d08c --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.insightIntentDriver.ets @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Want from '@ohos.app.ability.Want'; +import wantConstant from '@ohos.app.ability.wantConstant'; +import { BusinessError, AsyncCallback } from '@ohos.base'; +import insightIntent from './@ohos.app.ability.insightIntent'; +import AsyncCallbackWrapper from './utils/AbilityUtils'; + +export default namespace insightIntentDriver { + + loadLibrary("insight_intent_driver_ani_kit.z") + + export interface ExecuteParam { + bundleName: string; + moduleName: string; + abilityName: string; + insightIntentName: string; + insightIntentParam: Record; + executeMode: insightIntent.ExecuteMode; + displayId?: number; + uris?: Array; + flags?: number; + } + + export native function nativeExecuteSync(param: ExecuteParam, + callback: AsyncCallbackWrapper, + isCallback: boolean): void; + + export function execute(param: ExecuteParam, callback: AsyncCallback): void { + let pCallback = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + nativeExecuteSync(param, pCallback, true); + }); + } + + export function execute(param: ExecuteParam): Promise { + let pPromise = new Promise(( + resolve: (data: insightIntent.ExecuteResult) => void, + reject: (error: BusinessError) => void) => { + let pCallback = new AsyncCallbackWrapper(( + err: BusinessError, data: insightIntent.ExecuteResult) => { + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + nativeExecuteSync(param, pCallback, false); + }); + }); + return pPromise; + } +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.ability.wantAgent.ets b/frameworks/ets/ets/@ohos.app.ability.wantAgent.ets new file mode 100644 index 0000000000000000000000000000000000000000..dc084c94b9ad24b73d0631eeb405cdcc87eccb16 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.wantAgent.ets @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BusinessError, AsyncCallback } from '@ohos.base'; +import Want from '@ohos.app.ability.Want'; +import { WantAgentInfo as _WantAgentInfo } from 'wantAgent.wantAgentInfo'; +import { TriggerInfo as _TriggerInfo } from 'wantAgent.triggerInfo'; +import AsyncCallbackWrapper from './utils/AbilityUtils'; + +namespace wantAgent { + loadLibrary("aniwantagent.z"); + + native function nativeGetBundleName(agent: WantAgent, callback: AsyncCallbackWrapper): void; + native function nativeGetUid(agent: WantAgent, callback: AsyncCallbackWrapper): void; + native function nativeGetOperationType(agent: WantAgent, callback: AsyncCallbackWrapper): void; + native function nativeCancel(agent: WantAgent, callback: AsyncCallbackWrapper): void; + native function nativeEqual(agent: WantAgent, otherAgent: WantAgent, callback: AsyncCallbackWrapper): void; + native function nativeTrigger(agent: WantAgent, triggerInfo: TriggerInfo, callback?: AsyncCallbackWrapper): void; + native function nativeGetWant(agent: WantAgent, callback: AsyncCallbackWrapper): void; + native function nativeGetWantAgent(agent: WantAgentInfo, callback: AsyncCallbackWrapper): void; + export function getBundleName(agent: WantAgent, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void =>{ + nativeGetBundleName(agent, myCall); + }); + } + export function getBundleName(agent: WantAgent): Promise { + return new Promise((resolve: (data:string)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: string)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void =>{ + nativeGetBundleName(agent, myCall); + }); + }); + } + export function getUid(agent: WantAgent, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void =>{ + nativeGetUid(agent, myCall); + }); + } + export function getUid(agent: WantAgent): Promise { + return new Promise((resolve: (data:number)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: number)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void =>{ + nativeGetUid(agent, myCall); + }); + }); + } + export function getWant(agent: WantAgent, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void =>{ + nativeGetWant(agent, myCall); + }); + } + export function getWant(agent: WantAgent): Promise { + return new Promise((resolve: (data:Want)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: Want)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void =>{ + nativeGetWant(agent, myCall); + }); + }); + } + export function cancel(agent: WantAgent, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void =>{ + nativeCancel(agent, myCall); + }); + } + export function cancel(agent: WantAgent): Promise { + return new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError)=>{ + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void =>{ + nativeCancel(agent, myCall); + }); + }); + } + export function trigger(agent: WantAgent, triggerInfo: TriggerInfo, callback?: AsyncCallback): void { + taskpool.execute((): void =>{ + if (callback == undefined) { + nativeTrigger(agent, triggerInfo); + } else { + let myCall = new AsyncCallbackWrapper(callback); + nativeTrigger(agent, triggerInfo, myCall); + } + }); + } + export function equal(agent: WantAgent, otherAgent: WantAgent, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void =>{ + nativeEqual(agent, otherAgent, myCall); + }); + } + export function equal(agent: WantAgent, otherAgent: WantAgent): Promise { + return new Promise((resolve: (data:boolean)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: boolean)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void =>{ + nativeEqual(agent, otherAgent, myCall); + }); + }); + } + export function getWantAgent(info: WantAgentInfo, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void =>{ + nativeGetWantAgent(info, myCall); + }); + } + export function getWantAgent(info: WantAgentInfo): Promise { + return new Promise((resolve: (data:WantAgent)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: WantAgent)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void =>{ + nativeGetWantAgent(info, myCall); + }); + }); + } + export function getOperationType(agent: WantAgent, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void =>{ + nativeGetOperationType(agent, myCall); + }); + } + export function getOperationType(agent: WantAgent): Promise { + return new Promise((resolve: (data:number)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: number)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void =>{ + nativeGetOperationType(agent, myCall); + }); + }); + } + + export enum WantAgentFlags { + ONE_TIME_FLAG = 0, + NO_BUILD_FLAG, + CANCEL_PRESENT_FLAG, + UPDATE_PRESENT_FLAG, + CONSTANT_FLAG, + REPLACE_ELEMENT, + REPLACE_ACTION, + REPLACE_URI, + REPLACE_ENTITIES, + REPLACE_BUNDLE + } + export enum OperationType { + UNKNOWN_TYPE = 0, + START_ABILITY, + START_ABILITIES, + START_SERVICE, + SEND_COMMON_EVENT, + START_SERVICE_EXTENSION = 6 + } + export interface CompleteData { + info: WantAgent; + want: Want; + finalCode: number; + finalData: string; + extraInfo?: Record; + } + + class CompleteDataImpl implements CompleteData { + public info: WantAgent; + public want: Want; + public finalCode: number; + public finalData: string; + public extraInfo?: Record; + } + + export type TriggerInfo = _TriggerInfo; + export type WantAgentInfo = _WantAgentInfo; +} +export type WantAgent = object; +export default wantAgent; diff --git a/frameworks/ets/ets/@ohos.app.ability.wantConstant.ets b/frameworks/ets/ets/@ohos.app.ability.wantConstant.ets new file mode 100644 index 0000000000000000000000000000000000000000..9cbcab73129dd1ea31273138ff8b29330e18ddf4 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.wantConstant.ets @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace wantConstant { + export enum Params { + DLP_PARAMS_SANDBOX = 'ohos.dlp.params.sandbox', + DLP_PARAMS_BUNDLE_NAME = 'ohos.dlp.params.bundleName', + DLP_PARAMS_MODULE_NAME = 'ohos.dlp.params.moduleName', + DLP_PARAMS_ABILITY_NAME = 'ohos.dlp.params.abilityName', + DLP_PARAMS_INDEX = 'ohos.dlp.params.index', + HIDE_SENSITIVE_TYPE = 'ohos.media.params.hideSensitiveType', + ABILITY_BACK_TO_OTHER_MISSION_STACK = 'ability.params.backToOtherMissionStack', + ABILITY_RECOVERY_RESTART = 'ohos.ability.params.abilityRecoveryRestart', + CONTENT_TITLE_KEY = 'ohos.extra.param.key.contentTitle', + SHARE_ABSTRACT_KEY = 'ohos.extra.param.key.shareAbstract', + SHARE_URL_KEY = 'ohos.extra.param.key.shareUrl', + SUPPORT_CONTINUE_PAGE_STACK_KEY = 'ohos.extra.param.key.supportContinuePageStack', + SUPPORT_CONTINUE_SOURCE_EXIT_KEY = 'ohos.extra.param.key.supportContinueSourceExit', + ASSERT_FAULT_SESSION_ID = 'ohos.ability.params.asssertFaultSessionId', + SHOW_MODE_KEY = 'ohos.extra.param.key.showMode', + PARAMS_STREAM = 'ability.params.stream', + APP_CLONE_INDEX_KEY = 'ohos.extra.param.key.appCloneIndex', + CALLER_REQUEST_CODE = 'ohos.extra.param.key.callerRequestCode', + PAGE_PATH = 'ohos.param.atomicservice.pagePath', + ROUTER_NAME = 'ohos.param.atomicservice.routerName', + PAGE_SOURCE_FILE = 'ohos.param.atomicservice.pageSourceFile', + BUILD_FUNCTION = 'ohos.param.atomicservice.buildFunction', + SUB_PACKAGE_NAME = 'ohos.param.atomicservice.subpackageName', + APP_INSTANCE_KEY = 'ohos.extra.param.key.appInstance', + CREATE_APP_INSTANCE_KEY = 'ohos.extra.param.key.createAppInstance', + CALLER_APP_CLONE_INDEX = 'ohos.param.callerAppCloneIndex', + LAUNCH_REASON_MESSAGE = 'ohos.params.launchReasonMessage', + } + + export enum Flags { + FLAG_AUTH_READ_URI_PERMISSION = 0x00000001, + FLAG_AUTH_WRITE_URI_PERMISSION = 0x00000002, + FLAG_AUTH_PERSISTABLE_URI_PERMISSION = 0x00000040, + FLAG_INSTALL_ON_DEMAND = 0x00000800, + FLAG_ABILITY_ON_COLLABORATE = 0x00002000, + FLAG_START_WITHOUT_TIPS = 0x40000000 + } + + export enum ShowMode { + WINDOW = 0, + EMBEDDED_FULL = 1 + } +} + +export default wantConstant; diff --git a/frameworks/ets/ets/@ohos.application.testRunner.ets b/frameworks/ets/ets/@ohos.application.testRunner.ets new file mode 100644 index 0000000000000000000000000000000000000000..656882170ec8ce557fcb33acc3c8e4dad77abfc8 --- /dev/null +++ b/frameworks/ets/ets/@ohos.application.testRunner.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default interface TestRunner { + onPrepare(): void; + + onRun(): void; + } + \ No newline at end of file diff --git a/frameworks/ets/ets/BUILD.gn b/frameworks/ets/ets/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..e692229ae8e6afface32d379d3c467c820e8081c --- /dev/null +++ b/frameworks/ets/ets/BUILD.gn @@ -0,0 +1,1010 @@ +# 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") + +generate_static_abc("ability_runtime_want_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.Want.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_want_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_want_abc_etc") { + source = "$target_out_dir/ability_runtime_want_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_want_abc" ] +} + +generate_static_abc("ability_runtime_want_constant_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.wantConstant.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_want_constant_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_want_constant_abc_etc") { + source = "$target_out_dir/ability_runtime_want_constant_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_want_constant_abc" ] +} + +generate_static_abc("ability_runtime_configuration_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.Configuration.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_configuration_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_configuration_abc_etc") { + source = "$target_out_dir/ability_runtime_configuration_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_configuration_abc" ] +} + +generate_static_abc("ability_runtime_configuration_constant_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.ConfigurationConstant.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_configuration_constant_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_configuration_constant_abc_etc") { + source = "$target_out_dir/ability_runtime_configuration_constant_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_configuration_constant_abc" ] +} + +generate_static_abc("ability_runtime_ability_constant_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.AbilityConstant.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_ability_constant_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_constant_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_constant_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_constant_abc" ] +} + +generate_static_abc("ability_runtime_abilityResult_abc") { + base_url = "./" + files = [ "./ability/abilityResult.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_abilityResult_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_abilityResult_abc_etc") { + source = "$target_out_dir/ability_runtime_abilityResult_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_abilityResult_abc" ] +} + +generate_static_abc("ability_runtime_context_abc") { + base_url = "./" + files = [ "./application/Context.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_context_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_context_abc_etc") { + source = "$target_out_dir/ability_runtime_context_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_context_abc" ] +} + +generate_static_abc("ability_runtime_base_context_abc") { + base_url = "./" + files = [ "./application/BaseContext.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_base_context_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_base_context_abc_etc") { + source = "$target_out_dir/ability_runtime_base_context_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_base_context_abc" ] +} + +generate_static_abc("ability_runtime_application_context_abc") { + base_url = "./" + files = [ "./application/ApplicationContext.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_application_context_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_application_context_abc_etc") { + source = "$target_out_dir/ability_runtime_application_context_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_application_context_abc" ] +} + +generate_static_abc("ability_runtime_event_hub_abc") { + base_url = "./" + files = [ "./application/EventHub.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_event_hub_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_event_hub_abc_etc") { + source = "$target_out_dir/ability_runtime_event_hub_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_event_hub_abc" ] +} + +generate_static_abc("ability_runtime_extension_context_abc") { + base_url = "./" + files = [ "./application/ExtensionContext.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_extension_context_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_extension_context_abc_etc") { + source = "$target_out_dir/ability_runtime_extension_context_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_extension_context_abc" ] +} + +generate_static_abc("ability_runtime_ability_stage_context_abc") { + base_url = "./" + files = [ "./application/AbilityStageContext.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_ability_stage_context_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_stage_context_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_stage_context_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_stage_context_abc" ] +} + +generate_static_abc("ability_runtime_ability_stage_monitor_abc") { + base_url = "./" + files = [ "./application/AbilityStageMonitor.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_ability_stage_monitor_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_stage_monitor_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_stage_monitor_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_stage_monitor_abc" ] +} + +generate_static_abc("ability_runtime_ability_stage_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.AbilityStage.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_ability_stage_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_stage_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_stage_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_stage_abc" ] +} + +generate_static_abc("ability_runtime_ability_context_constant_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.contextConstant.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_ability_context_constant_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_context_constant_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_context_constant_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_context_constant_abc" ] +} + +generate_static_abc("ability_runtime_ui_ability_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.UIAbility.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_ui_ability_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ui_ability_abc_etc") { + source = "$target_out_dir/ability_runtime_ui_ability_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ui_ability_abc" ] +} + +generate_static_abc("ability_runtime_ui_ability_context_abc") { + base_url = "./" + files = [ "./application/UIAbilityContext.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_ui_ability_context_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ui_ability_context_abc_etc") { + source = "$target_out_dir/ability_runtime_ui_ability_context_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ui_ability_context_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_start_options_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.StartOptions.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_start_options_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_start_options_abc_etc") { + source = "$target_out_dir/ability_runtime_start_options_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_start_options_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_ability_state_data_abc") { + base_url = "./" + files = [ "./application/AbilityStateData.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_ability_state_data_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_state_data_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_state_data_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_state_data_abc" ] +} + +generate_static_abc("ability_runtime_shell_cmd_result_abc") { + base_url = "./" + files = [ "./application/shellCmdResult.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_shell_cmd_result_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_shell_cmd_result_abc_etc") { + source = "$target_out_dir/ability_runtime_shell_cmd_result_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_shell_cmd_result_abc" ] +} + +generate_static_abc("ability_runtime_want_agent_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.wantAgent.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_want_agent_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_want_agent_abc_etc") { + source = "$target_out_dir/ability_runtime_want_agent_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_want_agent_abc" ] +} + +generate_static_abc("ability_runtime_trigger_info_abc") { + base_url = "./" + files = [ "./wantAgent/triggerInfo.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_trigger_info_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_trigger_info_abc_etc") { + source = "$target_out_dir/ability_runtime_trigger_info_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_trigger_info_abc" ] +} + +generate_static_abc("ability_runtime_want_agent_info_abc") { + base_url = "./" + files = [ "./wantAgent/wantAgentInfo.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_want_agent_info_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_want_agent_info_abc_etc") { + source = "$target_out_dir/ability_runtime_want_agent_info_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_want_agent_info_abc" ] +} + +generate_static_abc("ability_runtime_ability_utils_abc") { + base_url = "./" + files = [ "./utils/AbilityUtils.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_ability_utils_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_utils_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_utils_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_utils_abc" ] +} + +generate_static_abc("ability_ability_manager_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.abilityManager.ets" ] + + dst_file = "$target_out_dir/ability_ability_manager.abc" + out_puts = [ "$target_out_dir/ability_ability_manager.abc" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_ability_manager.abc" +} + +ohos_prebuilt_etc("ability_ability_manager_abc_etc") { + source = "$target_out_dir/ability_ability_manager.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_ability_manager_abc" ] +} + +generate_static_abc("ability_ability_application_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.application.ets" ] + + dst_file = "$target_out_dir/ability_ability_application.abc" + out_puts = [ "$target_out_dir/ability_ability_application.abc" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_ability_application.abc" +} + +ohos_prebuilt_etc("ability_ability_application_abc_etc") { + source = "$target_out_dir/ability_ability_application.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_ability_application_abc" ] +} + +generate_static_abc("service_extension_ability") { + base_url = "./" + files = [ + "./@ohos.app.ability.ServiceExtensionAbility.ets", + "./application/ServiceExtensionContext.ets", + ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/service_extension_ability.abc" +} + +ohos_prebuilt_etc("service_extension_ability_abc_etc") { + source = "$target_out_dir/service_extension_ability.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":service_extension_ability" ] +} + +generate_static_abc("ability_runtime_app_state_data_abc") { + base_url = "./" + files = [ "./application/AppStateData.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_app_state_data_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_app_state_data_abc_etc") { + source = "$target_out_dir/ability_runtime_app_state_data_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_app_state_data_abc" ] +} + +generate_static_abc("ability_runtime_process_data_abc") { + base_url = "./" + files = [ "./application/ProcessData.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_process_data_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_process_data_abc_etc") { + source = "$target_out_dir/ability_runtime_process_data_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_process_data_abc" ] +} + +generate_static_abc("ability_runtime_process_information_abc") { + base_url = "./" + files = [ "./application/ProcessInformation.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_process_information_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_process_information_abc_etc") { + source = "$target_out_dir/ability_runtime_process_information_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_process_information_abc" ] +} + +generate_static_abc("ability_runtime_running_app_clone_abc") { + base_url = "./" + files = [ "./application/RunningAppClone.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_running_app_clone_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_running_app_clone_abc_etc") { + source = "$target_out_dir/ability_runtime_running_app_clone_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_running_app_clone_abc" ] +} + +generate_static_abc("ability_runtime_running_multi_appinfo_abc") { + base_url = "./" + files = [ "./application/RunningMultiAppInfo.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_running_multi_appinfo_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_running_multi_appinfo_abc_etc") { + source = "$target_out_dir/ability_runtime_running_multi_appinfo_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_running_multi_appinfo_abc" ] +} + +generate_static_abc("ability_runtime_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" ] +} + +generate_static_abc("ability_runtime_multi_app_mode_abc") { + base_url = "./" + files = [ "./application/MultiAppMode.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_multi_app_mode_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_multi_app_mode_abc_etc") { + source = "$target_out_dir/ability_runtime_multi_app_mode_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_multi_app_mode_abc" ] +} + +generate_static_abc("ability_runtime_app_manager_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.appManager.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_app_manager_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_app_manager_abc_etc") { + source = "$target_out_dir/ability_runtime_app_manager_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_app_manager_abc" ] +} + +generate_static_abc("ui_extension_ability_ani_abc") { + base_url = "./" + + files = [ + "./application/UIExtensionContext.ets", + "./@ohos.app.ability.UIExtensionAbility.ets", + "./@ohos.app.ability.UIExtensionContentSession.ets", + ] + + dst_file = "$target_out_dir/ui_extension_ability_ani.abc" + out_puts = [ "$target_out_dir/ui_extension_ability_ani.abc" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ui_extension_ability_ani.abc" +} + +ohos_prebuilt_etc("ui_extension_ability_ani_etc") { + source = "$target_out_dir/ui_extension_ability_ani.abc" + deps = [ ":ui_extension_ability_ani_abc" ] + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" +} + +generate_static_abc("ability_runtime_ability_caller_abc") { + base_url = "./" + files = [ "./caller/Caller.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_ability_caller_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_caller_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_caller_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_caller_abc" ] +} + +generate_static_abc("ability_runtime_ability_callee_abc") { + base_url = "./" + files = [ "./callee/Callee.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_runtime_ability_callee_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_ability_callee_abc_etc") { + source = "$target_out_dir/ability_runtime_ability_callee_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_ability_callee_abc" ] +} + +generate_static_abc("ability_delegator_abc") { + base_url = "./" + files = [ "./application/AbilityDelegator.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_delegator_abc.abc" +} + +ohos_prebuilt_etc("ability_delegator_abc_etc") { + source = "$target_out_dir/ability_delegator_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_delegator_abc" ] +} + +generate_static_abc("ability_delegator_args_abc") { + base_url = "./" + files = [ "./application/abilityDelegatorArgs.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_delegator_args_abc.abc" +} + +ohos_prebuilt_etc("ability_delegator_args_abc_etc") { + source = "$target_out_dir/ability_delegator_args_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_delegator_args_abc" ] +} + +generate_static_abc("ability_delegator_ability_monitor_abc") { + base_url = "." + files = [ "./application/AbilityMonitor.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_delegator_ability_monitor_abc.abc" +} + +ohos_prebuilt_etc("ability_delegator_ability_monitor_abc_etc") { + source = "$target_out_dir/ability_delegator_ability_monitor_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_delegator_ability_monitor_abc" ] +} + +generate_static_abc("ability_delegator_registry_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.abilityDelegatorRegistry.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_delegator_registry_abc.abc" +} + +ohos_prebuilt_etc("ability_delegator_registry_abc_etc") { + source = "$target_out_dir/ability_delegator_registry_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_delegator_registry_abc" ] +} + +generate_static_abc("ability_delegator_application_testRunner_abc") { + base_url = "./" + files = [ "./@ohos.application.testRunner.ets" ] + + is_boot_abc = "True" + device_dst_file = + "/system/framework/ability_delegator_application_testRunner_abc.abc" +} + +ohos_prebuilt_etc("ability_delegator_application_testRunner_abc_etc") { + source = "$target_out_dir/ability_delegator_application_testRunner_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_delegator_application_testRunner_abc" ] +} + +generate_static_abc("ability_runtime_OpenLink_Options_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.OpenLinkOptions.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_OpenLink_Options_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_OpenLink_Options_abc_etc") { + source = "$target_out_dir/ability_runtime_OpenLink_Options_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_OpenLink_Options_abc" ] +} + +generate_static_abc("ability_runtime_insight_intent_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.insightIntent.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_insight_intent_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_insight_intent_abc_etc") { + source = "$target_out_dir/ability_runtime_insight_intent_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_insight_intent_abc" ] +} + +generate_static_abc("ability_runtime_insight_intent_context_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.InsightIntentContext.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_insight_intent_context_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_insight_intent_context_abc_etc") { + source = "$target_out_dir/ability_runtime_insight_intent_context_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_insight_intent_context_abc" ] +} + +generate_static_abc("ability_runtime_insight_intent_driver_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.insightIntentDriver.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_insight_intent_driver_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_insight_intent_driver_abc_etc") { + source = "$target_out_dir/ability_runtime_insight_intent_driver_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_insight_intent_driver_abc" ] +} + +generate_static_abc("ability_runtime_insight_intent_executor_abc") { + base_url = "./" + files = [ "./@ohos.app.ability.InsightIntentExecutor.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_insight_intent_executor_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_insight_intent_executor_abc_etc") { + source = "$target_out_dir/ability_runtime_insight_intent_executor_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_insight_intent_executor_abc" ] +} + +generate_static_abc("ability_runtime_auto_fill_type_abc") { + base_url = "./" + files = [ "./application/AutoFillType.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_auto_fill_type_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_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_auto_fill_type_abc_etc") { + source = "$target_out_dir/ability_runtime_auto_fill_type_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_auto_fill_type_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_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_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" ] +} + +group("ets_packages") { + deps = [ + ":ability_ability_application_abc_etc", + ":ability_ability_manager_abc_etc", + ":ability_delegator_abc_etc", + ":ability_delegator_ability_monitor_abc_etc", + ":ability_delegator_application_testRunner_abc_etc", + ":ability_delegator_args_abc_etc", + ":ability_delegator_registry_abc_etc", + ":ability_runtime_abilityResult_abc_etc", + ":ability_runtime_ability_callee_abc_etc", + ":ability_runtime_ability_caller_abc_etc", + ":ability_runtime_ability_constant_abc_etc", + ":ability_runtime_ability_context_constant_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_auto_fill_type_abc_etc", + ":ability_runtime_base_context_abc_etc", + ":ability_runtime_configuration_abc_etc", + ":ability_runtime_configuration_constant_abc_etc", + ":ability_runtime_context_abc_etc", + ":ability_runtime_custom_data_abc_etc", + ":ability_runtime_environment_callback_abc_etc", + ":ability_runtime_event_hub_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_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", + ":ability_runtime_ui_ability_abc_etc", + ":ability_runtime_ui_ability_context_abc_etc", + ":ability_runtime_want_abc_etc", + ":ability_runtime_want_agent_abc_etc", + ":ability_runtime_want_agent_info_abc_etc", + ":ability_runtime_want_constant_abc_etc", + ":service_extension_ability_abc_etc", + ":ui_extension_ability_ani_etc", + ":ability_runtime_OpenLink_Options_abc_etc", + ":ability_runtime_AbilityRunningInfo_abc_etc", + ] +} diff --git a/frameworks/ets/ets/ability/abilityResult.ets b/frameworks/ets/ets/ability/abilityResult.ets new file mode 100644 index 0000000000000000000000000000000000000000..0c7f53b5751854e244577f4edb5323083b713377 --- /dev/null +++ b/frameworks/ets/ets/ability/abilityResult.ets @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Want from '@ohos.app.ability.Want'; + +export interface AbilityResult { + resultCode: number; + want?: Want; +} + +class AbilityResultInner implements AbilityResult { + resultCode: number; + want?: Want | undefined = {}; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/AbilityDelegator.ets b/frameworks/ets/ets/application/AbilityDelegator.ets new file mode 100644 index 0000000000000000000000000000000000000000..e8ee2156abbc1d78bb85431f7f56e3e446c57ff2 --- /dev/null +++ b/frameworks/ets/ets/application/AbilityDelegator.ets @@ -0,0 +1,463 @@ +/* + * 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 { AbilityMonitor } from 'application.AbilityMonitor'; +import Want from '@ohos.app.ability.Want'; +import Context from 'application.Context'; +import { BusinessError, AsyncCallback } from '@ohos.base'; +import { ShellCmdResult } from 'application.shellCmdResult'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import AsyncCallbackWrapper from '../utils/AbilityUtils'; +import { AbilityStageMonitor } from 'application.AbilityStageMonitor'; +import AbilityStage from '@ohos.app.ability.AbilityStage'; + +export interface AbilityDelegator { + printSync(msg: string): void; + + getAppContext(): Context; + + finishTest(msg: string, code: number, callback: AsyncCallback): void; + + finishTest(msg: string, code: number): Promise; + + executeShellCommand(cmd: String, callback: AsyncCallback): void; + + executeShellCommand(cmd: String, timeoutSecs: number, callback: AsyncCallback): void; + + executeShellCommand(cmd: string, timeoutSecs?: number): Promise; + + addAbilityMonitor(monitor: AbilityMonitor, callback: AsyncCallback): void; + addAbilityMonitor(monitor: AbilityMonitor): Promise; + + addAbilityMonitorSync(monitor: AbilityMonitor): void; + + removeAbilityMonitor(monitor: AbilityMonitor, callback: AsyncCallback): void + removeAbilityMonitor(monitor: AbilityMonitor): Promise; + + removeAbilityMonitorSync(monitor: AbilityMonitor): void; + + waitAbilityMonitor(monitor: AbilityMonitor, callback: AsyncCallback): void; + waitAbilityMonitor(monitor: AbilityMonitor, timeout: number, callback: AsyncCallback): void; + waitAbilityMonitor(monitor: AbilityMonitor, timeout?: number): Promise; + + addAbilityStageMonitor(monitor: AbilityStageMonitor, callback: AsyncCallback): void; + addAbilityStageMonitor(monitor: AbilityStageMonitor): Promise; + + addAbilityStageMonitorSync(monitor: AbilityStageMonitor): void; + + removeAbilityStageMonitor(monitor: AbilityStageMonitor, callback: AsyncCallback): void; + removeAbilityStageMonitor(monitor: AbilityStageMonitor): Promise; + + removeAbilityStageMonitorSync(monitor: AbilityStageMonitor): void; + + waitAbilityStageMonitor(monitor: AbilityStageMonitor, callback: AsyncCallback): void; + waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout: number, callback: AsyncCallback): void; + waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout?: number): Promise; + + doAbilityForeground(ability: UIAbility, callback: AsyncCallback): void; + doAbilityForeground(ability: UIAbility): Promise; + + doAbilityBackground(ability: UIAbility, callback: AsyncCallback): void; + doAbilityBackground(ability: UIAbility): Promise; + + print(msg: string, callback: AsyncCallback): void; + print(msg: string): Promise; + + getAbilityState(ability: UIAbility): number; + + setMockList(mockList: Record): void; + + startAbility(want: Want, callback: AsyncCallback): void; + startAbility(want: Want): Promise; + + getCurrentTopAbility(callback: AsyncCallback); + getCurrentTopAbility(): Promise; +} + +class AbilityDelegatorInner implements AbilityDelegator { + public native nativeGetCurrentTopAbility(callback: AsyncCallbackWrapper): UIAbility; + + public native printSync(msg: string): void; + + public native getAppContext(): Context; + + public native nativeFinishTest(msg: String, code: number, callback: AsyncCallbackWrapper): void; + + public native nativeExecuteShellCommand(cmd: string, timeoutSecs: number, + callback: AsyncCallbackWrapper): void; + + public native nativeAddAbilityMonitor(monitor: AbilityMonitor, callback: AsyncCallbackWrapper): void; + public native addAbilityMonitorSync(monitor: AbilityMonitor): void; + + public native removeAbilityMonitorAsync(monitor: AbilityMonitor, callback: AsyncCallbackWrapper): void; + public native removeAbilityMonitorSync(monitor: AbilityMonitor): void; + + public native waitAbilityMonitorAsync(monitor: AbilityMonitor, timeout: number, + callback: AsyncCallbackWrapper): void; + + public native addAbilityStageMonitorAsync(monitor: AbilityStageMonitor, callback: AsyncCallbackWrapper): void; + public native addAbilityStageMonitorSync(monitor: AbilityStageMonitor): void; + + public native removeAbilityStageMonitorAsync(monitor: AbilityStageMonitor, callback: AsyncCallbackWrapper): void; + public native removeAbilityStageMonitorSync(monitor: AbilityStageMonitor): void; + + public native waitAbilityStageMonitorAsync(monitor: AbilityStageMonitor, timeout: number, + callback: AsyncCallbackWrapper): void; + + public native doAbilityForegroundAsync(ability: UIAbility, callback: AsyncCallbackWrapper): void; + + public native doAbilityBackgroundAsync(ability: UIAbility, callback: AsyncCallbackWrapper): void; + + public native printAsync(msg: string, callback: AsyncCallbackWrapper): void; + + public native setMockList(mockList: Record): void; + + public native getAbilityState(ability: UIAbility): number; + + public native nativeStartAbility(want: Want, callback: AsyncCallbackWrapper): void; + + finishTest(msg: string, code: number, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeFinishTest(msg, code, myCall); + }); + } + finishTest(msg: string, code: number): Promise { + let p: Promise = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeFinishTest(msg, code, myCall); + }); + }); + return p; + } + + executeShellCommand(cmd: string, callback: AsyncCallback): void { + let timeoutSecs = 0; + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeExecuteShellCommand(cmd, timeoutSecs, myCall); + }); + } + executeShellCommand(cmd: string, timeoutSecs: number, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeExecuteShellCommand(cmd, timeoutSecs, myCall); + }); + } + executeShellCommand(cmd: string, timeoutSecs?: number): Promise { + let p = new Promise((resolve: (data: ShellCmdResult) => void, + reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: ShellCmdResult) => { + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + if (timeoutSecs == null) { + this.nativeExecuteShellCommand(cmd, 0, myCall); + } else { + this.nativeExecuteShellCommand(cmd, timeoutSecs as double, myCall); + } + }); + }); + return p; + } + + addAbilityMonitor(monitor: AbilityMonitor, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeAddAbilityMonitor(monitor, myCall); + }); + } + addAbilityMonitor(monitor: AbilityMonitor): Promise { + let p = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeAddAbilityMonitor(monitor, myCall); + }); + }); + return p; + } + + removeAbilityMonitor(monitor: AbilityMonitor, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.removeAbilityMonitorAsync(monitor, myCall); + }); + } + removeAbilityMonitor(monitor: AbilityMonitor): Promise { + let p = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.removeAbilityMonitorAsync(monitor, myCall); + }); + }); + return p; + } + + waitAbilityMonitor(monitor: AbilityMonitor, callback: AsyncCallback): void { + let timeout = -1; + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.waitAbilityMonitorAsync(monitor, timeout, myCall); + }); + } + waitAbilityMonitor(monitor: AbilityMonitor, timeout: number, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.waitAbilityMonitorAsync(monitor, timeout, myCall); + }); + } + waitAbilityMonitor(monitor: AbilityMonitor, timeout?: number): Promise { + let p = new Promise((resolve: (data: UIAbility) => void, + reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: UIAbility) => { + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + if (timeout == null) { + this.waitAbilityMonitorAsync(monitor, -1, myCall); + } else { + this.waitAbilityMonitorAsync(monitor, timeout as double, myCall); + } + }); + }); + return p; + } + + addAbilityStageMonitor(monitor: AbilityStageMonitor, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.addAbilityStageMonitorAsync(monitor, myCall); + }); + } + addAbilityStageMonitor(monitor: AbilityStageMonitor): Promise { + let p = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.addAbilityStageMonitorAsync(monitor, myCall); + }); + }); + return p; + } + + removeAbilityStageMonitor(monitor: AbilityStageMonitor, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.removeAbilityStageMonitorAsync(monitor, myCall); + }); + } + removeAbilityStageMonitor(monitor: AbilityStageMonitor): Promise { + let p = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.removeAbilityStageMonitorAsync(monitor, myCall); + }); + }); + return p; + } + + waitAbilityStageMonitor(monitor: AbilityStageMonitor, callback: AsyncCallback): void { + let timeout = -1; + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.waitAbilityStageMonitorAsync(monitor, timeout, myCall); + }); + } + waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout: number, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.waitAbilityStageMonitorAsync(monitor, timeout, myCall); + }); + } + waitAbilityStageMonitor(monitor: AbilityStageMonitor, timeout?: number): Promise { + let p = new Promise((resolve: (data: AbilityStage) => void, + reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: AbilityStage) => { + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + if (timeout == null) { + this.waitAbilityStageMonitorAsync(monitor, -1, myCall); + } else { + this.waitAbilityStageMonitorAsync(monitor, timeout as double, myCall); + } + }); + }); + return p; + } + + doAbilityForeground(ability: UIAbility, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.doAbilityForegroundAsync(ability, myCall); + }); + } + doAbilityForeground(ability: UIAbility): Promise { + let p: Promise = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.doAbilityForegroundAsync(ability, myCall); + }); + }); + return p; + } + + doAbilityBackground(ability: UIAbility, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.doAbilityBackgroundAsync(ability, myCall); + }); + } + doAbilityBackground(ability: UIAbility): Promise { + let p: Promise = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.doAbilityBackgroundAsync(ability, myCall); + }); + }); + return p; + } + + print(msg: string, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.printAsync(msg, myCall); + }); + } + print(msg: string): Promise { + let p: Promise = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.printAsync(msg, myCall); + }); + }); + return p; + } + + startAbility(want: Want, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartAbility(want, myCall); + }); + } + startAbility(want: Want): Promise { + let p: Promise = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeStartAbility(want, myCall); + }); + }); + return p; + } + + getCurrentTopAbility(callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + let p = taskpool.execute((): UIAbility => { + this.nativeGetCurrentTopAbility(myCall) + }); + console.log("getCurrentTopAbility callback2_04"); + } + getCurrentTopAbility(): Promise { + let p: Promise = new Promise((resolve: (v: UIAbility) => void, reject: (error: Error) => void) => { + console.log("getCurrentTopAbility promise1_01"); + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): UIAbility => { + this.nativeGetCurrentTopAbility(myCall); + }); + }); + return p; + } +} diff --git a/frameworks/ets/ets/application/AbilityMonitor.ets b/frameworks/ets/ets/application/AbilityMonitor.ets new file mode 100644 index 0000000000000000000000000000000000000000..cccdd0e60f4d64fc4afd2e005a54fc4de848cf12 --- /dev/null +++ b/frameworks/ets/ets/application/AbilityMonitor.ets @@ -0,0 +1,48 @@ +/* + * 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 UIAbility from '@ohos.app.ability.UIAbility'; + +export default interface AbilityMonitor { + + moduleName: string; + abilityName: string; + onAbilityCreate: (ability: UIAbility) => void; + onAbilityForeground: (ability: UIAbility) => void; + onAbilityBackground: (ability: UIAbility) => void; + onAbilityDestroy: (ability: UIAbility) => void; + onWindowStageCreate: (ability: UIAbility) => void; + onWindowStageRestore: (ability: UIAbility) => void; + onWindowStageDestroy: (ability: UIAbility) => void; + +} + +class AbilityMonitorInner implements AbilityMonitor { + moduleName: string = ""; + abilityName: string = ""; + onAbilityCreate: (ability: UIAbility) => void = (ability: UIAbility) => { + }; + onAbilityForeground: (ability: UIAbility) => void = (ability: UIAbility) => { + }; + onAbilityBackground: (ability: UIAbility) => void = (ability: UIAbility) => { + }; + onAbilityDestroy: (ability: UIAbility) => void = (ability: UIAbility) => { + }; + onWindowStageCreate: (ability: UIAbility) => void = (ability: UIAbility) => { + }; + onWindowStageRestore: (ability: UIAbility) => void = (ability: UIAbility) => { + }; + onWindowStageDestroy: (ability: UIAbility) => void = (ability: UIAbility) => { + }; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/AbilityRunningInfo.ets b/frameworks/ets/ets/application/AbilityRunningInfo.ets new file mode 100644 index 0000000000000000000000000000000000000000..7ae0768d2e406795811e65cf1c21026ea6ea26c5 --- /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: number; + uid: number; + processName: string; + startTime: number; + abilityState: abilityManager.AbilityState; +} + +class AbilityRunningInfoImpl implements AbilityRunningInfo { + ability: ElementName = {}; + pid: number; + uid: number; + processName: string = ''; + startTime: number; + abilityState: abilityManager.AbilityState = abilityManager.AbilityState.INITIAL; +} diff --git a/frameworks/ets/ets/application/AbilityStageContext.ets b/frameworks/ets/ets/application/AbilityStageContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..bd7169c6459e136733e359f70ec496f497629297 --- /dev/null +++ b/frameworks/ets/ets/application/AbilityStageContext.ets @@ -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. + */ + +import Context from 'application.Context' +import { Configuration } from '@ohos.app.ability.Configuration' +import { HapModuleInfo } from 'bundleManager.HapModuleInfo'; + +// remove local declaration after Any type is supported +type Any = Object | null | undefined + +export default class AbilityStageContext extends Context { + static { + loadLibrary("context_ani"); + loadLibrary("ability_stage_context_ani_kit.z"); + } + config?: Configuration; + currentHapModuleInfo: HapModuleInfo; + native constructor(); + constructor(currentHapModuleInfo: HapModuleInfo) { + super(); + this.currentHapModuleInfo = currentHapModuleInfo; + } + + private static native nativeTransferStatic(input: ESValue): Object; + private static native nativeTransferDynamic(input: Object): ESValue; + + static transferStatic(input: Any): Object { + return AbilityStageContext.nativeTransferStatic(ESValue.wrap(input)); + } + + static transferDynamic(input: Object): Any { + return AbilityStageContext.nativeTransferDynamic(input).unwrap(); + } +} diff --git a/frameworks/ets/ets/application/AbilityStageMonitor.ets b/frameworks/ets/ets/application/AbilityStageMonitor.ets new file mode 100644 index 0000000000000000000000000000000000000000..62825a9a188d3ac13064ff7f735ce38b1554ec65 --- /dev/null +++ b/frameworks/ets/ets/application/AbilityStageMonitor.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default interface AbilityStageMonitor { + moduleName: string; + srcEntrance: string; +} + +class AbilityStageMonitorInner implements AbilityStageMonitor { + public moduleName: string = ''; + public srcEntrance: string = ''; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/AbilityStartCallback.ets b/frameworks/ets/ets/application/AbilityStartCallback.ets new file mode 100644 index 0000000000000000000000000000000000000000..a444eb813a529bf6b3a69c40dfb97f958227a3a1 --- /dev/null +++ b/frameworks/ets/ets/application/AbilityStartCallback.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 { AbilityResult } from 'ability.abilityResult'; + + export default class AbilityStartCallback { + onError(code: int, name: string, message: string) {} + onResult?:(parameter: AbilityResult)=>void = (parameter:AbilityResult) => {} +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/AbilityStateData.ets b/frameworks/ets/ets/application/AbilityStateData.ets new file mode 100644 index 0000000000000000000000000000000000000000..256b244426b9f9f8e8b6071852ed3adcc03b92b5 --- /dev/null +++ b/frameworks/ets/ets/application/AbilityStateData.ets @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default class AbilityStateData { + readonly moduleName: string = ''; + readonly bundleName: string = ''; + readonly abilityName: string = ''; + readonly pid: int; + readonly uid: int; + readonly state: int; + readonly abilityType: int; + readonly isAtomicService: boolean; + readonly appCloneIndex?: int; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/AppStateData.ets b/frameworks/ets/ets/application/AppStateData.ets new file mode 100644 index 0000000000000000000000000000000000000000..ca1f7eff420657335d9535807cd4d5a28410e9f6 --- /dev/null +++ b/frameworks/ets/ets/application/AppStateData.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export default class AppStateData { + bundleName: string = ''; + uid: number; + state: number; + isSplitScreenMode: boolean; + isFloatingWindowMode: boolean; +} diff --git a/frameworks/ets/ets/application/ApplicationContext.ets b/frameworks/ets/ets/application/ApplicationContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..cdba8ab952af261866576c8c18455972a99dde0c --- /dev/null +++ b/frameworks/ets/ets/application/ApplicationContext.ets @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Context from 'application.Context' +import EnvironmentCallback from '@ohos.app.ability.EnvironmentCallback'; +import { BusinessError, AsyncCallback } from '@ohos.base' +import AsyncCallbackWrapper from '../utils/AbilityUtils'; +import type ApplicationStateChangeCallback from '@ohos.app.ability.ApplicationStateChangeCallback'; +import Want from '@ohos.app.ability.Want'; +import { ProcessInformation } from 'application.ProcessInformation'; +import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant'; + +// remove local declaration after Any type is supported +type Any = Object | null | undefined + +export default class ApplicationContext extends Context { + static { + loadLibrary("application_context_ani_kit.z"); + } + + public native nativekillAllProcessesSync(clearPageStack: boolean, callback: AsyncCallbackWrapper): void; + public native nativeOnSync(type: 'environment', callback: EnvironmentCallback): number; + public native nativeOffSync(type: 'environment', callbackId: number, callback: AsyncCallbackWrapper): void; + public native nativepreloadUIExtensionAbilitySync(want: Want, callback: AsyncCallbackWrapper): void; + public native setSupportedProcessCacheSync(isSupported: boolean): void; + public native nativegetRunningProcessInformation(callback: AsyncCallbackWrapper>): void; + public native nativeclearUpApplicationData(callback: AsyncCallbackWrapper): void; + public native nativesetLanguage(language: string): void; + public native nativesetFontSizeScale(fontSizeScale: number): void; + public native nativesetColorMode(colorMode: ConfigurationConstant.ColorMode): void; + public native nativesetFont(font: string): void; + public native nativerestartApp(want: Want): void; + public native nativeOnApplicationStateChangeSync(callback: ApplicationStateChangeCallback): void; + public native nativeOffApplicationStateChangeSync(callback?: ApplicationStateChangeCallback): void; + public native nativegetCurrentAppCloneIndex(): number; + public native nativegetCurrentInstanceKey(): string; + private static native nativeTransferStatic(input: ESValue): Object; + private static native nativeTransferDynamic(input: Object): ESValue; + + setSupportedProcessCache(isSupported: boolean): void { + taskpool.execute((): void => { + this.setSupportedProcessCacheSync(isSupported); + }); + } + + on(type: 'applicationStateChange', callback: ApplicationStateChangeCallback): void { + this.nativeOnApplicationStateChangeSync(callback); + } + + off(type: 'applicationStateChange', callback?: ApplicationStateChangeCallback): void { + this.nativeOffApplicationStateChangeSync(callback); + } + + on(type: 'environment', callback: EnvironmentCallback): number { + return this.nativeOnSync(type, callback); + } + + off(type: 'environment', callbackId: number, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeOffSync(type, callbackId, myCall); + }); + } + + off(type: 'environment', callbackId: number): Promise { + let p = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeOffSync(type, callbackId, myCall); + }); + }); + return p; + } + + preloadUIExtensionAbility(want: Want): Promise { + let p = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativepreloadUIExtensionAbilitySync(want, myCall); + }); + }); + return p; + } + + killAllProcesses(callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativekillAllProcessesSync(false, myCall); + }); + } + + killAllProcesses(): Promise { + let p = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativekillAllProcessesSync(false, myCall); + }); + }); + return p; + } + + killAllProcesses(clearPageStack: boolean): Promise { + let p = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativekillAllProcessesSync(clearPageStack, myCall); + }); + }); + return p; + } + + getRunningProcessInformation(callback: AsyncCallback>): void { + let myCall = new AsyncCallbackWrapper>(callback); + taskpool.execute((): void => { + this.nativegetRunningProcessInformation(myCall); + }); + } + + getRunningProcessInformation(): Promise> { + let p = new Promise>((resolve: (data: Array) => void, + reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper>((err: BusinessError, + data: Array) => { + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativegetRunningProcessInformation(myCall); + }); + }); + return p; + } + + clearUpApplicationData(callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeclearUpApplicationData(myCall); + }); + } + + clearUpApplicationData(): Promise { + let p = + new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeclearUpApplicationData(myCall); + }); + }); + return p; + } + + setLanguage(language: string): void { + this.nativesetLanguage(language); + } + + setFontSizeScale(fontSizeScale: number): void { + this.nativesetFontSizeScale(fontSizeScale); + } + + setColorMode(colorMode: ConfigurationConstant.ColorMode): void { + this.nativesetColorMode(colorMode); + } + + getCurrentInstanceKey(): string { + return this.nativegetCurrentInstanceKey(); + } + + getCurrentAppCloneIndex(): number { + return this.nativegetCurrentAppCloneIndex(); + } + + setFont(font: string): void { + this.nativesetFont(font); + } + + restartApp(want: Want): void { + taskpool.execute((): void => { + this.nativerestartApp(want); + }); + } + + static transferStatic(input: Any): Object { + return ApplicationContext.nativeTransferStatic(ESValue.wrap(input)); + } + + static transferDynamic(input: Object): Any { + return ApplicationContext.nativeTransferDynamic(input).unwrap(); + } +} diff --git a/frameworks/ets/ets/application/AutoFillType.ets b/frameworks/ets/ets/application/AutoFillType.ets new file mode 100644 index 0000000000000000000000000000000000000000..122dee5a1757cf9baf614f7b192dfdb0573ed26c --- /dev/null +++ b/frameworks/ets/ets/application/AutoFillType.ets @@ -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. + */ + +export enum AutoFillType { + UNSPECIFIED = 0, + PASSWORD = 1, + USER_NAME = 2, + NEW_PASSWORD = 3, + FULL_STREET_ADDRESS = 4, + HOUSE_NUMBER = 5, + DISTRICT_ADDRESS = 6, + CITY_ADDRESS = 7, + PROVINCE_ADDRESS = 8, + COUNTRY_ADDRESS = 9, + PERSON_FULL_NAME = 10, + PERSON_LAST_NAME = 11, + PERSON_FIRST_NAME = 12, + PHONE_NUMBER = 13, + PHONE_COUNTRY_CODE = 14, + FULL_PHONE_NUMBER = 15, + EMAIL_ADDRESS = 16, + BANK_CARD_NUMBER = 17, + ID_CARD_NUMBER = 18, + NICKNAME = 24, + DETAIL_INFO_WITHOUT_STREET = 25, + FORMAT_ADDRESS = 26, + PASSPORT_NUMBER = 27, + VALIDITY = 28, + ISSUE_AT = 29, + ORGANIZATION = 30, + TAX_ID = 31, + ADDRESS_CITY_AND_STATE = 32, + FLIGHT_NUMBER = 33, + LICENSE_NUMBER = 34, + LICENSE_FILE_NUMBER = 35, + LICENSE_PLATE = 36, + ENGINE_NUMBER = 37, + LICENSE_CHASSIS_NUMBER = 38 +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/BaseContext.ets b/frameworks/ets/ets/application/BaseContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..2e9e42158db0f925bef44484f492b1f900b47652 --- /dev/null +++ b/frameworks/ets/ets/application/BaseContext.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. + */ + +export default class BaseContext { + public nativeContext : long = 0; + public stageMode: boolean; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/Context.ets b/frameworks/ets/ets/application/Context.ets new file mode 100644 index 0000000000000000000000000000000000000000..40dc82ee95beb89fde0926931f8e303dce941aaf --- /dev/null +++ b/frameworks/ets/ets/application/Context.ets @@ -0,0 +1,103 @@ +/* + * 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 BaseContext from 'application.BaseContext' +import ApplicationContext from 'application.ApplicationContext' +import EventHub from 'application.EventHub'; +import contextConstant from '@ohos.app.ability.contextConstant' +import { ApplicationInfo } from 'bundleManager.ApplicationInfo' +import resmgr from '@ohos.resourceManager' +import { AsyncCallback } from '@ohos.base'; +import { BusinessError } from '@ohos.base'; +import AsyncCallbackWrapper from '../utils/AbilityUtils'; + +// remove local declaration after Any type is supported +type Any = Object | null | undefined + +export class Context extends BaseContext { + static { + loadLibrary("context_ani"); + loadLibrary("context_ani_kit.z"); + } + filesDir: string = ""; + tempDir: string = ""; + preferencesDir: string = ""; + databaseDir: string = ""; + cacheDir: string = ""; + applicationInfo: ApplicationInfo; + eventHub: EventHub = new EventHub(); + resourceManager: resmgr.ResourceManager; + processName: string = ""; + native constructor(); + constructor(applicationInfo: ApplicationInfo, resourceManager: resmgr.ResourceManager) { + super(); + this.applicationInfo = applicationInfo; + this.resourceManager = resourceManager; + } + + public native getApplicationContextSync(): ApplicationContext; + public native createModuleResourceManagerSync(bundleName: string, moduleName: string): resmgr.ResourceManager; + public native nativeGetGroupDir(dataGroupID: string, callback: AsyncCallbackWrapper): void; + private static native nativeTransferStatic(input: ESValue): Object; + private static native nativeTransferDynamic(input: Object): ESValue; + private native switchArea(mode: contextConstant.AreaMode): void; + private native getArea(): contextConstant.AreaMode; + + getApplicationContext(): ApplicationContext { + return this.getApplicationContextSync(); + } + + createModuleResourceManager(bundleName: string, moduleName: string): resmgr.ResourceManager { + return this.createModuleResourceManagerSync(bundleName, moduleName); + } + + 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, data: string) => { + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeGetGroupDir(dataGroupID, myCall); + }); + }); + } + + static transferStatic(input: Any): Object { + return Context.nativeTransferStatic(ESValue.wrap(input)); + } + + static transferDynamic(input: Object): Any { + return Context.nativeTransferDynamic(input).unwrap(); + } + + set area(mode: contextConstant.AreaMode) { + this.switchArea(mode); + } + + get area(): contextConstant.AreaMode { + return this.getArea(); + } +} diff --git a/frameworks/ets/ets/application/CustomData.ets b/frameworks/ets/ets/application/CustomData.ets new file mode 100644 index 0000000000000000000000000000000000000000..5e588bee98f77b3047b1d7d7c5fc7705ef853109 --- /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/EventHub.ets b/frameworks/ets/ets/application/EventHub.ets new file mode 100644 index 0000000000000000000000000000000000000000..e207537e5099779524cb7b09aaa303eefaea8b5a --- /dev/null +++ b/frameworks/ets/ets/application/EventHub.ets @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default class EventHub { + private eventMap: Map> = new Map>(); + + private getCloneArray(event: string): Array { + if (this.eventMap.get(event)) { + const array: Array = this.eventMap.get(event) as Array; + const cloneArray = deepcopy>(array) as Array; + return cloneArray; + } + return new Array(); + } + + on(event: string, callback: Object) { + if (!this.eventMap.get(event)) { + this.eventMap.set(event, new Array()); + } + let array: Array = this.eventMap.get(event) as Array; + if (array.indexOf(callback) === -1) { + array.push(callback); + } + } + + off(event: string, callback: Object) { + if (this.eventMap.get(event)) { + let cbArray: Array = this.eventMap.get(event) as Array; + let index: number = cbArray.indexOf(callback); + if (index > -1) { + for (; index + 1 < cbArray.length; index++) { + cbArray[index] = cbArray[index + 1]; + } + cbArray.pop(); + } + } + } + + off(event: string) { + if (this.eventMap.get(event)) { + this.eventMap.delete(event); + } + } + + emit(event:string) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + let f = cloneArray[i] as () => void; + f(); + } + } + + emit(event:string, p1: P1) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + let f = cloneArray[i] as (p1: P1) => void; + f(p1); + } + } + + emit(event: string, p1: P1, p2: P2) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2) => void; + f(p1, p2); + } + } + + emit(event: string, p1: P1, p2: P2, p3: P3) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2, p3: P3) => void; + f(p1, p2, p3); + } + } + + emit(event: string, p1: P1, p2: P2, p3: P3, p4: P4) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2, p3: P3, p4: P4) => void; + f(p1, p2, p3, p4); + } + } + + emit(event: string, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) => void; + f(p1, p2, p3, p4, p5); + } + } + + emit(event: string, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) => void; + f(p1, p2, p3, p4, p5, p6); + } + } + + emit(event: string, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) => void; + f(p1, p2, p3, p4, p5, p6, p7); + } + } + + emit(event: string, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8) => void; + f(p1, p2, p3, p4, p5, p6, p7, p8); + } + } + + emit(event: string, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9) => void; + f(p1, p2, p3, p4, p5, p6, p7, p8, p9); + } + } + + emit(event: string, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10) => void; + f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); + } + } + + emit(event: string, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11) => void; + f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); + } + } + + emit(event: string, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12) => void; + f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); + } + } + + emit(event: string, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13) => void; + f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); + } + } + + emit(event: string, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14) => void; + f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); + } + } + + emit(event: string, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15) => void; + f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); + } + } + + emit(event: string, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16) { + const cloneArray: Array = this.getCloneArray(event); + for (let i = 0; i < cloneArray.length; ++i) { + const f = cloneArray[i] as (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16) => void; + f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16); + } + } +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/ExtensionContext.ets b/frameworks/ets/ets/application/ExtensionContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..593e35756276d2fac2ac013172a1a91fe6d4fc9c --- /dev/null +++ b/frameworks/ets/ets/application/ExtensionContext.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 Context from 'application.Context' +import {ExtensionAbilityInfo} from 'bundleManager.ExtensionAbilityInfo' +import { Configuration } from '@ohos.app.ability.Configuration'; +import { HapModuleInfo } from 'bundleManager.HapModuleInfo'; + +export default class ExtensionContext extends Context { + static { + loadLibrary("context_ani"); + } + extensionAbilityInfo: ExtensionAbilityInfo; + config: Configuration; + currentHapModuleInfo: HapModuleInfo; + native constructor(); + constructor(config: Configuration, extensionAbilityInfo: ExtensionAbilityInfo, currentHapModuleInfo: HapModuleInfo) { + super(); + this.config = config; + this.extensionAbilityInfo = extensionAbilityInfo; + this.currentHapModuleInfo = currentHapModuleInfo; + } +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/ExtensionRunningInfo.ets b/frameworks/ets/ets/application/ExtensionRunningInfo.ets new file mode 100644 index 0000000000000000000000000000000000000000..90c40be7a00112c858ca8a07a7e7c03620431273 --- /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: number; + uid: number; + processName: string; + startTime: number; + clientPackage: Array; + type: bundle.ExtensionAbilityType; +} + +class ExtensionRunningInfoInner implements ExtensionRunningInfo { + extension: ElementName = {}; + pid: number; + uid: number; + processName: string = ''; + startTime: number; + clientPackage: Array = []; + type: bundle.ExtensionAbilityType = bundle.ExtensionAbilityType.FORM; +} diff --git a/frameworks/ets/ets/application/MultiAppMode.ets b/frameworks/ets/ets/application/MultiAppMode.ets new file mode 100644 index 0000000000000000000000000000000000000000..dc7d9e233f782d518072108699989c2b6780ac0c --- /dev/null +++ b/frameworks/ets/ets/application/MultiAppMode.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export enum MultiAppMode { + NOT_SUPPORTED = 0, + MULTI_INSTANCE = 1, + APP_CLONE = 2 +} diff --git a/frameworks/ets/ets/application/ProcessData.ets b/frameworks/ets/ets/application/ProcessData.ets new file mode 100644 index 0000000000000000000000000000000000000000..5bec6929cbf8dbe0cce8d6285dcb565b9c51d9d0 --- /dev/null +++ b/frameworks/ets/ets/application/ProcessData.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export default class ProcessData { + bundleName: string = ''; + pid: number; + uid: number; + state: number; + isContinuousTask: boolean; + isKeepAlive: boolean; +} diff --git a/frameworks/ets/ets/application/ProcessInformation.ets b/frameworks/ets/ets/application/ProcessInformation.ets new file mode 100644 index 0000000000000000000000000000000000000000..81f36fd7f85b38f8efbbf314fe05769c28c273a2 --- /dev/null +++ b/frameworks/ets/ets/application/ProcessInformation.ets @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import appManager from '@ohos.app.ability.appManager'; +import bundleManager from '@ohos.bundle.bundleManager'; + +export interface ProcessInformation { + pid: number; + uid: number; + processName: string; + bundleNames: Array; + state: appManager.ProcessState; + bundleType: bundleManager.BundleType; + appCloneIndex?: number; +} + +export default class ProcessInformationInner implements ProcessInformation { + pid: number; + uid: number; + processName: string = ''; + bundleNames: Array = []; + state: appManager.ProcessState = appManager.ProcessState.STATE_CREATE; + bundleType: bundleManager.BundleType = bundleManager.BundleType.APP; + appCloneIndex?: number; +} diff --git a/frameworks/ets/ets/application/RunningAppClone.ets b/frameworks/ets/ets/application/RunningAppClone.ets new file mode 100644 index 0000000000000000000000000000000000000000..97f4d909c71a8e4aeb68f547900c4f4c14448d0f --- /dev/null +++ b/frameworks/ets/ets/application/RunningAppClone.ets @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface RunningAppClone { + appCloneIndex: number; + uid: number; + pids: Array; +} + +class RunningAppCloneInner implements RunningAppClone { + appCloneIndex: number; + uid: number; + pids: Array = []; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/RunningMultiAppInfo.ets b/frameworks/ets/ets/application/RunningMultiAppInfo.ets new file mode 100644 index 0000000000000000000000000000000000000000..0fdaf2517ef6c82314a6367350e435a7f33d98ce --- /dev/null +++ b/frameworks/ets/ets/application/RunningMultiAppInfo.ets @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { MultiAppMode } from 'application.MultiAppMode'; +import { RunningAppClone } from 'application.RunningAppClone'; +import { RunningMultiInstanceInfo } from 'application.RunningMultiInstanceInfo'; + +export interface RunningMultiAppInfo { + bundleName: string; + mode: MultiAppMode; + runningMultiInstances?: Array; + runningAppClones?: Array; +} + +export default class RunningMultiAppInfoInner implements RunningMultiAppInfo { + bundleName: string = ''; + mode: MultiAppMode = MultiAppMode.NOT_SUPPORTED; + runningMultiInstances?: Array; + runningAppClones?: Array; +} diff --git a/frameworks/ets/ets/application/RunningMultiInstanceInfo.ets b/frameworks/ets/ets/application/RunningMultiInstanceInfo.ets new file mode 100644 index 0000000000000000000000000000000000000000..10ce3036172120357be840706ba20822a41651f1 --- /dev/null +++ b/frameworks/ets/ets/application/RunningMultiInstanceInfo.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface RunningMultiInstanceInfo { + instanceKey: string; +} + +class RunningMultiInstanceInfoInner implements RunningMultiInstanceInfo { + instanceKey: string = ''; +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/ServiceExtensionContext.ets b/frameworks/ets/ets/application/ServiceExtensionContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..e868ac50cdcc2aa8c081dd8f7b9efa9bbaf2253d --- /dev/null +++ b/frameworks/ets/ets/application/ServiceExtensionContext.ets @@ -0,0 +1,130 @@ +/* + * 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'; +import { ConnectOptions } from 'ability.connectOptions'; +import StartOptions from '@ohos.app.ability.StartOptions'; +import Want from '@ohos.app.ability.Want'; +import { AsyncCallback } from '@ohos.base'; +import { BusinessError } from '@ohos.base'; +import hilog from '@ohos.hilog'; +import ExtensionContext from 'application.ExtensionContext'; +import AsyncCallbackWrapper from '../utils/AbilityUtils'; + +export default class ServiceExtensionContext extends ExtensionContext { + nativeServiceExtensionContext: long = 0; + native nativeTerminateSelfSync(callback:AsyncCallbackWrapper): void; + native nativeStartAbilitySync(want: Want, callback: AsyncCallbackWrapper): void; + native nativeStartAbilitySync(want: Want, options: StartOptions, callback:AsyncCallbackWrapper): void; + native nativeStartServiceExtensionAbilitySync(want: Want, callback: AsyncCallbackWrapper): void; + native nativeStopServiceExtensionAbility(want: Want, callback: AsyncCallbackWrapper): void; + + terminateSelf(callback:AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeTerminateSelfSync(myCall); + }); + } + + terminateSelf(): Promise { + let p = new Promise((resolve: (data: undefined) => void, reject:(err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeTerminateSelfSync(myCall); + }); + }); + return p; + } + + startAbility(want: Want, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartAbilitySync(want, myCall); + }); + } + + startAbility(want: Want, options: StartOptions, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartAbilitySync(want, options, myCall); + }); + } + + 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)=>{ + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeStartAbilitySync(want, options, myCall); + }); + }); + return p; + } + + startServiceExtensionAbility(want: Want, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartServiceExtensionAbilitySync(want, myCall); + }); + } + + startServiceExtensionAbility(want: Want): Promise { + let p = new Promise((resolve: (data: undefined)=>void, reject:(err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeStartServiceExtensionAbilitySync(want, myCall); + }); + }); + return p; + } + + stopServiceExtensionAbility(want: Want, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStopServiceExtensionAbility(want, myCall); + }); + } + + stopServiceExtensionAbility(want: Want): Promise { + return new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeStopServiceExtensionAbility(want, myCall); + }); + }); + } +} diff --git a/frameworks/ets/ets/application/UIAbilityContext.ets b/frameworks/ets/ets/application/UIAbilityContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..6cd38d8892bff0933ad662fda2737a4c404fac74 --- /dev/null +++ b/frameworks/ets/ets/application/UIAbilityContext.ets @@ -0,0 +1,345 @@ +/* + * 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 { AbilityInfo } from 'bundleManager.AbilityInfo'; +import Want from '@ohos.app.ability.Want'; +import StartOptions from '@ohos.app.ability.StartOptions'; +import { BusinessError, AsyncCallback } from '@ohos.base'; +import { AbilityResult } from 'ability.abilityResult'; +import AbilityStartCallback from 'application.AbilityStartCallback'; +import { Configuration } from '@ohos.app.ability.Configuration'; +import Context from 'application.Context'; +import window from '@ohos.window'; +import { Caller } from '@ohos.app.ability.UIAbility'; +import { HapModuleInfo } from 'bundleManager.HapModuleInfo'; +import AsyncCallbackWrapper from '../utils/AbilityUtils'; +import OpenLinkOptions from '@ohos.app.ability.OpenLinkOptions'; +import { LocalStorage } from '@ohos.arkui.stateManagement'; + +// remove local declaration after Any type is supported +type Any = Object | null | undefined + +export default class UIAbilityContext extends Context { + static { + loadLibrary("context_ani"); + } + + config: Configuration; + abilityInfo: AbilityInfo; + windowStage: window.WindowStage; + currentHapModuleInfo: HapModuleInfo; + + native constructor(); + constructor(config: Configuration, abilityInfo: AbilityInfo, windowStage: window.WindowStage, currentHapModuleInfo: HapModuleInfo) { + super(); + this.config = config; + this.abilityInfo = abilityInfo; + this.windowStage = windowStage; + this.currentHapModuleInfo = currentHapModuleInfo; + } + + private static native nativeTransferStatic(input: ESValue): Object; + private static native nativeTransferDynamic(input: Object): ESValue; + static transferStatic(input: Any): Object { + return UIAbilityContext.nativeTransferStatic(ESValue.wrap(input)); + } + static transferDynamic(input: Object): Any { + return UIAbilityContext.nativeTransferDynamic(input).unwrap(); + } + + private native nativeStartAbilitySync(want: Want, callback: AsyncCallbackWrapper): void; + private native nativeStartAbilitySync(want: Want, options: StartOptions, callback:AsyncCallbackWrapper): void; + private native nativeStartAbilityForResult(want: Want, callback:AsyncCallbackWrapper): void; + private native nativeStartAbilityForResult(want: Want, startOptions: StartOptions, callback:AsyncCallbackWrapper): void; + private native nativeTerminateSelfSync(callback:AsyncCallbackWrapper): void; + private native nativeTerminateSelfWithResult(parameter: AbilityResult, callback:AsyncCallbackWrapper): void; + private native nativeReportDrawnCompletedSync(callback:AsyncCallbackWrapper): void; + private native nativeStartAbilityByTypeSync(type: string, wantParam: Record, startCallback: AbilityStartCallback): BusinessError; + private native nativeStartServiceExtensionAbilitySync(want: Want, callback: AsyncCallbackWrapper): void; + private native nativeStartAbilityByCallSync(want: Want): Caller; + private native nativeOpenLinkSync(link: string, myCallback:AsyncCallbackWrapper, options?: OpenLinkOptions, callback?: AsyncCallbackWrapper): void; + private native nativeRestoreWindowStage(localStorage: LocalStorage): boolean; + private native nativeIsTerminating(): boolean; + private native nativeMoveAbilityToBackground(callback: AsyncCallbackWrapper): void; + private native nativeRequestModalUIExtension(pickerWant: Want, callback: AsyncCallbackWrapper): void; + startAbility(want: Want, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartAbilitySync(want, myCall); + }); + } + + startAbility(want: Want, options: StartOptions, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartAbilitySync(want, options, myCall); + }); + } + + startAbility(want: Want): Promise { + let p:Promise = new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError)=>{ + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeStartAbilitySync(want, myCall); + }); + }); + return p; + } + + startAbility(want: Want, options: StartOptions): Promise { + let p = new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError)=>{ + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeStartAbilitySync(want, options, myCall); + }); + }); + return p; + } + + 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): Promise{ + let p = new Promise((resolve: (data: AbilityResult)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError, data: AbilityResult)=>{ + if (err.code == 0) { + resolve(data); + } 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, data: AbilityResult)=>{ + if (err.code == 0) { + resolve(data); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeStartAbilityForResult(want, startOptions, myCall); + }); + }); + return p; + } + + terminateSelf(callback:AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeTerminateSelfSync(myCall); + }); + } + + terminateSelf(): Promise { + let p = new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError)=>{ + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeTerminateSelfSync(myCall); + }); + }); + return p; + } + + terminateSelfWithResult(parameter: AbilityResult, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeTerminateSelfWithResult(parameter, myCall); + }); + } + + terminateSelfWithResult(parameter: AbilityResult): Promise{ + let p = new Promise((resolve: (data: undefined)=>void, reject:(err: BusinessError)=>void):void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError)=>{ + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeTerminateSelfWithResult(parameter, myCall); + }); + }); + return p; + } + + reportDrawnCompleted(callback:AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeReportDrawnCompletedSync(myCall); + }); + } + + 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; + 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; + } + + startServiceExtensionAbility(want: Want, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + this.nativeStartServiceExtensionAbilitySync(want, myCall); + } + + startServiceExtensionAbility(want: Want): Promise { + let p = new Promise((resolve: (data: undefined)=>void, reject:(err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + this.nativeStartServiceExtensionAbilitySync(want, myCall); + }); + return p; + } + + startAbilityByCall(want: Want): Promise { + return taskpool.execute((): Caller => { + return this.nativeStartAbilityByCallSync(want); + }) as Promise; + } + + openLink(link: string, options?: OpenLinkOptions, callback?: AsyncCallback): Promise { + return new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let finalOptions: OpenLinkOptions | undefined = undefined; + if (options) { + finalOptions = options; + } + let callParam: AsyncCallbackWrapper | undefined = undefined; + if (callback) { + callParam = new AsyncCallbackWrapper(callback); + } + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute(() => { + this.nativeOpenLinkSync(link, myCall, finalOptions, callParam); + }); + }); + } + + restoreWindowStage(localStorage: LocalStorage): void { + this.nativeRestoreWindowStage(localStorage); + } + + isTerminating(): boolean { + return this.nativeIsTerminating(); + } + + moveAbilityToBackground(): Promise { + return new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let syncCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute(() => { + this.nativeMoveAbilityToBackground(syncCall); + }); + }); + } + + requestModalUIExtension(pickerWant: Want, callback: AsyncCallback): void { + let syncCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeRequestModalUIExtension(pickerWant, syncCall); + }); + } + + requestModalUIExtension(pickerWant: Want): Promise { + return new Promise((resolve: (data: undefined) => void, reject: (err: BusinessError) => void): void => { + let syncCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute(() => { + this.nativeRequestModalUIExtension(pickerWant, syncCall); + }); + }); + } +} diff --git a/frameworks/ets/ets/application/UIExtensionContext.ets b/frameworks/ets/ets/application/UIExtensionContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..565278a9ddb11e9a304a76a3e664b5e85e206e42 --- /dev/null +++ b/frameworks/ets/ets/application/UIExtensionContext.ets @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Want from '@ohos.app.ability.Want'; +import StartOptions from '@ohos.app.ability.StartOptions'; +import { AbilityResult } from 'ability.abilityResult'; +import { AsyncCallback } from '@ohos.base'; +import { BusinessError } from '@ohos.base'; +import AsyncCallbackWrapper from '../utils/AbilityUtils'; +import ExtensionContext from 'application.ExtensionContext'; +import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant'; + +export default class UIExtensionContext extends ExtensionContext { + native terminateSelfSync(callback:AsyncCallbackWrapper): void; + native terminateSelfWithResultSync(parameter: AbilityResult, callback: AsyncCallbackWrapper): void; + private native nativeStartAbilitySync(want: Want, callback: AsyncCallbackWrapper): void; + private native nativeStartAbilitySync(want: Want, options: StartOptions, callback:AsyncCallbackWrapper): void; + + terminateSelf(callback:AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.terminateSelfSync(myCall); + }); + } + + terminateSelf(): Promise { + let p = new Promise((resolve: (data: undefined) => void, reject:(err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.terminateSelfSync(myCall); + }); + }); + return p; + } + + terminateSelfWithResult(parameter: AbilityResult, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.terminateSelfWithResultSync(parameter, myCall); + }); + } + + terminateSelfWithResult(parameter: AbilityResult): Promise { + let p = new Promise((resolve: (data: undefined)=>void, reject:(err: BusinessError) => void): void => { + let myCall = new AsyncCallbackWrapper((err: BusinessError) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.terminateSelfWithResultSync(parameter, myCall); + }); + }); + return p; + } + + startAbility(want: Want, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartAbilitySync(want, myCall); + }); + } + + startAbility(want: Want, options: StartOptions, callback: AsyncCallback): void { + let myCall = new AsyncCallbackWrapper(callback); + taskpool.execute((): void => { + this.nativeStartAbilitySync(want, options, myCall); + }); + } + + 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) => { + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void => { + this.nativeStartAbilitySync(want, options, myCall); + }); + }); + return p; + } + + native setColorMode(colorMode: ConfigurationConstant.ColorMode): void; + + native nativeReportDrawnCompleted(callback:AsyncCallbackWrapper): void; + 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/abilityDelegatorArgs.ets b/frameworks/ets/ets/application/abilityDelegatorArgs.ets new file mode 100644 index 0000000000000000000000000000000000000000..23135832108aa10a3b9636755fe288c39f800ffd --- /dev/null +++ b/frameworks/ets/ets/application/abilityDelegatorArgs.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. + */ + +export interface AbilityDelegatorArgs { + bundleName: string; + parameters: Record; + testCaseNames: string; + testRunnerClassName: string; + } + + class AbilityDelegatorArgsInner implements AbilityDelegatorArgs { + public bundleName: string = ''; + public parameters: Record = {}; + public testCaseNames: string = ''; + public testRunnerClassName: string = ''; + } + \ No newline at end of file diff --git a/frameworks/ets/ets/application/shellCmdResult.ets b/frameworks/ets/ets/application/shellCmdResult.ets new file mode 100644 index 0000000000000000000000000000000000000000..5250b377d4d19603097dea71fdd1b855f9605c39 --- /dev/null +++ b/frameworks/ets/ets/application/shellCmdResult.ets @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +interface ShellCmdResult { + stdResult: string; + exitCode: number; + } + + class ShellCmdResultImpl implements ShellCmdResult { + public stdResult: string = ''; + public exitCode: number = 0; + } + + export default ShellCmdResult; diff --git a/frameworks/ets/ets/callee/Callee.ets b/frameworks/ets/ets/callee/Callee.ets new file mode 100644 index 0000000000000000000000000000000000000000..01f1b9aa7b6d09679952379f53189a93b2a2dd44 --- /dev/null +++ b/frameworks/ets/ets/callee/Callee.ets @@ -0,0 +1,86 @@ +/* + * 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'; +import rpc from '@ohos.rpc'; +import { BusinessError } from '@ohos.base'; +import { Callee, CalleeCallback } from '@ohos.app.ability.UIAbility'; + +const domainID = 0x0000; +const TAG = 'UIAbility'; + +const EVENT_CALL_NOTIFY = 1; +const REQUEST_SUCCESS = 0; +const REQUEST_FAILED = 1; +const PERMISSION_ABILITY_BACKGROUND_COMMUNICATION = 'ohos.permission.ABILITY_BACKGROUND_COMMUNICATION'; + +const ERROR_CODE_INVALID_PARAM = 401; +const ERROR_CODE_FUNC_REGISTERED = 16200004; +const ERROR_CODE_FUNC_NOT_EXIST = 16200005; +const ERROR_CODE_INNER_ERROR = 16000050; + +const ERROR_MSG_INVALID_PARAM = 'Invalid input parameter.'; +const ERROR_MSG_FUNC_REGISTERED = 'Method registered. The method has registered.'; +const ERROR_MSG_FUNC_NOT_EXIST = 'The method has not been registered.'; +const ERROR_MSG_INNER_ERROR = 'Inner Error.'; + +let errMap = new Map(); +errMap.set(ERROR_CODE_INVALID_PARAM, ERROR_MSG_INVALID_PARAM); +errMap.set(ERROR_CODE_FUNC_REGISTERED, ERROR_MSG_FUNC_REGISTERED); +errMap.set(ERROR_CODE_FUNC_NOT_EXIST, ERROR_MSG_FUNC_NOT_EXIST); +errMap.set(ERROR_CODE_INNER_ERROR, ERROR_MSG_INNER_ERROR); + +function buildError(code: number): BusinessError { + return new BusinessError(code, new Error(errMap.get(code) as string)); +} + +export class CalleeImpl extends rpc.RemoteObject implements Callee { + private callList = new Map(); + private startUpNewRule = false; + constructor() { + super('rpc.application.callee'); + hilog.info(domainID, TAG, 'Callee constructor is OK'); + } + + setNewRuleFlag(flag: boolean): void { + this.startUpNewRule = flag; + } + + onRemoteMessageRequest(code: number, data: rpc.MessageSequence, reply: rpc.MessageSequence, + option: rpc.MessageOption): Boolean|Promise { + hilog.info(domainID, TAG, 'Callee onRemoteMessageRequest code [' + code + ']'); + return true; + } + + on(method: string, callback: CalleeCallback): void { + if (this.callList.has(method)) { + hilog.info(domainID, TAG, 'Callee on error, [' + method + '] has registered'); + throw buildError(ERROR_CODE_FUNC_REGISTERED); + } + + this.callList.set(method, callback); + hilog.info(domainID, TAG, 'Callee on method [' + method + ']'); + } + + off(method: string): void { + if (!this.callList.has(method)) { + hilog.info(domainID, TAG, 'Callee off error, this.callList not found ' + method); + throw buildError(ERROR_CODE_FUNC_NOT_EXIST); + } + + this.callList.delete(method); + hilog.info(domainID, TAG, 'Callee off method [' + method + ']'); + } +} \ No newline at end of file diff --git a/frameworks/ets/ets/caller/Caller.ets b/frameworks/ets/ets/caller/Caller.ets new file mode 100644 index 0000000000000000000000000000000000000000..668debeae4aa08a2cae693c5ee5fc4618709f274 --- /dev/null +++ b/frameworks/ets/ets/caller/Caller.ets @@ -0,0 +1,98 @@ +/* + * 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'; +import rpc from '@ohos.rpc'; +import { BusinessError } from '@ohos.base'; +import { Caller, OnReleaseCallback, OnRemoteStateChangeCallback } from '@ohos.app.ability.UIAbility'; + +const domainID = 0x0000; +const TAG = 'UIAbility'; + +const EVENT_CALL_NOTIFY = 1; +const REQUEST_SUCCESS = 0; + +const ERROR_CODE_INVALID_PARAM = 401; +const ERROR_CODE_CALLER_RELEASED = 16200001; +const ERROR_CODE_CLAAEE_INVALID = 16200002; +const ERROR_CODE_INNER_ERROR = 16000050; + +const ERROR_MSG_INVALID_PARAM = 'Invalid input parameter.'; +const ERROR_MSG_CALLER_RELEASED = 'Caller released. The caller has been released.'; +const ERROR_MSG_CLAAEE_INVALID = 'The callee does not exist.'; +const ERROR_MSG_INNER_ERROR = 'Inner Error.'; + +let errMap = new Map(); +errMap.set(ERROR_CODE_INVALID_PARAM, ERROR_MSG_INVALID_PARAM); +errMap.set(ERROR_CODE_CALLER_RELEASED, ERROR_MSG_CALLER_RELEASED); +errMap.set(ERROR_CODE_CLAAEE_INVALID, ERROR_MSG_CLAAEE_INVALID); +errMap.set(ERROR_CODE_INNER_ERROR, ERROR_MSG_INNER_ERROR); + +function buildError(code: number): BusinessError { + return new BusinessError(code, new Error(errMap.get(code) as string)); +} + +export class ReleaseCallback { + private myFun_: OnReleaseCallback = (msg: string) => {} + constructor(myFun: OnReleaseCallback) { + this.myFun_ = myFun; + } + invoke(msg: string): void { + this.myFun_(msg); + } +} + +export class CallerImpl implements Caller { + nativeCaller: long; + private callee: rpc.IRemoteObject | null = null; + native nativeReleaseSync(): void; + native nativeOnReleaseSync(callback: ReleaseCallback): void; + native nativeOnRemoteStateChangeSync(callback: OnRemoteStateChangeCallback): void; + private releaseState = false; + + constructor() { + hilog.info(domainID, TAG, 'Caller::constructor'); + } + + call(method: string, data: rpc.Parcelable): Promise { + return new Promise((resolve: (data: undefined)=>void, reject: (error: Error) => void): void => { + hilog.info(domainID, TAG, 'Caller call'); + resolve(undefined); + return; + }); + } + + release(): void { + hilog.info(domainID, TAG, 'Caller release called.'); + if (this.releaseState === true) { + hilog.info(domainID, TAG, 'Caller release remoteObj releaseState is true'); + throw buildError(ERROR_CODE_CALLER_RELEASED); + } + + if (this.callee == null) { + hilog.info(domainID, TAG, 'Caller release call remoteObj is released'); + throw buildError(ERROR_CODE_CLAAEE_INVALID); + } + + this.releaseState = true; + this.callee = null; + this.nativeReleaseSync(); + } + + onRelease(callback: OnReleaseCallback): void { + hilog.info(domainID, TAG, 'onRelease called'); + this.nativeOnReleaseSync(new ReleaseCallback(callback)); + } +} diff --git a/frameworks/ets/ets/utils/AbilityUtils.ets b/frameworks/ets/ets/utils/AbilityUtils.ets new file mode 100644 index 0000000000000000000000000000000000000000..b12da5e18c399dfc1d833148b18a73b210c9ac9b --- /dev/null +++ b/frameworks/ets/ets/utils/AbilityUtils.ets @@ -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. + */ + +import { BusinessError, AsyncCallback } from '@ohos.base'; +import hilog from '@ohos.hilog' + +const DOMAIN_ID = 0xD001300; +const TAG = 'AbilityUtils'; +const LEVEL = 100; + +export default class AsyncCallbackWrapper { + private myFun_:AsyncCallback = (err: BusinessError, data: T) => {} + + constructor(myFun:AsyncCallback){ + this.myFun_ = myFun; + } + + invoke(err: BusinessError, data: T) : void { + this.myFun_(err, data); + } +} + +export class AbilityUtils { + public static getClassType(obj: Object): ClassType | undefined { + try { + let type = Type.of(obj); + return type as ClassType; + } catch (err) { + hilog.error(DOMAIN_ID, TAG, `getClassType error: ${err}`); + return undefined; + } + } + + public static isInherited(type: ClassType, methodName: string, stopBaseClassType: ClassType): boolean | undefined { + let currType = type; + let level = 0; + while (!currType.equals(stopBaseClassType)) { + try { + for (let methodIdx = 0; methodIdx < currType.getMethodsNum(); methodIdx++) { + const method = currType.getMethod(methodIdx) + if (method.getName().equals(methodName)) { + if (!method.isInherited()) { + return false; + } + } + } + let baseType = currType.getBaseType(); + if (baseType.equals(currType)) { + hilog.error(DOMAIN_ID, TAG, `isInherited: baseType equals currType (${currType.getName()})`); + return undefined; + } + level++; + if (level >= LEVEL) { + hilog.error(DOMAIN_ID, TAG, `isInherited: inheritance level >= ${LEVEL}, aborting`); + return undefined; + } + currType = baseType; + } catch (err) { + hilog.error(DOMAIN_ID, TAG, `isInherited error: ${err}`); + return undefined; + } + } + return true; + } +} \ No newline at end of file diff --git a/frameworks/ets/ets/wantAgent/triggerInfo.ets b/frameworks/ets/ets/wantAgent/triggerInfo.ets new file mode 100644 index 0000000000000000000000000000000000000000..0653b0f4486ae3725cba8558a9fa12a9c590cd5b --- /dev/null +++ b/frameworks/ets/ets/wantAgent/triggerInfo.ets @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Want from '@ohos.app.ability.Want'; +import StartOptions from '@ohos.app.ability.StartOptions'; + +export interface TriggerInfo { + code: number; + want?: Want; + permission?: string; + extraInfo?: Record; + extraInfos?: Record; + startOptions?: StartOptions; +} + +class TriggerInfoImpl implements TriggerInfo { + public code: number; + public want?: Want; + public permission?: string; + public extraInfo?: Record; + public extraInfos?: Record; + public startOptions?: StartOptions; +} diff --git a/frameworks/ets/ets/wantAgent/wantAgentInfo.ets b/frameworks/ets/ets/wantAgent/wantAgentInfo.ets new file mode 100644 index 0000000000000000000000000000000000000000..e5b0df9f8437c64c3a1a144f60817f722d3ed38f --- /dev/null +++ b/frameworks/ets/ets/wantAgent/wantAgentInfo.ets @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Want from '@ohos.app.ability.Want'; +import type abilityWantAgent from '@ohos.app.ability.wantAgent'; + +export interface WantAgentInfo { + wants: Array; + actionType?: abilityWantAgent.OperationType; + requestCode: number; + actionFlags?: Array; + extraInfo?: Record; + extraInfos?: Record; +} + +class WantAgentInfoImpl implements WantAgentInfo { + public wants: Array = new Array; + public actionType?: abilityWantAgent.OperationType; + public requestCode: number; + public actionFlags?: Array; + public extraInfo?: Record; + public extraInfos?: Record; +} diff --git a/frameworks/js/napi/app/ability_delegator/BUILD.gn b/frameworks/js/napi/app/ability_delegator/BUILD.gn index 8a4fe6813819b4af05f546911c96314966a10086..c94532cd49d406737b01cb17271c7b8ff6983773 100644 --- a/frameworks/js/napi/app/ability_delegator/BUILD.gn +++ b/frameworks/js/napi/app/ability_delegator/BUILD.gn @@ -60,6 +60,7 @@ template("delegator") { "ipc:ipc_napi", "ipc:ipc_single", "napi:ace_napi", + "runtime_core:ani", ] cflags_cc = [] diff --git a/frameworks/js/napi/app/ability_delegator/ability_monitor.cpp b/frameworks/js/napi/app/ability_delegator/ability_monitor.cpp index 5eab898a5a901bbcb2b765670410e073a933a738..950c81b07a06927125620b3d38b27c6374c1b446 100644 --- a/frameworks/js/napi/app/ability_delegator/ability_monitor.cpp +++ b/frameworks/js/napi/app/ability_delegator/ability_monitor.cpp @@ -32,82 +32,138 @@ AbilityMonitor::AbilityMonitor(const std::string &name, const std::string &modul : IAbilityMonitor(name, moduleName), jsMonitor_(jsAbilityMonitor) {} -void AbilityMonitor::OnAbilityStart(const std::weak_ptr &abilityObj) +void AbilityMonitor::OnAbilityStart(const std::weak_ptr &abilityObj) { TAG_LOGI(AAFwkTag::DELEGATOR, "called"); + auto baseProperty = abilityObj.lock(); + if (!baseProperty) { + TAG_LOGE(AAFwkTag::DELEGATOR, "abilityObj is expired"); + return; + } + auto jsbaseProperty = std::static_pointer_cast(baseProperty); + if (jsMonitor_ == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "jsMonitor_ is nullptr"); return; } - jsMonitor_->OnAbilityCreate(abilityObj); + jsMonitor_->OnAbilityCreate(jsbaseProperty->object_); } -void AbilityMonitor::OnAbilityForeground(const std::weak_ptr &abilityObj) +void AbilityMonitor::OnAbilityForeground(const std::weak_ptr &abilityObj) { TAG_LOGI(AAFwkTag::DELEGATOR, "called"); + auto baseProperty = abilityObj.lock(); + if (!baseProperty) { + TAG_LOGE(AAFwkTag::DELEGATOR, "abilityObj is expired"); + return; + } + auto jsbaseProperty = std::static_pointer_cast(baseProperty); + if (jsMonitor_ == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "jsMonitor_ is nullptr"); return; } - jsMonitor_->OnAbilityForeground(abilityObj); + jsMonitor_->OnAbilityForeground(jsbaseProperty->object_); } -void AbilityMonitor::OnAbilityBackground(const std::weak_ptr &abilityObj) +void AbilityMonitor::OnAbilityBackground(const std::weak_ptr &abilityObj) { TAG_LOGI(AAFwkTag::DELEGATOR, "called"); + auto baseProperty = abilityObj.lock(); + if (!baseProperty) { + TAG_LOGE(AAFwkTag::DELEGATOR, "abilityObj is expired"); + return; + } + auto jsbaseProperty = std::static_pointer_cast(baseProperty); + if (jsMonitor_ == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "jsMonitor_ is nullptr"); return; } - jsMonitor_->OnAbilityBackground(abilityObj); + jsMonitor_->OnAbilityBackground(jsbaseProperty->object_); } -void AbilityMonitor::OnAbilityStop(const std::weak_ptr &abilityObj) +void AbilityMonitor::OnAbilityStop(const std::weak_ptr &abilityObj) { TAG_LOGI(AAFwkTag::DELEGATOR, "called"); + auto baseProperty = abilityObj.lock(); + if (!baseProperty) { + TAG_LOGE(AAFwkTag::DELEGATOR, "abilityObj is expired"); + return; + } + auto jsbaseProperty = std::static_pointer_cast(baseProperty); + if (jsMonitor_ == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "jsMonitor_ is nullptr"); return; } - jsMonitor_->OnAbilityDestroy(abilityObj); + jsMonitor_->OnAbilityDestroy(jsbaseProperty->object_); } -void AbilityMonitor::OnWindowStageCreate(const std::weak_ptr &abilityObj) +void AbilityMonitor::OnWindowStageCreate(const std::weak_ptr &abilityObj) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); TAG_LOGI(AAFwkTag::DELEGATOR, "called"); + auto baseProperty = abilityObj.lock(); + if (!baseProperty) { + TAG_LOGE(AAFwkTag::DELEGATOR, "abilityObj is expired"); + return; + } + auto jsbaseProperty = std::static_pointer_cast(baseProperty); + if (jsMonitor_ == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "jsMonitor_ is nullptr"); return; } - jsMonitor_->OnWindowStageCreate(abilityObj); + jsMonitor_->OnWindowStageCreate(jsbaseProperty->object_); } -void AbilityMonitor::OnWindowStageRestore(const std::weak_ptr &abilityObj) +void AbilityMonitor::OnWindowStageRestore(const std::weak_ptr &abilityObj) { TAG_LOGI(AAFwkTag::DELEGATOR, "called"); + auto baseProperty = abilityObj.lock(); + if (!baseProperty) { + TAG_LOGE(AAFwkTag::DELEGATOR, "abilityObj is expired"); + return; + } + auto jsbaseProperty = std::static_pointer_cast(baseProperty); + if (jsMonitor_ == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "jsMonitor_ is nullptr"); return; } - jsMonitor_->OnWindowStageRestore(abilityObj); + jsMonitor_->OnWindowStageRestore(jsbaseProperty->object_); } -void AbilityMonitor::OnWindowStageDestroy(const std::weak_ptr &abilityObj) +void AbilityMonitor::OnWindowStageDestroy(const std::weak_ptr &abilityObj) { TAG_LOGI(AAFwkTag::DELEGATOR, "called"); + auto baseProperty = abilityObj.lock(); + if (!baseProperty) { + TAG_LOGE(AAFwkTag::DELEGATOR, "abilityObj is expired"); + return; + } + auto jsbaseProperty = std::static_pointer_cast(baseProperty); + if (jsMonitor_ == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "jsMonitor_ is nullptr"); return; } - jsMonitor_->OnWindowStageDestroy(abilityObj); + jsMonitor_->OnWindowStageDestroy(jsbaseProperty->object_); } } // namespace AbilityDelegatorJs } // namespace OHOS diff --git a/frameworks/js/napi/app/ability_delegator/ability_monitor.h b/frameworks/js/napi/app/ability_delegator/ability_monitor.h index 433a48b48281f7dc729448f8da41a3063d011f87..37bb4b5b2fb95b0a66115bb7cdc31357be394977 100644 --- a/frameworks/js/napi/app/ability_delegator/ability_monitor.h +++ b/frameworks/js/napi/app/ability_delegator/ability_monitor.h @@ -56,49 +56,49 @@ public: * * @param abilityObj Indicates the ability object. */ - void OnAbilityStart(const std::weak_ptr &abilityObj) override; + void OnAbilityStart(const std::weak_ptr &abilityObj) override; /** * Called when ability is in foreground. * * @param abilityObj Indicates the ability object. */ - void OnAbilityForeground(const std::weak_ptr &abilityObj) override; + void OnAbilityForeground(const std::weak_ptr &abilityObj) override; /** * Called when ability is in background. * * @param abilityObj Indicates the ability object. */ - void OnAbilityBackground(const std::weak_ptr &abilityObj) override; + void OnAbilityBackground(const std::weak_ptr &abilityObj) override; /** * Called when ability is stopped. * * @param abilityObj Indicates the ability object. */ - void OnAbilityStop(const std::weak_ptr &abilityObj) override; + void OnAbilityStop(const std::weak_ptr &abilityObj) override; /** * Called when window stage is created. * * @param abilityObj Indicates the ability object. */ - void OnWindowStageCreate(const std::weak_ptr &abilityObj) override; + void OnWindowStageCreate(const std::weak_ptr &abilityObj) override; /** * Called when window stage is restored. * * @param abilityObj Indicates the ability object. */ - void OnWindowStageRestore(const std::weak_ptr &abilityObj) override; + void OnWindowStageRestore(const std::weak_ptr &abilityObj) override; /** * Called when window stage is destroyed. * * @param abilityObj Indicates the ability object. */ - void OnWindowStageDestroy(const std::weak_ptr &abilityObj) override; + void OnWindowStageDestroy(const std::weak_ptr &abilityObj) override; private: std::shared_ptr jsMonitor_; diff --git a/frameworks/js/napi/app/ability_delegator/js_ability_delegator.cpp b/frameworks/js/napi/app/ability_delegator/js_ability_delegator.cpp index a609dc5ed261f4aa24be53a653f342e9a242596e..783c917c3a42376f2fb1bf659a43a51caad076e4 100644 --- a/frameworks/js/napi/app/ability_delegator/js_ability_delegator.cpp +++ b/frameworks/js/napi/app/ability_delegator/js_ability_delegator.cpp @@ -127,7 +127,8 @@ JSAbilityDelegator::JSAbilityDelegator() { auto delegator = AbilityDelegatorRegistry::GetAbilityDelegator(); if (delegator) { - auto clearFunc = [](const std::shared_ptr &property) { + auto clearFunc = [](const std::shared_ptr &baseProperty) { + auto property = std::static_pointer_cast(baseProperty); TAG_LOGI(AAFwkTag::DELEGATOR, "clearFunc called"); if (!property) { TAG_LOGE(AAFwkTag::DELEGATOR, "null property"); @@ -499,7 +500,6 @@ napi_value JSAbilityDelegator::OnRemoveAbilityStageMonitorSync(napi_env env, Nap napi_value JSAbilityDelegator::OnWaitAbilityMonitor(napi_env env, NapiCallbackInfo& info) { TAG_LOGI(AAFwkTag::DELEGATOR, "argc: %{public}d", static_cast(info.argc)); - std::shared_ptr monitor = nullptr; TimeoutCallback opt {false, false}; int64_t timeout = 0; @@ -508,7 +508,6 @@ napi_value JSAbilityDelegator::OnWaitAbilityMonitor(napi_env env, NapiCallbackIn return ThrowJsError(env, INCORRECT_PARAMETERS, "Parse monitor want failed, removeAbilityMonitor must be Monitor."); } - auto abilityObjectBox = std::make_shared(); NapiAsyncTask::ExecuteCallback execute = [monitor, timeout, opt, abilityObjectBox]() { TAG_LOGI(AAFwkTag::DELEGATOR, "execute called"); @@ -517,23 +516,22 @@ napi_value JSAbilityDelegator::OnWaitAbilityMonitor(napi_env env, NapiCallbackIn AAFwkTag::DELEGATOR, "null abilityObjectBox"); return; } - auto delegator = AbilityDelegatorRegistry::GetAbilityDelegator(); if (!delegator) { TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); return; } - - std::shared_ptr property = opt.hasTimeoutPara ? + std::shared_ptr property = opt.hasTimeoutPara ? delegator->WaitAbilityMonitor(monitor, timeout) : delegator->WaitAbilityMonitor(monitor); - if (!property || property->object_.expired()) { + auto jsProperty = std::static_pointer_cast(property); + if (!jsProperty || jsProperty->object_.expired()) { TAG_LOGE(AAFwkTag::DELEGATOR, "invalid property"); return; } - abilityObjectBox->object_ = property->object_; + abilityObjectBox->object_ = jsProperty->object_; std::unique_lock lck(g_mutexAbilityRecord); - g_abilityRecord.emplace(property->object_, property->token_); + g_abilityRecord.emplace(jsProperty->object_, jsProperty->token_); }; NapiAsyncTask::CompleteCallback complete = [abilityObjectBox](napi_env env, NapiAsyncTask &task, int32_t status) { @@ -581,14 +579,15 @@ napi_value JSAbilityDelegator::OnWaitAbilityStageMonitor(napi_env env, NapiCallb TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); return; } - std::shared_ptr result; + std::shared_ptr result; result = opt.hasTimeoutPara ? delegator->WaitAbilityStageMonitor(monitor, timeout) : delegator->WaitAbilityStageMonitor(monitor); - if (!result || result->object_.expired()) { + auto jsStageProperty = std::static_pointer_cast(result); + if (!jsStageProperty || jsStageProperty->object_.expired()) { TAG_LOGE(AAFwkTag::DELEGATOR, "waitAbilityStageMonitor failed"); return; } - abilityStageObjBox->object_ = result->object_; + abilityStageObjBox->object_ = jsStageProperty->object_; }; NapiAsyncTask::CompleteCallback complete = [abilityStageObjBox](napi_env env, NapiAsyncTask &task, int32_t status) { @@ -795,15 +794,16 @@ napi_value JSAbilityDelegator::OnGetCurrentTopAbility(napi_env env, NapiCallback } auto property = delegator->GetCurrentTopAbility(); - if (!property || property->object_.expired()) { - TAG_LOGE(AAFwkTag::DELEGATOR, "invalid property"); + auto jsProperty = std::static_pointer_cast(property); + if (!jsProperty || jsProperty->object_.expired()) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid jsProperty"); task.Reject(env, CreateJsError(env, COMMON_FAILED, "Calling GetCurrentTopAbility failed.")); } else { { std::unique_lock lck(g_mutexAbilityRecord); - g_abilityRecord.emplace(property->object_, property->token_); + g_abilityRecord.emplace(jsProperty->object_, jsProperty->token_); } - ResolveWithNoError(env, task, property->object_.lock()->GetNapiValue()); + ResolveWithNoError(env, task, jsProperty->object_.lock()->GetNapiValue()); } }; diff --git a/frameworks/native/ability/BUILD.gn b/frameworks/native/ability/BUILD.gn index e4f5a06ba62307af4ddfb2c27d0920d222498807..f0dd8b2acb4cd61a1f7b189d158e4563a5f485d4 100644 --- a/frameworks/native/ability/BUILD.gn +++ b/frameworks/native/ability/BUILD.gn @@ -59,10 +59,12 @@ ohos_shared_library("ability_context_native") { "ability_runtime/connection_manager.cpp", "ability_runtime/dialog_request_callback_impl.cpp", "ability_runtime/dialog_ui_extension_callback.cpp", + "ability_runtime/ets_extension_context.cpp", "ability_runtime/js_extension_context.cpp", "ability_runtime/local_call_container.cpp", "ability_runtime/local_call_record.cpp", "native/js_ui_extension_callback.cpp", + "native/sts_ui_extension_callback.cpp", ] deps = [ @@ -75,6 +77,7 @@ ohos_shared_library("ability_context_native") { "${ability_runtime_native_path}/ability/native:dialog_request_callback", "${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", ] external_deps = [ @@ -92,6 +95,8 @@ ohos_shared_library("ability_context_native") { "image_framework:image_native", "ipc:ipc_core", "napi:ace_napi", + "runtime_core:ani", + "bundle_framework:bms_ani_common", ] public_external_deps = [ "ability_base:extractortool", diff --git a/frameworks/native/ability/ability_runtime/ability_context_impl.cpp b/frameworks/native/ability/ability_runtime/ability_context_impl.cpp index 4e9e6400986b9ab290e60938f1cc063a1acdbf90..8e51b491e88fa1113050155820c1db69295f0eac 100644 --- a/frameworks/native/ability/ability_runtime/ability_context_impl.cpp +++ b/frameworks/native/ability/ability_runtime/ability_context_impl.cpp @@ -699,6 +699,13 @@ ErrCode AbilityContextImpl::RestoreWindowStage(napi_env env, napi_value contentS return ERR_OK; } +ErrCode AbilityContextImpl::RestoreWindowStage(NativeReference* contentStorage) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "called"); + contentStorage_ = std::unique_ptr(contentStorage); + return ERR_OK; +} + ErrCode AbilityContextImpl::StartAbilityByCall( const AAFwk::Want& want, const std::shared_ptr& callback, int32_t accountId) { diff --git a/frameworks/native/ability/ability_runtime/ets_extension_context.cpp b/frameworks/native/ability/ability_runtime/ets_extension_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ece2571d88e16589ed1f7c40ba14d84ee5f92d3b --- /dev/null +++ b/frameworks/native/ability/ability_runtime/ets_extension_context.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_context.h" +#include "ani_common_configuration.h" +#include "hilog_tag_wrapper.h" +#include "common_fun_ani.h" +#include "sts_context_utils.h" + +namespace OHOS { +namespace AbilityRuntime { + +bool SetExtensionAbilityInfo(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context, std::shared_ptr abilityInfo) +{ + bool iRet = false; + if (aniEnv == nullptr || context == nullptr || abilityInfo == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "aniEnv or context or abilityInfo is nullptr"); + return iRet; + } + auto hapModuleInfo = context->GetHapModuleInfo(); + ani_status status = ANI_OK; + if (abilityInfo && hapModuleInfo) { + auto isExist = [&abilityInfo](const OHOS::AppExecFwk::ExtensionAbilityInfo& info) { + TAG_LOGD(AAFwkTag::CONTEXT, "%{public}s, %{public}s", info.bundleName.c_str(), info.name.c_str()); + return info.bundleName == abilityInfo->bundleName && info.name == abilityInfo->name; + }; + auto infoIter = std::find_if( + hapModuleInfo->extensionInfos.begin(), hapModuleInfo->extensionInfos.end(), isExist); + if (infoIter == hapModuleInfo->extensionInfos.end()) { + TAG_LOGE(AAFwkTag::CONTEXT, "set extensionAbilityInfo fail"); + return iRet; + } + ani_field extensionAbilityInfoField; + status = aniEnv->Class_FindField(contextClass, "extensionAbilityInfo", &extensionAbilityInfoField); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return iRet; + } + ani_object extAbilityInfoObj = OHOS::AppExecFwk::CommonFunAni::ConvertExtensionInfo(aniEnv, *infoIter); + status = aniEnv->Object_SetField_Ref(contextObj, extensionAbilityInfoField, + reinterpret_cast(extAbilityInfoObj)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return iRet; + } + iRet = true; + } + return iRet; +} + +bool SetConfiguration( + ani_env *env, ani_class cls, ani_object contextObj, const std::shared_ptr &context) +{ + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "aniEnv or context is nullptr"); + return false; + } + + ani_field field = nullptr; + auto configuration = context->GetConfiguration(); + ani_ref configurationRef = OHOS::AppExecFwk::WrapConfiguration(env, *configuration); + + ani_status status = env->Class_FindField(cls, "config", &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return false; + } + + status = env->Object_SetField_Ref(contextObj, field, configurationRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return false; + } + return true; +} + +void CreatEtsExtensionContext(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context, + std::shared_ptr abilityInfo) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "CreatEtsExtensionContext Call"); + if (aniEnv == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "aniEnv or context is nullptr"); + return; + } + + if (!SetExtensionAbilityInfo(aniEnv, contextClass, contextObj, context, abilityInfo)) { + TAG_LOGE(AAFwkTag::CONTEXT, "SetExtensionAbilityInfo fail"); + return; + } + + if (!SetConfiguration(aniEnv, contextClass, contextObj, context)) { + TAG_LOGE(AAFwkTag::CONTEXT, "SetConfiguration fail"); + return; + } +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/ability/native/BUILD.gn b/frameworks/native/ability/native/BUILD.gn index ebe5d632aa080acd2ab8db3ce26e2629cc63f678..29d0c9bd676209e1b2f750dbad874f5ffb5d6774 100644 --- a/frameworks/native/ability/native/BUILD.gn +++ b/frameworks/native/ability/native/BUILD.gn @@ -122,6 +122,7 @@ ohos_shared_library("abilitykit_utils") { branch_protector_ret = "pac_ret" include_dirs = [ + "${ability_runtime_path}/interfaces/inner_api/runtime/include", "${ability_runtime_path}/interfaces/kits/native/ability/native", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", "${ability_runtime_innerkits_path}/ability_manager/include", @@ -255,8 +256,10 @@ ohos_shared_library("abilitykit_native") { branch_protector_ret = "pac_ret" include_dirs = [ + "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", "${ability_runtime_path}/utils/global/time/include", "${ability_runtime_path}/interfaces/kits/native/ability/native/ui_service_extension_ability/connection", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", ] sources = [ @@ -274,6 +277,8 @@ ohos_shared_library("abilitykit_native") { "${ability_runtime_native_path}/ability/native/ability_runtime/js_ability_context.cpp", "${ability_runtime_native_path}/ability/native/ability_runtime/js_caller_complex.cpp", "${ability_runtime_native_path}/ability/native/ability_runtime/js_uiservice_ability_connection.cpp", + "${ability_runtime_native_path}/ability/native/ability_runtime/sts_ability_context.cpp", + "${ability_runtime_native_path}/ability/native/ability_runtime/sts_caller_complex.cpp", "${ability_runtime_native_path}/ability/native/ability_runtime/ui_ability_servicehost_stub_impl.cpp", "${ability_runtime_native_path}/ability/native/continuation/distributed/continuation_handler.cpp", "${ability_runtime_native_path}/ability/native/continuation/distributed/continuation_manager.cpp", @@ -291,6 +296,7 @@ ohos_shared_library("abilitykit_native") { "${ability_runtime_native_path}/ability/native/query_erms_observer_proxy.cpp", "${ability_runtime_native_path}/ability/native/query_erms_observer_stub.cpp", "${ability_runtime_native_path}/ability/native/service_ability_impl.cpp", + "${ability_runtime_native_path}/ability/native/sts_free_install_observer.cpp", "${ability_runtime_native_path}/appkit/app/app_context.cpp", "${ability_runtime_native_path}/appkit/app/context_container.cpp", "${ability_runtime_native_path}/appkit/app/context_deal.cpp", @@ -328,6 +334,7 @@ ohos_shared_library("abilitykit_native") { "${ability_runtime_native_path}/appkit:app_context_utils", "${ability_runtime_native_path}/appkit:appkit_delegator", "${ability_runtime_native_path}/appkit:appkit_manager_helper", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", "${ability_runtime_path}/utils/global/freeze:freeze_util", "${ability_runtime_services_path}/common:app_util", "${ability_runtime_services_path}/common:event_report", @@ -342,7 +349,9 @@ ohos_shared_library("abilitykit_native") { "access_token:libaccesstoken_sdk", "access_token:libtoken_callback_sdk", "access_token:libtokenid_sdk", + "ace_engine:ace_uicontent", "bundle_framework:appexecfwk_base", + "bundle_framework:bms_ani_common", "c_utils:utils", "common_event_service:cesfwk_innerkits", "eventhandler:libeventhandler", @@ -352,10 +361,13 @@ ohos_shared_library("abilitykit_native") { "init:libbegetutil", "ipc:ipc_core", "ipc:ipc_napi", + "ipc:rpc_ani", "ipc:rpc", "json:nlohmann_json_static", "napi:ace_napi", "resource_management:global_resmgr", + "runtime_core:ani", + "runtime_core:ani_helpers", "samgr:samgr_proxy", "window_manager:windowstage_kit", ] @@ -664,6 +676,7 @@ config("insight_intent_executor_public_config") { ohos_shared_library("insight_intent_executor") { sources = [ + "${ability_runtime_native_path}/ability/native/insight_intent_executor/ets_insight_intent_executor.cpp", "${ability_runtime_native_path}/ability/native/insight_intent_executor/insight_intent_executor.cpp", "${ability_runtime_native_path}/ability/native/insight_intent_executor/insight_intent_executor_mgr.cpp", "${ability_runtime_native_path}/ability/native/insight_intent_executor/js_insight_intent_executor.cpp", @@ -678,6 +691,7 @@ ohos_shared_library("insight_intent_executor") { "${ability_runtime_napi_path}/inner/napi_common:napi_common", "${ability_runtime_native_path}/ability/native:ability_business_error", "${ability_runtime_native_path}/insight_intent/insight_intent_context:insightintentcontext", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", ] external_deps = [ @@ -693,6 +707,7 @@ ohos_shared_library("insight_intent_executor") { "ipc:ipc_core", "ipc:ipc_napi", "napi:ace_napi", + "runtime_core:ani", "window_manager:libwm", ] @@ -726,6 +741,7 @@ config("uiability_config") { ohos_shared_library("uiabilitykit_native") { include_dirs = [ + "${ability_runtime_path}/frameworks/ets/ani/ani_common/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", @@ -734,6 +750,7 @@ ohos_shared_library("uiabilitykit_native") { sources = [ "${ability_runtime_native_path}/ability/native/ability_runtime/js_ui_ability.cpp", + "${ability_runtime_native_path}/ability/native/ability_runtime/sts_ui_ability.cpp", "${ability_runtime_native_path}/ability/native/continuation/distributed/continuation_handler_stage.cpp", "${ability_runtime_native_path}/ability/native/continuation/distributed/continuation_manager_stage.cpp", "${ability_runtime_native_path}/ability/native/continuation/distributed/reverse_continuation_scheduler_primary_stage.cpp", @@ -764,6 +781,7 @@ ohos_shared_library("uiabilitykit_native") { "${ability_runtime_native_path}/appkit:app_context", "${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}/utils/global/freeze:freeze_util", "${ability_runtime_services_path}/common:event_report", ] @@ -782,8 +800,11 @@ ohos_shared_library("uiabilitykit_native") { "hitrace:hitrace_meter", "ipc:ipc_core", "ipc:ipc_napi", + "ipc:rpc_ani", "resource_management:global_resmgr", + "runtime_core:ani", "samgr:samgr_proxy", + "window_manager:windowstageani_kit", ] public_external_deps = [ "bundle_framework:appexecfwk_core", @@ -904,6 +925,7 @@ ohos_shared_library("form_extension") { defines += [ "AMS_LOG_DOMAIN = 0xD001300" ] if (ability_runtime_graphics) { include_dirs = [ + "${ability_runtime_path}/frameworks/ets/ani/form_extension_ability/include", "${ability_runtime_path}/interfaces/kits/native/ability/native", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime", ] @@ -914,6 +936,8 @@ ohos_shared_library("form_extension") { "${ability_runtime_native_path}/ability/native/form_runtime/js_form_extension.cpp", "${ability_runtime_native_path}/ability/native/form_runtime/js_form_extension_context.cpp", "${ability_runtime_native_path}/appkit/ability_runtime/form_extension_context.cpp", + "${ability_runtime_path}/frameworks/ets/ani/form_extension_ability/src/sts_form_extension.cpp", + "${ability_runtime_path}/frameworks/ets/ani/form_extension_ability/src/sts_form_extension_context.cpp", ] deps = [ @@ -924,6 +948,7 @@ ohos_shared_library("form_extension") { "${ability_runtime_native_path}/ability:ability_context_native", "${ability_runtime_native_path}/ability/native:ability_business_error", "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", ] external_deps = [ @@ -937,6 +962,7 @@ ohos_shared_library("form_extension") { "ipc:ipc_core", "ipc:ipc_napi", "napi:ace_napi", + "runtime_core:ani", ] if (form_fwk_enable) { @@ -1000,6 +1026,8 @@ ohos_shared_library("service_extension") { defines = [ "AMS_LOG_TAG = \"Ability\"" ] defines += [ "AMS_LOG_DOMAIN = 0xD001300" ] include_dirs = [ + "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", + "${ability_runtime_path}/frameworks/ets/ani/service_extension_ability/include", "${ability_runtime_path}/interfaces/kits/native/ability/native", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime", ] @@ -1009,6 +1037,8 @@ ohos_shared_library("service_extension") { "${ability_runtime_native_path}/ability/native/js_service_extension_context.cpp", "${ability_runtime_native_path}/ability/native/service_extension.cpp", "${ability_runtime_native_path}/appkit/ability_runtime/service_extension_context.cpp", + "${ability_runtime_path}/frameworks/ets/ani/service_extension_ability/src/sts_service_extension.cpp", + "${ability_runtime_path}/frameworks/ets/ani/service_extension_ability/src/sts_service_extension_context.cpp", ] deps = [ @@ -1024,6 +1054,8 @@ ohos_shared_library("service_extension") { "${ability_runtime_native_path}/ability/native:insight_intent_executor", "${ability_runtime_native_path}/appkit:app_context", "${ability_runtime_native_path}/insight_intent/insight_intent_context:insightintentcontext", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_native_path}/appkit:app_context_utils", ] external_deps = [ @@ -1037,9 +1069,12 @@ ohos_shared_library("service_extension") { "hitrace:hitrace_meter", "ipc:ipc_core", "ipc:ipc_napi", + "ipc:rpc_ani", "napi:ace_napi", + "runtime_core:ani", "safwk:system_ability_fwk", "samgr:samgr_proxy", + "bundle_framework:bms_ani_common", ] if (ability_runtime_graphics) { @@ -1551,7 +1586,12 @@ config("ui_extension_public_config") { } ohos_shared_library("ui_extension") { - include_dirs = [ "${ability_runtime_path}/interfaces/kits/native/ability/native/ui_service_extension_ability/connection" ] + include_dirs = [ + "${ability_runtime_path}/interfaces/kits/native/ability/native/ui_service_extension_ability/connection", + "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", + "${ability_runtime_path}/frameworks/ets/ani/ui_extension_ability/include", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", + ] sources = [ "${ability_runtime_native_path}/ability/native/ui_extension_ability/js_embeddable_ui_ability_context.cpp", "${ability_runtime_native_path}/ability/native/ui_extension_ability/js_ui_extension.cpp", @@ -1562,6 +1602,9 @@ ohos_shared_library("ui_extension") { "${ability_runtime_native_path}/ability/native/ui_extension_base/js_uiservice_uiext_connection.cpp", "${ability_runtime_native_path}/ability/native/ui_extension_base/ui_extension_context.cpp", "${ability_runtime_native_path}/ability/native/ui_extension_base/ui_extension_servicehost_stub_impl.cpp", + "${ability_runtime_path}/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension.cpp", + "${ability_runtime_path}/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension_content_session.cpp", + "${ability_runtime_path}/frameworks/ets/ani/ui_extension_ability/src/sts_ui_extension_context.cpp", ] public_configs = [ ":ui_extension_public_config" ] @@ -1580,6 +1623,7 @@ ohos_shared_library("ui_extension") { "${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_path}/frameworks/ets/ani/ani_common:ani_common", ] external_deps = [ @@ -1589,6 +1633,7 @@ ohos_shared_library("ui_extension") { "ability_base:zuri", "access_token:libaccesstoken_sdk", "access_token:libtokenid_sdk", + "bundle_framework:bms_ani_common", "c_utils:utils", "eventhandler:libeventhandler", "hilog:libhilog", @@ -1596,7 +1641,9 @@ ohos_shared_library("ui_extension") { "ipc:ipc_core", "ipc:ipc_napi", "napi:ace_napi", + "runtime_core:ani", "window_manager:embeddablewindowstage_kit", + "window_manager:embeddablewindowstageani_kit", "window_manager:extensionwindow_napi", "window_manager:windowstage_kit", ] @@ -2314,6 +2361,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" ] @@ -2343,6 +2426,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_loader.cpp b/frameworks/native/ability/native/ability_loader.cpp index 1c26bd9c57a4b15d9a00a68a3e7fae84e03eb1b1..b3b20bbcb7344f6f14b5730c2c55fb751d4f83b5 100644 --- a/frameworks/native/ability/native/ability_loader.cpp +++ b/frameworks/native/ability/native/ability_loader.cpp @@ -52,21 +52,23 @@ Ability *AbilityLoader::GetAbilityByName(const std::string &abilityName) return nullptr; } -AbilityRuntime::Extension *AbilityLoader::GetExtensionByName(const std::string &abilityName) +AbilityRuntime::Extension *AbilityLoader::GetExtensionByName(const std::string &abilityName, + const std::string &language) { auto it = extensions_.find(abilityName); if (it != extensions_.end()) { - return it->second(); + return it->second(language); } - TAG_LOGE(AAFwkTag::ABILITY, "failed:%{public}s", abilityName.c_str()); + TAG_LOGI(AAFwkTag::ABILITY, "failed:%{public}s", abilityName.c_str()); return nullptr; } -AbilityRuntime::UIAbility *AbilityLoader::GetUIAbilityByName(const std::string &abilityName) +AbilityRuntime::UIAbility *AbilityLoader::GetUIAbilityByName(const std::string &abilityName, + const std::string &language) { auto it = uiAbilities_.find(abilityName); if (it != uiAbilities_.end()) { - return it->second(); + return it->second(language); } TAG_LOGE(AAFwkTag::ABILITY, "failed:%{public}s", abilityName.c_str()); return nullptr; diff --git a/frameworks/native/ability/native/ability_runtime/js_ui_ability.cpp b/frameworks/native/ability/native/ability_runtime/js_ui_ability.cpp index fdb6b8341508f60ff51120277cd6c277701c7b0f..aa29748f1839887dab42d90f289398ebeba13ce1 100644 --- a/frameworks/native/ability/native/ability_runtime/js_ui_ability.cpp +++ b/frameworks/native/ability/native/ability_runtime/js_ui_ability.cpp @@ -44,6 +44,7 @@ #include "js_window_stage.h" #include "scene_board_judgement.h" #endif +#include "ohos_application.h" #include "napi_common_configuration.h" #include "napi_common_want.h" #include "napi_remote_object.h" @@ -122,12 +123,11 @@ napi_value OnPrepareTerminatePromiseCallback(napi_env env, napi_callback_info in TAG_LOGI(AAFwkTag::UIABILITY, "OnPrepareTerminatePromiseCallback end"); return nullptr; } -} // namespace -napi_value AttachJsAbilityContext(napi_env env, void *value, void *extValue) +napi_value AttachJsAbilityContext(napi_env env, void *value, void *) { TAG_LOGD(AAFwkTag::UIABILITY, "called"); - if (value == nullptr || extValue == nullptr) { + if (value == nullptr) { TAG_LOGE(AAFwkTag::UIABILITY, "invalid params"); return nullptr; } @@ -137,26 +137,22 @@ napi_value AttachJsAbilityContext(napi_env env, void *value, void *extValue) return nullptr; } std::shared_ptr systemModule = nullptr; - auto screenModePtr = reinterpret_cast *>(extValue)->lock(); - if (screenModePtr == nullptr) { - TAG_LOGE(AAFwkTag::UIABILITY, "null screenModePtr"); - return nullptr; - } - if (*screenModePtr == AAFwk::IDLE_SCREEN_MODE) { + int32_t screenMode = ptr->GetScreenMode(); + if (screenMode == AAFwk::IDLE_SCREEN_MODE) { auto uiAbiObject = CreateJsAbilityContext(env, ptr); CHECK_POINTER_AND_RETURN(uiAbiObject, nullptr); systemModule = std::shared_ptr(JsRuntime::LoadSystemModuleByEngine(env, "application.AbilityContext", &uiAbiObject, 1).release()); } else { auto emUIObject = JsEmbeddableUIAbilityContext::CreateJsEmbeddableUIAbilityContext(env, - ptr, nullptr, *screenModePtr); + ptr, nullptr, screenMode); CHECK_POINTER_AND_RETURN(emUIObject, nullptr); systemModule = std::shared_ptr(JsRuntime::LoadSystemModuleByEngine(env, "application.EmbeddableUIAbilityContext", &emUIObject, 1).release()); } CHECK_POINTER_AND_RETURN(systemModule, nullptr); auto contextObj = systemModule->GetNapiValue(); - napi_coerce_to_native_binding_object(env, contextObj, DetachCallbackFunc, AttachJsAbilityContext, value, extValue); + napi_coerce_to_native_binding_object(env, contextObj, DetachCallbackFunc, AttachJsAbilityContext, value, nullptr); auto workContext = new (std::nothrow) std::weak_ptr(ptr); if (workContext != nullptr) { napi_status status = napi_wrap(env, contextObj, workContext, @@ -174,6 +170,30 @@ napi_value AttachJsAbilityContext(napi_env env, void *value, void *extValue) return contextObj; } +void BindContext(napi_env env, std::unique_ptr contextRef, JsRuntime& jsRuntime, + const std::shared_ptr abilityContext) +{ + CHECK_POINTER(contextRef); + napi_value contextObj = contextRef->GetNapiValue(); + if (!CheckTypeForNapiValue(env, contextObj, napi_object)) { + TAG_LOGE(AAFwkTag::UIABILITY, "get ability native object failed"); + return; + } + auto workContext = new (std::nothrow) std::weak_ptr(abilityContext); + CHECK_POINTER(workContext); + napi_coerce_to_native_binding_object( + env, contextObj, DetachCallbackFunc, AttachJsAbilityContext, workContext, nullptr); + abilityContext->Bind(jsRuntime, contextRef.release()); + napi_wrap( + env, contextObj, workContext, + [](napi_env, void* data, void* hint) { + TAG_LOGD(AAFwkTag::UIABILITY, "finalizer for weak_ptr ability context is called"); + delete static_cast*>(data); + }, + nullptr, nullptr); +} +} // namespace + UIAbility *JsUIAbility::Create(const std::unique_ptr &runtime) { return new (std::nothrow) JsUIAbility(static_cast(*runtime)); @@ -256,6 +276,50 @@ void JsUIAbility::UpdateAbilityObj(std::shared_ptr abilityInfo, false, abilityInfo->srcEntrance); } +void JsUIAbility::CreateAndBindContext(const std::shared_ptr application, + const std::shared_ptr record, + const std::shared_ptr abilityContext, + const std::unique_ptr& runtime) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (application == nullptr || record == nullptr || abilityContext == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null application or record or abilityContext"); + return; + } + if (runtime == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null runtime"); + return; + } + auto& jsRuntime = static_cast(*runtime); + HandleScope handleScope(jsRuntime); + napi_env env = jsRuntime.GetNapiEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + auto want = record->GetWant(); + if (want == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null want"); + return; + } + int32_t screenMode = want->GetIntParam(AAFwk::SCREEN_MODE_KEY, AAFwk::ScreenMode::IDLE_SCREEN_MODE); + abilityContext->SetScreenMode(screenMode); + + std::unique_ptr contextRef; + if (screenMode == AAFwk::IDLE_SCREEN_MODE) { + napi_value contextObj = CreateJsAbilityContext(env, abilityContext); + CHECK_POINTER(contextObj); + contextRef = JsRuntime::LoadSystemModuleByEngine(env, "application.AbilityContext", &contextObj, 1); + } else { + napi_value contextObj = + JsEmbeddableUIAbilityContext::CreateJsEmbeddableUIAbilityContext(env, abilityContext, nullptr, screenMode); + CHECK_POINTER(contextObj); + contextRef = JsRuntime::LoadSystemModuleByEngine(env, "application.EmbeddableUIAbilityContext", &contextObj, 1); + } + + BindContext(env, std::move(contextRef), jsRuntime, abilityContext); +} + void JsUIAbility::SetAbilityContext(std::shared_ptr abilityInfo, std::shared_ptr want, const std::string &moduleName, const std::string &srcPath) { @@ -274,6 +338,7 @@ void JsUIAbility::SetAbilityContext(std::shared_ptr abilityInfo, } napi_value contextObj = nullptr; int32_t screenMode = want->GetIntParam(AAFwk::SCREEN_MODE_KEY, AAFwk::ScreenMode::IDLE_SCREEN_MODE); + abilityContext_->SetScreenMode(screenMode); CreateJSContext(env, contextObj, screenMode); CHECK_POINTER(shellContextRef_); contextObj = shellContextRef_->GetNapiValue(); @@ -283,15 +348,9 @@ void JsUIAbility::SetAbilityContext(std::shared_ptr abilityInfo, } auto workContext = new (std::nothrow) std::weak_ptr(abilityContext_); CHECK_POINTER(workContext); - screenModePtr_ = std::make_shared(screenMode); - auto workScreenMode = new (std::nothrow) std::weak_ptr(screenModePtr_); - if (workScreenMode == nullptr) { - TAG_LOGE(AAFwkTag::UIABILITY, "null workScreenMode"); - delete workContext; - return; - } + napi_coerce_to_native_binding_object( - env, contextObj, DetachCallbackFunc, AttachJsAbilityContext, workContext, workScreenMode); + env, contextObj, DetachCallbackFunc, AttachJsAbilityContext, workContext, nullptr); abilityContext_->Bind(jsRuntime_, shellContextRef_.get()); napi_set_named_property(env, obj, "context", contextObj); TAG_LOGD(AAFwkTag::UIABILITY, "set ability context"); @@ -302,15 +361,12 @@ void JsUIAbility::SetAbilityContext(std::shared_ptr abilityInfo, [](napi_env, void *data, void *hint) { TAG_LOGD(AAFwkTag::UIABILITY, "finalizer for weak_ptr ability context is called"); delete static_cast *>(data); - delete static_cast *>(hint); - }, workScreenMode, nullptr); + }, nullptr, nullptr); if (status != napi_ok && workContext != nullptr) { TAG_LOGE(AAFwkTag::UIABILITY, "napi_wrap Failed: %{public}d", status); delete workContext; - delete workScreenMode; return; } - TAG_LOGI(AAFwkTag::UIABILITY, "End"); } @@ -961,7 +1017,7 @@ void JsUIAbility::DoOnForeground(const Want &want) } OnWillForeground(); - + TAG_LOGD(AAFwkTag::UIABILITY, "move scene to foreground, sceneFlag_: %{public}d", UIAbility::sceneFlag_); AddLifecycleEventBeforeJSCall(FreezeUtil::TimeoutState::FOREGROUND, METHOD_NAME); HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, "scene_->GoForeground"); diff --git a/frameworks/native/ability/native/ability_runtime/sts_ability_context.cpp b/frameworks/native/ability/native/ability_runtime/sts_ability_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..724f7d86fd044229ea89f032a78dc4a2fead2674 --- /dev/null +++ b/frameworks/native/ability/native/ability_runtime/sts_ability_context.cpp @@ -0,0 +1,1066 @@ +/* + * 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 "ability_runtime/sts_ability_context.h" + +#include +#include +#include +#include +#include + +#include "ability_manager_client.h" +#include "ability_manager_errors.h" +#include "ability_business_error.h" +#include "app_utils.h" +#include "event_handler.h" +#include "hilog_tag_wrapper.h" +#include "hitrace_meter.h" +#include "interop_js/arkts_esvalue.h" +#include "interop_js/hybridgref_ani.h" +#include "interop_js/hybridgref_napi.h" +#include "ipc_skeleton.h" +#include "sts_data_struct_converter.h" +#include "mission_info.h" +#include "ani_common_want.h" +#include "ani_common_start_options.h" +#include "ani_common_configuration.h" +#include "ani_common_ability_result.h" +#include "ani_enum_convert.h" +#include "open_link_options.h" +#include "start_options.h" +#include "sts_ui_extension_callback.h" +#include "tokenid_kit.h" +#include "ui_ability_servicehost_stub_impl.h" +#include "ui_service_extension_connection_constants.h" +#include "uri.h" +#include "want.h" +#include "common_fun_ani.h" +#include "sts_caller_complex.h" +#include "sts_context_utils.h" +#include "sts_error_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +std::mutex StsAbilityContext::requestCodeMutex_; +const std::string APP_LINKING_ONLY = "appLinkingOnly"; +namespace { + static std::once_flag g_bindNativeMethodsFlag; + +constexpr const char* UI_ABILITY_CONTEXT_CLASS_NAME = "Lapplication/UIAbilityContext/UIAbilityContext;"; +constexpr int32_t CALLER_TIME_OUT = 10; // 10s +struct StartAbilityByCallData { + sptr remoteCallee; + std::mutex mutexlock; + std::condition_variable condition; +}; + +void GenerateCallerCallBack(std::shared_ptr calls, + std::shared_ptr callerCallBack) +{ + if (calls == nullptr || callerCallBack == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null calls or null callerCallBack"); + return; + } + auto callBackDone = [weakData = std::weak_ptr(calls)] (const sptr &obj) { + TAG_LOGI(AAFwkTag::UIABILITY, "callBackDone called start"); + auto calldata = weakData.lock(); + if (calldata == nullptr) { + TAG_LOGW(AAFwkTag::UIABILITY, "calldata released"); + return; + } + std::lock_guard lock(calldata->mutexlock); + calldata->remoteCallee = obj; + calldata->condition.notify_all(); + }; + + callerCallBack->SetCallBack(callBackDone); +} + +void WaitForCalleeObj(std::shared_ptr callData) +{ + if (callData == nullptr) { + return; + } + if (callData->remoteCallee == nullptr) { + std::unique_lock lock(callData->mutexlock); + if (callData->remoteCallee != nullptr) { + return; + } + if (callData->condition.wait_for(lock, std::chrono::seconds(CALLER_TIME_OUT)) == std::cv_status::timeout) { + TAG_LOGE(AAFwkTag::UIABILITY, "callExecute waiting callee timeout"); + } + } +} +} +std::shared_ptr StsAbilityContext::GetAbilityContext(ani_env *env, ani_object aniObj) +{ + ani_long nativeContextLong; + ani_class cls {}; + ani_field contextField = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return nullptr; + } + if ((status = env->FindClass(UI_ABILITY_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeContext", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_GetField_Long(aniObj, contextField, &nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return nullptr; + } + auto weakContext = reinterpret_cast*>(nativeContextLong); + return weakContext != nullptr ? weakContext->lock() : nullptr; +} + +ani_object StsAbilityContext::SetAbilityContext(ani_env *env, const std::shared_ptr &context) +{ + ani_class cls {}; + ani_status status = ANI_ERROR; + ani_object contextObj = nullptr; + ani_method method {}; + ani_field field = nullptr; + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null context"); + return nullptr; + } + if ((status = env->FindClass(UI_ABILITY_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeContext", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return nullptr; + } + auto workContext = new (std::nothrow) std::weak_ptr(context); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "workContext nullptr"); + return nullptr; + } + ani_long nativeContextLong = (ani_long)workContext; + + if ((status = env->Object_SetField_Long(contextObj, field, nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + delete workContext; + workContext = nullptr; + return nullptr; + } + return contextObj; +} + +void StsAbilityContext::InheritWindowMode(ani_env *env, ani_object aniObj, AAFwk::Want &want) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "called"); +#ifdef SUPPORT_SCREEN + // only split mode need inherit + auto context = GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "context null"); + return; + } + auto windowMode = context->GetCurrentWindowMode(); + if (AAFwk::AppUtils::GetInstance().IsInheritWindowSplitScreenMode() && + (windowMode == AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY || + windowMode == AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY)) { + want.SetParam(AAFwk::Want::PARAM_RESV_WINDOW_MODE, windowMode); + } + TAG_LOGD(AAFwkTag::CONTEXT, "window mode is %{public}d", windowMode); +#endif +} + +void StsAbilityContext::AddFreeInstallObserver(ani_env *env, const AAFwk::Want &want, ani_object callback, + const std::shared_ptr &context, bool isOpenLink) +{ + // adapter free install async return install and start result + TAG_LOGD(AAFwkTag::CONTEXT, "called"); + int ret = 0; + if (!context) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + return; + } + if (freeInstallObserver_ == nullptr) { + ani_vm *etsVm = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GetVM(&etsVm)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + } + freeInstallObserver_ = new StsFreeInstallObserver(etsVm); + ret = context->AddFreeInstallObserver(freeInstallObserver_); + } + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "addFreeInstallObserver error"); + } + std::string startTime = want.GetStringParam(AAFwk::Want::PARAM_RESV_START_TIME); + if (isOpenLink) { + std::string url = want.GetUriString(); + freeInstallObserver_->AddStsObserverObject(env, startTime, url, callback); + return; + } + TAG_LOGI(AAFwkTag::CONTEXT, "addStsObserver"); + std::string bundleName = want.GetElement().GetBundleName(); + std::string abilityName = want.GetElement().GetAbilityName(); + freeInstallObserver_->AddStsObserverObject( + env, bundleName, abilityName, startTime, callback); +} + +void StsAbilityContext::StartAbilityInner([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + ani_object wantObj, ani_object opt, ani_object call) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + AAFwk::Want want; + OHOS::AppExecFwk::UnwrapWant(env, wantObj, want); + auto context = StsAbilityContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "context null"); + ThrowStsInvalidParamError(env, "context null"); + return; + } + InheritWindowMode(env, aniObj, want); + + if ((want.GetFlags() & AAFwk::Want::FLAG_INSTALL_ON_DEMAND) == AAFwk::Want::FLAG_INSTALL_ON_DEMAND) { + std::string startTime = std::to_string(std::chrono::duration_cast(std::chrono:: + system_clock::now().time_since_epoch()).count()); + want.SetParam(AAFwk::Want::PARAM_RESV_START_TIME, startTime); + AddFreeInstallObserver(env, want, call, context); + } + ErrCode innerErrCode = ERR_OK; + if (opt != nullptr) { + AAFwk::StartOptions startOptions; + OHOS::AppExecFwk::UnwrapStartOptionsWithProcessOption(env, opt, startOptions); + innerErrCode = context->StartAbility(want, startOptions, -1); + } else { + innerErrCode = context->StartAbility(want, -1); + } + ani_object aniObject = CreateStsError(env, AbilityErrorCode::ERROR_OK); + if (innerErrCode != ERR_OK) { + aniObject = CreateStsErrorByNativeErr(env, innerErrCode); + } + if ((want.GetFlags() & AAFwk::Want::FLAG_INSTALL_ON_DEMAND) == AAFwk::Want::FLAG_INSTALL_ON_DEMAND) { + if (innerErrCode != ERR_OK && freeInstallObserver_ != nullptr) { + std::string bundleName = want.GetElement().GetBundleName(); + std::string abilityName = want.GetElement().GetAbilityName(); + std::string startTime = want.GetStringParam(AAFwk::Want::PARAM_RESV_START_TIME); + freeInstallObserver_->OnInstallFinished(bundleName, abilityName, startTime, innerErrCode); + } + } else { + AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + } +} + +void StsAbilityContext::StartAbility1([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + ani_object wantObj, ani_object call) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + GetInstance().StartAbilityInner(env, aniObj, wantObj, nullptr, call); +} + +void StsAbilityContext::StartAbility2([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + ani_object wantObj, ani_object opt, ani_object call) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + GetInstance().StartAbilityInner(env, aniObj, wantObj, opt, call); +} + +int32_t StsAbilityContext::GenerateRequestCode() +{ + static int32_t curRequestCode_ = 0; + std::lock_guard lock(requestCodeMutex_); + curRequestCode_ = (curRequestCode_ == INT_MAX) ? 0 : (curRequestCode_ + 1); + return curRequestCode_; +} + +// TO DO: free install +void StsAbilityContext::StartAbilityForResultInner(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object startOptionsObj, ani_object callback) +{ + auto context = StsAbilityContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "GetAbilityContext is nullptr"); + ThrowStsErrorByNativeErr(env, static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)); + return; + } + AAFwk::Want want; + OHOS::AppExecFwk::UnwrapWant(env, wantObj, want); + AAFwk::StartOptions startOptions; + if (startOptionsObj) { + OHOS::AppExecFwk::UnwrapStartOptions(env, startOptionsObj, startOptions); + } + TAG_LOGE(AAFwkTag::UIABILITY, "displayId:%{public}d", startOptions.GetDisplayID()); + std::string startTime = std::to_string(std::chrono::duration_cast(std::chrono:: + system_clock::now().time_since_epoch()).count()); + 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) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + return; + } + RuntimeTask task = [etsVm, callbackRef, element = want.GetElement(), flags = want.GetFlags(), startTime] + (int resultCode, const AAFwk::Want &want, bool isInner) { + TAG_LOGD(AAFwkTag::CONTEXT, "start async callback"); + ani_status status = ANI_ERROR; + ani_env *env = nullptr; + if ((status = etsVm->GetEnv(ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + 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; + } + auto errCode = isInner ? resultCode : 0; + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, errCode), abilityResult); + }; + auto requestCode = GenerateRequestCode(); + (startOptionsObj == nullptr) ? context->StartAbilityForResult(want, requestCode, std::move(task)) : + context->StartAbilityForResult(want, startOptions, requestCode, std::move(task)); + return; +} + +// TO DO: free install +void StsAbilityContext::StartAbilityForResult1(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + StartAbilityForResultInner(env, aniObj, wantObj, nullptr, callback); +} + +// TO DO: free install +void StsAbilityContext::StartAbilityForResult2(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object startOptionsObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + StartAbilityForResultInner(env, aniObj, wantObj, startOptionsObj, callback); +} + +void StsAbilityContext::TerminateSelf( + ani_env *env, ani_object aniObj, ani_object callback) +{ + ani_object aniObject = nullptr; + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + auto context = StsAbilityContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "context null"); + aniObject = CreateStsInvalidParamError(env, "context null"); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); + return; + } + ErrCode ret = context->TerminateSelf(); + if (ret == static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT) || ret == ERR_OK) { + aniObject = CreateStsError(env, static_cast(ret)); + } else { + aniObject = CreateStsErrorByNativeErr(env, static_cast(ret)); + } + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); +} + +void StsAbilityContext::TerminateSelfWithResult( + ani_env *env, ani_object aniObj, ani_object abilityResult, ani_object callback) +{ + ani_object aniObject = nullptr; + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + auto context = StsAbilityContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "GetAbilityContext is nullptr"); + aniObject = CreateStsInvalidParamError(env, "context null"); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); + return; + } + AAFwk::Want want; + int resultCode = 0; + OHOS::AppExecFwk::UnWrapAbilityResult(env, abilityResult, resultCode, want); + context->SetTerminating(true); + ErrCode ret = context->TerminateAbilityWithResult(want, resultCode); + if (ret == static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT) || ret == ERR_OK) { + aniObject = CreateStsError(env, static_cast(ret)); + } else { + aniObject = CreateStsErrorByNativeErr(env, static_cast(ret)); + } + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); +} + +void StsAbilityContext::reportDrawnCompletedSync([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + ani_object callback) +{ + ani_object aniObject = nullptr; + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + auto context = GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "context null"); + aniObject = CreateStsInvalidParamError(env, "context null"); + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); + return; + } + ErrCode ret = context->ReportDrawnCompleted(); + if (ret == ERR_OK) { + aniObject = CreateStsError(env, static_cast(ret)); + } else { + aniObject = CreateStsErrorByNativeErr(env, static_cast(ret)); + } + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); +} + +ani_object StsAbilityContext::StartAbilityByTypeSync([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_string aniType, ani_ref aniWantParam, ani_object startCallback) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "call"); + auto context = GetAbilityContext(env, aniObj); + ani_object aniObject = CreateStsError(env, AbilityErrorCode::ERROR_OK); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "get abilityContext failed."); + ThrowStsInvalidParamError(env, "context null"); + return aniObject; + } + + std::string type; + if (!AppExecFwk::GetStdString(env, aniType, type)) { + TAG_LOGE(AAFwkTag::UI_EXT, "parse type failed"); + ThrowStsInvalidParamError(env, "Parse param type failed, type must be string."); + return aniObject; + } + + AAFwk::WantParams wantParam; + if (!AppExecFwk::UnwrapWantParams(env, aniWantParam, wantParam)) { + TAG_LOGE(AAFwkTag::UI_EXT, "parse wantParam failed"); + ThrowStsInvalidParamError(env, "Parse param want failed, want must be Want."); + return aniObject; + } + + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "get aniVM failed"); + ThrowStsInvalidParamError(env, "Get aniVm failed."); + return aniObject; + } + ErrCode innerErrCode = ERR_OK; + std::shared_ptr callback = std::make_shared(); + callback->SetStsCallbackObject(aniVM, startCallback); + innerErrCode = context->StartAbilityByType(type, wantParam, callback); + if (innerErrCode == ERR_OK) { + return aniObject; + } else if (innerErrCode == static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)) { + return CreateStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + } else { + return CreateStsErrorByNativeErr(env, innerErrCode); + } +} + +void StsAbilityContext::StartServiceExtensionAbilitySync([[maybe_unused]]ani_env *env, + [[maybe_unused]]ani_object aniObj, [[maybe_unused]] ani_object wantObj, [[maybe_unused]] ani_object callbackobj) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "call"); + ani_object errorObject = nullptr; + ErrCode ret = ERR_OK; + auto context = StsAbilityContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "GetAbilityContext is nullptr"); + ret = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + errorObject = CreateStsError(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callbackobj, errorObject, nullptr); + return; + } + AAFwk::Want want; + if (!OHOS::AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::UIABILITY, "UnwrapWant filed"); + errorObject = CreateStsInvalidParamError(env, "UnwrapWant filed"); + AppExecFwk::AsyncCallback(env, callbackobj, errorObject, nullptr); + } + ret = context->StartServiceExtensionAbility(want); + if (ret == ERR_OK) { + errorObject = CreateStsError(env, static_cast(ret)); + } else { + errorObject = CreateStsErrorByNativeErr(env, static_cast(ret)); + } + AppExecFwk::AsyncCallback(env, callbackobj, errorObject, nullptr); +} + +ani_object StsAbilityContext::StartAbilityByCall(ani_env *env, ani_object aniObj, ani_object wantObj) +{ + TAG_LOGI(AAFwkTag::UIABILITY, "StartAbilityByCall"); + auto context = GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "GetAbilityContext is nullptr"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return nullptr; + } + + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::UIABILITY, "parse want failed"); + ThrowStsInvalidParamError(env, "Parse param want failed, want must be Want."); + return nullptr; + } + auto callData = std::make_shared(); + auto callerCallBack = std::make_shared(); + GenerateCallerCallBack(callData, callerCallBack); + auto ret = context->StartAbilityByCall(want, callerCallBack, -1); + if (ret != 0) { + TAG_LOGE(AAFwkTag::UIABILITY, "startAbility failed"); + ThrowStsErrorByNativeErr(env, ret); + return nullptr; + } + WaitForCalleeObj(callData); + + if (callData->remoteCallee == nullptr) { + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + return nullptr; + } + + std::weak_ptr abilityContext(context); + auto releaseCallFunc = [abilityContext] (std::shared_ptr callback) -> ErrCode { + auto contextForRelease = abilityContext.lock(); + if (contextForRelease == nullptr) { + return -1; + } + return contextForRelease->ReleaseCall(callback); + }; + auto caller = CreateEtsCaller(env, releaseCallFunc, callData->remoteCallee, callerCallBack); + if (caller == nullptr) { + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + } + return caller; +} + +void StsAbilityContext::NativeOpenLinkSync(ani_env *env, ani_object aniObj, ani_string aniLink, + ani_object myCallbackobj, ani_object optionsObj, ani_object callbackobj) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "NativeOpenLinkSync"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + ani_status status = ANI_ERROR; + ani_boolean isOptionsUndefined = true; + if ((status = env->Reference_IsUndefined(optionsObj, &isOptionsUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + } + ani_boolean isCallbackUndefined = true; + if ((status = env->Reference_IsUndefined(callbackobj, &isCallbackUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + } + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + } + GetInstance().OpenLinkInner(env, aniObj, aniLink, myCallbackobj, optionsObj, callbackobj, + !isOptionsUndefined, !isCallbackUndefined); +} + +void StsAbilityContext::NativeRestoreWindowStage(ani_env *env, ani_object aniObj, ani_object localStorage) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "NativeRestoreWindowStage"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + auto context = StsAbilityContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return; + } + ani_status status = ANI_ERROR; + ani_boolean isLocalStorageUndefined = true; + if ((status = env->Reference_IsUndefined(localStorage, &isLocalStorageUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return; + } + if (isLocalStorageUndefined) { + TAG_LOGE(AAFwkTag::CONTEXT, "null localStorage"); + ThrowStsTooFewParametersError(env); + return; + } + ani_ref global = nullptr; + if ((status = env->GlobalReference_Create(localStorage, &global)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status : %{public}d", status); + return; + } + STSNativeReferenceWrapper* etsNativeRef = nullptr; + etsNativeRef = new STSNativeReferenceWrapper(); + etsNativeRef->ref_ = std::make_shared(); + etsNativeRef->ref_->aniRef = global; + auto errcode = context->RestoreWindowStage(etsNativeRef); + if (errcode != 0) { + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + return; + } +} + +bool StsAbilityContext::NativeIsTerminating(ani_env *env, ani_object aniObj) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "NativeIsTerminating"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return false; + } + auto context = StsAbilityContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return false; + } + return context->IsTerminating(); +} + +void StsAbilityContext::NativeMoveAbilityToBackground(ani_env *env, ani_object aniObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "NativeMoveAbilityToBackground"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + auto context = StsAbilityContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + AppExecFwk::AsyncCallback(env, callback, + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)), nullptr); + return; + } + ErrCode ret = ERR_OK; + ani_object errorObject = nullptr; + ret = context->MoveUIAbilityToBackground(); + errorObject = CreateStsErrorByNativeErr(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callback, errorObject, nullptr); +} + +void StsAbilityContext::NativeRequestModalUIExtension(ani_env *env, ani_object aniObj, + ani_string pickerWantObj, ani_object callbackObj) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "NativeRequestModalUIExtension"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + ani_object errorObject = nullptr; + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, pickerWantObj, want)) { + TAG_LOGE(AAFwkTag::UIABILITY, "parse want failed"); + ThrowStsInvalidParamError(env, "Parse param want failed, want must be Want."); + return; + } + auto context = StsAbilityContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "null context"); + errorObject = CreateStsErrorByNativeErr(env, + static_cast(AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT)); + AppExecFwk::AsyncCallback(env, callbackObj, errorObject, nullptr); + return; + } + + ErrCode ret = ERR_OK; + ret = AAFwk::AbilityManagerClient::GetInstance()->RequestModalUIExtension(want); + errorObject = CreateStsErrorByNativeErr(env, static_cast(ret)); + AppExecFwk::AsyncCallback(env, callbackObj, errorObject, nullptr); +} + +ani_object StsAbilityContext::NativeTransferStatic(ani_env *env, ani_object, ani_object input) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "transfer static UIAbilityContext"); + void *unwrapResult = nullptr; + bool success = arkts_esvalue_unwrap(env, input, &unwrapResult); + if (!success) { + TAG_LOGE(AAFwkTag::UIABILITY, "failed to unwrap"); + ThrowStsTransferClassError(env); + return nullptr; + } + if (unwrapResult == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null unwrapResult"); + ThrowStsTransferClassError(env); + return nullptr; + } + auto context = reinterpret_cast *>(unwrapResult)->lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null context"); + ThrowStsTransferClassError(env); + return nullptr; + } + + auto abilityContext = Context::ConvertTo(context); + if (abilityContext == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext"); + ThrowStsTransferClassError(env); + return nullptr; + } + auto &bindingObj = abilityContext->GetBindingObject(); + if (bindingObj == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null bindingObj"); + ThrowStsTransferClassError(env); + return nullptr; + } + auto staticContext = bindingObj->Get(); + if (staticContext == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null staticContext"); + ThrowStsTransferClassError(env); + return nullptr; + } + return reinterpret_cast(*staticContext); +} + +ani_object StsAbilityContext::NativeTransferDynamic(ani_env *env, ani_object, ani_object input) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "transfer dynamic UIAbilityContext"); + if (!IsInstanceOf(env, input)) { + TAG_LOGE(AAFwkTag::UIABILITY, "not UIAbilityContext"); + ThrowStsTransferClassError(env); + return nullptr; + } + + auto context = GetAbilityContext(env, input); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null context"); + ThrowStsTransferClassError(env); + return nullptr; + } + auto abilityContext = Context::ConvertTo(context); + if (abilityContext == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext"); + ThrowStsTransferClassError(env); + return nullptr; + } + auto &bindingObj = abilityContext->GetBindingObject(); + if (bindingObj == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null bindingObj"); + ThrowStsTransferClassError(env); + return nullptr; + } + auto dynamicContext = bindingObj->Get(); + if (dynamicContext == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null dynamicContext"); + ThrowStsTransferClassError(env); + return nullptr; + } + // Not support yet + ThrowStsTransferClassError(env); + return nullptr; +} + +bool BindNativeMethods(ani_env *env, ani_class &cls) +{ + ani_status status = env->FindClass(UI_ABILITY_CONTEXT_CLASS_NAME, &cls); + if (status != ANI_OK || cls == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return false; + } + std::call_once(g_bindNativeMethodsFlag, [&status, env, cls]() { + std::array functions = { + ani_native_function { "nativeStartAbilitySync", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(StsAbilityContext::StartAbility1) }, + ani_native_function { "nativeStartAbilitySync", + "L@ohos/app/ability/Want/Want;L@ohos/app/ability/StartOptions/StartOptions;Lutils/AbilityUtils/" + "AsyncCallbackWrapper;:V", + reinterpret_cast(StsAbilityContext::StartAbility2) }, + ani_native_function { "nativeStartAbilityForResult", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(StsAbilityContext::StartAbilityForResult1) }, + ani_native_function { "nativeStartAbilityForResult", + "L@ohos/app/ability/Want/Want;L@ohos/app/ability/StartOptions/StartOptions;Lutils/AbilityUtils/" + "AsyncCallbackWrapper;:V", + reinterpret_cast(StsAbilityContext::StartAbilityForResult2) }, + ani_native_function { "nativeTerminateSelfSync", "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(StsAbilityContext::TerminateSelf) }, + ani_native_function { "nativeTerminateSelfWithResult", + "Lability/abilityResult/AbilityResult;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(StsAbilityContext::TerminateSelfWithResult) }, + ani_native_function { "nativeReportDrawnCompletedSync", "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(StsAbilityContext::reportDrawnCompletedSync) }, + ani_native_function { "nativeStartAbilityByTypeSync", nullptr, + reinterpret_cast(StsAbilityContext::StartAbilityByTypeSync) }, + ani_native_function { "nativeStartServiceExtensionAbilitySync", nullptr, + reinterpret_cast(StsAbilityContext::StartServiceExtensionAbilitySync) }, + ani_native_function { "nativeStartAbilityByCallSync", + "L@ohos/app/ability/Want/Want;:L@ohos/app/ability/UIAbility/Caller;", + reinterpret_cast(StsAbilityContext::StartAbilityByCall) }, + ani_native_function { "nativeOpenLinkSync", nullptr, + reinterpret_cast(StsAbilityContext::NativeOpenLinkSync) }, + ani_native_function { "nativeRestoreWindowStage", nullptr, + reinterpret_cast(StsAbilityContext::NativeRestoreWindowStage) }, + ani_native_function { "nativeIsTerminating", nullptr, + reinterpret_cast(StsAbilityContext::NativeIsTerminating) }, + ani_native_function { "nativeMoveAbilityToBackground", nullptr, + reinterpret_cast(StsAbilityContext::NativeMoveAbilityToBackground) }, + ani_native_function { "nativeRequestModalUIExtension", nullptr, + reinterpret_cast(StsAbilityContext::NativeRequestModalUIExtension) }, + ani_native_function { "nativeTransferStatic", "Lstd/interop/ESValue;:Lstd/core/Object;", + reinterpret_cast(StsAbilityContext::NativeTransferStatic) }, + ani_native_function { "nativeTransferDynamic", "Lstd/core/Object;:Lstd/interop/ESValue;", + reinterpret_cast(StsAbilityContext::NativeTransferDynamic) }, + }; + status = env->Class_BindNativeMethods(cls, functions.data(), functions.size()); + }); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return false; + } + return true; +} + +void StsAbilityContext::OpenLinkInner(ani_env *env, ani_object aniObj, ani_string aniLink, ani_object myCallbackobj, + ani_object optionsObj, ani_object callbackobj, bool haveOptionsParm, bool haveCallBackParm) +{ + ani_object aniObject = nullptr; + std::string link(""); + AAFwk::OpenLinkOptions openLinkOptions; + AAFwk::Want want; + want.SetParam(APP_LINKING_ONLY, false); + if (!AppExecFwk::GetStdString(env, aniLink, link)) { + TAG_LOGE(AAFwkTag::UIABILITY, "parse link failed"); + aniObject = CreateStsInvalidParamError(env, "Parse param link failed, link must be string."); + AppExecFwk::AsyncCallback(env, myCallbackobj, aniObject, nullptr); + return; + } + if (haveOptionsParm) { + TAG_LOGD(AAFwkTag::UIABILITY, "OpenLink Have option"); + StsAbilityContext::UnWrapOpenLinkOptions(env, optionsObj, openLinkOptions, want); + } + want.SetUri(link); + std::string startTime = std::to_string(std::chrono::duration_cast(std::chrono:: + system_clock::now().time_since_epoch()).count()); + want.SetParam(AAFwk::Want::PARAM_RESV_START_TIME, startTime); + int requestCode = -1; + ErrCode ErrCode = ERR_OK; + auto context = StsAbilityContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "GetAbilityContext is nullptr"); + ErrCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = CreateStsError(env, static_cast(ErrCode)); + AppExecFwk::AsyncCallback(env, myCallbackobj, aniObject, nullptr); + return; + } + AddFreeInstallObserver(env, want, myCallbackobj, context, true); + if (haveCallBackParm) { + TAG_LOGD(AAFwkTag::UIABILITY, "OpenLink Have Callback"); + CreateOpenLinkTask(env, callbackobj, context, want, requestCode); + } + ErrCode = context->OpenLink(want, requestCode); + if (ErrCode == AAFwk::ERR_OPEN_LINK_START_ABILITY_DEFAULT_OK) { + aniObject = CreateStsError(env, static_cast(ERR_OK)); + } else { + aniObject = CreateStsErrorByNativeErr(env, static_cast(ErrCode)); + } + AppExecFwk::AsyncCallback(env, myCallbackobj, aniObject, nullptr); +} + +void StsAbilityContext::UnWrapOpenLinkOptions(ani_env *env, ani_object optionsObj, + AAFwk::OpenLinkOptions &openLinkOptions, AAFwk::Want &want) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "UnWrapOpenLinkOptions"); + ani_status status = ANI_ERROR; + ani_ref ParamRef = nullptr; + if ((status = env->Object_GetPropertyByName_Ref(optionsObj, "parameters", &ParamRef)) == ANI_OK) { + AAFwk::WantParams wantParam; + if (AppExecFwk::UnwrapWantParams(env, ParamRef, wantParam)) { + want.SetParams(wantParam); + } else { + TAG_LOGE(AAFwkTag::UIABILITY, "UnwrapWantParams failed"); + } + } + if ((status = env->Object_GetPropertyByName_Ref(optionsObj, APP_LINKING_ONLY.c_str(), &ParamRef)) == ANI_OK) { + bool appLinkingOnly = AppExecFwk::GetBoolOrUndefined(env, optionsObj, "appLinkingOnly"); + openLinkOptions.SetAppLinkingOnly(appLinkingOnly); + want.SetParam(APP_LINKING_ONLY, appLinkingOnly); + } + if (!want.HasParameter(APP_LINKING_ONLY)) { + want.SetParam(APP_LINKING_ONLY, false); + } +} + +void StsAbilityContext::CreateOpenLinkTask(ani_env *env, const ani_object callbackobj, + std::shared_ptr context, AAFwk::Want &want, int &requestCode) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "CreateOpenLinkTask"); + want.SetParam(AAFwk::Want::PARAM_RESV_FOR_RESULT, true); + ani_vm *etsVm = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GetVM(&etsVm)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + return; + } + ani_ref callbackRef = nullptr; + if ((status = env->GlobalReference_Create(callbackobj, &callbackRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status: %{public}d", status); + return; + } + RuntimeTask task = [etsVm, callbackRef] (int resultCode, const AAFwk::Want &want, bool isInner) { + TAG_LOGD(AAFwkTag::CONTEXT, "start async callback"); + ani_status status = ANI_ERROR; + ani_env *env = nullptr; + if ((status = etsVm->GetEnv(ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + return; + } + ani_object abilityResult = AppExecFwk::WrapAbilityResult(env, resultCode, want); + if (abilityResult == nullptr) { + TAG_LOGW(AAFwkTag::CONTEXT, "null abilityResult"); + isInner = true; + resultCode = ERR_INVALID_VALUE; + } + auto errCode = isInner ? resultCode : 0; + AppExecFwk::AsyncCallback(env, reinterpret_cast(callbackRef), + OHOS::AbilityRuntime::CreateStsErrorByNativeErr(env, errCode), abilityResult); + }; + requestCode = GenerateRequestCode(); + context->InsertResultCallbackTask(requestCode, std::move(task)); +} + +bool StsAbilityContext::IsInstanceOf(ani_env *env, ani_object aniObj) +{ + ani_class cls {}; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return false; + } + if ((status = env->FindClass(UI_ABILITY_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return false; + } + ani_boolean isInstanceOf = false; + if ((status = env->Object_InstanceOf(aniObj, cls, &isInstanceOf)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return false; + } + return isInstanceOf; +} + +bool SetAbilityInfo(ani_env *env, ani_class cls, ani_object contextObj, const std::shared_ptr &context) +{ + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env or context"); + return false; + } + ani_field field = nullptr; + auto abilityInfo = context->GetAbilityInfo(); + ani_ref abilityInfoRef = AppExecFwk::CommonFunAni::ConvertAbilityInfo(env, *abilityInfo); + + ani_status status = env->Class_FindField(cls, "abilityInfo", &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return false; + } + + status = env->Object_SetField_Ref(contextObj, field, abilityInfoRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return false; + } + return true; +} + +bool SetConfiguration( + ani_env *env, ani_class cls, ani_object contextObj, const std::shared_ptr &context) +{ + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env or context"); + return false; + } + ani_field field = nullptr; + auto configuration = context->GetConfiguration(); + ani_ref configurationRef = OHOS::AppExecFwk::WrapConfiguration(env, *configuration); + + ani_status status = env->Class_FindField(cls, "config", &field); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return false; + } + + status = env->Object_SetField_Ref(contextObj, field, configurationRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return false; + } + return true; +} + +bool SetHapModuleInfo( + ani_env *env, ani_class cls, ani_object contextObj, const std::shared_ptr &context) +{ + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env or context"); + return false; + } + ani_status status = ANI_OK; + auto hapModuleInfo = context->GetHapModuleInfo(); + if (hapModuleInfo == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "hapModuleInfo is nullptr"); + return false; + } + ani_ref hapModuleInfoRef = AppExecFwk::CommonFunAni::ConvertHapModuleInfo(env, *hapModuleInfo); + if (hapModuleInfoRef != nullptr) { + status = env->Object_SetPropertyByName_Ref(contextObj, "currentHapModuleInfo", hapModuleInfoRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "Object_SetPropertyByName_Ref failed, status: %{public}d", status); + return false; + } + } + return true; +} + + +ani_ref CreateStsAbilityContext(ani_env *env, const std::shared_ptr &context) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env or context"); + return nullptr; + } + ani_class cls {}; + if (!BindNativeMethods(env, cls)) { + TAG_LOGE(AAFwkTag::UIABILITY, "BindNativeMethods failed"); + return nullptr; + } + ani_object contextObj = StsAbilityContext::SetAbilityContext(env, context); + if (contextObj == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null contextObj"); + return nullptr; + } + ContextUtil::StsCreatContext(env, cls, contextObj, context); + if (!SetAbilityInfo(env, cls, contextObj, context)) { + TAG_LOGE(AAFwkTag::UIABILITY, "SetAbilityInfo failed"); + return nullptr; + } + if (!SetConfiguration(env, cls, contextObj, context)) { + TAG_LOGE(AAFwkTag::UIABILITY, "SetConfiguration failed"); + return nullptr; + } + if (!SetHapModuleInfo(env, cls, contextObj, context)) { + TAG_LOGE(AAFwkTag::UIABILITY, "SetHapModuleInfo failed"); + return nullptr; + } + return contextObj; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/ability/native/ability_runtime/sts_caller_complex.cpp b/frameworks/native/ability/native/ability_runtime/sts_caller_complex.cpp new file mode 100644 index 0000000000000000000000000000000000000000..693a68d179c2df73204e210af15e37efa1e2dabd --- /dev/null +++ b/frameworks/native/ability/native/ability_runtime/sts_caller_complex.cpp @@ -0,0 +1,262 @@ +/* + * 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 "sts_caller_complex.h" + +#include + +#include "ability_business_error.h" +#include "ani_remote_object.h" +#include "hilog_tag_wrapper.h" +#include "sts_error_utils.h" + +namespace { // nameless +using namespace OHOS; +using namespace OHOS::AbilityRuntime; +class EtsCallerComplex; + +static std::once_flag g_bindNativeMethodsFlag; + +EtsCallerComplex *GetComplexPtrFrom(ani_env *env, ani_object aniObj) +{ + ani_long nativeCaller; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "null env"); + return nullptr; + } + if ((status = env->Object_GetFieldByName_Long(aniObj, "nativeCaller", &nativeCaller)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "status : %{public}d", status); + return nullptr; + } + return reinterpret_cast(nativeCaller); +} + +ani_ref GetEtsRemoteObj(ani_env *env, ani_object aniObj) +{ + ani_ref etsRemoteObj = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "null env"); + return nullptr; + } + if ((status = env->Object_GetFieldByName_Ref(aniObj, "callee", &etsRemoteObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "status : %{public}d", status); + return nullptr; + } + return etsRemoteObj; +} + +void ReleaseNativeRemote(ani_env *env, ani_ref aniObj) +{ + TAG_LOGI(AAFwkTag::ABILITY, "ReleaseNativeRemote"); +} + +ani_object AniCreateRemoteObj(ani_env *env, sptr callee) +{ + TAG_LOGI(AAFwkTag::ABILITY, "AniCreateRemoteObj"); + ani_object etsRemoteObj = ANI_ohos_rpc_CreateJsRemoteObject(env, callee); + return etsRemoteObj; +} + +class EtsCallerComplex { +public: + explicit EtsCallerComplex(ReleaseCallFunc releaseCallFunc, std::shared_ptr callerCallBack) + : releaseCallFunc_(releaseCallFunc), callerCallBack_(callerCallBack) {} + ~EtsCallerComplex() = default; + + static void ReleaseCall(ani_env *env, ani_object aniObj) + { + TAG_LOGI(AAFwkTag::ABILITY, "ReleaseCall"); + auto ptr = GetComplexPtrFrom(env, aniObj); + if (ptr == nullptr) { + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + return; + } + ptr->ReleaseCallInner(env); + + auto etsRemoteObj = GetEtsRemoteObj(env, aniObj); + ReleaseNativeRemote(env, etsRemoteObj); + } + + static void SetOnRelease(ani_env *env, ani_object aniObj, ani_object callback) + { + TAG_LOGI(AAFwkTag::ABILITY, "SetOnRelease"); + auto ptr = GetComplexPtrFrom(env, aniObj); + if (ptr == nullptr || ptr->callerCallBack_ == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "SetOnRelease null"); + return; + } + ani_vm *aniVM = nullptr; + if (env->GetVM(&aniVM) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "get aniVM failed"); + return; + } + ani_ref callbackRef = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GlobalReference_Create(callback, &callbackRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "callbackRef: %{public}d", status); + return; + } + ptr->callerCallBack_->SetOnRelease([aniVM, callbackRef](const std::string &msg) { + ani_string aniMsg = nullptr; + ani_status status = ANI_ERROR; + ani_env *aniEnv = nullptr; + if ((status = aniVM->GetEnv(ANI_VERSION_1, &aniEnv)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "GetEnv failed, status : %{public}d", status); + return; + } + if ((status = aniEnv->String_NewUTF8(msg.c_str(), msg.size(), &aniMsg)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "String_NewUTF8 failed %{public}d", status); + return; + } + status = aniEnv->Object_CallMethodByName_Void(reinterpret_cast(callbackRef), "invoke", + "Lstd/core/String;:V", aniMsg); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "OnRelease call failed %{public}d", status); + } + aniEnv->GlobalReference_Delete(callbackRef); + }); + } + + static void SetOnRemoteStateChange(ani_env *env, ani_object aniObj, ani_object callback) + { + TAG_LOGI(AAFwkTag::ABILITY, "SetOnRemoteStateChange"); + } + +private: + void ReleaseCallInner(ani_env *env) + { + TAG_LOGD(AAFwkTag::ABILITY, "called"); + if (callerCallBack_ == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "null CallBacker"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + return; + } + + if (!releaseCallFunc_) { + TAG_LOGE(AAFwkTag::ABILITY, "null releaseFunc"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + return; + } + + callerCallBack_->SetCallBack(nullptr); + int32_t innerErrorCode = releaseCallFunc_(callerCallBack_); + if (innerErrorCode != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "ReleaseAbility failed %{public}d", static_cast(innerErrorCode)); + ThrowStsError(env, innerErrorCode); + } + } + +private: + ReleaseCallFunc releaseCallFunc_; + std::shared_ptr callerCallBack_; +}; + +bool BindNativeMethods(ani_env *env, ani_class &cls) +{ + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "cls null"); + return false; + } + ani_status status = ANI_OK; + std::call_once(g_bindNativeMethodsFlag, [&status, env, cls]() { + std::array functions = { + ani_native_function { "nativeReleaseSync", nullptr, + reinterpret_cast(EtsCallerComplex::ReleaseCall) }, + ani_native_function { "nativeOnReleaseSync", "Lcaller/Caller/ReleaseCallback;:V", + reinterpret_cast(EtsCallerComplex::SetOnRelease) }, + ani_native_function { "nativeOnRemoteStateChangeSync", "Lstd/core/Function1;:V", + reinterpret_cast(EtsCallerComplex::SetOnRemoteStateChange) }, + }; + + status = env->Class_BindNativeMethods(cls, functions.data(), functions.size()); + }); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "status: %{public}d", status); + return false; + } + return true; +} +} // nameless + +namespace OHOS { +namespace AbilityRuntime { +ani_object CreateEtsCaller(ani_env *env, ReleaseCallFunc releaseCallFunc, + sptr callee, std::shared_ptr callback) +{ + ani_class cls {}; + ani_status status = ANI_ERROR; + ani_object callerObj = nullptr; + ani_method method {}; + + if ((status = env->FindClass("Lcaller/Caller/CallerImpl;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "status : %{public}d", status); + return nullptr; + } + if (!BindNativeMethods(env, cls)) { + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "status : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &callerObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "status : %{public}d", status); + return nullptr; + } + auto etsCaller = new (std::nothrow) EtsCallerComplex(releaseCallFunc, callback); + if (etsCaller == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "etsCaller is null"); + return nullptr; + } + ani_long nativeCaller = (ani_long)(etsCaller); + if ((status = env->Object_SetFieldByName_Long(callerObj, "nativeCaller", nativeCaller)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "status : %{public}d", status); + delete etsCaller; + return nullptr; + } + auto remoteObj = AniCreateRemoteObj(env, callee); + if ((status = env->Object_SetFieldByName_Ref(callerObj, "callee", remoteObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "status : %{public}d", status); + delete etsCaller; + return nullptr; + } + return callerObj; +} + +ani_object CreateEtsCallee(ani_env *env) +{ + ani_class cls {}; + ani_status status = ANI_ERROR; + ani_object calleeObj = nullptr; + ani_method method {}; + + if ((status = env->FindClass("Lcallee/Callee/CalleeImpl;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "CalleeImpl: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "callee ctor : %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &calleeObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "create callee: %{public}d", status); + return nullptr; + } + return calleeObj; +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/ability/native/ability_runtime/sts_ui_ability.cpp b/frameworks/native/ability/native/ability_runtime/sts_ui_ability.cpp new file mode 100644 index 0000000000000000000000000000000000000000..02adb10508cb73f44cd7996ebe8328863ca31b81 --- /dev/null +++ b/frameworks/native/ability/native/ability_runtime/sts_ui_ability.cpp @@ -0,0 +1,1475 @@ +/* + * 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 "sts_ui_ability.h" +#include +#include +#include + +#include "ability_business_error.h" +#include "ability_delegator_registry.h" +#include "ability_manager_client.h" +#include "ability_recovery.h" +#include "ability_start_setting.h" +#include "ani_remote_object.h" +#include "app_recovery.h" +#include "connection_manager.h" +#include "context/application_context.h" +#include "context/context.h" +#include "display_util.h" +#include "hilog_tag_wrapper.h" +#include "hitrace_meter.h" +#include "if_system_ability_manager.h" +#include "insight_intent_executor_info.h" +#include "insight_intent_executor_mgr.h" +#include "insight_intent_execute_param.h" +#include "ohos_application.h" +#include "sts_ability_context.h" +#include "sts_caller_complex.h" +#include "sts_data_struct_converter.h" +#ifdef SUPPORT_SCREEN +#include "ani_window_stage.h" +#include "distributed_client.h" +#include "scene_board_judgement.h" +#endif +#include "ani_common_want.h" +#include "string_wrapper.h" +#include "system_ability_definition.h" +#include "time_util.h" + +namespace OHOS { +namespace AbilityRuntime { +std::once_flag StsUIAbility::singletonFlag_; +namespace { +#ifdef SUPPORT_GRAPHICS +const std::string PAGE_STACK_PROPERTY_NAME = "pageStack"; +const std::string SUPPORT_CONTINUE_PAGE_STACK_PROPERTY_NAME = "ohos.extra.param.key.supportContinuePageStack"; +const std::string METHOD_NAME = "WindowScene::GoForeground"; +#endif +// Numerical base (radix) that determines the valid characters and their interpretation. +#ifdef SUPPORT_SCREEN +const int32_t BASE_DISPLAY_ID_NUM(10); +enum CollaborateResult { + ACCEPT = 0, + REJECT, +}; +[[maybe_unused]] static CollaborateResult CollaborateResult_ConvertStsToNative(const int32_t index) +{ + return static_cast(index); +} +[[maybe_unused]] static int32_t CollaborateResult_ConvertNativeToSts(const CollaborateResult value) +{ + return value; +} +#endif +constexpr const int32_t API12 = 12; +constexpr const int32_t API_VERSION_MOD = 100; +constexpr const char* UI_ABILITY_CONTEXT_CLASS_NAME = "Lapplication/UIAbilityContext/UIAbilityContext;"; +constexpr const char* UI_ABILITY_CLASS_NAME = "L@ohos/app/ability/UIAbility/UIAbility;"; + +void OnDestroyPromiseCallback(ani_env* env, ani_object aniObj) +{ + TAG_LOGI(AAFwkTag::UIABILITY, "OnDestroyPromiseCallback"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + ani_long destroyCallbackPoint = 0; + ani_status status = ANI_ERROR; + if ((status = env->Object_GetFieldByName_Long(aniObj, "destroyCallbackPoint", &destroyCallbackPoint)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return; + } + auto *callbackInfo = reinterpret_cast *>(destroyCallbackPoint); + if (callbackInfo == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null callbackInfo"); + return; + } + callbackInfo->Call(); + AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo); +} +} // namespace + +UIAbility *StsUIAbility::Create(const std::unique_ptr &runtime) +{ + return new (std::nothrow) StsUIAbility(static_cast(*runtime)); +} + +StsUIAbility::StsUIAbility(STSRuntime &stsRuntime) : stsRuntime_(stsRuntime) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); +} + +StsUIAbility::~StsUIAbility() +{ + TAG_LOGI(AAFwkTag::UIABILITY, "called"); + if (abilityContext_ != nullptr) { + abilityContext_->Unbind(); + } +} + +void StsUIAbility::Init(std::shared_ptr record, + const std::shared_ptr application, std::shared_ptr &handler, + const sptr &token) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (record == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null localAbilityRecord"); + return; + } + auto abilityInfo = record->GetAbilityInfo(); + if (abilityInfo == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityInfo"); + return; + } + UIAbility::Init(record, application, handler, token); +#ifdef SUPPORT_GRAPHICS + if (abilityContext_ != nullptr) { + AppExecFwk::AppRecovery::GetInstance().AddAbility( + shared_from_this(), abilityContext_->GetAbilityInfo(), abilityContext_->GetToken()); + } +#endif + std::string srcPath(abilityInfo->package); + if (!abilityInfo->isModuleJson) { + /* temporary compatibility api8 + config.json */ + srcPath.append("/assets/js/"); + if (!abilityInfo->srcPath.empty()) { + srcPath.append(abilityInfo->srcPath); + } + srcPath.append("/").append(abilityInfo->name).append(".abc"); + } else { + if (abilityInfo->srcEntrance.empty()) { + TAG_LOGE(AAFwkTag::UIABILITY, "empty srcEntrance"); + return; + } + srcPath.append("/"); + srcPath.append(abilityInfo->srcEntrance); + auto pos = srcPath.rfind("."); + if (pos != std::string::npos) { + srcPath.erase(pos); + srcPath.append(".abc"); + } + TAG_LOGD(AAFwkTag::UIABILITY, "stsAbility srcPath: %{public}s", srcPath.c_str()); + } + + std::string moduleName(abilityInfo->moduleName); + moduleName.append("::").append(abilityInfo->name); + + SetAbilityContext(abilityInfo, record->GetWant(), moduleName, srcPath); +} + +bool StsUIAbility::BindNativeMethods() +{ + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "env null"); + return false; + } + ani_class cls {}; + ani_status status = env->FindClass(UI_ABILITY_CLASS_NAME, &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "FindClass failed status: %{public}d", status); + return false; + } + std::call_once(singletonFlag_, [&status, env, cls]() { + std::array functions = { + ani_native_function { "nativeOnDestroyCallback", ":V", reinterpret_cast(OnDestroyPromiseCallback) }, + }; + status = env->Class_BindNativeMethods(cls, functions.data(), functions.size()); + }); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "Class_BindNativeMethods failed status: %{public}d", status); + return false; + } + return true; +} + +void StsUIAbility::UpdateAbilityObj( + std::shared_ptr abilityInfo, const std::string &moduleName, const std::string &srcPath) +{ + std::string key = moduleName + "::" + srcPath; + std::unique_ptr moduleObj = nullptr; + stsAbilityObj_ = stsRuntime_.LoadModule( + moduleName, srcPath, abilityInfo->hapPath, abilityInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE, + false, abilityInfo->srcEntrance); + + if (!BindNativeMethods()) { + TAG_LOGE(AAFwkTag::UIABILITY, "BindNativeMethods failed"); + return; + } + ani_status status = ANI_ERROR; + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + auto callee = CreateEtsCallee(env); + if ((status = env->Object_SetFieldByName_Ref(stsAbilityObj_->aniObj, "callee", callee)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "set callee status : %{public}d", status); + } +} + +void StsUIAbility::CreateAndBindContext(const std::shared_ptr application, + const std::shared_ptr record, + const std::shared_ptr abilityContext, + const std::unique_ptr& runtime) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (application == nullptr || record == nullptr || abilityContext == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null application or record or abilityContext"); + return; + } + if (runtime == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null runtime"); + return; + } + auto& stsRuntime = static_cast(*runtime); + auto env = stsRuntime.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + auto want = record->GetWant(); + if (want == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null want"); + return; + } + + int32_t screenMode = want->GetIntParam(AAFwk::SCREEN_MODE_KEY, AAFwk::ScreenMode::IDLE_SCREEN_MODE); + abilityContext->SetScreenMode(screenMode); + if (screenMode == AAFwk::IDLE_SCREEN_MODE) { + ani_ref contextObj = CreateStsAbilityContext(env, abilityContext); + ani_ref* contextGlobalRef = new ani_ref; + ani_status status = ANI_ERROR; + if ((status = env->GlobalReference_Create(contextObj, contextGlobalRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return; + } + abilityContext->Bind(stsRuntime, contextGlobalRef); + } + // no CreateAniEmbeddableUIAbilityContext +} + +void StsUIAbility::SetAbilityContext(std::shared_ptr abilityInfo, std::shared_ptr want, + const std::string &moduleName, const std::string &srcPath) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + UpdateAbilityObj(abilityInfo, moduleName, srcPath); + if (stsAbilityObj_ == nullptr || abilityContext_ == nullptr || want == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsAbilityObj_ or abilityContext_ or want"); + return; + } + ani_ref contextObj = nullptr; + int32_t screenMode = want->GetIntParam(AAFwk::SCREEN_MODE_KEY, AAFwk::ScreenMode::IDLE_SCREEN_MODE); + CreateAniContext(env, contextObj, screenMode); +} + +void StsUIAbility::CreateAniContext(ani_env *env, ani_ref contextGlobalRef, int32_t screenMode) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + if (screenMode == AAFwk::IDLE_SCREEN_MODE) { + ani_ref contextObj = CreateStsAbilityContext(env, abilityContext_); + if (contextObj == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null contextObj"); + return; + } + ani_field field = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GlobalReference_Create(contextObj, &contextGlobalRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return; + } + if ((status = env->Class_FindField(stsAbilityObj_->aniCls, "context", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return; + } + if ((status = env->Object_SetField_Ref(stsAbilityObj_->aniObj, field, contextGlobalRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return; + } + shellContextRef_ = std::make_shared(); + ani_class cls {}; + if ((status = env->FindClass(UI_ABILITY_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return; + } + shellContextRef_->aniCls = cls; + shellContextRef_->aniObj = reinterpret_cast(contextGlobalRef); + shellContextRef_->aniRef = contextGlobalRef; + abilityContext_->Bind(stsRuntime_, &(shellContextRef_->aniRef)); + } + // no CreateAniEmbeddableUIAbilityContext +} + +void StsUIAbility::OnStart(const Want &want, sptr sessionInfo) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); + UIAbility::OnStart(want, sessionInfo); + + if (!stsAbilityObj_) { + TAG_LOGE(AAFwkTag::UIABILITY, "not found Ability.js"); + return; + } + auto env = stsRuntime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::UIABILITY, "env not found Ability.sts"); + return; + } + + ani_status status = ANI_ERROR; + ani_ref wantObj = OHOS::AppExecFwk::WrapWant(env, want); + if (wantObj == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); + return; + } + ani_ref wantRef = nullptr; + if ((status = env->GlobalReference_Create(wantObj, &wantRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + } + + ani_field field = nullptr; + if ((status = env->Class_FindField(stsAbilityObj_->aniCls, "launchWant", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + } + if ((status = env->Object_SetField_Ref(stsAbilityObj_->aniObj, field, wantRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + } + if ((status = env->Class_FindField(stsAbilityObj_->aniCls, "lastRequestWant", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + } + if ((status = env->Object_SetField_Ref(stsAbilityObj_->aniObj, field, wantRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + } + auto launchParam = GetLaunchParam(); + if (InsightIntentExecuteParam::IsInsightIntentExecute(want)) { + launchParam.launchReason = AAFwk::LaunchReason::LAUNCHREASON_INSIGHT_INTENT; + } + ani_ref launchParamRef = CreateStsLaunchParam(env, launchParam); + const char *signature = + "L@ohos/app/ability/Want/Want;L@ohos/app/ability/AbilityConstant/AbilityConstant/LaunchParam;:V"; + + std::string methodName = "OnStart"; + auto applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } + AddLifecycleEventBeforeJSCall(FreezeUtil::TimeoutState::FOREGROUND, methodName); + CallObjectMethod(false, "onCreate", signature, wantRef, launchParamRef); + AddLifecycleEventAfterJSCall(FreezeUtil::TimeoutState::FOREGROUND, methodName); + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator( + AbilityRuntime::Runtime::Language::STS); + if (delegator) { + TAG_LOGD(AAFwkTag::UIABILITY, "call PostPerformStart"); + delegator->PostPerformStart(CreateADelegatorAbilityProperty()); + } + applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } + TAG_LOGD(AAFwkTag::UIABILITY, "end"); +} + +void StsUIAbility::AddLifecycleEventBeforeJSCall(FreezeUtil::TimeoutState state, const std::string &methodName) const +{ + auto entry = std::string("StsUIAbility::") + methodName + " begin"; + FreezeUtil::GetInstance().AddLifecycleEvent(AbilityContext::token_, entry); +} + +void StsUIAbility::AddLifecycleEventAfterJSCall(FreezeUtil::TimeoutState state, const std::string &methodName) const +{ + auto entry = std::string("StsUIAbility::") + methodName + " end"; + FreezeUtil::GetInstance().AddLifecycleEvent(AbilityContext::token_, entry); +} + +int32_t StsUIAbility::OnShare(WantParams &wantParam) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (stsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsAbilityObj_"); + return ERR_INVALID_VALUE; + } + TAG_LOGD(AAFwkTag::UIABILITY, "end"); + return ERR_OK; +} + +void StsUIAbility::OnStop() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (abilityContext_) { + TAG_LOGD(AAFwkTag::UIABILITY, "set terminating true"); + abilityContext_->SetTerminating(true); + } + UIAbility::OnStop(); + + auto applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } + CallObjectMethod(false, "onDestroy", nullptr); + OnStopCallback(); + TAG_LOGD(AAFwkTag::UIABILITY, "end"); +} + +void StsUIAbility::OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback) +{ + if (callbackInfo == nullptr) { + isAsyncCallback = false; + OnStop(); + return; + } + + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "Begin"); + if (abilityContext_) { + TAG_LOGD(AAFwkTag::UIABILITY, "set terminating true"); + abilityContext_->SetTerminating(true); + } + + UIAbility::OnStop(); + + auto applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } + std::weak_ptr weakPtr = shared_from_this(); + auto asyncCallback = [abilityWeakPtr = weakPtr]() { + auto ability = abilityWeakPtr.lock(); + if (ability == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null ability"); + return; + } + ability->OnStopCallback(); + }; + callbackInfo->Push(asyncCallback); + + ani_long destroyCallbackPoint = (ani_long)callbackInfo; + ani_status status = ANI_ERROR; + ani_field field = nullptr; + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr || stsAbilityObj_ == nullptr) { + isAsyncCallback = false; + OnStop(); + return; + } + if ((status = env->Class_FindField(stsAbilityObj_->aniCls, "destroyCallbackPoint", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + } + if ((status = env->Object_SetField_Long(stsAbilityObj_->aniObj, field, destroyCallbackPoint)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + } + + isAsyncCallback = CallObjectMethod(true, "callOnDestroy", ":Z"); + TAG_LOGI(AAFwkTag::UIABILITY, "callOnDestroy isAsyncCallback: %{public}d", isAsyncCallback); + if (!isAsyncCallback) { + OnStopCallback(); + return; + } + TAG_LOGD(AAFwkTag::UIABILITY, "end"); +} + +void StsUIAbility::OnStopCallback() +{ + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator( + AbilityRuntime::Runtime::Language::STS); + if (delegator) { + TAG_LOGD(AAFwkTag::UIABILITY, "call PostPerformStop"); + delegator->PostPerformStop(CreateADelegatorAbilityProperty()); + } + + bool ret = ConnectionManager::GetInstance().DisconnectCaller(AbilityContext::token_); + if (ret) { + ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid()); + TAG_LOGD(AAFwkTag::UIABILITY, "the service connection is not disconnected"); + } + + auto applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } +} + +#ifdef SUPPORT_SCREEN +void StsUIAbility::OnSceneCreated() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); + UIAbility::OnSceneCreated(); + auto stsAppWindowStage = CreateAppWindowStage(); + if (stsAppWindowStage == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsAppWindowStage"); + return; + } + + UpdateStsWindowStage(reinterpret_cast(stsAppWindowStage)); + stsWindowStageObj_ = std::make_shared(); + stsWindowStageObj_->aniObj = stsAppWindowStage; + ani_ref entryObjectRef = nullptr; + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + if (env->GlobalReference_Create(stsAppWindowStage, &entryObjectRef) != + ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "GlobalReference_Create failed"); + return; + } + stsWindowStageObj_->aniRef = entryObjectRef; + + auto applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } + { + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, "onWindowStageCreate"); + std::string methodName = "OnSceneCreated"; + AddLifecycleEventBeforeJSCall(FreezeUtil::TimeoutState::FOREGROUND, methodName); + const char *signature = "L@ohos/window/window/WindowStage;:V"; + CallObjectMethod(false, "onWindowStageCreate", signature, stsAppWindowStage); + AddLifecycleEventAfterJSCall(FreezeUtil::TimeoutState::FOREGROUND, methodName); + } + + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator( + AbilityRuntime::Runtime::Language::STS); + if (delegator) { + TAG_LOGD(AAFwkTag::UIABILITY, "call PostPerformScenceCreated"); + delegator->PostPerformScenceCreated(CreateADelegatorAbilityProperty()); + } + + applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } + + TAG_LOGD(AAFwkTag::UIABILITY, "end"); +} + +void StsUIAbility::OnSceneRestored() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + UIAbility::OnSceneRestored(); + TAG_LOGD(AAFwkTag::UIABILITY, "OnSceneRestored called"); + + auto stsAppWindowStage = CreateAppWindowStage(); + if (stsAppWindowStage == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsAppWindowStage"); + return; + } + UpdateStsWindowStage(reinterpret_cast(stsAppWindowStage)); + stsWindowStageObj_ = std::make_shared(); + stsWindowStageObj_->aniObj = stsAppWindowStage; + CallObjectMethod(false, "onWindowStageRestore", nullptr, stsAppWindowStage); +} + +void StsUIAbility::OnSceneWillDestroy() +{ + TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); + if (stsWindowStageObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsWindowStageObj_"); + return; + } + CallObjectMethod(false, "onWindowStageWillDestroy", nullptr, stsWindowStageObj_->aniRef); +} + +void StsUIAbility::onSceneDestroyed() +{ + TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); + UIAbility::onSceneDestroyed(); + + auto applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } + + UpdateStsWindowStage(nullptr); + const char *signature = ":V"; + CallObjectMethod(false, "onWindowStageDestroy", signature); + + if (scene_ != nullptr) { + auto window = scene_->GetMainWindow(); + if (window != nullptr) { + TAG_LOGD(AAFwkTag::UIABILITY, "unRegisterDisplaymovelistener"); + window->UnregisterDisplayMoveListener(abilityDisplayMoveListener_); + } + } + + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator( + AbilityRuntime::Runtime::Language::STS); + if (delegator) { + TAG_LOGD(AAFwkTag::UIABILITY, "call PostPerformScenceDestroyed"); + delegator->PostPerformScenceDestroyed(CreateADelegatorAbilityProperty()); + } + + applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } + TAG_LOGD(AAFwkTag::UIABILITY, "end"); +} + +void StsUIAbility::OnForeground(const Want &want) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); + if (abilityInfo_) { + } + + UIAbility::OnForeground(want); + + if (CheckIsSilentForeground()) { + TAG_LOGD(AAFwkTag::UIABILITY, "silent foreground, do not call 'onForeground'"); + return; + } + CallOnForegroundFunc(want); +} + +void StsUIAbility::CallOnForegroundFunc(const Want &want) +{ + if (stsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsAbilityObj_"); + return; + } + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + ani_status status = ANI_ERROR; + ani_field field = nullptr; + ani_ref wantRef = OHOS::AppExecFwk::WrapWant(env, want); + if (wantRef == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); + return; + } + auto applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } + + if ((status = env->Class_FindField(stsAbilityObj_->aniCls, "lastRequestWant", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + } + if ((status = env->Object_SetField_Ref(stsAbilityObj_->aniObj, field, wantRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + } + std::string methodName = "OnForeground"; + AddLifecycleEventBeforeJSCall(FreezeUtil::TimeoutState::FOREGROUND, methodName); + CallObjectMethod(false, "onForeground", nullptr, wantRef); + AddLifecycleEventAfterJSCall(FreezeUtil::TimeoutState::FOREGROUND, methodName); + + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator( + AbilityRuntime::Runtime::Language::STS); + if (delegator) { + TAG_LOGD(AAFwkTag::UIABILITY, "call PostPerformForeground"); + delegator->PostPerformForeground(CreateADelegatorAbilityProperty()); + } + + applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } + TAG_LOGD(AAFwkTag::UIABILITY, "end"); +} + +void StsUIAbility::OnBackground() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); + auto applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } + std::string methodName = "OnBackground"; + + AddLifecycleEventBeforeJSCall(FreezeUtil::TimeoutState::BACKGROUND, methodName); + const char *signature = ":V"; + CallObjectMethod(false, "onBackground", signature); + AddLifecycleEventAfterJSCall(FreezeUtil::TimeoutState::BACKGROUND, methodName); + + UIAbility::OnBackground(); + + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator( + AbilityRuntime::Runtime::Language::STS); + if (delegator) { + TAG_LOGD(AAFwkTag::UIABILITY, "call PostPerformBackground"); + delegator->PostPerformBackground(CreateADelegatorAbilityProperty()); + } + + applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } + TAG_LOGD(AAFwkTag::UIABILITY, "end"); +} + +bool StsUIAbility::OnBackPress() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); + UIAbility::OnBackPress(); + bool ret = CallObjectMethod(true, "onBackPressed", nullptr); + TAG_LOGD(AAFwkTag::UIABILITY, "ret: %{public}d", ret); + return ret; +} + +ani_object StsUIAbility::CreateAppWindowStage() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + auto env = stsRuntime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::UIABILITY, "env not found Ability.sts"); + return nullptr; + } + TAG_LOGE(AAFwkTag::UIABILITY, "CreateAppWindowStage start"); + auto scene = GetScene(); + if (!scene) { + TAG_LOGE(AAFwkTag::UIABILITY, "scene not found"); + return nullptr; + } + ani_object stsWindowStage = CreateAniWindowStage(env, scene); + if (stsWindowStage == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsWindowStage"); + return nullptr; + } + TAG_LOGE(AAFwkTag::UIABILITY, "CreateAppWindowStage end"); + return stsWindowStage; +} + +void StsUIAbility::GetPageStackFromWant(const Want &want, std::string &pageStack) +{ + auto stringObj = AAFwk::IString::Query(want.GetParams().GetParam(PAGE_STACK_PROPERTY_NAME)); + if (stringObj != nullptr) { + pageStack = AAFwk::String::Unbox(stringObj); + } +} + +bool StsUIAbility::IsRestorePageStack(const Want &want) +{ + return want.GetBoolParam(SUPPORT_CONTINUE_PAGE_STACK_PROPERTY_NAME, true); +} + +void StsUIAbility::RestorePageStack(const Want &want) +{ + if (IsRestorePageStack(want)) { + std::string pageStack; + GetPageStackFromWant(want, pageStack); + auto window = scene_->GetMainWindow(); + if (window == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null window"); + } + auto wrapper = static_cast(abilityContext_->GetContentStorage().release()); + if (wrapper != nullptr) { + auto env = stsRuntime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::UIABILITY, "env not found Ability.sts"); + return; + } + if (wrapper->ref_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null STSNativeReference"); + return; + } + if (wrapper->ref_->aniRef == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null aniRef"); + return; + } + TAG_LOGD(AAFwkTag::UIABILITY, "NapiSetUIContent"); + window->NapiSetUIContent(pageStack, env, reinterpret_cast(wrapper->ref_->aniRef), + Rosen::BackupAndRestoreType::CONTINUATION); + } else { + TAG_LOGE(AAFwkTag::UIABILITY, "null content storage"); + } + } +} + +void StsUIAbility::AbilityContinuationOrRecover(const Want &want) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "launch reason: %{public}d, last exit reasion: %{public}d", launchParam_.launchReason, + launchParam_.lastExitReason); + if (IsRestoredInContinuation()) { + RestorePageStack(want); + OnSceneRestored(); + NotifyContinuationResult(want, true); + } else if (ShouldRecoverState(want)) { + std::string pageStack = abilityRecovery_->GetSavedPageStack(AppExecFwk::StateReason::DEVELOPER_REQUEST); + + auto mainWindow = scene_->GetMainWindow(); + if (mainWindow != nullptr) { + } else { + TAG_LOGE(AAFwkTag::UIABILITY, "null mainWindow"); + } + OnSceneRestored(); + } else { + if (ShouldDefaultRecoverState(want) &&abilityRecovery_ != nullptr &&scene_ != nullptr) { + TAG_LOGD(AAFwkTag::UIABILITY, "need restore"); + std::string pageStack = abilityRecovery_->GetSavedPageStack(AppExecFwk::StateReason::DEVELOPER_REQUEST); + auto mainWindow = scene_->GetMainWindow(); + if (!pageStack.empty() &&mainWindow != nullptr) { + mainWindow->SetRestoredRouterStack(pageStack); + } + } + OnSceneCreated(); + } +} + +void StsUIAbility::DoOnForeground(const Want &want) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (scene_ == nullptr) { + if ((abilityContext_ == nullptr) || (sceneListener_ == nullptr)) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext or sceneListener_"); + return; + } + DoOnForegroundForSceneIsNull(want); + } else { + auto window = scene_->GetMainWindow(); + if (window != nullptr &&want.HasParameter(Want::PARAM_RESV_WINDOW_MODE)) { + auto windowMode = want.GetIntParam( + Want::PARAM_RESV_WINDOW_MODE, AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_UNDEFINED); + window->SetWindowMode(static_cast(windowMode)); + windowMode_ = windowMode; + TAG_LOGD(AAFwkTag::UIABILITY, "set window mode: %{public}d", windowMode); + } + } + + auto window = scene_->GetMainWindow(); + if (window != nullptr &&securityFlag_) { + window->SetSystemPrivacyMode(true); + } + + if (CheckIsSilentForeground()) { + TAG_LOGI(AAFwkTag::UIABILITY, "silent foreground, do not show window"); + return; + } + + TAG_LOGD(AAFwkTag::UIABILITY, "move scene to foreground, sceneFlag_: %{public}d", UIAbility::sceneFlag_); + AddLifecycleEventBeforeJSCall(FreezeUtil::TimeoutState::FOREGROUND, METHOD_NAME); + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, "scene_->GoForeground"); + scene_->GoForeground(UIAbility::sceneFlag_); + TAG_LOGD(AAFwkTag::UIABILITY, "end"); +} + +void StsUIAbility::DoOnForegroundForSceneIsNull(const Want &want) +{ + scene_ = std::make_shared(); + int32_t displayId = AAFwk::DisplayUtil::GetDefaultDisplayId(); + if (setting_ != nullptr) { + std::string strDisplayId = setting_->GetProperty(OHOS::AppExecFwk::AbilityStartSetting::WINDOW_DISPLAY_ID_KEY); + std::regex formatRegex("[0-9]{0,9}$"); + std::smatch sm; + bool flag = std::regex_match(strDisplayId, sm, formatRegex); + if (flag &&!strDisplayId.empty()) { + displayId = strtol(strDisplayId.c_str(), nullptr, BASE_DISPLAY_ID_NUM); + TAG_LOGD(AAFwkTag::UIABILITY, "displayId: %{public}d", displayId); + } else { + TAG_LOGW(AAFwkTag::UIABILITY, "formatRegex: [%{public}s] failed", strDisplayId.c_str()); + } + } + auto option = GetWindowOption(want); + Rosen::WMError ret = Rosen::WMError::WM_OK; + auto sessionToken = GetSessionToken(); + auto identityToken = GetIdentityToken(); + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, "scene_->Init"); + if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled() &&sessionToken != nullptr) { + abilityContext_->SetWeakSessionToken(sessionToken); + ret = scene_->Init(displayId, abilityContext_, sceneListener_, option, sessionToken, identityToken); + } else { + ret = scene_->Init(displayId, abilityContext_, sceneListener_, option); + } + if (ret != Rosen::WMError::WM_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "init window scene failed"); + FreezeUtil::GetInstance().AppendLifecycleEvent(AbilityContext::token_, + std::string("JsUIAbility::DoOnForegroundForSceneIsNull; error ") + std::to_string(static_cast(ret))); + return; + } + + AbilityContinuationOrRecover(want); + auto window = scene_->GetMainWindow(); + if (window) { + TAG_LOGD(AAFwkTag::UIABILITY, "registerDisplayMoveListener, windowId: %{public}d", window->GetWindowId()); + abilityDisplayMoveListener_ = new AbilityDisplayMoveListener(weak_from_this()); + if (abilityDisplayMoveListener_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityDisplayMoveListener_"); + return; + } + window->RegisterDisplayMoveListener(abilityDisplayMoveListener_); + } +} + +void StsUIAbility::RequestFocus(const Want &want) +{ + TAG_LOGI(AAFwkTag::UIABILITY, "called"); + if (scene_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null scene_"); + return; + } + auto window = scene_->GetMainWindow(); + if (window != nullptr &&want.HasParameter(Want::PARAM_RESV_WINDOW_MODE)) { + auto windowMode = want.GetIntParam( + Want::PARAM_RESV_WINDOW_MODE, AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_UNDEFINED); + window->SetWindowMode(static_cast(windowMode)); + TAG_LOGD(AAFwkTag::UIABILITY, "set window mode: %{public}d", windowMode); + } + AddLifecycleEventBeforeJSCall(FreezeUtil::TimeoutState::FOREGROUND, METHOD_NAME); + scene_->GoForeground(UIAbility::sceneFlag_); + TAG_LOGI(AAFwkTag::UIABILITY, "end"); +} + +void StsUIAbility::ContinuationRestore(const Want &want) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (!IsRestoredInContinuation()) { + TAG_LOGE(AAFwkTag::UIABILITY, "not in continuation"); + return; + } + if (scene_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null scene_"); + return; + } + RestorePageStack(want); + OnSceneRestored(); + NotifyContinuationResult(want, true); +} + +std::shared_ptr StsUIAbility::GetJsWindowStage() +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (stsWindowStageObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsWindowStageObj_"); + } + return stsWindowStageObj_; +} + +const STSRuntime &StsUIAbility::GetSTSRuntime() +{ + return stsRuntime_; +} + +void StsUIAbility::ExecuteInsightIntentRepeateForeground(const Want &want, + const std::shared_ptr &executeParam, + std::unique_ptr callback) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (executeParam == nullptr) { + TAG_LOGW(AAFwkTag::UIABILITY, "null executeParam"); + RequestFocus(want); + InsightIntentExecutorMgr::TriggerCallbackInner(std::move(callback), ERR_OK); + return; + } + + auto asyncCallback = [weak = weak_from_this(), want](InsightIntentExecuteResult result) { + TAG_LOGD(AAFwkTag::UIABILITY, "request focus"); + auto ability = weak.lock(); + if (ability == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null ability"); + return; + } + ability->RequestFocus(want); + }; + callback->Push(asyncCallback); + + InsightIntentExecutorInfo executeInfo; + auto ret = GetInsightIntentExecutorInfo(want, executeParam, executeInfo); + if (!ret) { + TAG_LOGE(AAFwkTag::UIABILITY, "get intentExecutor failed"); + InsightIntentExecutorMgr::TriggerCallbackInner( + std::move(callback), static_cast(AbilityErrorCode::ERROR_CODE_INVALID_PARAM)); + return; + } + + ret = DelayedSingleton::GetInstance()->ExecuteInsightIntent( + stsRuntime_, executeInfo, std::move(callback)); + if (!ret) { + // callback has removed, release in insight intent executor. + TAG_LOGE(AAFwkTag::UIABILITY, "execute insightIntent failed"); + } +} + +void StsUIAbility::ExecuteInsightIntentMoveToForeground(const Want &want, + const std::shared_ptr &executeParam, + std::unique_ptr callback) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (executeParam == nullptr) { + TAG_LOGW(AAFwkTag::UIABILITY, "null executeParam"); + OnForeground(want); + InsightIntentExecutorMgr::TriggerCallbackInner(std::move(callback), ERR_OK); + return; + } + + if (abilityInfo_) { + } + UIAbility::OnForeground(want); + + auto asyncCallback = [weak = weak_from_this(), want](InsightIntentExecuteResult result) { + TAG_LOGD(AAFwkTag::UIABILITY, "begin call onForeground"); + auto ability = weak.lock(); + if (ability == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null ability"); + return; + } + ability->CallOnForegroundFunc(want); + }; + callback->Push(asyncCallback); + + InsightIntentExecutorInfo executeInfo; + auto ret = GetInsightIntentExecutorInfo(want, executeParam, executeInfo); + if (!ret) { + TAG_LOGE(AAFwkTag::UIABILITY, "get intentExecutor failed"); + InsightIntentExecutorMgr::TriggerCallbackInner( + std::move(callback), static_cast(AbilityErrorCode::ERROR_CODE_INVALID_PARAM)); + return; + } + + ret = DelayedSingleton::GetInstance()->ExecuteInsightIntent( + stsRuntime_, executeInfo, std::move(callback)); + if (!ret) { + // callback has removed, release in insight intent executor. + TAG_LOGE(AAFwkTag::UIABILITY, "execute insightIntent failed"); + } +} + +void StsUIAbility::ExecuteInsightIntentBackground(const Want &want, + const std::shared_ptr &executeParam, + std::unique_ptr callback) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (executeParam == nullptr) { + TAG_LOGW(AAFwkTag::UIABILITY, "null executeParam"); + InsightIntentExecutorMgr::TriggerCallbackInner(std::move(callback), ERR_OK); + return; + } + + if (abilityInfo_) { + } + + InsightIntentExecutorInfo executeInfo; + auto ret = GetInsightIntentExecutorInfo(want, executeParam, executeInfo); + if (!ret) { + TAG_LOGE(AAFwkTag::UIABILITY, "get intentExecutor failed"); + InsightIntentExecutorMgr::TriggerCallbackInner( + std::move(callback), static_cast(AbilityErrorCode::ERROR_CODE_INVALID_PARAM)); + return; + } + + ret = DelayedSingleton::GetInstance()->ExecuteInsightIntent( + stsRuntime_, executeInfo, std::move(callback)); + if (!ret) { + // callback has removed, release in insight intent executor. + TAG_LOGE(AAFwkTag::UIABILITY, "execute insightIntent failed"); + } +} + +bool StsUIAbility::GetInsightIntentExecutorInfo(const Want &want, + const std::shared_ptr &executeParam, InsightIntentExecutorInfo &executeInfo) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + + auto context = GetAbilityContext(); + if (executeParam == nullptr || context == nullptr || abilityInfo_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "param invalid"); + return false; + } + + if (executeParam->executeMode_ == AppExecFwk::ExecuteMode::UI_ABILITY_FOREGROUND &&stsWindowStageObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "param invalid"); + return false; + } + + const WantParams &wantParams = want.GetParams(); + executeInfo.srcEntry = wantParams.GetStringParam("ohos.insightIntent.srcEntry"); + executeInfo.hapPath = abilityInfo_->hapPath; + executeInfo.esmodule = abilityInfo_->compileMode == AppExecFwk::CompileMode::ES_MODULE; + executeInfo.windowMode = windowMode_; + executeInfo.token = context->GetToken(); + if (stsWindowStageObj_ != nullptr) { + std::shared_ptr etsNativeRef = std::make_shared(); + etsNativeRef->ref_ = stsWindowStageObj_; + executeInfo.pageLoader = etsNativeRef; + } + executeInfo.executeParam = executeParam; + return true; +} + +int32_t StsUIAbility::OnCollaborate(WantParams &wantParam) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "OnCollaborate: %{public}s", GetAbilityName().c_str()); + int32_t ret = CollaborateResult::REJECT; + + if (stsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsAbilityObj_"); + return ret; + } + ret = (ret == CollaborateResult::ACCEPT) ? CollaborateResult::ACCEPT : CollaborateResult::REJECT; + return ret; +} + +#endif + +int32_t StsUIAbility::OnContinue( + WantParams &wantParams, bool &isAsyncOnContinue, const AppExecFwk::AbilityInfo &abilityInfo) +{ + TAG_LOGI(AAFwkTag::UIABILITY, "called"); + if (stsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsAbilityObj_"); + return AppExecFwk::ContinuationManagerStage::OnContinueResult::ON_CONTINUE_ERR; + } + TAG_LOGI(AAFwkTag::UIABILITY, "end"); + return 0; +} + +int32_t StsUIAbility::OnSaveState(int32_t reason, WantParams &wantParams) +{ + if (stsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsAbilityObj_"); + return -1; + } + return -1; +} + +void StsUIAbility::OnConfigurationUpdated(const Configuration &configuration) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + UIAbility::OnConfigurationUpdated(configuration); + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (abilityContext_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext"); + return; + } + auto fullConfig = abilityContext_->GetConfiguration(); + if (fullConfig == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null fullConfig"); + return; + } + + TAG_LOGD(AAFwkTag::UIABILITY, "fullConfig: %{public}s", fullConfig->GetName().c_str()); +} + +void StsUIAbility::OnMemoryLevel(int level) +{ + UIAbility::OnMemoryLevel(level); + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (stsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsAbilityObj_"); + return; + } +} + +void StsUIAbility::UpdateContextConfiguration() +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (abilityContext_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext_"); + return; + } +} + +void StsUIAbility::OnNewWant(const Want &want) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + UIAbility::OnNewWant(want); + +#ifdef SUPPORT_SCREEN + if (scene_) { + scene_->OnNewWant(want); + } +#endif + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + if (stsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsAbilityObj_"); + return; + } + ani_status status = ANI_OK; + ani_field field = nullptr; + ani_ref wantRef = OHOS::AppExecFwk::WrapWant(env, want); + if (wantRef == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); + return; + } + + auto applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } + if ((status = env->Class_FindField(stsAbilityObj_->aniCls, "lastRequestWant", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + } + if ((status = env->Object_SetField_Ref(stsAbilityObj_->aniObj, field, wantRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + } + auto launchParam = GetLaunchParam(); + if (InsightIntentExecuteParam::IsInsightIntentExecute(want)) { + launchParam.launchReason = AAFwk::LaunchReason::LAUNCHREASON_INSIGHT_INTENT; + } + ani_ref launchParamRef = CreateStsLaunchParam(env, launchParam); + std::string methodName = "OnNewWant"; + AddLifecycleEventBeforeJSCall(FreezeUtil::TimeoutState::FOREGROUND, methodName); + const char *signature = + "L@ohos/app/ability/Want/Want;L@ohos/app/ability/AbilityConstant/AbilityConstant/LaunchParam;:V"; + CallObjectMethod(false, "onNewWant", signature, wantRef, launchParamRef); + AddLifecycleEventAfterJSCall(FreezeUtil::TimeoutState::FOREGROUND, methodName); + + applicationContext = AbilityRuntime::Context::GetApplicationContext(); + if (applicationContext != nullptr) { + } + TAG_LOGD(AAFwkTag::UIABILITY, "end"); +} + +void StsUIAbility::OnAbilityResult(int requestCode, int resultCode, const Want &resultData) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + UIAbility::OnAbilityResult(requestCode, resultCode, resultData); + if (abilityContext_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext_"); + return; + } + abilityContext_->OnAbilityResult(requestCode, resultCode, resultData); + TAG_LOGD(AAFwkTag::UIABILITY, "end"); +} + +sptr StsUIAbility::CallRequest() +{ + TAG_LOGI(AAFwkTag::UIABILITY, "CallRequest"); + if (stsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext_"); + return nullptr; + } + + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return nullptr; + } + auto obj = stsAbilityObj_->aniObj; + ani_status status = ANI_ERROR; + ani_ref calleeRef = nullptr; + status = env->Object_GetFieldByName_Ref(obj, "callee", &calleeRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "get callee: %{public}d", status); + return nullptr; + } + auto remoteObj = AniGetNativeRemoteObject(env, reinterpret_cast(calleeRef)); + if (remoteObj == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "AniGetNativeRemoteObject null"); + } + return remoteObj; +} + +bool StsUIAbility::CallObjectMethod(bool withResult, const char *name, const char *signature, ...) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name); + TAG_LOGI(AAFwkTag::UIABILITY, "StsUIAbility call sts, name: %{public}s", name); + if (stsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsAbilityObj"); + return false; + } + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return false; + } + auto obj = stsAbilityObj_->aniObj; + auto cls = stsAbilityObj_->aniCls; + ani_status status = ANI_ERROR; + + ani_method method {}; + if ((status = env->Class_FindMethod(cls, name, signature, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return false; + } + env->ResetError(); + if (withResult) { + ani_boolean res = false; + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Boolean_V(obj, method, &res, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + stsRuntime_.HandleUncaughtError(); + return false; + } + va_end(args); + return res; + } + int64_t timeStart = AbilityRuntime::TimeUtil::SystemTimeMillisecond(); + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(obj, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + stsRuntime_.HandleUncaughtError(); + return false; + } + va_end(args); + int64_t timeEnd = AbilityRuntime::TimeUtil::SystemTimeMillisecond(); + TAG_LOGI(AAFwkTag::UIABILITY, "end, name: %{public}s, time: %{public}s", name, + std::to_string(timeEnd - timeStart).c_str()); + return false; +} + +std::shared_ptr StsUIAbility::CreateADelegatorAbilityProperty() +{ + if (abilityContext_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext_"); + return nullptr; + } + auto property = std::make_shared(); + property->token_ = abilityContext_->GetToken(); + property->name_ = GetAbilityName(); + property->moduleName_ = GetModuleName(); + if (GetApplicationInfo() == nullptr || GetApplicationInfo()->bundleName.empty()) { + property->fullName_ = GetAbilityName(); + } else { + std::string::size_type pos = GetAbilityName().find(GetApplicationInfo()->bundleName); + if (pos == std::string::npos || pos != 0) { + property->fullName_ = GetApplicationInfo()->bundleName + "." + GetAbilityName(); + } else { + property->fullName_ = GetAbilityName(); + } + } + property->lifecycleState_ = GetState(); + property->object_ = stsAbilityObj_; + return property; +} + +void StsUIAbility::Dump(const std::vector ¶ms, std::vector &info) +{ + UIAbility::Dump(params, info); + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr || stsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null env or stsAbilityObj"); + return; + } + ani_object arrayObj = nullptr; + if (!AppExecFwk::WrapArrayString(env, arrayObj, params)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "WrapArrayString failed"); + return; + } + if (!stsAbilityObj_->aniObj || !stsAbilityObj_->aniCls) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null aniObj or aniCls"); + return; + } + ani_status status = ANI_ERROR; + ani_method method = nullptr; + if ((status = env->Class_FindMethod(stsAbilityObj_->aniCls, "onDump", nullptr, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Class_FindMethod FAILED: %{public}d", status); + return; + } + if (!method) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "find method onDump failed"); + return; + } + ani_ref strArrayRef; + if ((status = env->Object_CallMethod_Ref(stsAbilityObj_->aniObj, method, &strArrayRef, arrayObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Object_CallMethod_Ref FAILED: %{public}d", status); + return; + } + if (!strArrayRef) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null strArrayRef"); + return; + } + std::vector dumpInfoStrArray; + if (!AppExecFwk::UnwrapArrayString(env, reinterpret_cast(strArrayRef), dumpInfoStrArray)) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "UnwrapArrayString failed"); + return; + } + for (auto dumpInfoStr:dumpInfoStrArray) { + info.push_back(dumpInfoStr); + } + TAG_LOGD(AAFwkTag::UIABILITY, "dump info size: %{public}zu", info.size()); +} + +std::shared_ptr StsUIAbility::GetStsAbility() +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (stsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null stsAbilityObj_"); + } + return stsAbilityObj_; +} + +#ifdef SUPPORT_SCREEN +void StsUIAbility::UpdateStsWindowStage(ani_ref windowStage) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "called"); + if (shellContextRef_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null shellContextRef_"); + return; + } + ani_object contextObj = shellContextRef_->aniObj; + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + ani_field field = nullptr; + ani_class cls = shellContextRef_->aniCls; + ani_status status = ANI_ERROR; + if (windowStage == nullptr) { + if ((status = env->Class_FindField(cls, "windowStage", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return; + } + ani_ref nullRef = nullptr; + env->GetNull(&nullRef); + if ((status = env->Object_SetField_Ref(contextObj, field, nullRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return; + } + return; + } + if ((status = env->Class_FindField(cls, "windowStage", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return; + } + if ((status = env->Object_SetField_Ref(contextObj, field, windowStage)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status : %{public}d", status); + return; + } +} +#endif +bool StsUIAbility::CheckSatisfyTargetAPIVersion(int32_t version) +{ + auto applicationInfo = GetApplicationInfo(); + if (!applicationInfo) { + TAG_LOGE(AAFwkTag::UIABILITY, "null targetAPIVersion"); + return false; + } + TAG_LOGD(AAFwkTag::UIABILITY, "targetAPIVersion: %{public}d", applicationInfo->apiTargetVersion); + return applicationInfo->apiTargetVersion % API_VERSION_MOD >= version; +} + +bool StsUIAbility::BackPressDefaultValue() +{ + return CheckSatisfyTargetAPIVersion(API12) ? true : false; +} + +void StsUIAbility::OnAfterFocusedCommon(bool isFocused) +{ + auto abilityContext = GetAbilityContext(); + if (abilityContext == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext"); + return; + } + auto applicationContext = abilityContext->GetApplicationContext(); + if (applicationContext == nullptr || applicationContext->IsAbilityLifecycleCallbackEmpty()) { + TAG_LOGD(AAFwkTag::UIABILITY, "null applicationContext or lifecycleCallback"); + return; + } + if (isFocused) { + } else { + } +} +} // namespace AbilityRuntime +} // namespace OHOS 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 0000000000000000000000000000000000000000..ee3405f5d72bbe7f0bfc282816b57a3de8bc831e --- /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/etc/extension_blocklist_config.json b/frameworks/native/ability/native/etc/extension_blocklist_config.json index cfca065c9fcb4d12cf4786cc123147860008f51f..bd95c3bdbce24a7d417c8bbeb21f81fb2a4e99ac 100644 --- a/frameworks/native/ability/native/etc/extension_blocklist_config.json +++ b/frameworks/native/ability/native/etc/extension_blocklist_config.json @@ -147,28 +147,71 @@ "DistributedExtensionAbility": [ "ability.featureAbility", "ability.particleAbility", + "accessibility.config", + "account.appAccount", "account.distributedAccount", "account.osAccount", - "backgroundTaskManager", - "bluetooth", - "bluetoothManager", + "app.form.formBindingData", + "app.form.FormExtensionAbility", + "app.form.formHost", + "app.form.formInfo", + "app.form.formProvider", + "application.formBindingData", + "application.formError", + "application.formHost", + "application.formInfo", + "application.formProvider", "connectedTag", - "geolocation", - "geoLocationManager", + "contact", + "continuation.continuationManager", + "core.liveview.liveViewManager", + "core.scan.customScan", + "core.scan.detectBarcode", + "core.scan.generateBarcode", + "core.scan.scanBarcode", + "core.scan.scanCore", + "file.AlbumPickerComponent", + "file.photoAccessHelper", + "file.PhotoPickerComponent", + "file.picker", + "file.RecentPhotoComponent", + "file.sendablePhotoAccessHelper", + "formError", + "formHost", + "inputMethod", + "multimedia.audio", + "multimedia.avsession", + "multimedia.camera", + "multimedia.cameraPicker", + "multimedia.mediaLibrary", + "multimedia.movingphotoview", + "multimodalInput.inputMonitor", "nfc.cardEmulation", "nfc.controller", "nfc.tag", "nfctech", + "notification", + "notificationManager", + "notificationSubscribe", + "power", + "prompt", + "promptAction", "reminderAgent", "reminderAgentManager", + "screen", + "screenshot", + "ServiceExtensionContext", "tagSession", "telephony.call", - "telephony.data", - "telephony.observer", - "telephony.radio", "telephony.sim", "telephony.sms", - "wallpaper" + "telephony.voipCall", + "UIAbilityContext", + "userIAM.faceAuth", + "userIAM.userAuth", + "vibrator", + "wallpaper", + "window" ], "WorkSchedulerExtension": [ "backgroundTaskManager", diff --git a/frameworks/native/ability/native/extension_ability_thread.cpp b/frameworks/native/ability/native/extension_ability_thread.cpp index 5bd8fe9cd73587a7d9dd5d7cb01cdea3ad215cb9..e158c55c7396f4ec80c6a88f119747a133c95bf7 100644 --- a/frameworks/native/ability/native/extension_ability_thread.cpp +++ b/frameworks/native/ability/native/extension_ability_thread.cpp @@ -237,7 +237,13 @@ void ExtensionAbilityThread::HandleAttach(const std::shared_ptr abilityInfo = abilityRecord->GetAbilityInfo(); + if (abilityInfo == nullptr) { + TAG_LOGE(AAFwkTag::EXT, "null abilityInfo"); + return; + } + auto extension = AppExecFwk::AbilityLoader::GetInstance().GetExtensionByName(abilityName, + abilityInfo->codeLanguage); if (extension == nullptr) { TAG_LOGE(AAFwkTag::EXT, "null extension"); return; diff --git a/frameworks/native/ability/native/form_extension.cpp b/frameworks/native/ability/native/form_extension.cpp index 44dd1c9ca7c193bee2cc18def4f51e3efbdd6b51..c59378c7229e45beb6193a85a5464884e6944f72 100644 --- a/frameworks/native/ability/native/form_extension.cpp +++ b/frameworks/native/ability/native/form_extension.cpp @@ -18,6 +18,7 @@ #include "configuration_utils.h" #include "form_extension_context.h" #include "form_runtime/js_form_extension.h" +#include "sts_form_extension.h" #include "hilog_tag_wrapper.h" #include "runtime.h" @@ -29,10 +30,12 @@ FormExtension* FormExtension::Create(const std::unique_ptr& runtime) if (!runtime) { return new FormExtension(); } - TAG_LOGI(AAFwkTag::FORM_EXT, "call"); + TAG_LOGI(AAFwkTag::FORM_EXT, "call %{public}d", runtime->GetLanguage()); switch (runtime->GetLanguage()) { case Runtime::Language::JS: return JsFormExtension::Create(runtime); + case Runtime::Language::STS: + return STSFormExtension::Create(runtime); default: return new FormExtension(); } diff --git a/frameworks/native/ability/native/insight_intent_executor/ets_insight_intent_executor.cpp b/frameworks/native/ability/native/insight_intent_executor/ets_insight_intent_executor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..246567892a9d16738caf899aeb679baea6b9949b --- /dev/null +++ b/frameworks/native/ability/native/insight_intent_executor/ets_insight_intent_executor.cpp @@ -0,0 +1,495 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ets_insight_intent_executor.h" +#include "hitrace_meter.h" +#include "ability_transaction_callback_info.h" +#include "hilog_tag_wrapper.h" +#include "insight_intent_constant.h" +#include "insight_intent_execute_result.h" +#include "sts_runtime.h" +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "ani_common_execute_result.h" + +#undef STATE_PATTERN_NAIVE_H +#define STATE_PATTERN_NAIVE_STATE state_ +#include "state_pattern_naive.h" + +namespace OHOS::AbilityRuntime { + +std::shared_ptr EtsInsightIntentExecutor::Create(STSRuntime& runtime) +{ + std::shared_ptr ptr = std::make_shared(runtime); + return ptr; +} + +using State = EtsInsightIntentExecutor::State; + +EtsInsightIntentExecutor::EtsInsightIntentExecutor(STSRuntime& runtime) : runtime_(runtime) +{ } + +EtsInsightIntentExecutor::~EtsInsightIntentExecutor() +{ + state_ = State::DESTROYED; + TAG_LOGD(AAFwkTag::INTENT, "~EtsInsightIntentExecutor called"); + + if (contextObj_ && contextObj_->aniRef) { + ani_env *env = runtime_.GetAniEnv(); + if (env != nullptr) { + env->GlobalReference_Delete(contextObj_->aniRef); + } + } + if (etsObj_ && etsObj_->aniRef) { + ani_env *env = runtime_.GetAniEnv(); + if (env != nullptr) { + env->GlobalReference_Delete(etsObj_->aniRef); + } + } +} + +bool EtsInsightIntentExecutor::Init(const InsightIntentExecutorInfo& insightIntentInfo) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::Init called"); + STATE_PATTERN_NAIVE_ACCEPT(State::CREATED, false); + state_ = State::INITIALIZED; + InsightIntentExecutor::Init(insightIntentInfo); + + auto env = runtime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + etsObj_ = EtsInsightIntentExecutor::LoadEtsCode(insightIntentInfo, runtime_); + if (etsObj_ == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null etsObj_"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null Context"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + contextCpp_ = std::make_shared(context); + contextObj_ = CreateEtsInsightIntentContext(env, contextCpp_); + if (contextObj_ == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null contextObj_"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + ani_status status = ANI_ERROR; + if ((status = env->Object_SetFieldByName_Ref(etsObj_->aniObj, "context", contextObj_->aniRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + ani_class executorClass = nullptr; + if ((status = env->FindClass("L@ohos/app/ability/InsightIntentExecutor/InsightIntentExecutor;", + &executorClass)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "find InsightIntentExecutor failed status: %{public}d", status); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + etsObj_->aniCls = executorClass; + + std::array functions = { + ani_native_function {"nativeOnExecuteResult", nullptr, reinterpret_cast(OnExecuteResult)}, + }; + if ((status = env->Class_BindNativeMethods(etsObj_->aniCls, functions.data(), functions.size())) != ANI_OK) { + if (status != ANI_ALREADY_BINDED) { + TAG_LOGE(AAFwkTag::INTENT, "Class_BindNativeMethods failed status: %{public}d", status); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + } + if ((status = env->Object_SetFieldByName_Long(etsObj_->aniObj, "nativeExecutor", + reinterpret_cast(this))) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + return true; +} + +bool EtsInsightIntentExecutor::ExecuteIntentCheckError() +{ + ReplyFailedInner(); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); +} + +bool EtsInsightIntentExecutor::HandleExecuteEtsIntent( + InsightIntentExecuteMode mode, + const std::string& name, + const AAFwk::WantParams& param, + const std::shared_ptr& pageLoader, + std::unique_ptr callback, + bool& isAsync) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::HandleExecuteEtsIntent called"); + STATE_PATTERN_NAIVE_ACCEPT(State::INITIALIZED, false); + state_ = State::EXECUTING; + + if (callback == nullptr || callback->IsEmpty()) { + TAG_LOGE(AAFwkTag::INTENT, "null callback"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + callback_ = std::move(callback); + bool successful = false; + switch (mode) { + case InsightIntentExecuteMode::UIABILITY_FOREGROUND: + if (!EtsInsightIntentExecutor::CheckParametersUIAbilityForeground(pageLoader)) { + TAG_LOGE(AAFwkTag::INTENT, "CheckParametersUIAbilityForeground error"); + return ExecuteIntentCheckError(); + } + successful = ExecuteInsightIntentUIAbilityForeground(name, param, pageLoader); + break; + case InsightIntentExecuteMode::UIABILITY_BACKGROUND: + if (!EtsInsightIntentExecutor::CheckParametersUIAbilityBackground()) { + TAG_LOGE(AAFwkTag::INTENT, "CheckParametersUIAbilityBackground error"); + return ExecuteIntentCheckError(); + } + successful = ExecuteInsightIntentUIAbilityBackground(name, param); + break; + case InsightIntentExecuteMode::UIEXTENSION_ABILITY: + if (!EtsInsightIntentExecutor::CheckParametersUIExtension(pageLoader)) { + TAG_LOGE(AAFwkTag::INTENT, "CheckParametersUIExtension error"); + return ExecuteIntentCheckError(); + } + successful = ExecuteInsightIntentUIExtension(name, param, pageLoader); + break; + case InsightIntentExecuteMode::SERVICE_EXTENSION_ABILITY: + if (!EtsInsightIntentExecutor::CheckParametersServiceExtension()) { + TAG_LOGE(AAFwkTag::INTENT, "CheckParametersServiceExtension error"); + return ExecuteIntentCheckError(); + } + successful = ExecuteInsightIntentServiceExtension(name, param); + break; + default: + TAG_LOGE(AAFwkTag::INTENT, "InsightIntentExecuteMode not supported yet"); + return ExecuteIntentCheckError(); + } + isAsync = isAsync_; + if (!successful) { + ReplyFailedInner(); + } + return successful; +} + +std::unique_ptr EtsInsightIntentExecutor::LoadEtsCode( + const InsightIntentExecutorInfo& info, + STSRuntime& runtime) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::LoadEtsCode called"); + auto executeParam = info.executeParam; + if (executeParam == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null executeParam"); + return std::make_unique(); + } + + std::string moduleName(executeParam->moduleName_); + std::string srcPath(executeParam->moduleName_ + "/" + info.srcEntry); + + auto pos = srcPath.rfind('.'); + if (pos == std::string::npos) { + return std::make_unique(); + } + srcPath.erase(pos); + srcPath.append(".abc"); + + std::unique_ptr etsObj = + runtime.LoadModule(moduleName, srcPath, info.hapPath, info.esmodule, false, info.srcEntry); + return etsObj; +} + +void EtsInsightIntentExecutor::ReplyFailed(InsightIntentExecutorAsyncCallback* callback, + InsightIntentInnerErr innerErr) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ReplyFailed called"); + if (callback == nullptr) { + return; + } + AppExecFwk::InsightIntentExecuteResult errorResult{}; + errorResult.innerErr = innerErr; + callback->Call(errorResult); + delete callback; +} + +void EtsInsightIntentExecutor::ReplySucceeded(InsightIntentExecutorAsyncCallback* callback, + std::shared_ptr resultCpp) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ReplySucceeded called"); + if (callback == nullptr) { + return; + } + if (resultCpp == nullptr) { + ReplyFailed(callback); + return; + } + resultCpp->innerErr = InsightIntentInnerErr::INSIGHT_INTENT_ERR_OK; + callback->Call(*resultCpp); + delete callback; +} + +void EtsInsightIntentExecutor::ReplyFailedInner(InsightIntentInnerErr innerErr) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ReplyFailedInner called"); + state_ = EtsInsightIntentExecutor::State::INVALID; + auto* callback = callback_.release(); + EtsInsightIntentExecutor::ReplyFailed(callback, innerErr); +} + +void EtsInsightIntentExecutor::ReplySucceededInner(std::shared_ptr resultCpp) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ReplySucceededInner called"); + state_ = EtsInsightIntentExecutor::State::EXECUTATION_DONE; + auto* callback = callback_.release(); + EtsInsightIntentExecutor::ReplySucceeded(callback, resultCpp); +} + +bool EtsInsightIntentExecutor::HandleResultReturnedFromEtsFunc(ani_env *env, ani_ref result, bool isAsync) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::HandleResultReturnedFromEtsFunc called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + if (result == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null intent result"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + + AppExecFwk::InsightIntentExecuteResult resultInner; + ani_object resultObject = static_cast(result); + if (!OHOS::AbilityRuntime::UnwrapExecuteResult(env, resultObject, resultInner)) { + TAG_LOGE(AAFwkTag::INTENT, "UnwrapExecuteResult failed"); + STATE_PATTERN_NAIVE_STATE_SET_AND_RETURN(State::INVALID, false); + } + std::shared_ptr resultCpp = + std::make_shared(resultInner); + if (isAsync) { + TAG_LOGI(AAFwkTag::INTENT, "Is promise"); + auto* callback = callback_.release(); + EtsInsightIntentExecutor::ReplySucceeded(callback, resultCpp); + } else { + TAG_LOGI(AAFwkTag::INTENT, "Not promise"); + ReplySucceededInner(resultCpp); + } + return true; +} + +bool EtsInsightIntentExecutor::CheckParametersUIAbilityForeground( + const std::shared_ptr& windowStage) +{ + return windowStage != nullptr; +} + +ani_ref EtsInsightIntentExecutor::CallObjectMethod(bool withResult, const char* name, const char* signature, ...) +{ + ani_status status = ANI_ERROR; + ani_method method = nullptr; + auto env = runtime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return nullptr; + } + if ((status = env->Class_FindMethod(etsObj_->aniCls, name, signature, &method)) != ANI_OK) { + return nullptr; + } + if (method == nullptr) { + return nullptr; + } + ani_ref result = nullptr; + va_list args; + if (withResult) { + va_start(args, signature); + if ((status = env->Object_CallMethod_Ref_V(etsObj_->aniObj, method, &result, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + } + va_end(args); + return result; + } + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(etsObj_->aniObj, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + } + va_end(args); + return nullptr; +} + +bool EtsInsightIntentExecutor::ExecuteInsightIntentUIAbilityForeground( + const std::string& name, + const AAFwk::WantParams& param, + const std::shared_ptr& windowStage) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ExecuteInsightIntentUIAbilityForeground called"); + auto env = runtime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return false; + } + + ani_string aniName = AppExecFwk::GetAniString(env, name); + ani_ref aniWantParams = OHOS::AppExecFwk::WrapWantParams(env, param); + ani_ref result = CallObjectMethod(true, "callOnExecuteInUIAbilityForegroundMode", nullptr, aniName, + aniWantParams, windowStage->aniObj); + if (result == nullptr) { + return false; + } + + ani_boolean isAsync = false; + if (env->Object_GetFieldByName_Boolean(etsObj_->aniObj, "isOnExecuteInUIAbilityForegroundModeAsync", + &isAsync) != ANI_OK) { + return false; + } + + isAsync_ = static_cast(isAsync); + if (isAsync_) { + return true; + } else { + return HandleResultReturnedFromEtsFunc(env, result, isAsync_); + } +} + +bool EtsInsightIntentExecutor::CheckParametersUIAbilityBackground() +{ + return true; +} + +bool EtsInsightIntentExecutor::ExecuteInsightIntentUIAbilityBackground( + const std::string& name, + const AAFwk::WantParams& param) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ExecuteInsightIntentUIAbilityBackground called"); + auto env = runtime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return false; + } + + ani_string aniName = AppExecFwk::GetAniString(env, name); + ani_ref aniWantParams = OHOS::AppExecFwk::WrapWantParams(env, param); + ani_ref result = CallObjectMethod(true, "callOnExecuteInUIAbilityBackgroundMode", nullptr, aniName, + aniWantParams); + if (result == nullptr) { + return false; + } + + ani_boolean isAsync = false; + if (env->Object_GetFieldByName_Boolean(etsObj_->aniObj, "isOnExecuteInUIAbilityBackgroundModeAsync", + &isAsync) != ANI_OK) { + return false; + } + + isAsync_ = static_cast(isAsync); + if (isAsync_) { + return true; + } else { + return HandleResultReturnedFromEtsFunc(env, result, isAsync_); + } +} + +bool EtsInsightIntentExecutor::CheckParametersUIExtension( + const std::shared_ptr& UIExtensionContentSession) +{ + return UIExtensionContentSession != nullptr; +} + +bool EtsInsightIntentExecutor::ExecuteInsightIntentUIExtension( + const std::string& name, + const AAFwk::WantParams& param, + const std::shared_ptr& UIExtensionContentSession) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ExecuteInsightIntentUIExtension called"); + auto env = runtime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return false; + } + + ani_string aniName = AppExecFwk::GetAniString(env, name); + ani_ref aniWantParams = OHOS::AppExecFwk::WrapWantParams(env, param); + ani_ref result = CallObjectMethod(true, "callOnExecuteInUIExtensionAbility", nullptr, aniName, + aniWantParams, UIExtensionContentSession->aniObj); + if (result == nullptr) { + return false; + } + + ani_boolean isAsync = false; + if (env->Object_GetFieldByName_Boolean(etsObj_->aniObj, "isOnExecuteInUIExtensionAbilityAsync", + &isAsync) != ANI_OK) { + return false; + } + + isAsync_ = static_cast(isAsync); + if (isAsync_) { + return true; + } else { + return HandleResultReturnedFromEtsFunc(env, result, isAsync_); + } +} + +bool EtsInsightIntentExecutor::CheckParametersServiceExtension() +{ + return true; +} + +bool EtsInsightIntentExecutor::ExecuteInsightIntentServiceExtension( + const std::string& name, + const AAFwk::WantParams& param) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentExecutor::ExecuteInsightIntentServiceExtension called"); + auto env = runtime_.GetAniEnv(); + if (!env) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return false; + } + + ani_string aniName = AppExecFwk::GetAniString(env, name); + ani_ref aniWantParams = OHOS::AppExecFwk::WrapWantParams(env, param); + ani_ref result = CallObjectMethod(true, "callOnExecuteInServiceExtensionAbility", nullptr, aniName, + aniWantParams); + if (result == nullptr) { + return false; + } + + ani_boolean isAsync = false; + if (env->Object_GetFieldByName_Boolean(etsObj_->aniObj, "isOnExecuteInServiceExtensionAbilityAsync", + &isAsync) != ANI_OK) { + return false; + } + isAsync_ = static_cast(isAsync); + if (isAsync_) { + return true; + } else { + return HandleResultReturnedFromEtsFunc(env, result, isAsync_); + } +} + +void EtsInsightIntentExecutor::OnExecuteResult(ani_env *env, [[maybe_unused]]ani_object aniObj, ani_object result) +{ + if (result == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null result"); + return; + } + + ani_long nativeExecutor = 0; + if (env->Object_GetFieldByName_Long(aniObj, "nativeExecutor", &nativeExecutor) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "nativeExecutor failed"); + return; + } + ((EtsInsightIntentExecutor*)nativeExecutor)->HandleResultReturnedFromEtsFunc(env, result, true); +} +} // namespace OHOS::AbilityRuntime diff --git a/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor.cpp b/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor.cpp index 542ec780fccd81a66124770d0ad62673e227417d..71f28661a40e3c047472346430512ac13dc4b72d 100644 --- a/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor.cpp +++ b/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor.cpp @@ -15,9 +15,11 @@ #include "insight_intent_executor.h" #include "js_insight_intent_executor.h" +#include "ets_insight_intent_executor.h" #include "hilog_tag_wrapper.h" #include "js_runtime.h" +#include "sts_runtime.h" #include "runtime.h" namespace OHOS::AbilityRuntime { @@ -28,6 +30,9 @@ std::shared_ptr InsightIntentExecutor::Create(Runtime& ru case Runtime::Language::JS: return static_cast>(JsInsightIntentExecutor::Create( static_cast(runtime))); + case Runtime::Language::STS: + return static_cast>(EtsInsightIntentExecutor::Create( + static_cast(runtime))); default: return nullptr; } diff --git a/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor_mgr.cpp b/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor_mgr.cpp index 8fcbd977db6a8f936465839b611fe340a29d815c..c721310a47a348e737d20b5901669c86b390dc27 100644 --- a/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor_mgr.cpp +++ b/frameworks/native/ability/native/insight_intent_executor/insight_intent_executor_mgr.cpp @@ -17,7 +17,7 @@ #include "ability_business_error.h" #include "hilog_tag_wrapper.h" - +#include "ets_insight_intent_executor.h" namespace OHOS { namespace AbilityRuntime { InsightIntentExecutorMgr::InsightIntentExecutorMgr() @@ -70,9 +70,18 @@ bool InsightIntentExecutorMgr::ExecuteInsightIntent(Runtime& runtime, const Insi AddInsightIntentExecutor(executeParam->insightIntentId_, intentExecutor); bool isAsync = false; - auto ret = intentExecutor->HandleExecuteIntent(static_cast(executeParam->executeMode_), - executeParam->insightIntentName_, *executeParam->insightIntentParam_, executeInfo.pageLoader, - std::move(callback), isAsync); + bool ret = false; + if (runtime.GetLanguage() == AbilityRuntime::Runtime::Language::STS) { + ret = std::static_pointer_cast(intentExecutor)->HandleExecuteEtsIntent( + static_cast(executeParam->executeMode_), + executeParam->insightIntentName_, *executeParam->insightIntentParam_, + std::static_pointer_cast(executeInfo.pageLoader)->ref_, + std::move(callback), isAsync); + } else { + ret = intentExecutor->HandleExecuteIntent(static_cast(executeParam->executeMode_), + executeParam->insightIntentName_, *executeParam->insightIntentParam_, executeInfo.pageLoader, + std::move(callback), isAsync); + } if (!ret) { TAG_LOGE(AAFwkTag::INTENT, "Handle Execute intent failed"); // callback has removed, if execute insight intent failed, call in sub function. diff --git a/frameworks/native/ability/native/js_service_extension.cpp b/frameworks/native/ability/native/js_service_extension.cpp index af93427c6735ef659629adc498659fd1844c9884..39f43a0e043026c03dd948bea2939c35ac9ee7d7 100644 --- a/frameworks/native/ability/native/js_service_extension.cpp +++ b/frameworks/native/ability/native/js_service_extension.cpp @@ -529,48 +529,6 @@ bool JsServiceExtension::HandleInsightIntent(const AAFwk::Want &want) return true; } -bool JsServiceExtension::GetInsightIntentExecutorInfo(const Want &want, - const std::shared_ptr &executeParam, - InsightIntentExecutorInfo &executorInfo) -{ - TAG_LOGD(AAFwkTag::SERVICE_EXT, "called"); - auto context = GetContext(); - if (executeParam == nullptr || context == nullptr || abilityInfo_ == nullptr) { - TAG_LOGE(AAFwkTag::SERVICE_EXT, "Param invalid"); - return false; - } - - const WantParams &wantParams = want.GetParams(); - executorInfo.srcEntry = wantParams.GetStringParam(AppExecFwk::INSIGHT_INTENT_SRC_ENTRY); - executorInfo.hapPath = abilityInfo_->hapPath; - executorInfo.esmodule = abilityInfo_->compileMode == AppExecFwk::CompileMode::ES_MODULE; - executorInfo.token = context->GetToken(); - executorInfo.executeParam = executeParam; - return true; -} - -bool JsServiceExtension::OnInsightIntentExecuteDone(uint64_t intentId, - const AppExecFwk::InsightIntentExecuteResult &result) -{ - TAG_LOGI(AAFwkTag::SERVICE_EXT, "Notify execute done, intentId %{public}" PRIu64"", intentId); - auto context = GetContext(); - if (context == nullptr) { - TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); - return false; - } - auto token = context->GetToken(); - if (token == nullptr) { - TAG_LOGE(AAFwkTag::SERVICE_EXT, "null token"); - return false; - } - auto ret = AAFwk::AbilityManagerClient::GetInstance()->ExecuteInsightIntentDone(token, intentId, result); - if (ret != ERR_OK) { - TAG_LOGE(AAFwkTag::SERVICE_EXT, "Notify execute done failed"); - return false; - } - return true; -} - napi_value JsServiceExtension::CallObjectMethod(const char* name, napi_value const* argv, size_t argc) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name); diff --git a/frameworks/native/ability/native/recovery/ability_recovery.cpp b/frameworks/native/ability/native/recovery/ability_recovery.cpp index 4c9f16dc990b6912e0b4b940faafc5043a21385b..a8387c5bf62dd7ef4f1ecedf8e5234466c588feb 100644 --- a/frameworks/native/ability/native/recovery/ability_recovery.cpp +++ b/frameworks/native/ability/native/recovery/ability_recovery.cpp @@ -59,6 +59,34 @@ static std::string GetSaveAppCachePath(int32_t savedStateId) return fileDir + "/" + fileName; } } +// enum OnSaveResult { +// ALL_AGREE = 0, +// CONTINUATION_REJECT = 1, +// CONTINUATION_MISMATCH = 2, +// RECOVERY_AGREE = 3, +// RECOVERY_REJECT = 4, +// ALL_REJECT +// } +OnSaveResult OnSaveResult_ConvertStsToNative(const int32_t index) +{ + return static_cast(index); +} +OnSaveResult OnSaveResult_ConvertNativeToSts(const OnSaveResult value) +{ + return value; +} +// enum StateType { +// CONTINUATION = 0, +// APP_RECOVERY = 1 +// } +static StateType StateType_ConvertStsToNative(const int32_t index) +{ + return static_cast(index); +} +static int32_t StateType_ConvertNativeToSts(const StateType value) +{ + return value; +} AbilityRecovery::AbilityRecovery() : isEnable_(false), restartFlag_(RestartFlag::ALWAYS_RESTART), saveOccasion_(SaveOccasionFlag::SAVE_WHEN_ERROR), saveMode_(SaveModeFlag::SAVE_WITH_FILE) @@ -425,6 +453,7 @@ bool AbilityRecovery::IsSaveAbilityState(StateReason reason) case StateReason::CPP_CRASH: case StateReason::JS_ERROR: case StateReason::CJ_ERROR: + case StateReason::STS_ERROR: case StateReason::APP_FREEZE: if ((saveOccasion_ & SaveOccasionFlag::SAVE_WHEN_ERROR) != 0) { ret = true; diff --git a/frameworks/native/ability/native/recovery/app_recovery.cpp b/frameworks/native/ability/native/recovery/app_recovery.cpp index 5358f9d8133cbbdee7f7f3bef56d1b45a4b4d793..d5581c3c41c8397085236983edbbfbed5b7f8bbc 100644 --- a/frameworks/native/ability/native/recovery/app_recovery.cpp +++ b/frameworks/native/ability/native/recovery/app_recovery.cpp @@ -377,6 +377,7 @@ bool AppRecovery::ShouldSaveAppState(StateReason reason) case StateReason::CPP_CRASH: case StateReason::JS_ERROR: case StateReason::CJ_ERROR: + case StateReason::STS_ERROR: case StateReason::APP_FREEZE: // appfreeze could not callback to js function safely. if ((saveOccasion_ & SaveOccasionFlag::SAVE_WHEN_ERROR) != 0) { ret = true; @@ -422,6 +423,11 @@ bool AppRecovery::ShouldRecoverApp(StateReason reason) } break; + case StateReason::STS_ERROR: + if (isAlwaysStart || (restartFlag_ & RestartFlag::RESTART_WHEN_STS_CRASH) != 0) { + ret = true; + } + break; case StateReason::APP_FREEZE: if (isAlwaysStart || (restartFlag_ & RestartFlag::RESTART_WHEN_APP_FREEZE) != 0) { ret = true; diff --git a/frameworks/native/ability/native/service_extension.cpp b/frameworks/native/ability/native/service_extension.cpp index 0838b03f9aa3437b08bcb5bc1047d4e7b1c0d9df..db8b841a22b8385eb9d06704cf5b540506553c97 100644 --- a/frameworks/native/ability/native/service_extension.cpp +++ b/frameworks/native/ability/native/service_extension.cpp @@ -18,9 +18,11 @@ #include "configuration_utils.h" #include "connection_manager.h" #include "hilog_tag_wrapper.h" +#include "ability_manager_client.h" #include "js_service_extension.h" #include "runtime.h" #include "service_extension_context.h" +#include "sts_service_extension.h" namespace OHOS { namespace AbilityRuntime { @@ -46,6 +48,8 @@ ServiceExtension* ServiceExtension::Create(const std::unique_ptr& runti switch (runtime->GetLanguage()) { case Runtime::Language::JS: return JsServiceExtension::Create(runtime); + case Runtime::Language::STS: + return StsServiceExtension::Create(runtime); default: return new ServiceExtension(); @@ -89,5 +93,47 @@ void ServiceExtension::OnConfigurationUpdated(const AppExecFwk::Configuration &c auto configUtils = std::make_shared(); configUtils->UpdateGlobalConfig(configuration, context->GetResourceManager()); } + +bool ServiceExtension::GetInsightIntentExecutorInfo(const Want &want, + const std::shared_ptr &executeParam, + InsightIntentExecutorInfo &executorInfo) +{ + TAG_LOGD(AAFwkTag::SERVICE_EXT, "GetInsightIntentExecutorInfo called"); + auto context = GetContext(); + if (executeParam == nullptr || context == nullptr || abilityInfo_ == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Param invalid"); + return false; + } + + const WantParams &wantParams = want.GetParams(); + executorInfo.srcEntry = wantParams.GetStringParam(AppExecFwk::INSIGHT_INTENT_SRC_ENTRY); + executorInfo.hapPath = abilityInfo_->hapPath; + executorInfo.esmodule = abilityInfo_->compileMode == AppExecFwk::CompileMode::ES_MODULE; + executorInfo.token = context->GetToken(); + executorInfo.executeParam = executeParam; + return true; +} + +bool ServiceExtension::OnInsightIntentExecuteDone(uint64_t intentId, + const AppExecFwk::InsightIntentExecuteResult &result) +{ + TAG_LOGI(AAFwkTag::SERVICE_EXT, "Notify execute done, intentId %{public}" PRIu64"", intentId); + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context"); + return false; + } + auto token = context->GetToken(); + if (token == nullptr) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "null token"); + return false; + } + auto ret = AAFwk::AbilityManagerClient::GetInstance()->ExecuteInsightIntentDone(token, intentId, result); + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::SERVICE_EXT, "Notify execute done failed"); + return false; + } + return true; +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/native/ability/native/sts_free_install_observer.cpp b/frameworks/native/ability/native/sts_free_install_observer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b7a335a48fe2f51afc5d97ad2f0fe2ef2c6b80e --- /dev/null +++ b/frameworks/native/ability/native/sts_free_install_observer.cpp @@ -0,0 +1,182 @@ +/* + * 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 "sts_free_install_observer.h" + +#include "ability_business_error.h" +#include "ani_common_ability_result.h" +#include "ani_common_configuration.h" +#include "ani_common_start_options.h" +#include "ani_common_want.h" +#include "ani_common_util.h" +#include "hilog_tag_wrapper.h" +#include "hitrace_meter.h" + +namespace OHOS { +namespace AbilityRuntime { +StsFreeInstallObserver::StsFreeInstallObserver(ani_vm *etsVm) : etsVm_(etsVm) {} + +StsFreeInstallObserver::~StsFreeInstallObserver() = default; + +void StsFreeInstallObserver::OnInstallFinished( + const std::string &bundleName, const std::string &abilityName, const std::string &startTime, const int &resultCode) +{ + TAG_LOGD(AAFwkTag::FREE_INSTALL, "call"); + HandleOnInstallFinished(bundleName, abilityName, startTime, resultCode); +} + +void StsFreeInstallObserver::OnInstallFinishedByUrl(const std::string &startTime, const std::string& url, + const int &resultCode) +{ + TAG_LOGD(AAFwkTag::FREE_INSTALL, "call"); + HandleOnInstallFinishedByUrl(startTime, url, resultCode); +} + +void StsFreeInstallObserver::HandleOnInstallFinished( + const std::string &bundleName, const std::string &abilityName, const std::string &startTime, const int &resultCode) +{ + TAG_LOGD(AAFwkTag::FREE_INSTALL, "call"); + std::vector callbacks; + { + std::unique_lock lock(stsObserverObjectListLock_); + for (auto it = stsObserverObjectList_.begin(); it != stsObserverObjectList_.end();) { + if ((it->bundleName != bundleName) || (it->abilityName != abilityName) || (it->startTime != startTime)) { + it++; + continue; + } + if (it->callBack == nullptr) { + it++; + continue; + } + callbacks.emplace_back(it->callBack); + it = stsObserverObjectList_.erase(it); + } + } + + for (auto callback : callbacks) { + CallCallback(callback, resultCode); + FinishAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str())); + } +} + +void StsFreeInstallObserver::HandleOnInstallFinishedByUrl(const std::string &startTime, const std::string& url, + const int &resultCode) +{ + TAG_LOGD(AAFwkTag::FREE_INSTALL, "call"); + std::vector callbacks; + { + std::unique_lock lock(stsObserverObjectListLock_); + for (auto it = stsObserverObjectList_.begin(); it != stsObserverObjectList_.end();) { + if ((it->startTime != startTime) || (it->url != url)) { + it++; + continue; + } + if (it->callBack == nullptr) { + it++; + continue; + } + callbacks.emplace_back(it->callBack); + it = stsObserverObjectList_.erase(it); + } + } + + for (auto callback : callbacks) { + CallCallback(callback, resultCode); + FinishAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str())); + } +} + +void StsFreeInstallObserver::CallCallback(ani_object callback, int32_t resultCode) +{ + TAG_LOGD(AAFwkTag::FREE_INSTALL, "call"); + if (callback == nullptr) { + TAG_LOGE(AAFwkTag::FREE_INSTALL, "callback is nullptr."); + return; + } + if (etsVm_ == nullptr) { + TAG_LOGE(AAFwkTag::FREE_INSTALL, "etsVm_ is nullptr."); + return; + } + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + ani_option interopEnabled { "--interop=disable", nullptr }; + ani_options aniArgs { 1, &interopEnabled }; + if ((etsVm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status : %{public}d", status); + } + ani_object aniObject = CreateStsError(env, AbilityErrorCode::ERROR_OK); + if (resultCode != ERR_OK) { + aniObject = CreateStsErrorByNativeErr(env, resultCode); + } + AppExecFwk::AsyncCallback(env, callback, aniObject, nullptr); +} + +void StsFreeInstallObserver::AddStsObserverObject(ani_env *env, const std::string &bundleName, + const std::string &abilityName, const std::string &startTime, ani_object callBack) +{ + TAG_LOGD(AAFwkTag::FREE_INSTALL, "call"); + { + std::unique_lock lock(stsObserverObjectListLock_); + for (auto it = stsObserverObjectList_.begin(); it != stsObserverObjectList_.end(); ++it) { + if (it->bundleName == bundleName && it->abilityName == abilityName && it->startTime == startTime) { + TAG_LOGW(AAFwkTag::FREE_INSTALL, "The StsFreeInstallObserverObject has been added"); + return; + } + } + } + StartAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str())); + StsFreeInstallObserverObject object; + object.bundleName = bundleName; + object.abilityName = abilityName; + object.startTime = startTime; + AddStsObserverCommon(env, object, callBack); +} + +void StsFreeInstallObserver::AddStsObserverObject(ani_env *env, const std::string &startTime, + const std::string &url, ani_object callBack) +{ + TAG_LOGD(AAFwkTag::FREE_INSTALL, "call"); + { + std::unique_lock lock(stsObserverObjectListLock_); + for (auto it = stsObserverObjectList_.begin(); it != stsObserverObjectList_.end(); ++it) { + if (it->startTime == startTime && it->url == url) { + TAG_LOGW(AAFwkTag::FREE_INSTALL, "add stsObject"); + return; + } + } + } + StartAsyncTrace(HITRACE_TAG_ABILITY_MANAGER, "StartFreeInstall", atoi(startTime.c_str())); + StsFreeInstallObserverObject object; + object.url = url; + object.startTime = startTime; + AddStsObserverCommon(env, object, callBack); +} + +void StsFreeInstallObserver::AddStsObserverCommon( + ani_env *env, StsFreeInstallObserverObject &object, ani_object callBack) +{ + TAG_LOGD(AAFwkTag::FREE_INSTALL, "call"); + std::unique_lock lock(stsObserverObjectListLock_); + ani_ref global = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->GlobalReference_Create(callBack, &global)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "status : %{public}d", status); + return; + } + object.callBack = reinterpret_cast(global); + stsObserverObjectList_.emplace_back(object); +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/ability/native/sts_ui_extension_callback.cpp b/frameworks/native/ability/native/sts_ui_extension_callback.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b47deaf9b631cbd109786ca9a37236b77edee0a2 --- /dev/null +++ b/frameworks/native/ability/native/sts_ui_extension_callback.cpp @@ -0,0 +1,191 @@ +/* + * 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 "sts_ui_extension_callback.h" + +#include "ability_business_error.h" +#include "ani_common_ability_result.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;"; +} + +StsUIExtensionCallback::StsUIExtensionCallback() : JsUIExtensionCallback(nullptr) +{ +} + +StsUIExtensionCallback::~StsUIExtensionCallback() +{ +} + +void StsUIExtensionCallback::SetSessionId(int32_t sessionId) +{ + aniSessionId_ = sessionId; +} + +void StsUIExtensionCallback::SetUIContent(Ace::UIContent* uiContent) +{ + aniUIContent_ = uiContent; +} + +void StsUIExtensionCallback::OnError(int32_t number) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "call"); + auto aniEnv = GetAniEnv(); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null aniEnv"); + return; + } + ani_status status = ANI_ERROR; + ani_class clsCall = nullptr; + if ((status = aniEnv->FindClass(ABILITY_START_CLASS_NAME, &clsCall)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "find AbilityStartCallback class failed, status : %{public}d", status); + return; + } + ani_method method = nullptr; + if ((status = aniEnv->Class_FindMethod(clsCall, "onError", "ILstd/core/String;Lstd/core/String;:V", + &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "find onError method failed, status : %{public}d", status); + return; + } + 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 + ani_string aniName; + if ((status = aniEnv->String_NewUTF8(name.c_str(), name.length(), &aniName)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "String_NewUTF8 failed, status : %{public}d", status); + return; + } + ani_string aniMsg; + if ((status = aniEnv->String_NewUTF8(message.c_str(), message.length(), &aniMsg)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "String_NewUTF8 failed, status : %{public}d", status); + return; + } + ani_int aniCode = number; + if ((status = aniEnv->Object_CallMethod_Void(reinterpret_cast(startAbilityAniCallback_), + method, aniCode, aniName, aniMsg)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "call onError method failed, status : %{public}d", status); + return; + } + CloseModalUIExtension(); +} + +void StsUIExtensionCallback::OnResult(int32_t resultCode, const AAFwk::Want &want) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "call"); + auto aniEnv = GetAniEnv(); + if (aniEnv == nullptr || startAbilityAniCallback_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null aniEnv"); + return; + } + ani_status status = ANI_ERROR; + ani_object startCallback = reinterpret_cast(startAbilityAniCallback_); + ani_ref onResultRef {}; + if ((status = aniEnv->Object_GetFieldByName_Ref(startCallback, "onResult", &onResultRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "get onResult failed, status : %{public}d", status); + return; + } + ani_fn_object onResultFn = reinterpret_cast(onResultRef); + ani_object abilityResultObj = AppExecFwk::WrapAbilityResult(aniEnv, resultCode, want); + if (abilityResultObj == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "create abilityResultObj failed"); + return; + } + + ani_ref abilityResultObjRef = nullptr; + if ((status = aniEnv->GlobalReference_Create(abilityResultObj, &abilityResultObjRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GlobalReference_Create abilityResultObj failed, status : %{public}d", status); + return; + } + ani_ref argv[] = { abilityResultObjRef }; + if ((status = aniEnv->FunctionalObject_Call(onResultFn, 1, argv, nullptr)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "call onResult fn failed, status : %{public}d", status); + return; + } + CloseModalUIExtension(); +} + +void StsUIExtensionCallback::OnRelease(int32_t code) +{ + TAG_LOGI(AAFwkTag::UI_EXT, "call, code:%{public}d", code); + CloseModalUIExtension(); +} + +void StsUIExtensionCallback::SetStsCallbackObject(ani_vm* aniVM, ani_object aniObject) +{ + TAG_LOGD(AAFwkTag::UI_EXT, "call"); + if (aniVM == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null aniVM"); + return; + } + aniVM_ = aniVM; + ani_env *aniEnv = nullptr; + ani_status status = ANI_ERROR; + if ((status = aniVM_->GetEnv(ANI_VERSION_1, &aniEnv)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GetEnv failed, status : %{public}d", status); + return; + } + + ani_ref startAbilityCallbackRef = nullptr; + if ((status = aniEnv->GlobalReference_Create(aniObject, &startAbilityCallbackRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "GlobalReference_Create failed, status : %{public}d", status); + return; + } + startAbilityAniCallback_ = startAbilityCallbackRef; +} + +ani_env* StsUIExtensionCallback::GetAniEnv() +{ + TAG_LOGD(AAFwkTag::UI_EXT, "call"); + if (aniVM_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null aniVM_"); + return nullptr; + } + ani_env *aniEnv = nullptr; + ani_status status = ANI_ERROR; + if ((status = aniVM_->GetEnv(ANI_VERSION_1, &aniEnv)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UI_EXT, "get env failed, status : %{public}d", status); + return nullptr; + } + return aniEnv; +} + +void StsUIExtensionCallback::CloseModalUIExtension() +{ + if (aniUIContent_ == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null aniUIContent_"); + return; + } + aniUIContent_->CloseModalUIExtension(aniSessionId_); +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/ability/native/ui_ability.cpp b/frameworks/native/ability/native/ui_ability.cpp index df7129067910f5c8a616d529d6f9a89d25cfec19..492b0632eef49ed6c1bd83c27404d9f0edf90b61 100644 --- a/frameworks/native/ability/native/ui_ability.cpp +++ b/frameworks/native/ability/native/ui_ability.cpp @@ -24,6 +24,7 @@ #include "hilog_tag_wrapper.h" #include "hitrace_meter.h" #include "js_ui_ability.h" +#include "sts_ui_ability.h" #include "ability_context_impl.h" #include "application_configuration_manager.h" #ifdef CJ_FRONTEND @@ -40,6 +41,19 @@ namespace OHOS { namespace AbilityRuntime { namespace { +const std::unique_ptr& GetRuntime(const std::shared_ptr application, + Runtime::Language language) +{ + static std::unique_ptr runtimeNullptr = nullptr; + auto &runtimes = application->GetRuntime(); + for (auto& runtime : runtimes) { + if (runtime->GetLanguage() == language) { + return runtime; + } + } + return runtimeNullptr; +} + constexpr char DMS_SESSION_ID[] = "sessionId"; constexpr char DMS_ORIGIN_DEVICE_ID[] = "deviceId"; constexpr int32_t DEFAULT_DMS_SESSION_ID = 0; @@ -70,6 +84,8 @@ UIAbility *UIAbility::Create(const std::unique_ptr &runtime) case Runtime::Language::CJ: return CJUIAbility::Create(runtime); #endif + case Runtime::Language::STS: + return StsUIAbility::Create(runtime); default: return new (std::nothrow) UIAbility(); } @@ -652,6 +668,81 @@ int32_t UIAbility::OnShare(AAFwk::WantParams &wantParams) return ERR_OK; } +void UIAbility::BindHybridContext(const std::shared_ptr application, + const std::shared_ptr record) +{ + if (application == nullptr || record == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null application or record"); + return; + } + auto appInfo = application->GetApplicationInfo(); + if (appInfo == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null appInfo"); + return; + } + if (appInfo->codeLanguage != AppExecFwk::Constants::CODE_LANGUAGE_HYBRID) { + TAG_LOGD(AAFwkTag::UIABILITY, "not hybrid app, no need to create hybrid context"); + return; + } + + auto abilityInfo = record->GetAbilityInfo(); + if (abilityInfo == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityInfo"); + return; + } + if (abilityInfo->codeLanguage == APPLICAITON_CODE_LANGUAGE_ARKTS_1_0) { + BindStsContext(application, record); + } else if (abilityInfo->codeLanguage == APPLICAITON_CODE_LANGUAGE_ARKTS_1_2) { + BindJsContext(application, record); + } else { + TAG_LOGE(AAFwkTag::UIABILITY, "unknown codeLanguage"); + } +} + +void UIAbility::BindStsContext(const std::shared_ptr application, + const std::shared_ptr record) +{ + if (abilityContext_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext_"); + return; + } + auto& bindingObject = abilityContext_->GetBindingObject(); + if (bindingObject == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null bindingObject"); + return; + } + + auto* ptr = bindingObject->Get(); + if (ptr != nullptr) { + TAG_LOGD(AAFwkTag::UIABILITY, "sts context already binded"); + return; + } + StsUIAbility::CreateAndBindContext( + application, record, abilityContext_, GetRuntime(application, Runtime::Language::STS)); +} + +void UIAbility::BindJsContext(const std::shared_ptr application, + const std::shared_ptr record) +{ + if (abilityContext_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext_"); + return; + } + auto& bindingObject = abilityContext_->GetBindingObject(); + if (bindingObject == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null bindingObject"); + return; + } + + auto* ptr = bindingObject->Get(); + if (ptr != nullptr) { + TAG_LOGD(AAFwkTag::UIABILITY, "sts context already binded"); + return; + } + JsUIAbility::CreateAndBindContext( + application, record, abilityContext_, GetRuntime(application, Runtime::Language::JS)); +} + bool UIAbility::CheckIsSilentForeground() const { return isSilentForeground_; diff --git a/frameworks/native/ability/native/ui_ability_impl.cpp b/frameworks/native/ability/native/ui_ability_impl.cpp index a5df5cb0eb78cd7089265084904d2032e7e3620e..3192e88c04ecadb7b568da2c593e8a308fb4026c 100644 --- a/frameworks/native/ability/native/ui_ability_impl.cpp +++ b/frameworks/native/ability/native/ui_ability_impl.cpp @@ -49,6 +49,7 @@ void UIAbilityImpl::Init(const std::shared_ptr &app new (std::nothrow) WindowLifeCycleImpl(token_, shared_from_this()))); #endif ability_->Init(record, application, handler, token); + ability_->BindHybridContext(application, record); lifecycleState_ = AAFwk::ABILITY_STATE_INITIAL; TAG_LOGD(AAFwkTag::UIABILITY, "end"); } diff --git a/frameworks/native/ability/native/ui_ability_thread.cpp b/frameworks/native/ability/native/ui_ability_thread.cpp index d4c9193381ccd236037da7c5fc1e5d6b3e02c762..420ea25f11c728ae403051c6247b271c7a99388f 100644 --- a/frameworks/native/ability/native/ui_ability_thread.cpp +++ b/frameworks/native/ability/native/ui_ability_thread.cpp @@ -131,7 +131,8 @@ void UIAbilityThread::Attach(const std::shared_ptr } // 2.new ability - auto ability = AppExecFwk::AbilityLoader::GetInstance().GetUIAbilityByName(abilityName); + auto ability = AppExecFwk::AbilityLoader::GetInstance().GetUIAbilityByName( + abilityName, abilityRecord->GetAbilityInfo()->codeLanguage); if (ability == nullptr) { TAG_LOGE(AAFwkTag::UIABILITY, "null ability"); return; @@ -203,7 +204,8 @@ void UIAbilityThread::Attach(const std::shared_ptr } // 2.new ability - auto ability = AppExecFwk::AbilityLoader::GetInstance().GetUIAbilityByName(abilityName); + auto ability = AppExecFwk::AbilityLoader::GetInstance().GetUIAbilityByName( + abilityName, abilityRecord->GetAbilityInfo()->codeLanguage); if (ability == nullptr) { TAG_LOGE(AAFwkTag::UIABILITY, "null ability"); return; 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 e7ab4bc75a16da8a1d92d4d8dd073c4c30e8d81c..6fb0af36a2896d1a2a6c48a5b4dcb4e78e90f4df 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 @@ -496,39 +496,6 @@ void JsUIExtension::OnDisconnect(const AAFwk::Want &want) TAG_LOGD(AAFwkTag::UI_EXT, "JsUIExtension OnDisconnect end"); } -void JsUIExtension::OnCommandWindow(const AAFwk::Want &want, const sptr &sessionInfo, - AAFwk::WindowCommand winCmd) -{ - HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - if (sessionInfo == nullptr) { - TAG_LOGE(AAFwkTag::UI_EXT, "null sessionInfo"); - return; - } - TAG_LOGD(AAFwkTag::UI_EXT, "begin. persistentId: %{private}d, winCmd: %{public}d", - sessionInfo->persistentId, winCmd); - Extension::OnCommandWindow(want, sessionInfo, winCmd); - if (InsightIntentExecuteParam::IsInsightIntentExecute(want) && winCmd == AAFwk::WIN_CMD_FOREGROUND) { - if (ForegroundWindowWithInsightIntent(want, sessionInfo, false)) { - return; - } - } - switch (winCmd) { - case AAFwk::WIN_CMD_FOREGROUND: - ForegroundWindow(want, sessionInfo); - break; - case AAFwk::WIN_CMD_BACKGROUND: - BackgroundWindow(sessionInfo); - break; - case AAFwk::WIN_CMD_DESTROY: - DestroyWindow(sessionInfo); - break; - default: - TAG_LOGD(AAFwkTag::UI_EXT, "unsupported cmd"); - break; - } - OnCommandWindowDone(sessionInfo, winCmd); -} - bool JsUIExtension::ForegroundWindowInitInsightIntentExecutorInfo(const AAFwk::Want &want, const sptr &sessionInfo, InsightIntentExecutorInfo &executorInfo) { @@ -640,82 +607,6 @@ void JsUIExtension::PostInsightIntentExecuted(const sptr &se } } -void JsUIExtension::OnCommandWindowDone(const sptr &sessionInfo, AAFwk::WindowCommand winCmd) -{ - HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - TAG_LOGD(AAFwkTag::UI_EXT, "called"); - auto context = GetContext(); - if (context == nullptr) { - TAG_LOGE(AAFwkTag::UI_EXT, "null context"); - return; - } - AAFwk::AbilityCommand abilityCmd; - std::lock_guard lock(uiWindowMutex_); - if (uiWindowMap_.empty()) { - abilityCmd = AAFwk::ABILITY_CMD_DESTROY; - } else if (foregroundWindows_.empty()) { - abilityCmd = AAFwk::ABILITY_CMD_BACKGROUND; - } else { - abilityCmd = AAFwk::ABILITY_CMD_FOREGROUND; - } - AAFwk::AbilityManagerClient::GetInstance()->ScheduleCommandAbilityWindowDone( - context->GetToken(), sessionInfo, winCmd, abilityCmd); - TAG_LOGD(AAFwkTag::UI_EXT, "end"); -} - -void JsUIExtension::OnInsightIntentExecuteDone(const sptr &sessionInfo, - const AppExecFwk::InsightIntentExecuteResult &result) -{ - HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - if (sessionInfo == nullptr) { - TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo"); - return; - } - std::lock_guard lock(uiWindowMutex_); - TAG_LOGD(AAFwkTag::UI_EXT, "UIExtension component id: %{public}" PRId64, sessionInfo->uiExtensionComponentId); - auto componentId = sessionInfo->uiExtensionComponentId; - auto res = uiWindowMap_.find(componentId); - if (res != uiWindowMap_.end() && res->second != nullptr) { - WantParams params; - params.SetParam(INSIGHT_INTENT_EXECUTE_RESULT_CODE, Integer::Box(result.innerErr)); - WantParams resultParams; - resultParams.SetParam("code", Integer::Box(result.code)); - if (result.result != nullptr) { - sptr pWantParams = WantParamWrapper::Box(*result.result); - if (pWantParams != nullptr) { - resultParams.SetParam("result", pWantParams); - } - } - - auto size = result.uris.size(); - sptr uriArray = new (std::nothrow) Array(size, g_IID_IString); - if (uriArray == nullptr) { - TAG_LOGE(AAFwkTag::UI_EXT, "new uriArray failed"); - return; - } - for (std::size_t i = 0; i < size; i++) { - uriArray->Set(i, String::Box(result.uris[i])); - } - resultParams.SetParam("uris", uriArray); - resultParams.SetParam("flags", Integer::Box(result.flags)); - sptr pWantParams = WantParamWrapper::Box(resultParams); - if (pWantParams != nullptr) { - params.SetParam(INSIGHT_INTENT_EXECUTE_RESULT, pWantParams); - } - - Rosen::WMError ret = res->second->TransferExtensionData(params); - if (ret == Rosen::WMError::WM_OK) { - TAG_LOGD(AAFwkTag::UI_EXT, "TransferExtensionData success"); - } else { - TAG_LOGE(AAFwkTag::UI_EXT, "TransferExtensionData failed, ret=%{public}d", ret); - } - - res->second->Show(); - foregroundWindows_.emplace(componentId); - } - TAG_LOGD(AAFwkTag::UI_EXT, "end"); -} - void JsUIExtension::OnCommand(const AAFwk::Want &want, bool restart, int startId) { Extension::OnCommand(want, restart, startId); 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 a5036af4b4510665c28aa55e5c54088988996d7e..ec8b7c6492fd7b25ea2b539dbf061c6ab921c955 100755 --- a/frameworks/native/ability/native/ui_extension_ability/ui_extension.cpp +++ b/frameworks/native/ability/native/ui_extension_ability/ui_extension.cpp @@ -19,6 +19,13 @@ #include "js_ui_extension.h" #include "runtime.h" #include "ui_extension_context.h" +#include "sts_ui_extension.h" +#include "hitrace_meter.h" +#include "ability_manager_client.h" +#include "int_wrapper.h" +#include "want_params_wrapper.h" +#include "string_wrapper.h" +#include "array_wrapper.h" namespace OHOS { namespace AbilityRuntime { @@ -32,7 +39,8 @@ UIExtension* UIExtension::Create(const std::unique_ptr& runtime) switch (runtime->GetLanguage()) { case Runtime::Language::JS: return JsUIExtension::Create(runtime); - + case Runtime::Language::STS: + return StsUIExtension::Create(runtime); default: return new UIExtension(); } @@ -60,5 +68,114 @@ std::shared_ptr UIExtension::CreateAndInitContext( } return context; } + +void UIExtension::OnCommandWindow(const AAFwk::Want &want, const sptr &sessionInfo, + AAFwk::WindowCommand winCmd) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (sessionInfo == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null sessionInfo"); + return; + } + TAG_LOGD(AAFwkTag::UI_EXT, "begin. persistentId: %{private}d, winCmd: %{public}d", + sessionInfo->persistentId, winCmd); + Extension::OnCommandWindow(want, sessionInfo, winCmd); + if (InsightIntentExecuteParam::IsInsightIntentExecute(want) && winCmd == AAFwk::WIN_CMD_FOREGROUND) { + if (ForegroundWindowWithInsightIntent(want, sessionInfo, false)) { + return; + } + } + switch (winCmd) { + case AAFwk::WIN_CMD_FOREGROUND: + ForegroundWindow(want, sessionInfo); + break; + case AAFwk::WIN_CMD_BACKGROUND: + BackgroundWindow(sessionInfo); + break; + case AAFwk::WIN_CMD_DESTROY: + DestroyWindow(sessionInfo); + break; + default: + TAG_LOGD(AAFwkTag::UI_EXT, "unsupported cmd"); + break; + } + OnCommandWindowDone(sessionInfo, winCmd); +} + +void UIExtension::OnCommandWindowDone(const sptr &sessionInfo, AAFwk::WindowCommand winCmd) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UI_EXT, "OnCommandWindowDone called"); + auto context = GetContext(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "null context"); + return; + } + AAFwk::AbilityCommand abilityCmd; + std::lock_guard lock(uiWindowMutex_); + if (uiWindowMap_.empty()) { + abilityCmd = AAFwk::ABILITY_CMD_DESTROY; + } else if (foregroundWindows_.empty()) { + abilityCmd = AAFwk::ABILITY_CMD_BACKGROUND; + } else { + abilityCmd = AAFwk::ABILITY_CMD_FOREGROUND; + } + AAFwk::AbilityManagerClient::GetInstance()->ScheduleCommandAbilityWindowDone( + context->GetToken(), sessionInfo, winCmd, abilityCmd); + TAG_LOGD(AAFwkTag::UI_EXT, "end"); +} + +void UIExtension::OnInsightIntentExecuteDone(const sptr &sessionInfo, + const AppExecFwk::InsightIntentExecuteResult &result) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (sessionInfo == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo"); + return; + } + std::lock_guard lock(uiWindowMutex_); + TAG_LOGD(AAFwkTag::UI_EXT, "UIExtension component id: %{public}" PRId64, sessionInfo->uiExtensionComponentId); + auto componentId = sessionInfo->uiExtensionComponentId; + auto res = uiWindowMap_.find(componentId); + if (res != uiWindowMap_.end() && res->second != nullptr) { + WantParams params; + params.SetParam(INSIGHT_INTENT_EXECUTE_RESULT_CODE, Integer::Box(result.innerErr)); + WantParams resultParams; + resultParams.SetParam("code", Integer::Box(result.code)); + if (result.result != nullptr) { + sptr pWantParams = WantParamWrapper::Box(*result.result); + if (pWantParams != nullptr) { + resultParams.SetParam("result", pWantParams); + } + } + + auto size = result.uris.size(); + sptr uriArray = new (std::nothrow) Array(size, g_IID_IString); + if (uriArray == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT, "new uriArray failed"); + return; + } + for (std::size_t i = 0; i < size; i++) { + uriArray->Set(i, String::Box(result.uris[i])); + } + resultParams.SetParam("uris", uriArray); + resultParams.SetParam("flags", Integer::Box(result.flags)); + sptr pWantParams = WantParamWrapper::Box(resultParams); + if (pWantParams != nullptr) { + params.SetParam(INSIGHT_INTENT_EXECUTE_RESULT, pWantParams); + } + + Rosen::WMError ret = res->second->TransferExtensionData(params); + if (ret == Rosen::WMError::WM_OK) { + TAG_LOGD(AAFwkTag::UI_EXT, "TransferExtensionData success"); + } else { + TAG_LOGE(AAFwkTag::UI_EXT, "TransferExtensionData failed, ret=%{public}d", ret); + } + + res->second->Show(); + foregroundWindows_.emplace(componentId); + } + TAG_LOGD(AAFwkTag::UI_EXT, "end"); +} } } diff --git a/frameworks/native/ability/native/ui_extension_base/cj_ui_extension_content_session.cpp b/frameworks/native/ability/native/ui_extension_base/cj_ui_extension_content_session.cpp index 84bf00786200aef55a09f53a16509e9eb306c12a..67a9c2556d9e92c04cbd96d726852ed681241e4a 100644 --- a/frameworks/native/ability/native/ui_extension_base/cj_ui_extension_content_session.cpp +++ b/frameworks/native/ability/native/ui_extension_base/cj_ui_extension_content_session.cpp @@ -62,7 +62,7 @@ int32_t CJUIExtensionContentSession::LoadContent(const std::string& path) uiWindow_->TriggerBindModalUIExtension(); isFirstTriggerBindModal_ = false; } - Rosen::WMError ret = uiWindow_->NapiSetUIContent(path, nullptr, nullptr, + Rosen::WMError ret = uiWindow_->NapiSetUIContent(path, (napi_env)nullptr, nullptr, Rosen::BackupAndRestoreType::NONE, sessionInfo_->parentToken); if (ret != Rosen::WMError::WM_OK) { TAG_LOGE(AAFwkTag::UI_EXT, "NapiSetUIContent failed, ret=%{public}d", ret); diff --git a/frameworks/native/appkit/BUILD.gn b/frameworks/native/appkit/BUILD.gn index d4211c643290ffa415423970ff0247413e5f6501..36e849f53346f835a121987814696a4c3cf4dd45 100644 --- a/frameworks/native/appkit/BUILD.gn +++ b/frameworks/native/appkit/BUILD.gn @@ -60,6 +60,7 @@ config("appkit_public_config") { "${ability_runtime_path}/interfaces/kits/native/appkit/app", "${ability_runtime_path}/interfaces/kits/native/appkit/dfr", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_bundle_manager_helper", + "${ability_runtime_path}/sts_environment/interfaces/inner_api", ] if (ability_runtime_graphics) { @@ -75,7 +76,9 @@ config("appkit_public_config") { ohos_shared_library("appkit_native") { include_dirs = [ "native", + "${ability_runtime_path}/frameworks/ets/ani/context/context_util/include", "${ability_runtime_path}/interfaces/inner_api/error_utils/include", + "${ability_runtime_path}/interfaces/inner_api", "${ability_runtime_path}/interfaces/kits/native/appkit", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_bundle_manager_helper", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", @@ -83,8 +86,10 @@ ohos_shared_library("appkit_native") { "${ability_runtime_path}/interfaces/kits/native/appkit/dfr", "${ability_runtime_path}/interfaces/kits/native/appkit/app/task", "${ability_runtime_path}/interfaces/kits/native/appkit/app_startup", + "${ability_runtime_path}/sts_environment/interfaces/inner_api", "${ability_runtime_innerkits_path}/deps_wrapper/include", "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", "${ability_runtime_path}/interfaces/kits/native/ability/native", "${ability_runtime_path}/interfaces/kits/native/ability/native/recovery", "${ability_runtime_path}/utils/global/time/include", @@ -92,6 +97,9 @@ ohos_shared_library("appkit_native") { "${ability_runtime_services_path}/abilitymgr/include", "${ability_runtime_napi_path}/inner/napi_common", "${ability_runtime_utils_path}/global/constant", + "${ability_runtime_napi_path}/inner/napi_common/ani_common", + "${ability_runtime_path}/frameworks/ets/ani/app_manager/include/", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", ] configs = [ @@ -105,6 +113,8 @@ ohos_shared_library("appkit_native") { "${ability_runtime_native_path}/appkit/ability_runtime/app/ability_stage.cpp", "${ability_runtime_native_path}/appkit/ability_runtime/app/js_ability_stage.cpp", "${ability_runtime_native_path}/appkit/ability_runtime/app/js_ability_stage_context.cpp", + "${ability_runtime_native_path}/appkit/ability_runtime/app/sts_ability_stage.cpp", + "${ability_runtime_native_path}/appkit/ability_runtime/app/sts_ability_stage_context.cpp", "${ability_runtime_native_path}/appkit/app/ability_record_mgr.cpp", "${ability_runtime_native_path}/appkit/app/app_loader.cpp", "${ability_runtime_native_path}/appkit/app/application_cleaner.cpp", @@ -164,6 +174,10 @@ ohos_shared_library("appkit_native") { "${ability_runtime_native_path}/appkit:app_context", "${ability_runtime_native_path}/appkit:app_context_utils", "${ability_runtime_native_path}/appkit:appkit_manager_helper", + "${ability_runtime_native_path}/appkit:application_context_manager", + "${ability_runtime_path}/frameworks/ets/ani/ability_manager:ability_ability_manager_ani_kit", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_path}/frameworks/ets/ani/app_manager:ability_app_manager_ani_kit", "${ability_runtime_path}/js_environment/frameworks/js_environment:js_environment", "${ability_runtime_path}/utils/global/freeze:freeze_util", "${ability_runtime_services_path}/common:app_util", @@ -178,6 +192,7 @@ ohos_shared_library("appkit_native") { "access_token:libaccesstoken_sdk", "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", + "bundle_framework:bms_ani_common", "c_utils:utils", "common_event_service:cesfwk_innerkits", "ets_runtime:libark_jsruntime", @@ -205,6 +220,8 @@ ohos_shared_library("appkit_native") { "napi:ace_napi", "preferences:native_preferences", "resource_management:global_resmgr", + "resource_management:resourceManager_ani", + "runtime_core:ani", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] @@ -324,6 +341,7 @@ ohos_shared_library("app_context") { "${ability_runtime_native_path}/appkit/ability_runtime/context/application_state_change_callback.cpp", "${ability_runtime_native_path}/appkit/ability_runtime/context/context_impl.cpp", "${ability_runtime_native_path}/appkit/ability_runtime/context/environment_callback.cpp", + "${ability_runtime_native_path}/appkit/ability_runtime/context/ets_application_state_change_callback.cpp", "${ability_runtime_native_path}/appkit/app/overlay_event_subscriber.cpp", "${ability_runtime_native_path}/appkit/app/sys_mgr_client.cpp", ] @@ -352,6 +370,7 @@ ohos_shared_library("app_context") { "json:nlohmann_json_static", "napi:ace_napi", "resource_management:global_resmgr", + "runtime_core:ani", "samgr:samgr_proxy", ] public_external_deps = [ @@ -382,6 +401,8 @@ ohos_shared_library("app_context_utils") { "${ability_runtime_napi_path}/ability_auto_startup_callback", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", + "${ability_runtime_path}/frameworks/ets/ani/app_manager/include", ] configs = [ ":appkit_config" ] @@ -389,9 +410,12 @@ ohos_shared_library("app_context_utils") { public_configs = [ ":appkit_public_config" ] sources = [ + "ability_runtime/context/ets_enviroment_callback.cpp", "ability_runtime/context/js_application_context_utils.cpp", "ability_runtime/context/js_context_utils.cpp", "ability_runtime/context/js_resource_manager_utils.cpp", + "ability_runtime/context/sts_context_utils.cpp", + "ability_runtime/context/ets_application_context_utils.cpp", ] cflags = [] if (target_cpu == "arm") { @@ -408,6 +432,8 @@ ohos_shared_library("app_context_utils") { "${ability_runtime_native_path}/ability/native:auto_startup_callback", "${ability_runtime_native_path}/appkit:app_context", "${ability_runtime_native_path}/appkit:application_context_manager", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_path}/frameworks/ets/ani/app_manager:ability_app_manager_ani_kit", ] external_deps = [ @@ -416,6 +442,7 @@ ohos_shared_library("app_context_utils") { "access_token:libtokenid_sdk", "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", + "bundle_framework:bms_ani_common", "c_utils:utils", "hilog:libhilog", "hitrace:hitrace_meter", @@ -425,6 +452,8 @@ ohos_shared_library("app_context_utils") { "napi:ace_napi", "resource_management:global_resmgr", "resource_management:resmgr_napi_core", + "resource_management:resourceManager_ani", + "runtime_core:ani", ] public_external_deps = [ "ability_base:configuration" ] if (ability_runtime_graphics) { @@ -465,6 +494,7 @@ ohos_shared_library("appkit_delegator") { "${ability_runtime_native_path}/appkit/ability_delegator/iability_monitor.cpp", "${ability_runtime_native_path}/appkit/ability_delegator/iability_stage_monitor.cpp", "${ability_runtime_native_path}/appkit/ability_delegator/runner_runtime/js_test_runner.cpp", + "${ability_runtime_native_path}/appkit/ability_delegator/runner_runtime/sts_test_runner.cpp", "${ability_runtime_native_path}/appkit/ability_delegator/shell_cmd_result.cpp", "${ability_runtime_native_path}/appkit/ability_delegator/test_runner.cpp", "${ability_runtime_path}/tools/aa/src/shell_command_result.cpp", @@ -496,6 +526,7 @@ ohos_shared_library("appkit_delegator") { "ipc:ipc_core", "json:nlohmann_json_static", "napi:ace_napi", + "runtime_core:ani", "samgr:samgr_proxy", ] @@ -580,6 +611,11 @@ ohos_shared_library("appkit_manager_helper") { ohos_shared_library("application_context_manager") { branch_protector_ret = "pac_ret" + include_dirs = [ + "${ability_runtime_path}/interfaces/inner_api/runtime/include", + "${ability_runtime_path}/interfaces/kits/native/ability/native", + ] + sources = [ "${ability_runtime_native_path}/appkit/ability_runtime/context/application_context_manager.cpp" ] cflags = [] diff --git a/frameworks/native/appkit/ability_delegator/ability_delegator.cpp b/frameworks/native/appkit/ability_delegator/ability_delegator.cpp index 1449f61557fd7bd7e29303c5e7c9defd09967ce3..d7d3c4e6497d9d83fd759134c5af9d036d580ba8 100644 --- a/frameworks/native/appkit/ability_delegator/ability_delegator.cpp +++ b/frameworks/native/appkit/ability_delegator/ability_delegator.cpp @@ -115,7 +115,7 @@ size_t AbilityDelegator::GetStageMonitorsNum() } -std::shared_ptr AbilityDelegator::WaitAbilityMonitor( +std::shared_ptr AbilityDelegator::WaitAbilityMonitor( const std::shared_ptr &monitor) { if (!monitor) { @@ -134,7 +134,7 @@ std::shared_ptr AbilityDelegator::WaitAbilityMonitor( return obtainedAbility; } -std::shared_ptr AbilityDelegator::WaitAbilityStageMonitor( +std::shared_ptr AbilityDelegator::WaitAbilityStageMonitor( const std::shared_ptr &monitor) { if (!monitor) { @@ -151,7 +151,7 @@ std::shared_ptr AbilityDelegator::WaitAbilityStag return stage; } -std::shared_ptr AbilityDelegator::WaitAbilityMonitor( +std::shared_ptr AbilityDelegator::WaitAbilityMonitor( const std::shared_ptr &monitor, const int64_t timeoutMs) { if (!monitor) { @@ -170,7 +170,7 @@ std::shared_ptr AbilityDelegator::WaitAbilityMonitor( return obtainedAbility; } -std::shared_ptr AbilityDelegator::WaitAbilityStageMonitor( +std::shared_ptr AbilityDelegator::WaitAbilityStageMonitor( const std::shared_ptr &monitor, const int64_t timeoutMs) { if (!monitor) { @@ -208,7 +208,7 @@ AbilityDelegator::AbilityState AbilityDelegator::GetAbilityState(const sptrlifecycleState_); } -std::shared_ptr AbilityDelegator::GetCurrentTopAbility() +std::shared_ptr AbilityDelegator::GetCurrentTopAbility() { AppExecFwk::ElementName elementName = AAFwk::AbilityManagerClient::GetInstance()->GetTopAbility(); std::string bundleName = elementName.GetBundleName(); @@ -367,7 +367,7 @@ void AbilityDelegator::Print(const std::string &msg) testObserver->TestStatus(realMsg, 0); } -void AbilityDelegator::PostPerformStart(const std::shared_ptr &ability) +void AbilityDelegator::PostPerformStart(const std::shared_ptr &ability) { TAG_LOGI(AAFwkTag::DELEGATOR, "called"); @@ -388,14 +388,13 @@ void AbilityDelegator::PostPerformStart(const std::shared_ptrMatch(ability, true)) { - monitor->OnAbilityStart(ability->object_); + monitor->OnAbilityStart(ability); } } } -void AbilityDelegator::PostPerformStageStart(const std::shared_ptr &abilityStage) +void AbilityDelegator::PostPerformStageStart(const std::shared_ptr &abilityStage) { TAG_LOGI(AAFwkTag::DELEGATOR, "called"); if (!abilityStage) { @@ -417,7 +416,7 @@ void AbilityDelegator::PostPerformStageStart(const std::shared_ptr &ability) +void AbilityDelegator::PostPerformScenceCreated(const std::shared_ptr &ability) { TAG_LOGI(AAFwkTag::DELEGATOR, "called"); @@ -438,14 +437,13 @@ void AbilityDelegator::PostPerformScenceCreated(const std::shared_ptrMatch(ability)) { - monitor->OnWindowStageCreate(ability->object_); + if (monitor->Match(ability, true)) { + monitor->OnWindowStageCreate(ability); } } } -void AbilityDelegator::PostPerformScenceRestored(const std::shared_ptr &ability) +void AbilityDelegator::PostPerformScenceRestored(const std::shared_ptr &ability) { TAG_LOGI(AAFwkTag::DELEGATOR, "called"); @@ -466,14 +464,13 @@ void AbilityDelegator::PostPerformScenceRestored(const std::shared_ptrMatch(ability)) { - monitor->OnWindowStageRestore(ability->object_); + if (monitor->Match(ability, true)) { + monitor->OnWindowStageRestore(ability); } } } -void AbilityDelegator::PostPerformScenceDestroyed(const std::shared_ptr &ability) +void AbilityDelegator::PostPerformScenceDestroyed(const std::shared_ptr &ability) { TAG_LOGI(AAFwkTag::DELEGATOR, "called"); @@ -494,14 +491,13 @@ void AbilityDelegator::PostPerformScenceDestroyed(const std::shared_ptrMatch(ability)) { - monitor->OnWindowStageDestroy(ability->object_); + if (monitor->Match(ability, true)) { + monitor->OnWindowStageDestroy(ability); } } } -void AbilityDelegator::PostPerformForeground(const std::shared_ptr &ability) +void AbilityDelegator::PostPerformForeground(const std::shared_ptr &ability) { TAG_LOGI(AAFwkTag::DELEGATOR, "called"); @@ -522,14 +518,13 @@ void AbilityDelegator::PostPerformForeground(const std::shared_ptrMatch(ability)) { - monitor->OnAbilityForeground(ability->object_); + if (monitor->Match(ability, true)) { + monitor->OnAbilityForeground(ability); } } } -void AbilityDelegator::PostPerformBackground(const std::shared_ptr &ability) +void AbilityDelegator::PostPerformBackground(const std::shared_ptr &ability) { TAG_LOGI(AAFwkTag::DELEGATOR, "called"); @@ -550,14 +545,13 @@ void AbilityDelegator::PostPerformBackground(const std::shared_ptrMatch(ability)) { - monitor->OnAbilityBackground(ability->object_); + if (monitor->Match(ability, true)) { + monitor->OnAbilityBackground(ability); } } } -void AbilityDelegator::PostPerformStop(const std::shared_ptr &ability) +void AbilityDelegator::PostPerformStop(const std::shared_ptr &ability) { TAG_LOGI(AAFwkTag::DELEGATOR, "Enter"); @@ -578,9 +572,8 @@ void AbilityDelegator::PostPerformStop(const std::shared_ptrMatch(ability)) { - monitor->OnAbilityStop(ability->object_); + if (monitor->Match(ability, true)) { + monitor->OnAbilityStop(ability); } } @@ -613,7 +606,7 @@ AbilityDelegator::AbilityState AbilityDelegator::ConvertAbilityState( return abilityState; } -void AbilityDelegator::ProcessAbilityProperties(const std::shared_ptr &ability) +void AbilityDelegator::ProcessAbilityProperties(const std::shared_ptr &ability) { TAG_LOGI(AAFwkTag::DELEGATOR, "Enter"); @@ -636,7 +629,7 @@ void AbilityDelegator::ProcessAbilityProperties(const std::shared_ptr &ability) +void AbilityDelegator::RemoveAbilityProperty(const std::shared_ptr &ability) { TAG_LOGD(AAFwkTag::DELEGATOR, "called"); @@ -654,7 +647,7 @@ void AbilityDelegator::RemoveAbilityProperty(const std::shared_ptr AbilityDelegator::FindPropertyByToken(const sptr &token) +std::shared_ptr AbilityDelegator::FindPropertyByToken(const sptr &token) { TAG_LOGI(AAFwkTag::DELEGATOR, "Enter"); @@ -678,7 +671,7 @@ std::shared_ptr AbilityDelegator::FindPropertyByToken return {}; } -std::shared_ptr AbilityDelegator::FindPropertyByName(const std::string &name) +std::shared_ptr AbilityDelegator::FindPropertyByName(const std::string &name) { TAG_LOGI(AAFwkTag::DELEGATOR, "find property by %{public}s", name.c_str()); @@ -741,7 +734,7 @@ void AbilityDelegator::RegisterClearFunc(ClearFunc func) clearFunc_ = func; } -inline void AbilityDelegator::CallClearFunc(const std::shared_ptr &ability) +inline void AbilityDelegator::CallClearFunc(const std::shared_ptr &ability) { TAG_LOGI(AAFwkTag::DELEGATOR, "Enter"); if (clearFunc_) { diff --git a/frameworks/native/appkit/ability_delegator/ability_delegator_registry.cpp b/frameworks/native/appkit/ability_delegator/ability_delegator_registry.cpp index 7187c88382eac76eabb85137bf793722dba009b7..c11700597ffaf7b77acd34fd29099de85158baaa 100644 --- a/frameworks/native/appkit/ability_delegator/ability_delegator_registry.cpp +++ b/frameworks/native/appkit/ability_delegator/ability_delegator_registry.cpp @@ -17,20 +17,30 @@ namespace OHOS { namespace AppExecFwk { -std::shared_ptr AbilityDelegatorRegistry::abilityDelegator_ {}; +std::map> AbilityDelegatorRegistry::abilityDelegator_ {}; std::shared_ptr AbilityDelegatorRegistry::abilityDelegatorArgs_ {}; -std::shared_ptr AbilityDelegatorRegistry::GetAbilityDelegator() +std::shared_ptr AbilityDelegatorRegistry::GetAbilityDelegator( + const AbilityRuntime::Runtime::Language &language) { - auto p = reinterpret_cast(abilityDelegator_.get()); - return std::shared_ptr(abilityDelegator_, p); + auto it = abilityDelegator_.find(language); + if (it != abilityDelegator_.end()) { + auto p = reinterpret_cast(it->second.get()); + return std::shared_ptr(it->second, p); + } + return nullptr; } #ifdef CJ_FRONTEND std::shared_ptr AbilityDelegatorRegistry::GetCJAbilityDelegator() { - auto p = reinterpret_cast(abilityDelegator_.get()); - return std::shared_ptr(abilityDelegator_, p); + auto it = abilityDelegator_.find(AbilityRuntime::Runtime::Language::CJ); + if (it != abilityDelegator_.end()) { + auto p = reinterpret_cast(it->second.get()); + return std::shared_ptr(it->second, p); + } + return nullptr; } #endif @@ -40,10 +50,11 @@ std::shared_ptr AbilityDelegatorRegistry::GetArguments() } void AbilityDelegatorRegistry::RegisterInstance( - const std::shared_ptr& delegator, const std::shared_ptr& args) + const std::shared_ptr &delegator, const std::shared_ptr &args, + const AbilityRuntime::Runtime::Language &language) { - abilityDelegator_ = delegator; abilityDelegatorArgs_ = args; + abilityDelegator_.emplace(language, delegator); } } // namespace AppExecFwk } // namespace OHOS diff --git a/frameworks/native/appkit/ability_delegator/iability_delegator.cpp b/frameworks/native/appkit/ability_delegator/iability_delegator.cpp index c04df963af5bcd6eb0640250231a4dbb809adeef..9418ab42175622deb57e3b2707272a56470ec370 100644 --- a/frameworks/native/appkit/ability_delegator/iability_delegator.cpp +++ b/frameworks/native/appkit/ability_delegator/iability_delegator.cpp @@ -31,6 +31,7 @@ std::shared_ptr IAbilityDelegator::Create(const std::unique_p switch (runtime->GetLanguage()) { case AbilityRuntime::Runtime::Language::JS: + case AbilityRuntime::Runtime::Language::STS: return AbilityDelegator::Create(context, std::move(runner), observer); #ifdef CJ_FRONTEND case AbilityRuntime::Runtime::Language::CJ: diff --git a/frameworks/native/appkit/ability_delegator/iability_monitor.cpp b/frameworks/native/appkit/ability_delegator/iability_monitor.cpp index 17bf4c740bdd7cbcab6b11e4b3d3c28f9b02b33c..fb959aac0498fa336653b2032ed43af6071cddda 100644 --- a/frameworks/native/appkit/ability_delegator/iability_monitor.cpp +++ b/frameworks/native/appkit/ability_delegator/iability_monitor.cpp @@ -27,7 +27,7 @@ IAbilityMonitor::IAbilityMonitor(const std::string &abilityName, const std::string &moduleName) : abilityName_(abilityName), moduleName_(moduleName) {} -bool IAbilityMonitor::Match(const std::shared_ptr &ability, bool isNotify) +bool IAbilityMonitor::Match(const std::shared_ptr &ability, bool isNotify) { if (!ability) { TAG_LOGW(AAFwkTag::DELEGATOR, "invalid ability property"); @@ -69,12 +69,12 @@ bool IAbilityMonitor::Match(const std::shared_ptr &ab return true; } -std::shared_ptr IAbilityMonitor::WaitForAbility() +std::shared_ptr IAbilityMonitor::WaitForAbility() { return WaitForAbility(MAX_TIME_OUT); } -std::shared_ptr IAbilityMonitor::WaitForAbility(const int64_t timeoutMs) +std::shared_ptr IAbilityMonitor::WaitForAbility(const int64_t timeoutMs) { auto realTime = timeoutMs; if (timeoutMs <= 0) { @@ -92,25 +92,26 @@ std::shared_ptr IAbilityMonitor::WaitForAbility(const return matchedAbility_; } -void IAbilityMonitor::OnAbilityStart(const std::weak_ptr &abilityObj) +void IAbilityMonitor::OnAbilityStart(const std::weak_ptr &abilityObj) {} -void IAbilityMonitor::OnAbilityForeground(const std::weak_ptr &abilityObj) +void IAbilityMonitor::OnAbilityForeground(const std::weak_ptr &abilityObj) {} -void IAbilityMonitor::OnAbilityBackground(const std::weak_ptr &abilityObj) +void IAbilityMonitor::OnAbilityBackground(const std::weak_ptr &abilityObj) {} -void IAbilityMonitor::OnAbilityStop(const std::weak_ptr &abilityObj) +void IAbilityMonitor::OnAbilityStop(const std::weak_ptr &abilityObj) {} -void IAbilityMonitor::OnWindowStageCreate(const std::weak_ptr &abilityObj) +void IAbilityMonitor::OnWindowStageCreate(const std::weak_ptr &abilityObj) {} -void IAbilityMonitor::OnWindowStageRestore(const std::weak_ptr &abilityObj) +void IAbilityMonitor::OnWindowStageRestore(const std::weak_ptr &abilityObj) {} -void IAbilityMonitor::OnWindowStageDestroy(const std::weak_ptr &abilityObj) +void IAbilityMonitor::OnWindowStageDestroy(const std::weak_ptr &abilityObj) {} + } // namespace AppExecFwk } // namespace OHOS diff --git a/frameworks/native/appkit/ability_delegator/iability_stage_monitor.cpp b/frameworks/native/appkit/ability_delegator/iability_stage_monitor.cpp index 0a62b35ba875d50978d939623dd3a51aeddb04ee..5d14d38a3acb49953c25f6a75035df0e8b8f241a 100644 --- a/frameworks/native/appkit/ability_delegator/iability_stage_monitor.cpp +++ b/frameworks/native/appkit/ability_delegator/iability_stage_monitor.cpp @@ -21,7 +21,7 @@ IAbilityStageMonitor::IAbilityStageMonitor(const std::string &moduleName, const : moduleName_(moduleName), srcEntrance_(srcEntrance) {} -bool IAbilityStageMonitor::Match(const std::shared_ptr &abilityStage, bool isNotify) +bool IAbilityStageMonitor::Match(const std::shared_ptr &abilityStage, bool isNotify) { if (!abilityStage) { TAG_LOGE(AAFwkTag::DELEGATOR, "null abilityStage"); @@ -46,12 +46,12 @@ bool IAbilityStageMonitor::Match(const std::shared_ptr IAbilityStageMonitor::WaitForAbilityStage() +std::shared_ptr IAbilityStageMonitor::WaitForAbilityStage() { return WaitForAbilityStage(MAX_TIME_OUT); } -std::shared_ptr IAbilityStageMonitor::WaitForAbilityStage(const int64_t timeoutMs) +std::shared_ptr IAbilityStageMonitor::WaitForAbilityStage(const int64_t timeoutMs) { auto realTime = timeoutMs; if (timeoutMs <= 0) { diff --git a/frameworks/native/appkit/ability_delegator/runner_runtime/cj_test_runner.cpp b/frameworks/native/appkit/ability_delegator/runner_runtime/cj_test_runner.cpp index 57c1fcfe4324b3ee106a5f3a72d074489df3c2f4..812d2e3b20106eab0832cc43a8a6175491b98966 100644 --- a/frameworks/native/appkit/ability_delegator/runner_runtime/cj_test_runner.cpp +++ b/frameworks/native/appkit/ability_delegator/runner_runtime/cj_test_runner.cpp @@ -100,7 +100,7 @@ void CJTestRunner::Run() void CJTestRunner::ReportFinished(const std::string &msg) { TAG_LOGI(AAFwkTag::DELEGATOR, "Enter"); - auto delegator = AbilityDelegatorRegistry::GetCJAbilityDelegator(); + auto delegator = AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::CJ); if (!delegator) { TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); return; @@ -112,7 +112,7 @@ void CJTestRunner::ReportFinished(const std::string &msg) void CJTestRunner::ReportStatus(const std::string &msg) { TAG_LOGD(AAFwkTag::DELEGATOR, "Enter"); - auto delegator = AbilityDelegatorRegistry::GetCJAbilityDelegator(); + auto delegator = AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::CJ); if (!delegator) { TAG_LOGE(AAFwkTag::DELEGATOR, "null delegator"); return; diff --git a/frameworks/native/appkit/ability_delegator/runner_runtime/sts_test_runner.cpp b/frameworks/native/appkit/ability_delegator/runner_runtime/sts_test_runner.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d69d0a3ee2a90b6f52084e92a75afc04e5cf5d88 --- /dev/null +++ b/frameworks/native/appkit/ability_delegator/runner_runtime/sts_test_runner.cpp @@ -0,0 +1,184 @@ +/* + * 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 + +#include "ability_delegator_registry.h" +#include "hilog_tag_wrapper.h" +#include "runner_runtime/sts_test_runner.h" + +namespace OHOS { +namespace RunnerRuntime { +namespace { +const std::string CAPITALTESTRUNNER = "/ets/TestRunner/"; +const std::string LOWERCASETESTRUNNER = "/ets/testrunner/"; +} // namespace + +std::unique_ptr STSTestRunner::Create(const std::unique_ptr &runtime, + const std::shared_ptr &args, const AppExecFwk::BundleInfo &bundleInfo) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "STSTestRunner Create"); + if (!runtime) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid runtime"); + return nullptr; + } + + if (!args) { + TAG_LOGE(AAFwkTag::DELEGATOR, "invalid args"); + return nullptr; + } + + auto pTestRunner = new (std::nothrow) STSTestRunner(static_cast(*runtime), args, bundleInfo); + if (!pTestRunner) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null testRunner"); + return nullptr; + } + + return std::unique_ptr(pTestRunner); +} + +STSTestRunner::STSTestRunner( + STSRuntime &stsRuntime, const std::shared_ptr &args, const AppExecFwk::BundleInfo &bundleInfo) + : stsRuntime_(stsRuntime) +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "STSTestRunner constructor"); + std::string moduleName; + if (args) { + std::string srcPath; + if (bundleInfo.hapModuleInfos.back().isModuleJson) { + srcPath.append(args->GetTestModuleName()); + if (args->GetTestRunnerClassName().find("/") == std::string::npos) { + srcPath.append(LOWERCASETESTRUNNER); + } + moduleName = args->GetTestModuleName(); + } else { + srcPath.append(args->GetTestPackageName()); + srcPath.append("/assets/sts/TestRunner/"); + moduleName = args->GetTestPackageName(); + } + srcPath.append(args->GetTestRunnerClassName()); + srcPath.append(".abc"); + srcPath_ = srcPath; + } + TAG_LOGI(AAFwkTag::DELEGATOR, "srcPath: %{public}s", srcPath_.c_str()); + + if (!moduleName.empty()) { + for (auto hapModuleInfo : bundleInfo.hapModuleInfos) { + if ((hapModuleInfo.isModuleJson && hapModuleInfo.name == moduleName) || + hapModuleInfo.package == moduleName) { + hapPath_ = hapModuleInfo.hapPath; + break; + } + } + } else { + hapPath_ = bundleInfo.hapModuleInfos.back().hapPath; + } + AppExecFwk::HapModuleInfo entryHapModuleInfo; + if (!bundleInfo.hapModuleInfos.empty()) { + for (auto hapModuleInfo : bundleInfo.hapModuleInfos) { + if (hapModuleInfo.moduleType == AppExecFwk::ModuleType::ENTRY) { + entryHapModuleInfo = hapModuleInfo; + break; + } + } + } + TAG_LOGI(AAFwkTag::DELEGATOR, "hapPath: %{public}s", hapPath_.c_str()); + moduleName.append("::").append("TestRunner"); + stsTestRunnerObj_ = stsRuntime_.LoadModule(moduleName, srcPath_, hapPath_, + bundleInfo.hapModuleInfos.back().compileMode == AppExecFwk::CompileMode::ES_MODULE, + false, srcPath_); + if (!stsTestRunnerObj_ && srcPath_.find(LOWERCASETESTRUNNER) != std::string::npos) { + TAG_LOGI(AAFwkTag::DELEGATOR, "not found %{public}s , retry load capital address", srcPath_.c_str()); + std::regex src_pattern(LOWERCASETESTRUNNER); + srcPath_ = std::regex_replace(srcPath_, src_pattern, CAPITALTESTRUNNER); + TAG_LOGI(AAFwkTag::DELEGATOR, "capital address is %{public}s", srcPath_.c_str()); + stsTestRunnerObj_ = stsRuntime_.LoadModule(moduleName, srcPath_, hapPath_, + bundleInfo.hapModuleInfos.back().compileMode == AppExecFwk::CompileMode::ES_MODULE, + false, srcPath_); + } +} + +STSTestRunner::~STSTestRunner() = default; + +bool STSTestRunner::Initialize() +{ + return true; +} + +void STSTestRunner::Prepare() +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "STSTestRunner Prepare"); + if (stsTestRunnerObj_ != nullptr) { + TAG_LOGI(AAFwkTag::DELEGATOR, "use stsTestRunnerObj_"); + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null env"); + return; + } + if (env->ResetError() != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "ResetError failed"); + } + ani_method method; + ani_status status = ANI_ERROR; + status = env->Class_FindMethod(stsTestRunnerObj_->aniCls, "onPrepare", ":V", &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "get onPrepare failed status : %{public}d", status); + return; + } + TAG_LOGI(AAFwkTag::DELEGATOR, "get onPrepare success"); + + ani_int result; + status = env->Object_CallMethod_Void(stsTestRunnerObj_->aniObj, method, &result); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_CallMethod_Void onPrepare failed status : %{public}d", status); + } else { + TAG_LOGI(AAFwkTag::DELEGATOR, "Object_CallMethod_Void onPrepare success"); + } + } +} + +void STSTestRunner::Run() +{ + TAG_LOGI(AAFwkTag::DELEGATOR, "STSTestRunner Run"); + if (stsTestRunnerObj_ != nullptr) { + TAG_LOGI(AAFwkTag::DELEGATOR, "use stsTestRunnerObj_"); + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::DELEGATOR, "null env"); + return; + } + if (env->ResetError() != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "ResetError failed"); + } + ani_method method; + ani_status status = ANI_ERROR; + status = env->Class_FindMethod(stsTestRunnerObj_->aniCls, "onRun", ":V", &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "get onRun failed status : %{public}d", status); + return; + } + TAG_LOGI(AAFwkTag::DELEGATOR, "get onRun success"); + + ani_int result; + status = env->Object_CallMethod_Void(stsTestRunnerObj_->aniObj, method, &result); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::DELEGATOR, "Object_CallMethod_Void onRun failed status : %{public}d", status); + } else { + TAG_LOGI(AAFwkTag::DELEGATOR, "Object_CallMethod_Void onRun success"); + } + } +} +} // namespace RunnerRuntime +} // namespace OHOS diff --git a/frameworks/native/appkit/ability_delegator/test_runner.cpp b/frameworks/native/appkit/ability_delegator/test_runner.cpp index 617133065bee63732ac851bc5754530453667432..37c337d981782fd21b4bea8d27fccf3fc154ee87 100644 --- a/frameworks/native/appkit/ability_delegator/test_runner.cpp +++ b/frameworks/native/appkit/ability_delegator/test_runner.cpp @@ -20,6 +20,7 @@ #include "runner_runtime/cj_test_runner.h" #endif #include "runner_runtime/js_test_runner.h" +#include "runner_runtime/sts_test_runner.h" #include "runtime.h" #include "sys_mgr_client.h" #include "system_ability_definition.h" @@ -64,6 +65,8 @@ std::unique_ptr TestRunner::Create(const std::unique_ptr(); } diff --git a/frameworks/native/appkit/ability_runtime/app/ability_stage.cpp b/frameworks/native/appkit/ability_runtime/app/ability_stage.cpp index d00b2f545a5962330f6ef3469fda2bda9308cd64..611d5ad00443e70addfb5e00ffa342a5334385c8 100644 --- a/frameworks/native/appkit/ability_runtime/app/ability_stage.cpp +++ b/frameworks/native/appkit/ability_runtime/app/ability_stage.cpp @@ -22,6 +22,7 @@ #include "cj_ability_stage.h" #endif #include "js_ability_stage.h" +#include "sts_ability_stage.h" #include "runtime.h" namespace OHOS { @@ -41,6 +42,8 @@ std::shared_ptr AbilityStage::Create( case Runtime::Language::CJ: return CJAbilityStage::Create(runtime, hapModuleInfo); #endif + case Runtime::Language::STS: + return STSAbilityStage::Create(runtime, hapModuleInfo); default: return std::make_shared(); } diff --git a/frameworks/native/appkit/ability_runtime/app/sts_ability_stage.cpp b/frameworks/native/appkit/ability_runtime/app/sts_ability_stage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b49722b02bb0aec1f3e72edbe0524f5ececace23 --- /dev/null +++ b/frameworks/native/appkit/ability_runtime/app/sts_ability_stage.cpp @@ -0,0 +1,323 @@ +/* + * 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 "sts_ability_stage.h" +#include "ability_delegator_registry.h" +#include "freeze_util.h" +#include "hilog_tag_wrapper.h" +#include "configuration_convertor.h" +#include "sts_ability_stage_context.h" +#include "ani_common_configuration.h" +#include "ohos_application.h" +#include "startup_manager.h" +#include "hitrace_meter.h" +#include +#include +#include +#include +#include +#include +#include + +namespace OHOS { +namespace AbilityRuntime { +constexpr const char* PROFILE_FILE_PREFIX = "$profile:"; +constexpr const char* STARTUP_TASKS = "startupTasks"; +constexpr const char* NAME = "name"; +constexpr const char* SRC_ENTRY = "srcEntry"; +constexpr const char* DEPENDENCIES = "dependencies"; +constexpr const char* EXCLUDE_FROM_AUTO_START = "excludeFromAutoStart"; +constexpr const char* RUN_ON_THREAD = "runOnThread"; +constexpr const char* WAIT_ON_MAIN_THREAD = "waitOnMainThread"; +constexpr const char* CONFIG_ENTRY = "configEntry"; +constexpr const char *TASKPOOL = "taskPool"; +constexpr const char *TASKPOOL_LOWER = "taskpool"; + +namespace { +void RegisterStopPreloadSoCallback(STSRuntime& stsRuntime) +{ + std::shared_ptr startupManager = DelayedSingleton::GetInstance(); + if (startupManager == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null startupManager"); + return; + } +} +} // namespace + + +bool STSAbilityStage::UseCommonChunk(const AppExecFwk::HapModuleInfo& hapModuleInfo) +{ + for (auto &md: hapModuleInfo.metadata) { + if (md.name == "USE_COMMON_CHUNK") { + if (md.value != "true") { + TAG_LOGE(AAFwkTag::APPKIT, "USE_COMMON_CHUNK = %s{public}s", md.value.c_str()); + return false; + } + return true; + } + } + return false; +} + +std::shared_ptr STSAbilityStage::Create( + const std::unique_ptr& runtime, const AppExecFwk::HapModuleInfo& hapModuleInfo) +{ + if (runtime == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + return nullptr; + } + FreezeUtil::GetInstance().AddAppLifecycleEvent(0, "STSAbilityStage::Create"); + + auto& stsRuntime = static_cast(*runtime); + + std::string srcPath(hapModuleInfo.name); + std::string moduleName(hapModuleInfo.moduleName); + moduleName.append("::").append("AbilityStage"); + bool commonChunkFlag = UseCommonChunk(hapModuleInfo); + + RegisterStopPreloadSoCallback(stsRuntime); + + srcPath.append("/"); + if (!hapModuleInfo.srcEntrance.empty()) { + srcPath.append(hapModuleInfo.srcEntrance); + auto pos = srcPath.rfind("."); + if (pos != std::string::npos) { + srcPath.erase(pos); + srcPath.append(".abc"); + } + } + + std::unique_ptr moduleObj; + if (!hapModuleInfo.srcEntrance.empty()) { + moduleObj = stsRuntime.LoadModule(moduleName, srcPath, hapModuleInfo.hapPath, + hapModuleInfo.compileMode == AppExecFwk::CompileMode::ES_MODULE, commonChunkFlag, + hapModuleInfo.srcEntrance); + } + return std::make_shared(stsRuntime, std::move(moduleObj)); +} + +STSAbilityStage::STSAbilityStage(STSRuntime & stsRuntime, std::unique_ptr&& stsAbilityStageObj) + : stsRuntime_(stsRuntime), stsAbilityStageObj_(std::move(stsAbilityStageObj)) +{} + +STSAbilityStage::~STSAbilityStage() +{ + TAG_LOGI(AAFwkTag::APPKIT, "destructor"); + auto context = GetContext(); + if (context != nullptr) { + context->Unbind(); + } +} + +void STSAbilityStage::Init(const std::shared_ptr &context, + const std::weak_ptr application) +{ + AbilityStage::Init(context, application); + + if (!context) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + return; + } + + if (!stsAbilityStageObj_) { + TAG_LOGE(AAFwkTag::APPKIT, "null stage"); + return; + } + + SetJsAbilityStage(context); +} + +void STSAbilityStage::OnCreate(const AAFwk::Want &want) const +{ + AbilityStage::OnCreate(want); + + CallObjectMethod(false, "onCreate", ":V"); + + FreezeUtil::GetInstance().AddAppLifecycleEvent(0, "STSAbilityStage::OnCreate end"); + auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::STS); + if (delegator) { + delegator->PostPerformStageStart(CreateStageProperty()); + } +} + +void STSAbilityStage::OnDestroy() const +{ + AbilityStage::OnDestroy(); + CallObjectMethod(false, "onDestroy", ":V"); +} + +std::string STSAbilityStage::OnAcceptWant(const AAFwk::Want &want) +{ + return std::string(); +} + +std::string STSAbilityStage::OnNewProcessRequest(const AAFwk::Want &want) +{ + return std::string(); +} + +void STSAbilityStage::OnConfigurationUpdated(const AppExecFwk::Configuration& configuration) +{ + TAG_LOGD(AAFwkTag::APPKIT, "OnConfigurationUpdated called"); + AbilityStage::OnConfigurationUpdated(configuration); + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "env nullptr"); + return; + } + ani_object configObj = OHOS::AppExecFwk::WrapConfiguration(env, configuration); + if (configObj == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null configObj"); + return; + } + CallObjectMethod(false, "onConfigurationUpdate", "L@ohos/app/ability/Configuration/Configuration;:V", configObj); +} + +void STSAbilityStage::OnMemoryLevel(int32_t level) +{ +} + +int32_t STSAbilityStage::RunAutoStartupTask(const std::function &callback, bool &isAsyncCallback, + const std::shared_ptr &stageContext) +{ + isAsyncCallback = false; + return RunAutoStartupTaskInner(callback, isAsyncCallback); +} + +int32_t STSAbilityStage::RegisterAppStartupTask(const std::shared_ptr& hapModuleInfo) +{ + return ERR_OK; +} + +int32_t STSAbilityStage::RunAutoStartupTaskInner(const std::function &callback, bool &isAsyncCallback) +{ + return ERR_OK; +} + +std::unique_ptr STSAbilityStage::LoadJsOhmUrl(const std::string &srcEntry, + const std::string &ohmUrl, const std::string &moduleName, const std::string &hapPath, bool esmodule) +{ + return nullptr; +} + +std::unique_ptr STSAbilityStage::LoadJsSrcEntry(const std::string &srcEntry) +{ + return nullptr; +} + +bool STSAbilityStage::LoadJsStartupConfig(const std::string &srcEntry) +{ + return true; +} + +bool STSAbilityStage::CallObjectMethod(bool withResult, const char *name, const char *signature, ...) const +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name); + if (stsAbilityStageObj_ == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "stsAbilityStageObj_ nullptr"); + return false; + } + + auto env = stsRuntime_.GetAniEnv(); + STSAbilityStageContext::ResetEnv(env); + ani_status status = ANI_OK; + ani_method method = nullptr; + if ((status = env->Class_FindMethod(stsAbilityStageObj_->aniCls, name, signature, &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "status: %{public}d", status); + return false; + } + env->ResetError(); + if (withResult) { + ani_boolean res = 0; + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Boolean(stsAbilityStageObj_->aniObj, method, &res, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "status: %{public}d", status); + stsRuntime_.HandleUncaughtError(); + } + va_end(args); + return res; + } + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(stsAbilityStageObj_->aniObj, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "status: %{public}d", status); + stsRuntime_.HandleUncaughtError(); + return false; + } + va_end(args); + return false; +} + +std::shared_ptr STSAbilityStage::CreateStageProperty() const +{ + auto property = std::make_shared(); + return property; +} + +std::string STSAbilityStage::GetHapModuleProp(const std::string &propName) const +{ + return std::string(); +} + + +void STSAbilityStage::SetJsAbilityStage(const std::shared_ptr &context) +{ + if (context == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "context nullptr"); + return; + } + + if (!stsAbilityStageObj_) { + TAG_LOGE(AAFwkTag::APPKIT, "Not found AbilityStage.js"); + return; + } + + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "env nullptr"); + return; + } + + STSAbilityStageContext::ResetEnv(env); + + ani_object stageCtxObj = STSAbilityStageContext::CreateStsAbilityStageContext(env, context); + if (stageCtxObj == nullptr) { + STSAbilityStageContext::ResetEnv(env); + TAG_LOGE(AAFwkTag::ABILITY, "CreateStsAbilityStageContext failed"); + return; + } + + ani_status status = ANI_OK; + ani_field contextField; + status = env->Class_FindField(stsAbilityStageObj_->aniCls, "context", &contextField); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "Class_GetField context failed"); + STSAbilityStageContext::ResetEnv(env); + return; + } + ani_ref stageCtxObjRef = nullptr; + if (env->GlobalReference_Create(stageCtxObj, &stageCtxObjRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "GlobalReference_Create stageCtxObj failed"); + return; + } + if (env->Object_SetField_Ref(stsAbilityStageObj_->aniObj, contextField, stageCtxObjRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "Object_SetField_Ref stageCtxObj failed"); + STSAbilityStageContext::ResetEnv(env); + } +} + +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/appkit/ability_runtime/app/sts_ability_stage_context.cpp b/frameworks/native/appkit/ability_runtime/app/sts_ability_stage_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..84fdeea28362b62fbd4eb28b2ac2b3ad5f75cb54 --- /dev/null +++ b/frameworks/native/appkit/ability_runtime/app/sts_ability_stage_context.cpp @@ -0,0 +1,185 @@ +/* + * 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 "ability_runtime/context/context.h" +#include "sts_ability_stage_context.h" +#include "hilog_tag_wrapper.h" +#include "sts_runtime.h" +#include "configuration_convertor.h" +#include "ohos_application.h" +#include "ani_common_configuration.h" +#include "sts_context_utils.h" +#include "common_fun_ani.h" +namespace OHOS { +namespace AbilityRuntime { + +ani_ref STSAbilityStageContext::stsAbilityStageContextObj_ = nullptr; + +void STSAbilityStageContext::ResetEnv(ani_env* env) +{ + if (env) { + env->DescribeError(); + env->ResetError(); + } +} + +ani_object STSAbilityStageContext::CreateStsAbilityStageContext(ani_env* env, std::shared_ptr context) +{ + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "env nullptr or context nullptr"); + return nullptr; + } + + ani_status status = ANI_OK; + ani_class abilityStageCtxCls; + status = env->FindClass(STS_ABILITY_STAGE_CONTEXT_CLASS_NAME, &abilityStageCtxCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "call FindClass LAbilityStageContext failed, status:%{public}d", status); + return nullptr; + } + + ani_method method = nullptr; + status = env->Class_FindMethod(abilityStageCtxCls, "", ":V", &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "call Class_FindMethod ctor failed"); + return nullptr; + } + ani_object obj = nullptr; + status = env->Object_New(abilityStageCtxCls, method, &obj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "call Object_New abilityStageCtxCls failed"); + return nullptr; + } + stsAbilityStageContextObj_ = reinterpret_cast(obj); + + //bind context + auto workContext = new (std::nothrow) std::weak_ptr(context); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "workContext nullptr"); + return nullptr; + } + ani_field contextField; + status = env->Class_FindField(abilityStageCtxCls, "nativeContext", &contextField); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "call Class_FindField nativeContext failed"); + } + ani_long nativeContextLong = (ani_long)workContext; + status = env->Object_SetField_Long(obj, contextField, nativeContextLong); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "call Object_SetField_Long contextField failed"); + delete workContext; + return nullptr; + } + + // bind parent context + ContextUtil::StsCreatContext(env, abilityStageCtxCls, obj, context); + + //set Config class + auto configuration = context->GetConfiguration(); + if (configuration != nullptr) { + ani_object configObj = OHOS::AppExecFwk::WrapConfiguration(env, *configuration); + if (configObj != nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "configObj bind"); + ani_ref configObjRef = nullptr; + if (env->GlobalReference_Create(configObj, &configObjRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "GlobalReference_Create configObjRef failed"); + } + ani_field configField; + status = env->Class_FindField(abilityStageCtxCls, "config", &configField); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "Class_FindField config failed"); + } + if (env->Object_SetField_Ref(obj, configField, configObjRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "Object_SetField_Ref configField failed"); + } + } + } + //set HapModuleInfo class + ani_object moduleInfoObj = CreateHapModuleInfo(env, context); + if (moduleInfoObj != nullptr) { + ani_field moduleInfoField; + status = env->Class_FindField(abilityStageCtxCls, "currentHapModuleInfo", &moduleInfoField); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "Class_FindField currentHapModuleInfo failed"); + } + status = env->Object_SetField_Ref(obj, moduleInfoField, reinterpret_cast(moduleInfoObj)); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "Object_SetField_Ref moduleInfoField failed"); + } + } + ani_ref* contextGlobalRef = new (std::nothrow) ani_ref; + if ((status = env->GlobalReference_Create(obj, contextGlobalRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "status: %{public}d", status); + delete contextGlobalRef; + return obj; + } + context->Bind(contextGlobalRef); + return obj; +} + +ani_object STSAbilityStageContext::CreateHapModuleInfo(ani_env* env, const std::shared_ptr &context) +{ + if (env == nullptr || context == nullptr) { + return nullptr; + } + auto hapModuleInfo = context->GetHapModuleInfo(); + if (hapModuleInfo == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "hapModuleInfo is nullptr"); + return nullptr; + } + ani_object obj = AppExecFwk::CommonFunAni::ConvertHapModuleInfo(env, *hapModuleInfo); + return obj; +} + +void STSAbilityStageContext::ConfigurationUpdated(ani_env* env, + const std::shared_ptr &config) +{ + if (!config) { + TAG_LOGE(AAFwkTag::ABILITY_SIM, "null config"); + return; + } + ani_object configObj = OHOS::AppExecFwk::WrapConfiguration(env, *config); + + ani_class abilityStageCtxCls = nullptr; + ani_status status = env->FindClass(STS_ABILITY_STAGE_CLASS_NAME, &abilityStageCtxCls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "FindClass LAbilityStageContext failed, status:%{public}d", status); + } + + ani_method method = nullptr; + status = env->Class_FindMethod(abilityStageCtxCls, "", ":V", &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "call Class_FindMethod ctor failed"); + } + ani_object abilityStageCtxObj = nullptr; + status = env->Object_New(abilityStageCtxCls, method, &abilityStageCtxObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "call Object_New abilityStageCtxCls failed"); + } + + method = nullptr; + status = env->Class_FindMethod(abilityStageCtxCls, "onUpdateConfiguration", "LConfiguration;:V", &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "Class_FindMethod FAILED"); + return; + } + + status = env->Object_CallMethod_Void(abilityStageCtxObj, method, configObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "CALL Object_CallMethod_Void FAILED:"); + return; + } +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/appkit/ability_runtime/context/application_context_manager.cpp b/frameworks/native/appkit/ability_runtime/context/application_context_manager.cpp index b46e080eacf629b64309cb536ca732c00bc35826..dd8d930cf2e92dc42de2650115373f674f6283c3 100644 --- a/frameworks/native/appkit/ability_runtime/context/application_context_manager.cpp +++ b/frameworks/native/appkit/ability_runtime/context/application_context_manager.cpp @@ -88,5 +88,18 @@ void ApplicationContextManager::RemoveGlobalObject(napi_env env) applicationContextMap_.erase(env); } } + +void ApplicationContextManager::SetEtsGlobalObject( + std::shared_ptr applicationContextObj) +{ + std::lock_guard lock(applicationContextMutex_); + etsApplicationContextRef_ = applicationContextObj; +} + +std::shared_ptr ApplicationContextManager::GetEtsGlobalObject() +{ + std::lock_guard lock(applicationContextMutex_); + return etsApplicationContextRef_; +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/native/appkit/ability_runtime/context/ets_application_context_utils.cpp b/frameworks/native/appkit/ability_runtime/context/ets_application_context_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..89b5761d84df1df0b77e4978c5fab0924488f6b2 --- /dev/null +++ b/frameworks/native/appkit/ability_runtime/context/ets_application_context_utils.cpp @@ -0,0 +1,577 @@ +/* + * 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_context_utils.h" +#include "application_context_manager.h" +#include "hilog_tag_wrapper.h" +#include "sts_app_manager_utils.h" +#include "ani_enum_convert.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { + constexpr const char* STS_APPLICATION_CONTEXT_CLASS_NAME = "Lapplication/ApplicationContext/ApplicationContext;"; + constexpr double FOUNT_SIZE = 0.0; +} +std::weak_ptr applicationContext_; +std::shared_ptr etsEnviromentCallback_ = nullptr; +std::shared_ptr applicationStateCallback_ = nullptr; + +void EtsApplicationContextUtils::RestartApp([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_object wantObj) +{ + TAG_LOGD(AAFwkTag::APPKIT, "RestartApp Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext"); + return; + } + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::APPKIT, "Parse want failed"); + ThrowStsInvalidParamError(env, "Parse param want failed, want must be Want."); + return; + } + auto errCode = applicationContext->RestartApp(want); + if (errCode == ERR_INVALID_VALUE) { + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + } else if (errCode == AAFwk::ERR_RESTART_APP_INCORRECT_ABILITY) { + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_RESTART_APP_INCORRECT_ABILITY); + } else if (errCode == AAFwk::ERR_RESTART_APP_FREQUENT) { + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_RESTART_APP_FREQUENT); + } else if (errCode == AAFwk::NOT_TOP_ABILITY) { + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_NOT_TOP_ABILITY); + } else { + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + } + TAG_LOGD(AAFwkTag::APPKIT, "RestartApp errCode is %{public}d", errCode); +} + +void EtsApplicationContextUtils::SetFont([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_string font) +{ + TAG_LOGD(AAFwkTag::APPKIT, "SetFont Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext"); + return; + } + std::string stdFont = ""; + if (!AppExecFwk::GetStdString(env, font, stdFont)) { + TAG_LOGE(AAFwkTag::APPKIT, "Parse font failed"); + ThrowStsInvalidParamError(env, "Parse param font failed, font must be string."); + } + TAG_LOGD(AAFwkTag::APPKIT, "SetFont font %{public}s", stdFont.c_str()); + applicationContext->SetFont(stdFont); +} + +void EtsApplicationContextUtils::SetColorMode([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_enum_item colorMode) +{ + TAG_LOGD(AAFwkTag::APPKIT, "SetColorMode Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext"); + return; + } + ani_int mode; + if (!AAFwk::AniEnumConvertUtil::EnumConvertStsToNative(env, colorMode, mode)) { + ThrowStsInvalidParamError(env, "Parse param colorMode failed, colorMode must be number."); + TAG_LOGE(AAFwkTag::APPKIT, "Parse colorMode failed"); + return; + } + TAG_LOGD(AAFwkTag::APPKIT, "colorMode is %{public}d", mode); + applicationContext->SetColorMode(static_cast(mode)); +} + +void EtsApplicationContextUtils::SetLanguage([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_string language) +{ + TAG_LOGD(AAFwkTag::APPKIT, "SetLanguage Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext"); + return; + } + std::string stdLanguage = ""; + if (!AppExecFwk::GetStdString(env, language, stdLanguage)) { + TAG_LOGE(AAFwkTag::APPKIT, "Parse language failed"); + ThrowStsInvalidParamError(env, "Parse param language failed, language must be string."); + return; + } + applicationContext->SetLanguage(stdLanguage); + TAG_LOGD(AAFwkTag::APPKIT, "stdLanguage language %{public}s", stdLanguage.c_str()); +} + +void EtsApplicationContextUtils::SetFontSizeScale([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_double fontSizeScale) +{ + TAG_LOGD(AAFwkTag::APPKIT, "SetFontSizeScale Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext"); + return; + } + + double stdFontSizeScale = static_cast(fontSizeScale); + TAG_LOGD(AAFwkTag::APPKIT, "fontSizeScale: %{public}f", stdFontSizeScale); + if (fontSizeScale < FOUNT_SIZE) { + TAG_LOGE(AAFwkTag::APPKIT, "invalid size"); + ThrowStsInvalidParamError(env, "Invalid font size."); + return; + } + applicationContext->SetFontSizeScale(stdFontSizeScale); +} + +void EtsApplicationContextUtils::ClearUpApplicationData([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "ClearUpApplicationData Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "nativeContext is null"); + AppExecFwk::AsyncCallback(env, callback, CreateStsError(env, + (ani_int)AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT, + "applicationContext if already released."), nullptr); + return; + } + applicationContext->ClearUpApplicationData(); + AppExecFwk::AsyncCallback(env, callback, CreateStsError(env, AbilityErrorCode::ERROR_OK), nullptr); +} + +void EtsApplicationContextUtils::GetRunningProcessInformation([[maybe_unused]]ani_env *env, + [[maybe_unused]]ani_object aniObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "GetRunningProcessInformation Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + ani_object emptyArray = AppManagerSts::CreateEmptyAniArray(env); + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "nativeContext is null"); + AppExecFwk::AsyncCallback(env, callback, CreateStsError(env, + (ani_int)AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT, + "applicationContext if already released."), emptyArray); + return; + } + std::vector infos; + AppExecFwk::RunningProcessInfo processInfo; + ErrCode innerErrCode = applicationContext->GetProcessRunningInformation(processInfo); + if (innerErrCode == ERR_OK) { + infos.emplace_back(processInfo); + ani_object aniInfosRef = AppManagerSts::CreateRunningProcessInfoArray(env, infos); + if (aniInfosRef == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null array"); + AppExecFwk::AsyncCallback(env, callback, CreateStsError(env, + (ani_int)AbilityErrorCode::ERROR_CODE_INNER, "Initiate array failed."), emptyArray); + } else { + AppExecFwk::AsyncCallback(env, callback, CreateStsError(env, AbilityErrorCode::ERROR_OK), aniInfosRef); + } + } else { + AppExecFwk::AsyncCallback(env, callback, CreateStsError(env, + (ani_int)AbilityErrorCode::ERROR_CODE_INNER, "Get process infos failed."), emptyArray); + } +} + +void EtsApplicationContextUtils::NativeOnApplicationStateChangeSync([[maybe_unused]]ani_env *env, + [[maybe_unused]]ani_object aniObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "NativeOnApplicationStateChangeSync Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "nativeContext is null"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return; + } + if (applicationStateCallback_ != nullptr) { + applicationStateCallback_->Register(callback); + return; + } + applicationStateCallback_ = std::make_shared(env); + applicationStateCallback_->Register(callback); + applicationContext->RegisterApplicationStateChangeCallback(applicationStateCallback_); +} + +void EtsApplicationContextUtils::NativeOffApplicationStateChangeSync([[maybe_unused]]ani_env *env, + [[maybe_unused]]ani_object aniObj, ani_object callback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "NativeOffApplicationStateChangeSync Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + if (applicationStateCallback_ == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationStateCallback_"); + ThrowStsInvalidParamError( + 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"); + ThrowStsInvalidParamError(env, "Parse param call UnRegister failed, call UnRegister must be function."); + return; + } + if (applicationStateCallback_->IsEmpty()) { + applicationStateCallback_.reset(); + } +} + +ani_double EtsApplicationContextUtils::NativeOnSync([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_string type, ani_object envCallback) +{ + TAG_LOGD(AAFwkTag::APPKIT, "NativeOnSync Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "env is nullptr"); + return ANI_ERROR; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "nativeContext is null"); + AbilityRuntime::ThrowStsInvalidParamError(env, "nativeContext is null"); + return ANI_ERROR; + } + if (etsEnviromentCallback_ != nullptr) { + return ani_double(etsEnviromentCallback_->Register(envCallback)); + } + + etsEnviromentCallback_ = std::make_shared(env); + int32_t callbackId = etsEnviromentCallback_->Register(envCallback); + applicationContext->RegisterEnvironmentCallback(etsEnviromentCallback_); + + return ani_double(callbackId); +} + +void EtsApplicationContextUtils::NativeOffSync([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_string type, ani_double callbackId, ani_object call) +{ + TAG_LOGD(AAFwkTag::APPKIT, "NativeOffSync Call"); + 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, call, CreateStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM), nullptr); + return; + } + + if (etsEnviromentCallback_ == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "etsEnviromentCallback is null"); + AppExecFwk::AsyncCallback(env, call, CreateStsError(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, call, CreateStsError(env, + (ani_int)AbilityErrorCode::ERROR_CODE_INVALID_PARAM, "call UnRegister failed!"), nullptr); + return; + } + + AppExecFwk::AsyncCallback(env, call, CreateStsError(env, AbilityErrorCode::ERROR_OK), nullptr); +} + +void EtsApplicationContextUtils::killAllProcesses([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_boolean clearPageStack, ani_object call) +{ + TAG_LOGD(AAFwkTag::APPKIT, "killAllProcesses Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "env is nullptr"); + return; + } + ani_object aniObject = AbilityRuntime::CreateStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_OK); + ErrCode innerErrCode = ERR_OK; + auto context = applicationContext_.lock(); + if (!context) { + TAG_LOGE(AAFwkTag::APPKIT, "nativeContextLong is nullptr"); + innerErrCode = AbilityRuntime::ERR_ABILITY_RUNTIME_EXTERNAL_CONTEXT_NOT_EXIST; + aniObject = AbilityRuntime::CreateStsError(env, innerErrCode, "applicationContext is already released."); + AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + return; + } + AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + context->KillProcessBySelf(clearPageStack); +} + +void EtsApplicationContextUtils::PreloadUIExtensionAbility([[maybe_unused]]ani_env *env, + [[maybe_unused]]ani_object aniObj, ani_object wantObj, ani_object call) +{ + TAG_LOGD(AAFwkTag::APPKIT, "PreloadUIExtensionAbility Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + AAFwk::Want want; + if (!OHOS::AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::APPKIT, "Parse want failed"); + AppExecFwk::AsyncCallback(env, call, AbilityRuntime::CreateStsInvalidParamError(env, + "Parse param want failed, want must be Want."), nullptr); + return; + } + auto context = applicationContext_.lock(); + if (!context) { + AppExecFwk::AsyncCallback(env, call, AbilityRuntime::CreateStsErrorByNativeErr(env, + (int32_t)AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT), nullptr); + return; + } + auto hostBundleName = context->GetBundleName(); + TAG_LOGD(AAFwkTag::APPKIT, "HostBundleName is %{public}s", hostBundleName.c_str()); + auto innerErrCode = AAFwk::AbilityManagerClient::GetInstance()->PreloadUIExtensionAbility(want, hostBundleName); + if (innerErrCode == ERR_OK) { + AppExecFwk::AsyncCallback(env, call, AbilityRuntime::CreateStsError(env, + AbilityRuntime::AbilityErrorCode::ERROR_OK), nullptr); + } else { + TAG_LOGE(AAFwkTag::APPKIT, "OnPreloadUIExtensionAbility failed %{public}d", innerErrCode); + AppExecFwk::AsyncCallback(env, call, AbilityRuntime::CreateStsErrorByNativeErr(env, innerErrCode), nullptr); + } +} + +void EtsApplicationContextUtils::SetSupportedProcessCacheSync([[maybe_unused]]ani_env *env, + [[maybe_unused]]ani_object aniObj, ani_boolean value) +{ + TAG_LOGD(AAFwkTag::APPKIT, "SetSupportedProcessCacheSync Call"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return; + } + int32_t errCode = applicationContext->SetSupportedProcessCacheSelf(value); + if (errCode == AAFwk::ERR_CAPABILITY_NOT_SUPPORT) { + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_CAPABILITY_NOT_SUPPORT); + } else if (errCode != ERR_OK) { + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER); + } +} + +void EtsApplicationContextUtils::SetApplicationContextToEts(const std::shared_ptr + &abilityRuntimeContext) +{ + TAG_LOGD(AAFwkTag::APPKIT, "SetApplicationContextToEts Call"); + if (abilityRuntimeContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + return; + } + applicationContext_ = abilityRuntimeContext; +} + +ani_double EtsApplicationContextUtils::GetCurrentAppCloneIndex([[maybe_unused]]ani_env *env, + [[maybe_unused]]ani_object aniObj) +{ + auto context = applicationContext_.lock(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return ANI_ERROR; + } + if (context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return ANI_ERROR; + } + if (context->GetCurrentAppMode() != static_cast(AppExecFwk::MultiAppModeType::APP_CLONE)) { + TAG_LOGE(AAFwkTag::APPKIT, "not clone"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_NOT_APP_CLONE); + return ANI_ERROR; + } + int32_t appIndex = context->GetCurrentAppCloneIndex(); + return ani_double(appIndex); +} + +ani_string EtsApplicationContextUtils::GetCurrentInstanceKey([[maybe_unused]]ani_env *env, + [[maybe_unused]]ani_object aniObj) +{ + auto context = applicationContext_.lock(); + ani_string aniStr = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return nullptr; + } + if (context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return nullptr; + } + if (context->GetCurrentAppMode() != static_cast(AppExecFwk::MultiAppModeType::MULTI_INSTANCE)) { + AbilityRuntime::ThrowStsError(env, AbilityRuntime::AbilityErrorCode::ERROR_MULTI_INSTANCE_NOT_SUPPORTED); + TAG_LOGE(AAFwkTag::APPKIT, "not support"); + return nullptr; + } + std::string instanceKey = context->GetCurrentInstanceKey(); + aniStr = AppExecFwk::GetAniString(env, instanceKey); + return aniStr; +} + +void EtsApplicationContextUtils::BindApplicationContextFunc(ani_env* aniEnv, ani_class& contextClass) +{ + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null aniEnv"); + return; + } + std::array applicationContextFunctions = { + ani_native_function {"setSupportedProcessCacheSync", "Z:V", + reinterpret_cast(EtsApplicationContextUtils::SetSupportedProcessCacheSync)}, + ani_native_function {"nativekillAllProcessesSync", "ZLutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplicationContextUtils::killAllProcesses)}, + ani_native_function {"nativepreloadUIExtensionAbilitySync", + "L@ohos/app/ability/Want/Want;Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplicationContextUtils::PreloadUIExtensionAbility)}, + ani_native_function {"nativeOnSync", + "Lstd/core/String;L@ohos/app/ability/EnvironmentCallback/EnvironmentCallback;:D", + reinterpret_cast(EtsApplicationContextUtils::NativeOnSync)}, + ani_native_function {"nativeOffSync", + "Lstd/core/String;DLutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplicationContextUtils::NativeOffSync)}, + ani_native_function {"nativegetRunningProcessInformation", + "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplicationContextUtils::GetRunningProcessInformation)}, + ani_native_function {"nativeclearUpApplicationData", + "Lutils/AbilityUtils/AsyncCallbackWrapper;:V", + reinterpret_cast(EtsApplicationContextUtils::ClearUpApplicationData)}, + ani_native_function {"nativesetLanguage", "Lstd/core/String;:V", + reinterpret_cast(EtsApplicationContextUtils::SetLanguage)}, + ani_native_function {"nativesetFontSizeScale", "D:V", + reinterpret_cast(EtsApplicationContextUtils::SetFontSizeScale)}, + ani_native_function {"nativesetColorMode", + "L@ohos/app/ability/ConfigurationConstant/ConfigurationConstant/ColorMode;:V", + reinterpret_cast(EtsApplicationContextUtils::SetColorMode)}, + ani_native_function {"nativesetFont", "Lstd/core/String;:V", + reinterpret_cast(EtsApplicationContextUtils::SetFont)}, + ani_native_function {"nativerestartApp", "L@ohos/app/ability/Want/Want;:V", + reinterpret_cast(EtsApplicationContextUtils::RestartApp)}, + 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{"nativegetCurrentInstanceKey", ":Lstd/core/String;", + reinterpret_cast(EtsApplicationContextUtils::GetCurrentInstanceKey)}, + ani_native_function {"nativegetCurrentAppCloneIndex", ":D", + reinterpret_cast(EtsApplicationContextUtils::GetCurrentAppCloneIndex)}, + }; + ani_status status = aniEnv->Class_BindNativeMethods(contextClass, applicationContextFunctions.data(), + applicationContextFunctions.size()); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_BindNativeMethods failed status: %{public}d", status); + } +} + +void EtsApplicationContextUtils::CreateEtsApplicationContext(ani_env* aniEnv) +{ + TAG_LOGD(AAFwkTag::APPKIT, "CreateEtsApplicationContext Call"); + auto applicationContext = applicationContext_.lock(); + if (applicationContext == nullptr || aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null applicationContext or aniEnv"); + return; + } + ani_status status = ANI_ERROR; + ani_class applicationContextCls = nullptr; + if ((status = aniEnv->FindClass(STS_APPLICATION_CONTEXT_CLASS_NAME, &applicationContextCls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "FindClass ApplicationContext failed status: %{public}d", status); + return; + } + BindApplicationContextFunc(aniEnv, applicationContextCls); + ani_method contextCtorMethod = nullptr; + if ((status = aniEnv->Class_FindMethod(applicationContextCls, "", ":V", &contextCtorMethod)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_FindMethod ctor failed status: %{public}d", status); + return; + } + ani_object applicationContextObject = nullptr; + if ((status = aniEnv->Object_New(applicationContextCls, contextCtorMethod, &applicationContextObject)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_New failed status: %{public}d", status); + return; + } + ani_field contextField; + if ((status = aniEnv->Class_FindField(applicationContextCls, "nativeContext", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_FindField failed status: %{public}d", status); + return; + } + auto workContext = new (std::nothrow) std::weak_ptr(applicationContext); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "workContext nullptr"); + return; + } + ani_long nativeContextLong = (ani_long)workContext; + if ((status = aniEnv->Object_SetField_Long(applicationContextObject, contextField, nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_SetField_Long failed status: %{public}d", status); + delete workContext; + return; + } + SetAndBindApplicationObject(aniEnv, applicationContextObject, applicationContext); +} + +void EtsApplicationContextUtils::SetAndBindApplicationObject(ani_env* aniEnv, ani_object applicationContextObject, + std::shared_ptr applicationContext) +{ + ani_status status = ANI_ERROR; + ani_ref applicationContextObjectRef = nullptr; + if ((status = aniEnv->GlobalReference_Create(applicationContextObject, &applicationContextObjectRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "GlobalReference_Create failed status: %{public}d", status); + return; + } + auto stsReference = std::make_shared(); + stsReference->aniObj = applicationContextObject; + AbilityRuntime::ApplicationContextManager::GetApplicationContextManager().SetEtsGlobalObject(stsReference); + applicationContext->SetApplicationCtxObjRef(applicationContextObjectRef); + ani_ref* contextGlobalRef = new (std::nothrow) ani_ref; + if ((status = aniEnv->GlobalReference_Create(applicationContextObject, contextGlobalRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + delete contextGlobalRef; + return; + } + applicationContext->Bind(contextGlobalRef); +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/appkit/ability_runtime/context/ets_application_state_change_callback.cpp b/frameworks/native/appkit/ability_runtime/context/ets_application_state_change_callback.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e6e693a18eb53459abdd84c6b684b2097a0a2992 --- /dev/null +++ b/frameworks/native/appkit/ability_runtime/context/ets_application_state_change_callback.cpp @@ -0,0 +1,130 @@ +/* + * 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 "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_env *env) + : env_(env) +{ +} + +void EtsApplicationStateChangeCallback::CallEtsMethod(const std::string &methodName) +{ + TAG_LOGD(AAFwkTag::APPKIT, "MethodName = %{public}s", methodName.c_str()); + if (env_ == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + ani_class cls {}; + ani_status status = env_->FindClass(APPLICATION_STATE_CHANGE_CALLBACK, &cls); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "FindClass status: %{public}d", status); + 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); + 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); + } + } +} + +void EtsApplicationStateChangeCallback::NotifyApplicationForeground() +{ + CallEtsMethod("onApplicationForeground"); +} + +void EtsApplicationStateChangeCallback::NotifyApplicationBackground() +{ + CallEtsMethod("onApplicationBackground"); +} + +void EtsApplicationStateChangeCallback::Register(ani_object aniCallback) +{ + if (env_ == nullptr || aniCallback == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env or aniCallback"); + return; + } + ani_ref aniCallbackRef = nullptr; + ani_status status = ANI_ERROR; + if ((status = env_->GlobalReference_Create(aniCallback, &aniCallbackRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "GlobalReference_Create status : %{public}d", status); + return; + } + std::lock_guard lock(mutex_); + callbacks_.emplace(aniCallbackRef); +} + +bool EtsApplicationStateChangeCallback::UnRegister(ani_object aniCallback) +{ + ani_status status = ANI_ERROR; + std::lock_guard lock(mutex_); + if (env_ == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + 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(); + 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); + return false; + } + return callbacks_.erase(callback) == 1; + } + } + return false; +} + +bool EtsApplicationStateChangeCallback::IsEmpty() const +{ + std::lock_guard lock(mutex_); + return callbacks_.empty(); +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/appkit/ability_runtime/context/ets_enviroment_callback.cpp b/frameworks/native/appkit/ability_runtime/context/ets_enviroment_callback.cpp new file mode 100644 index 0000000000000000000000000000000000000000..64e1e00815623905fe05939a42c7d0bff939d371 --- /dev/null +++ b/frameworks/native/appkit/ability_runtime/context/ets_enviroment_callback.cpp @@ -0,0 +1,146 @@ +/* + * 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_env *env) + : env_(env) {} + +int32_t EtsEnviromentCallback::Register(ani_object aniCallback) +{ + if (env_ == nullptr) { + return -1; + } + int32_t callbackId = serialNumber_; + if (serialNumber_ < INT32_MAX) { + serialNumber_++; + } else { + serialNumber_ = 0; + } + ani_ref aniCallbackRef = nullptr; + env_->GlobalReference_Create(aniCallback, &aniCallbackRef); + + std::lock_guard lock(Mutex_); + enviromentAniCallbacks_.emplace(callbackId, aniCallbackRef); + 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; + } + TAG_LOGD(AAFwkTag::APPKIT, "callbacks_.callbackId: %{public}d", it->first); + return enviromentAniCallbacks_.erase(callbackId) == 1; +} + +void EtsEnviromentCallback::OnMemoryLevel(const int level) +{ + TAG_LOGD(AAFwkTag::APPKIT, "OnMemoryLevel Call"); + if (env_ == nullptr || enviromentAniCallbacks_.empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "null aniEnv"); + 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); + 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); + return; + } + ani_enum_item memoryLevel {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvertNativeToSts(env_, + APPLICATION_MEMORYLEVEL_ENUM, (AppExecFwk::MemoryLevel)level, memoryLevel); + if (memoryLevel == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "create memoryLevel failed"); + 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"); + 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); + } + } +} + +void EtsEnviromentCallback::OnConfigurationUpdated(const AppExecFwk::Configuration &config) +{ + TAG_LOGD(AAFwkTag::APPKIT, "OnConfigurationUpdated Call"); + if (env_ == nullptr || enviromentAniCallbacks_.empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "null aniEnv"); + 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); + 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); + return; + } + ani_object configObj = OHOS::AppExecFwk::WrapConfiguration(env_, config); + if (configObj == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "create configObj failed"); + 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"); + 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); + } + } +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/appkit/ability_runtime/context/sts_context_utils.cpp b/frameworks/native/appkit/ability_runtime/context/sts_context_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf43a59c81015ff2808d4d2cd40392e3841a54fa --- /dev/null +++ b/frameworks/native/appkit/ability_runtime/context/sts_context_utils.cpp @@ -0,0 +1,348 @@ +/* + * 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 "sts_context_utils.h" + +#include "ani_common_util.h" +#include "ani_enum_convert.h" +#include "application_context.h" +#include "application_context_manager.h" +#include "common_fun_ani.h" +#include "hilog_tag_wrapper.h" +#include "resourceManager.h" +#include "sts_error_utils.h" +#include "ani_common_util.h" +#include "ability_runtime_error_util.h" +#include "tokenid_kit.h" +#include "ipc_skeleton.h" +#include "js_runtime.h" +#include "js_runtime_utils.h" +#include "js_context_utils.h" +#include "native_engine/native_engine.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace ContextUtil { +namespace { +constexpr const char* AREA_MODE_ENUM_NAME = "L@ohos/app/ability/contextConstant/contextConstant/AreaMode;"; + +void BindContextDir(ani_env *aniEnv, ani_object contextObj, std::shared_ptr context) +{ + if (aniEnv == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "aniEnv or context is nullptr"); + return; + } + ani_status status = ANI_ERROR; + auto preferencesDir = context->GetPreferencesDir(); + ani_string preferencesDirString = nullptr; + aniEnv->String_NewUTF8(preferencesDir.c_str(), preferencesDir.size(), &preferencesDirString); + if ((status = aniEnv->Object_SetFieldByName_Ref(contextObj, "preferencesDir", preferencesDirString)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "preferencesDir SetField status: %{public}d", status); + return; + } + + auto databaseDir = context->GetDatabaseDir(); + ani_string databaseDirString = nullptr; + aniEnv->String_NewUTF8(databaseDir.c_str(), databaseDir.size(), &databaseDirString); + if ((status = aniEnv->Object_SetFieldByName_Ref(contextObj, "databaseDir", databaseDirString)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "databaseDir SetField status: %{public}d", status); + return; + } + + auto cacheDir = context->GetCacheDir(); + ani_string cacheDirString = nullptr; + aniEnv->String_NewUTF8(cacheDir.c_str(), cacheDir.size(), &cacheDirString); + if ((status = aniEnv->Object_SetFieldByName_Ref(contextObj, "cacheDir", cacheDirString)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "cacheDir SetField status: %{public}d", status); + return; + } + + auto filesDir = context->GetFilesDir(); + ani_string filesDirString = nullptr; + aniEnv->String_NewUTF8(filesDir.c_str(), filesDir.size(), &filesDirString); + if ((status = aniEnv->Object_SetFieldByName_Ref(contextObj, "filesDir", filesDirString)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "filesDir SetField status: %{public}d", status); + return; + } + + auto tempDir = context->GetTempDir(); + ani_string tempDirString = nullptr; + aniEnv->String_NewUTF8(tempDir.c_str(), tempDir.size(), &tempDirString); + if ((status = aniEnv->Object_SetFieldByName_Ref(contextObj, "tempDir", tempDirString)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "tempDir SetField status: %{public}d", status); + return; + } +} +} // namespace + +static std::weak_ptr context_; +void BindApplicationCtx(ani_env* aniEnv, ani_class contextClass, ani_object contextObj) +{ + // bind parent context field:applicationContext + ani_field applicationContextField; + if (aniEnv->Class_FindField(contextClass, "applicationContext", &applicationContextField) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_FindField failed"); + return; + } + auto appContextObj = ApplicationContextManager::GetApplicationContextManager().GetEtsGlobalObject(); + if (appContextObj == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "appContextObj is nullptr"); + return; + } + + if (aniEnv->Object_SetField_Ref(contextObj, applicationContextField, appContextObj->aniRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_SetField_Ref failed"); + return; + } +} + +void BindApplicationInfo(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context) +{ + ani_field applicationInfoField; + if (ANI_OK != aniEnv->Class_FindField(contextClass, "applicationInfo", &applicationInfoField)) { + TAG_LOGE(AAFwkTag::APPKIT, "find applicationInfo failed"); + return; + } + auto appInfo = context->GetApplicationInfo(); + ani_object appInfoObj = AppExecFwk::CommonFunAni::ConvertApplicationInfo(aniEnv, *appInfo); + if (aniEnv->Object_SetField_Ref(contextObj, applicationInfoField, + reinterpret_cast(appInfoObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_SetField_Ref failed"); + return; + } +} + +void BindResourceManager(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context) +{ + ani_field resourceManagerField; + if (ANI_OK != aniEnv->Class_FindField(contextClass, "resourceManager", &resourceManagerField)) { + TAG_LOGE(AAFwkTag::APPKIT, "find resourceManager failed"); + return; + } + auto resourceManager = context->GetResourceManager(); + ani_object resourceMgrObj = Global::Resource::ResMgrAddon::CreateResMgr(aniEnv, "", resourceManager, context); + if (aniEnv->Object_SetField_Ref(contextObj, resourceManagerField, + reinterpret_cast(resourceMgrObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_SetField_Ref failed"); + return; + } +} + +void BindParentProperty(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context) +{ + BindApplicationInfo(aniEnv, contextClass, contextObj, context); + BindResourceManager(aniEnv, contextClass, contextObj, context); + BindContextDir(aniEnv, contextObj, context); + + // bind parent context property + ani_field areaField; + ani_status status = ANI_ERROR; + if ((status = aniEnv->Class_FindField(contextClass, "area", &areaField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "find area failed, status: %{public}d", status); + return; + } + auto area = context->GetArea(); + ani_enum_item areaModeItem = nullptr; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvertNativeToSts(aniEnv, AREA_MODE_ENUM_NAME, area, areaModeItem); + + if ((status = aniEnv->Object_SetField_Ref(contextObj, areaField, (ani_ref)areaModeItem)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_SetField_Int failed, status: %{public}d", status); + return; + } +} + +void BindParentPropertyInner(ani_env *aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context) +{ + ani_status status = ANI_ERROR; + ani_field processNameField; + if ((status = aniEnv->Class_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; + } +} + +bool SetHapModuleInfo( + ani_env *env, ani_class cls, ani_object contextObj, const std::shared_ptr &context) +{ + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env or context"); + return false; + } + auto hapModuleInfo = context->GetHapModuleInfo(); + if (hapModuleInfo == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "hapModuleInfo is nullptr"); + return false; + } + ani_ref hapModuleInfoRef = AppExecFwk::CommonFunAni::ConvertHapModuleInfo(env, *hapModuleInfo); + if (hapModuleInfoRef == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "hapModuleInfoRef is nullptr"); + return false; + } + ani_status status = ANI_OK; + status = env->Object_SetPropertyByName_Ref(contextObj, "currentHapModuleInfo", hapModuleInfoRef); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_SetPropertyByName_Ref failed, status: %{public}d", status); + return false; + } + return true; +} + +void StsCreatContext(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, std::shared_ptr context) +{ + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "aniEnv is nullptr"); + return; + } + BindApplicationCtx(aniEnv, contextClass, contextObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "context is nullptr"); + return; + } + if (!SetHapModuleInfo(aniEnv, contextClass, contextObj, context)) { + TAG_LOGE(AAFwkTag::APPKIT, "SetHapModuleInfo fail"); + return; + } + context_ = context; + BindParentProperty(aniEnv, contextClass, contextObj, context); +} + +bool CheckCallerIsSystemApp() +{ + auto selfToken = IPCSkeleton::GetSelfTokenID(); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { + return false; + } + return true; +} + +ani_object CreateModuleResourceManagerSync([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_string bundleName, ani_string moduleName) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "env is nullptr"); + return {}; + } + std::string bundleName_ = ""; + AppExecFwk::AniStringToStdString(env, bundleName, bundleName_); + std::string moduleName_ = ""; + AppExecFwk::AniStringToStdString(env, moduleName, moduleName_); + auto context = context_.lock(); + if (!context) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return {}; + } + if (!CheckCallerIsSystemApp()) { + TAG_LOGE(AAFwkTag::APPKIT, "not system-app"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP); + return {}; + } + auto resourceManager = context->CreateModuleResourceManager(bundleName_, moduleName_); + if (resourceManager == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null resourceManager"); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return {}; + } + return Global::Resource::ResMgrAddon::CreateResMgr(env, "", resourceManager, context); +} + +ani_object GetApplicationContextSync([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj) +{ + auto appContextObj = ApplicationContextManager::GetApplicationContextManager().GetEtsGlobalObject(); + if (appContextObj != nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "appContextObj is not nullptr"); + return appContextObj->aniObj; + } + ThrowStsInvalidParamError(env, "appContextObj null"); + return {}; +} + +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::AniStringToStdString(env, dataGroupIdObj, dataGroupId)) { + TAG_LOGE(AAFwkTag::APPKIT, "Parse groupId failed"); + AppExecFwk::AsyncCallback(env, callBackObj, CreateStsError(env, + AbilityErrorCode::ERROR_CODE_INVALID_PARAM), nullptr); + ThrowStsInvalidParamError(env, "Parse param groupId failed, groupId must be string."); + return; + } + auto context = context_.lock(); + if (!context) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + AppExecFwk::AsyncCallback(env, callBackObj, CreateStsError(env, + AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT), nullptr); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return; + } + ErrCode ret = ERR_OK; + std::string path = context->GetGroupDir(dataGroupId); + ani_object errorObject = CreateStsError(env, static_cast(ret)); + ani_string aniPath = AppExecFwk::GetAniString(env, path); + AppExecFwk::AsyncCallback(env, callBackObj, errorObject, aniPath); +} + +void SwitchArea(ani_env *env, ani_object obj, ani_enum_item areaModeItem) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + } + int32_t areaMode = 0; + if (!AAFwk::AniEnumConvertUtil::EnumConvertStsToNative(env, areaModeItem, areaMode)) { + TAG_LOGE(AAFwkTag::APPKIT, "Parse area failed"); + return; + } + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + return; + } + context->SwitchArea(areaMode); + BindContextDir(env, obj, context); +} + +ani_enum_item GetArea(ani_env *env) +{ + ani_enum_item areaModeItem = nullptr; + auto context = context_.lock(); + if (env == nullptr || context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "env or context is null"); + return areaModeItem; + } + int32_t areaMode = static_cast(context->GetArea()); + OHOS::AAFwk::AniEnumConvertUtil::EnumConvertNativeToSts(env, AREA_MODE_ENUM_NAME, areaMode, areaModeItem); + return areaModeItem; +} +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/appkit/app/application_data_manager.cpp b/frameworks/native/appkit/app/application_data_manager.cpp index 6dfd3a4493efb0896184c21819410ade2e088f11..6e1b282e84d2bd85122458f5e38552cff4bb288d 100644 --- a/frameworks/native/appkit/app/application_data_manager.cpp +++ b/frameworks/native/appkit/app/application_data_manager.cpp @@ -59,6 +59,15 @@ bool ApplicationDataManager::NotifyCJUnhandledException(const std::string &errMs return AppRecovery::GetInstance().TryRecoverApp(StateReason::CJ_ERROR); } +bool ApplicationDataManager::NotifySTSUnhandledException(const std::string &errMsg) +{ + if (errorObserver_) { + errorObserver_->OnUnhandledException(errMsg); + return true; + } + return AppRecovery::GetInstance().TryRecoverApp(StateReason::STS_ERROR); +} + void ApplicationDataManager::RemoveErrorObserver() { errorObserver_ = nullptr; @@ -88,5 +97,15 @@ bool ApplicationDataManager::NotifyCJExceptionObject(const AppExecFwk::ErrorObje // and restart as developer wants return AppRecovery::GetInstance().TryRecoverApp(StateReason::CJ_ERROR); } + +bool ApplicationDataManager::NotifySTSExceptionObject(const AppExecFwk::ErrorObject &errorObj) +{ + TAG_LOGD(AAFwkTag::APPKIT, "Notify Exception error observer come"); + if (errorObserver_) { + errorObserver_->OnExceptionObject(errorObj); + return true; + } + return AppRecovery::GetInstance().TryRecoverApp(StateReason::STS_ERROR); +} } // namespace AppExecFwk } // namespace OHOS diff --git a/frameworks/native/appkit/app/child_main_thread.cpp b/frameworks/native/appkit/app/child_main_thread.cpp index 00de60113af92d284a185ac9792c3f999e888125..1e6f6079714facbbc323943f27dda5c918b34c18 100644 --- a/frameworks/native/appkit/app/child_main_thread.cpp +++ b/frameworks/native/appkit/app/child_main_thread.cpp @@ -288,7 +288,8 @@ void ChildMainThread::InitNativeLib(const BundleInfo &bundleInfo) } AppLibPathMap appLibPaths {}; - GetNativeLibPath(bundleInfo, hspList, appLibPaths); + AppLibPathMap appAbcLibPaths {}; + GetNativeLibPath(bundleInfo, hspList, appLibPaths, appAbcLibPaths); bool isSystemApp = bundleInfo.applicationInfo.isSystemApp; TAG_LOGD(AAFwkTag::APPKIT, "the application isSystemApp: %{public}d", isSystemApp); @@ -418,7 +419,7 @@ void ChildMainThread::UpdateNativeChildLibModuleName(const AppLibPathMap &appLib } void ChildMainThread::GetNativeLibPath(const BundleInfo &bundleInfo, const HspList &hspList, - AppLibPathMap &appLibPaths) + AppLibPathMap &appLibPaths, AppLibPathMap &appAbcLibPaths) { std::string nativeLibraryPath = bundleInfo.applicationInfo.nativeLibraryPath; if (!nativeLibraryPath.empty()) { @@ -429,19 +430,21 @@ void ChildMainThread::GetNativeLibPath(const BundleInfo &bundleInfo, const HspLi libPath += (libPath.back() == '/') ? nativeLibraryPath : "/" + nativeLibraryPath; TAG_LOGI(AAFwkTag::APPKIT, "napi lib path = %{private}s", libPath.c_str()); appLibPaths["default"].emplace_back(libPath); + appAbcLibPaths["default"].emplace_back(libPath); } for (auto &hapInfo : bundleInfo.hapModuleInfos) { TAG_LOGD(AAFwkTag::APPKIT, "moduleName: %{public}s, isLibIsolated: %{public}d, compressNativeLibs: %{public}d", hapInfo.moduleName.c_str(), hapInfo.isLibIsolated, hapInfo.compressNativeLibs); - GetHapSoPath(hapInfo, appLibPaths, hapInfo.hapPath.find(ABS_CODE_PATH)); + GetHapSoPath(hapInfo, appLibPaths, hapInfo.hapPath.find(ABS_CODE_PATH), appAbcLibPaths); } for (auto &hspInfo : hspList) { TAG_LOGD(AAFwkTag::APPKIT, "bundle:%s, module:%s, nativeLibraryPath:%s", hspInfo.bundleName.c_str(), hspInfo.moduleName.c_str(), hspInfo.nativeLibraryPath.c_str()); - GetHspNativeLibPath(hspInfo, appLibPaths, hspInfo.hapPath.find(ABS_CODE_PATH) != 0u); + GetHspNativeLibPath(hspInfo, appLibPaths, hspInfo.hapPath.find(ABS_CODE_PATH) != 0u, + bundleInfo.applicationInfo.bundleName, appAbcLibPaths); } } } // namespace AppExecFwk diff --git a/frameworks/native/appkit/app/dump_runtime_helper.cpp b/frameworks/native/appkit/app/dump_runtime_helper.cpp index cae296ed5745e0d76f83c40e0bd4c2b7e8f512b7..0e72373b50bf19f4874617dd860a8b9ece120223 100644 --- a/frameworks/native/appkit/app/dump_runtime_helper.cpp +++ b/frameworks/native/appkit/app/dump_runtime_helper.cpp @@ -39,7 +39,7 @@ void DumpRuntimeHelper::SetAppFreezeFilterCallback() TAG_LOGE(AAFwkTag::APPKIT, "null application"); return; } - auto& runtime = application_->GetRuntime(); + auto& runtime = application_->GetRuntime(AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_0); if (runtime == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); return; @@ -62,7 +62,7 @@ void DumpRuntimeHelper::DumpJsHeap(const OHOS::AppExecFwk::JsHeapDumpInfo &info) TAG_LOGE(AAFwkTag::APPKIT, "null application"); return; } - auto& runtime = application_->GetRuntime(); + auto& runtime = application_->GetRuntime(AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_0); if (runtime == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); return; diff --git a/frameworks/native/appkit/app/main_thread.cpp b/frameworks/native/appkit/app/main_thread.cpp index 65f4d37271340af64301106fabc08dbb7f1f5f86..4019f66addc70dca5108c4a88379eb5d86140b86 100644 --- a/frameworks/native/appkit/app/main_thread.cpp +++ b/frameworks/native/appkit/app/main_thread.cpp @@ -74,6 +74,7 @@ #include "if_system_ability_manager.h" #include "iservice_registry.h" #include "js_runtime.h" +#include "sts_runtime.h" #ifdef CJ_FRONTEND #include "cj_runtime.h" #endif @@ -85,6 +86,7 @@ #include "res_helper.h" #include "resource_manager.h" #include "runtime.h" +#include "sts_app_manager.h" #include "sys_mgr_client.h" #include "system_ability_definition.h" #include "task_handler_client.h" @@ -136,6 +138,7 @@ constexpr int32_t START_HIGH_SENSITIVE = 1; constexpr int32_t EXIT_HIGH_SENSITIVE = 2; constexpr int32_t UNSPECIFIED_USERID = -2; constexpr int32_t JS_ERROR_EXIT = -2; +constexpr int32_t STS_ERROR_EXIT = -3; constexpr int32_t TIME_OUT = 120; constexpr int32_t DEFAULT_SLEEP_TIME = 100000; @@ -161,6 +164,7 @@ constexpr char EVENT_KEY_APP_RUNING_UNIQUE_ID[] = "APP_RUNNING_UNIQUE_ID"; constexpr char DEVELOPER_MODE_STATE[] = "const.security.developermode.state"; constexpr char PRODUCT_ASSERT_FAULT_DIALOG_ENABLED[] = "persisit.sys.abilityms.support_assert_fault_dialog"; constexpr char KILL_REASON[] = "Kill Reason:Js Error"; +constexpr char STS_KILL_REASON[] = "Kill Reason:Sts Error"; const int32_t JSCRASH_TYPE = 3; const std::string JSVM_TYPE = "ARK"; @@ -196,7 +200,8 @@ constexpr int32_t PRELOAD_TASK_DELAY_TIME = 2000; //millisecond extern "C" int DFX_SetAppRunningUniqueId(const char* appRunningId, size_t len) __attribute__((weak)); } // namespace -void MainThread::GetNativeLibPath(const BundleInfo &bundleInfo, const HspList &hspList, AppLibPathMap &appLibPaths) +void MainThread::GetNativeLibPath(const BundleInfo &bundleInfo, const HspList &hspList, AppLibPathMap &appLibPaths, + AppLibPathMap &appAbcLibPaths) { std::string patchNativeLibraryPath = bundleInfo.applicationInfo.appQuickFix.deployedAppqfInfo.nativeLibraryPath; if (!patchNativeLibraryPath.empty()) { @@ -205,6 +210,7 @@ void MainThread::GetNativeLibPath(const BundleInfo &bundleInfo, const HspList &h patchLibPath += (patchLibPath.back() == '/') ? patchNativeLibraryPath : "/" + patchNativeLibraryPath; TAG_LOGD(AAFwkTag::APPKIT, "lib path = %{private}s", patchLibPath.c_str()); appLibPaths["default"].emplace_back(patchLibPath); + appAbcLibPaths["default"].emplace_back(patchLibPath); } std::string nativeLibraryPath = bundleInfo.applicationInfo.nativeLibraryPath; @@ -216,6 +222,7 @@ void MainThread::GetNativeLibPath(const BundleInfo &bundleInfo, const HspList &h libPath += (libPath.back() == '/') ? nativeLibraryPath : "/" + nativeLibraryPath; TAG_LOGD(AAFwkTag::APPKIT, "lib path = %{private}s", libPath.c_str()); appLibPaths["default"].emplace_back(libPath); + appAbcLibPaths["default"].emplace_back(libPath); } else { TAG_LOGI(AAFwkTag::APPKIT, "nativeLibraryPath is empty"); } @@ -224,14 +231,15 @@ void MainThread::GetNativeLibPath(const BundleInfo &bundleInfo, const HspList &h TAG_LOGD(AAFwkTag::APPKIT, "moduleName: %{public}s, isLibIsolated: %{public}d, compressNativeLibs: %{public}d.", hapInfo.moduleName.c_str(), hapInfo.isLibIsolated, hapInfo.compressNativeLibs); - GetPatchNativeLibPath(hapInfo, patchNativeLibraryPath, appLibPaths); - GetHapSoPath(hapInfo, appLibPaths, hapInfo.hapPath.find(ABS_CODE_PATH)); + GetPatchNativeLibPath(hapInfo, patchNativeLibraryPath, appLibPaths, appAbcLibPaths); + GetHapSoPath(hapInfo, appLibPaths, hapInfo.hapPath.find(ABS_CODE_PATH), appAbcLibPaths); } for (auto &hspInfo : hspList) { TAG_LOGD(AAFwkTag::APPKIT, "bundle:%s, module:%s, nativeLibraryPath:%s", hspInfo.bundleName.c_str(), hspInfo.moduleName.c_str(), hspInfo.nativeLibraryPath.c_str()); - GetHspNativeLibPath(hspInfo, appLibPaths, hspInfo.hapPath.find(ABS_CODE_PATH) != 0u); + GetHspNativeLibPath(hspInfo, appLibPaths, hspInfo.hapPath.find(ABS_CODE_PATH) != 0u, + bundleInfo.applicationInfo.bundleName, appAbcLibPaths); } } @@ -1305,6 +1313,119 @@ CJUncaughtExceptionInfo MainThread::CreateCjExceptionInfo(const std::string &bun return uncaughtExceptionInfo; } #endif +JsEnv::UncaughtExceptionInfo MainThread::CreateJsExceptionInfo(const std::string& bundleName, uint32_t versionCode, + const std::string& hapPath, std::string& appRunningId, int32_t pid, std::string& processName) +{ + JsEnv::UncaughtExceptionInfo uncaughtExceptionInfo; + uncaughtExceptionInfo.hapPath = hapPath; + wptr weak = this; + uncaughtExceptionInfo.uncaughtTask = [weak, bundleName, versionCode, appRunningId = std::move(appRunningId), pid, + processName](std::string summary, const JsEnv::ErrorObject errorObj) { + auto appThread = weak.promote(); + if (appThread == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null appThread"); + return; + } + time_t timet; + time(&timet); + HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::AAFWK, "JS_ERROR", + OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, EVENT_KEY_PACKAGE_NAME, bundleName, EVENT_KEY_VERSION, + std::to_string(versionCode), EVENT_KEY_TYPE, JSCRASH_TYPE, EVENT_KEY_HAPPEN_TIME, timet, EVENT_KEY_REASON, + errorObj.name, EVENT_KEY_JSVM, JSVM_TYPE, EVENT_KEY_SUMMARY, summary, EVENT_KEY_PNAME, processName, + EVENT_KEY_APP_RUNING_UNIQUE_ID, appRunningId); + ErrorObject appExecErrorObj = { .name = errorObj.name, .message = errorObj.message, .stack = errorObj.stack }; + FaultData faultData; + faultData.faultType = FaultDataType::JS_ERROR; + faultData.errorObject = appExecErrorObj; + DelayedSingleton::GetInstance()->NotifyAppFault(faultData); + auto napiEnv = (static_cast( + *appThread->application_->GetRuntime(AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_0))) + .GetNapiEnv(); + if (NapiErrorManager::GetInstance()->NotifyUncaughtException( + napiEnv, summary, appExecErrorObj.name, appExecErrorObj.message, appExecErrorObj.stack)) { + return; + } + if (ApplicationDataManager::GetInstance().NotifyUnhandledException(summary) && + ApplicationDataManager::GetInstance().NotifyExceptionObject(appExecErrorObj)) { + return; + } + TAG_LOGE(AAFwkTag::APPKIT, + "\n%{public}s is about to exit due to RuntimeError\nError " + "type:%{public}s\n%{public}s", + bundleName.c_str(), errorObj.name.c_str(), summary.c_str()); + bool foreground = false; + if (appThread->applicationImpl_ && + appThread->applicationImpl_->GetState() == ApplicationImpl::APP_STATE_FOREGROUND) { + foreground = true; + } + int result = HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::FRAMEWORK, "PROCESS_KILL", + HiviewDFX::HiSysEvent::EventType::FAULT, "PID", pid, "PROCESS_NAME", processName, "MSG", KILL_REASON, + "FOREGROUND", foreground); + TAG_LOGW(AAFwkTag::APPKIT, + "hisysevent write result=%{public}d, send event " + "[FRAMEWORK,PROCESS_KILL]," + " pid=%{public}d, processName=%{public}s, msg=%{public}s, " + "foreground=%{public}d", + result, pid, processName.c_str(), KILL_REASON, foreground); + AAFwk::ExitReason exitReason = { REASON_JS_ERROR, errorObj.name }; + AbilityManagerClient::GetInstance()->RecordAppExitReason(exitReason); + _exit(JS_ERROR_EXIT); + }; + return uncaughtExceptionInfo; +} + +StsEnv::STSUncaughtExceptionInfo MainThread::CreateStsExceptionInfo(const std::string& bundleName, uint32_t versionCode, + const std::string& hapPath, std::string& appRunningId, int32_t pid, std::string& processName) +{ + StsEnv::STSUncaughtExceptionInfo uncaughtExceptionInfo; + wptr weak = this; + uncaughtExceptionInfo.uncaughtTask = [weak, bundleName, versionCode, appRunningId = std::move(appRunningId), pid, + processName](std::string summary, const StsEnv::STSErrorObject errorObj) { + auto appThread = weak.promote(); + if (appThread == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null appThread"); + return; + } + time_t timet; + time(&timet); + HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::AAFWK, "STS_ERROR", + OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, EVENT_KEY_PACKAGE_NAME, bundleName, EVENT_KEY_VERSION, + std::to_string(versionCode), EVENT_KEY_TYPE, JSCRASH_TYPE, EVENT_KEY_HAPPEN_TIME, timet, EVENT_KEY_REASON, + errorObj.name, EVENT_KEY_JSVM, JSVM_TYPE, EVENT_KEY_SUMMARY, summary, EVENT_KEY_PNAME, processName, + EVENT_KEY_APP_RUNING_UNIQUE_ID, appRunningId); + ErrorObject appExecErrorObj = { .name = errorObj.name, .message = errorObj.message, .stack = errorObj.stack }; + FaultData faultData; + faultData.faultType = FaultDataType::STS_ERROR; + faultData.errorObject = appExecErrorObj; + DelayedSingleton::GetInstance()->NotifyAppFault(faultData); + if (ApplicationDataManager::GetInstance().NotifySTSUnhandledException(summary) && + ApplicationDataManager::GetInstance().NotifySTSExceptionObject(appExecErrorObj)) { + return; + } + TAG_LOGE(AAFwkTag::APPKIT, + "\n%{public}s is about to exit due to RuntimeError\nError " + "type:%{public}s\n%{public}s", + bundleName.c_str(), errorObj.name.c_str(), summary.c_str()); + bool foreground = false; + if (appThread->applicationImpl_ && + appThread->applicationImpl_->GetState() == ApplicationImpl::APP_STATE_FOREGROUND) { + foreground = true; + } + int result = HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::FRAMEWORK, "PROCESS_KILL", + HiviewDFX::HiSysEvent::EventType::FAULT, "PID", pid, "PROCESS_NAME", processName, "MSG", STS_KILL_REASON, + "FOREGROUND", foreground); + TAG_LOGW(AAFwkTag::APPKIT, + "hisysevent write result=%{public}d, send event " + "[FRAMEWORK,PROCESS_KILL]," + " pid=%{public}d, processName=%{public}s, msg=%{public}s, " + "foreground=%{public}d", + result, pid, processName.c_str(), STS_KILL_REASON, foreground); + AAFwk::ExitReason exitReason = { REASON_STS_ERROR, errorObj.name }; + AbilityManagerClient::GetInstance()->RecordAppExitReason(exitReason); + _exit(STS_ERROR_EXIT); + }; + return uncaughtExceptionInfo; +} /** * * @brief Launch the application. @@ -1462,7 +1583,8 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con } AppLibPathMap appLibPaths {}; - GetNativeLibPath(bundleInfo, hspList, appLibPaths); + AppLibPathMap appAbcLibPaths {}; + GetNativeLibPath(bundleInfo, hspList, appLibPaths, appAbcLibPaths); bool isSystemApp = bundleInfo.applicationInfo.isSystemApp; TAG_LOGD(AAFwkTag::APPKIT, "the application isSystemApp: %{public}d", isSystemApp); #ifdef CJ_FRONTEND @@ -1478,6 +1600,7 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con } else { #endif AbilityRuntime::JsRuntime::SetAppLibPath(appLibPaths, isSystemApp); + AbilityRuntime::STSRuntime::SetAppLibPath(appLibPaths, appAbcLibPaths); #ifdef CJ_FRONTEND } #endif @@ -1501,8 +1624,16 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con options.uid = bundleInfo.applicationInfo.uid; options.apiTargetVersion = appInfo.apiTargetVersion; options.pkgContextInfoJsonStringMap = pkgContextInfoJsonStringMap; + options.isStartWithDebug = appLaunchData.GetDebugApp(); #ifdef CJ_FRONTEND - options.lang = isCJApp ? AbilityRuntime::Runtime::Language::CJ : AbilityRuntime::Runtime::Language::JS; + if (isCJApp) { + options.langs.emplace(AbilityRuntime::Runtime::Language::CJ, true); + application_->SetCJApplication(true); + } else { + AddRuntimeLang(appInfo, options); + } +#else + AddRuntimeLang(appInfo, options); #endif if (applicationInfo_->appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG) { TAG_LOGD(AAFwkTag::APPKIT, "multi-thread mode: %{public}d", appLaunchData.GetMultiThread()); @@ -1527,12 +1658,13 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con static_cast(hapModuleInfo.aotCompileStatus); } } - auto runtime = AbilityRuntime::Runtime::Create(options); - if (!runtime) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + std::vector> runtimes = AbilityRuntime::Runtime::CreateRuntimes(options); + + if (runtimes.empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "runtimes empty"); return; } - + // need vm support if (appInfo.debug && appLaunchData.GetDebugApp()) { wptr weak = this; auto cb = [weak]() { @@ -1543,7 +1675,15 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con } return appThread->NotifyDeviceDisConnect(); }; - runtime->SetDeviceDisconnectCallback(cb); + for (const auto& runtime : runtimes) { + runtime->SetDeviceDisconnectCallback(cb); + } + } + // need vm support + if (appLaunchData.IsNeedPreloadModule()) { + for (auto &runtime : application_->GetRuntime()) { + PreloadModule(entryHapModuleInfo, runtime); + } } auto perfCmd = appLaunchData.GetPerfCmd(); @@ -1554,12 +1694,15 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con processName = processInfo_->GetProcessName(); TAG_LOGD(AAFwkTag::APPKIT, "pid is %{public}d, processName is %{public}s", pid, processName.c_str()); } - runtime->SetStopPreloadSoCallback([uid = bundleInfo.applicationInfo.uid, currentPid = pid, - bundleName = appInfo.bundleName]()-> void { - TAG_LOGD(AAFwkTag::APPKIT, "runtime callback and report load abc completed info to rss."); - ResHelper::ReportLoadAbcCompletedInfoToRss(uid, currentPid, bundleName); - }); + for (auto &runtime : application_->GetRuntime()) { + runtime->SetStopPreloadSoCallback([uid = bundleInfo.applicationInfo.uid, currentPid = pid, + bundleName = appInfo.bundleName]()-> void { + TAG_LOGD(AAFwkTag::APPKIT, "runtime callback and report load abc completed info to rss."); + ResHelper::ReportLoadAbcCompletedInfoToRss(uid, currentPid, bundleName); + }); + } AbilityRuntime::Runtime::DebugOption debugOption; + debugOption.codeLanguage = appInfo.codeLanguage; debugOption.isStartWithDebug = appLaunchData.GetDebugApp(); debugOption.processName = processName; debugOption.isDebugApp = appInfo.debug; @@ -1568,13 +1711,19 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con debugOption.isDebugFromLocal = appLaunchData.GetDebugFromLocal(); debugOption.perfCmd = perfCmd; debugOption.isDeveloperMode = isDeveloperMode_; - runtime->SetDebugOption(debugOption); + for (auto &runtime : application_->GetRuntime()) { + runtime->SetDebugOption(debugOption); + } if (perfCmd.find(PERFCMD_PROFILE) != std::string::npos || perfCmd.find(PERFCMD_DUMPHEAP) != std::string::npos) { TAG_LOGD(AAFwkTag::APPKIT, "perfCmd is %{public}s", perfCmd.c_str()); - runtime->StartProfiler(debugOption); + for (const auto& runtime : runtimes) { + runtime->StartProfiler(debugOption); + } } else { - runtime->StartDebugMode(debugOption); + for (const auto& runtime : runtimes) { + runtime->StartDebugMode(debugOption); + } } std::vector hqfInfos = appInfo.appQuickFix.deployedAppqfInfo.hqfInfos; @@ -1585,83 +1734,39 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con it->moduleName.c_str(), it->hqfFilePath.c_str()); modulePaths.insert(std::make_pair(it->moduleName, it->hqfFilePath)); } - runtime->RegisterQuickFixQueryFunc(modulePaths); + // need vm support + for (const auto& runtime : runtimes) { + runtime->RegisterQuickFixQueryFunc(modulePaths); + } } auto bundleName = appInfo.bundleName; auto versionCode = appInfo.versionCode; -#ifdef CJ_FRONTEND - if (!isCJApp) { -#endif - JsEnv::UncaughtExceptionInfo uncaughtExceptionInfo; - uncaughtExceptionInfo.hapPath = hapPath; - wptr weak = this; - uncaughtExceptionInfo.uncaughtTask = [weak, bundleName, versionCode, appRunningId = std::move(appRunningId), - pid, processName] (std::string summary, const JsEnv::ErrorObject errorObj) { - auto appThread = weak.promote(); - if (appThread == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null appThread"); - return; - } - time_t timet; - time(&timet); - HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::AAFWK, "JS_ERROR", - OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, - EVENT_KEY_PACKAGE_NAME, bundleName, - EVENT_KEY_VERSION, std::to_string(versionCode), - EVENT_KEY_TYPE, JSCRASH_TYPE, - EVENT_KEY_HAPPEN_TIME, timet, - EVENT_KEY_REASON, errorObj.name, - EVENT_KEY_JSVM, JSVM_TYPE, - EVENT_KEY_SUMMARY, summary, - EVENT_KEY_PNAME, processName, - EVENT_KEY_APP_RUNING_UNIQUE_ID, appRunningId); - ErrorObject appExecErrorObj = { - .name = errorObj.name, - .message = errorObj.message, - .stack = errorObj.stack - }; - FaultData faultData; - faultData.faultType = FaultDataType::JS_ERROR; - faultData.errorObject = appExecErrorObj; - DelayedSingleton::GetInstance()->NotifyAppFault(faultData); - auto napiEnv = - (static_cast(*appThread->application_->GetRuntime())).GetNapiEnv(); - if (NapiErrorManager::GetInstance()->NotifyUncaughtException( - napiEnv, summary, appExecErrorObj.name, - appExecErrorObj.message, appExecErrorObj.stack)) { - return; + + for (const auto& runtime : runtimes) { + switch (runtime->GetLanguage()) { + case AbilityRuntime::Runtime::Language::JS: { + auto expectionInfo = + CreateJsExceptionInfo(bundleName, versionCode, hapPath, appRunningId, pid, processName); + runtime->RegisterUncaughtExceptionHandler((void*)&expectionInfo); + break; } - if (ApplicationDataManager::GetInstance().NotifyUnhandledException(summary) && - ApplicationDataManager::GetInstance().NotifyExceptionObject(appExecErrorObj)) { - return; + case AbilityRuntime::Runtime::Language::CJ: { + auto expectionInfo = CreateCjExceptionInfo(bundleName, versionCode, hapPath); + runtime->RegisterUncaughtExceptionHandler((void*)&expectionInfo); + break; } - // if app's callback has been registered, let app decide whether exit or not. - TAG_LOGE(AAFwkTag::APPKIT, - "\n%{public}s is about to exit due to RuntimeError\nError type:%{public}s\n%{public}s", - bundleName.c_str(), errorObj.name.c_str(), summary.c_str()); - bool foreground = false; - if (appThread->applicationImpl_ && appThread->applicationImpl_->GetState() == - ApplicationImpl::APP_STATE_FOREGROUND) { - foreground = true; + case AbilityRuntime::Runtime::Language::STS: { + auto expectionInfo = + CreateStsExceptionInfo(bundleName, versionCode, hapPath, appRunningId, pid, processName); + runtime->RegisterUncaughtExceptionHandler((void*)&expectionInfo); + break; } - int result = HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::FRAMEWORK, "PROCESS_KILL", - HiviewDFX::HiSysEvent::EventType::FAULT, "PID", pid, "PROCESS_NAME", processName, - "MSG", KILL_REASON, "FOREGROUND", foreground); - TAG_LOGW(AAFwkTag::APPKIT, "hisysevent write result=%{public}d, send event [FRAMEWORK,PROCESS_KILL]," - " pid=%{public}d, processName=%{public}s, msg=%{public}s, foreground=%{public}d", result, pid, - processName.c_str(), KILL_REASON, foreground); - AAFwk::ExitReason exitReason = { REASON_JS_ERROR, errorObj.name }; - AbilityManagerClient::GetInstance()->RecordAppExitReason(exitReason); - _exit(JS_ERROR_EXIT); - }; - (static_cast(*runtime)).RegisterUncaughtExceptionHandler(uncaughtExceptionInfo); -#ifdef CJ_FRONTEND - } else { - auto expectionInfo = CreateCjExceptionInfo(bundleName, versionCode, hapPath); - (static_cast(*runtime)).RegisterUncaughtExceptionHandler(expectionInfo); + default: + break; + } } -#endif + wptr weak = this; auto callback = [weak](const AAFwk::ExitReason &exitReason) { auto appThread = weak.promote(); @@ -1673,14 +1778,25 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con }; applicationContext->RegisterProcessSecurityExit(callback); - application_->SetRuntime(std::move(runtime)); - + for (auto& runtime : runtimes) { + application_->AddRuntime(std::move(runtime)); + } + if (appInfo.codeLanguage == AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_2) { + application_->InitAniApplicationContext(); + application_->InitAniContext(); + } std::weak_ptr wpApplication = application_; AbilityLoader::GetInstance().RegisterUIAbility("UIAbility", - [wpApplication]() -> AbilityRuntime::UIAbility* { + [wpApplication](const std::string &language) -> AbilityRuntime::UIAbility* { auto app = wpApplication.lock(); if (app != nullptr) { - return AbilityRuntime::UIAbility::Create(app->GetRuntime()); + if (language == AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_2) { + return AbilityRuntime::UIAbility::Create( + app->GetRuntime(AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_2)); + } else { + return AbilityRuntime::UIAbility::Create( + app->GetRuntime(AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_0)); + } } TAG_LOGE(AAFwkTag::APPKIT, "failed"); return nullptr; @@ -1688,33 +1804,38 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con #ifdef CJ_FRONTEND if (!isCJApp) { #endif - auto& jsEngine = (static_cast(*application_->GetRuntime())).GetNativeEngine(); + auto &runtime = application_->GetRuntime(appInfo.codeLanguage); if (application_ != nullptr) { - LoadAllExtensions(jsEngine); + TAG_LOGE(AAFwkTag::APPKIT, "main_thread bundleName is %{public}s", + appInfo.bundleName.c_str()); + TAG_LOGE(AAFwkTag::APPKIT, "LoadAllExtensions lan:%{public}s", appInfo.codeLanguage.c_str()); + LoadAllExtensions(); } + if (appInfo.codeLanguage == AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_0) { + auto &jsEngine = (static_cast(*runtime)).GetNativeEngine(); + IdleTimeCallback callback = [wpApplication](int32_t idleTime) { + auto app = wpApplication.lock(); + if (app == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null app"); + return; + } + auto& runtime = app->GetRuntime(AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_0); + if (runtime == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + return; + } + auto& nativeEngine = (static_cast(*runtime)).GetNativeEngine(); + nativeEngine.NotifyIdleTime(idleTime); + }; + idleTime_ = std::make_shared(mainHandler_, callback); + idleTime_->Start(); - IdleTimeCallback callback = [wpApplication](int32_t idleTime) { - auto app = wpApplication.lock(); - if (app == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null app"); - return; - } - auto &runtime = app->GetRuntime(); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); - return; - } - auto& nativeEngine = (static_cast(*runtime)).GetNativeEngine(); - nativeEngine.NotifyIdleTime(idleTime); - }; - idleTime_ = std::make_shared(mainHandler_, callback); - idleTime_->Start(); - - IdleNotifyStatusCallback cb = idleTime_->GetIdleNotifyFunc(); - jsEngine.NotifyIdleStatusControl(cb); + IdleNotifyStatusCallback cb = idleTime_->GetIdleNotifyFunc(); + jsEngine.NotifyIdleStatusControl(cb); - auto helper = std::make_shared(application_); - helper->SetAppFreezeFilterCallback(); + auto helper = std::make_shared(application_); + helper->SetAppFreezeFilterCallback(); + } #ifdef CJ_FRONTEND } else { LoadAllExtensions(); @@ -1724,7 +1845,8 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con auto usertestInfo = appLaunchData.GetUserTestInfo(); if (usertestInfo) { - if (!PrepareAbilityDelegator(usertestInfo, isStageBased, entryHapModuleInfo, bundleInfo.targetVersion)) { + if (!PrepareAbilityDelegator(usertestInfo, isStageBased, entryHapModuleInfo, bundleInfo.targetVersion, + appInfo.codeLanguage)) { TAG_LOGE(AAFwkTag::APPKIT, "PrepareAbilityDelegator failed"); return; } @@ -1808,7 +1930,7 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con } #endif if (appLaunchData.IsNeedPreloadModule()) { - PreloadModule(entryHapModuleInfo, application_->GetRuntime()); + PreloadModule(entryHapModuleInfo, application_->GetRuntime(entryHapModuleInfo.codeLanguage)); } } @@ -2162,10 +2284,11 @@ void MainThread::LoadAllExtensions() std::string file = item.extensionLibFile; std::weak_ptr wApp = application_; AbilityLoader::GetInstance().RegisterExtension(item.extensionName, - [wApp, file]() -> AbilityRuntime::Extension* { + [wApp, file](const std::string& language) -> AbilityRuntime::Extension* { auto app = wApp.lock(); if (app != nullptr) { - return AbilityRuntime::ExtensionModuleLoader::GetLoader(file.c_str()).Create(app->GetRuntime()); + return AbilityRuntime::ExtensionModuleLoader::GetLoader(file.c_str()) + .Create(app->GetRuntime(language)); } TAG_LOGE(AAFwkTag::APPKIT, "failed"); return nullptr; @@ -2175,7 +2298,8 @@ void MainThread::LoadAllExtensions() } bool MainThread::PrepareAbilityDelegator(const std::shared_ptr &record, bool isStageBased, - const AppExecFwk::HapModuleInfo &entryHapModuleInfo, uint32_t targetVersion) + const AppExecFwk::HapModuleInfo &entryHapModuleInfo, uint32_t targetVersion, + const std::string &applicationCodeLanguage) { TAG_LOGD(AAFwkTag::APPKIT, "enter, isStageBased = %{public}d", isStageBased); if (!record) { @@ -2185,12 +2309,27 @@ bool MainThread::PrepareAbilityDelegator(const std::shared_ptr & auto args = std::make_shared(record->want); if (isStageBased) { // Stage model TAG_LOGD(AAFwkTag::APPKIT, "Stage model"); - auto testRunner = TestRunner::Create(application_->GetRuntime(), args, false); - auto delegator = IAbilityDelegator::Create(application_->GetRuntime(), application_->GetAppContext(), - std::move(testRunner), record->observer); - AbilityDelegatorRegistry::RegisterInstance(delegator, args); - delegator->SetApiTargetVersion(targetVersion); - delegator->Prepare(); + if (applicationCodeLanguage == AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_0) { + TAG_LOGI(AAFwkTag::DELEGATOR, "create 1.0 testrunner"); + auto& runtime = application_->GetRuntime(AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_0); + auto testRunner = TestRunner::Create(runtime, args, false); + auto delegator = IAbilityDelegator::Create(runtime, application_->GetAppContext(), + std::move(testRunner), record->observer); + AbilityDelegatorRegistry::RegisterInstance(delegator, args, AbilityRuntime::Runtime::Language::JS); + delegator->SetApiTargetVersion(targetVersion); + delegator->Prepare(); + } + + if (applicationCodeLanguage == AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_2) { + TAG_LOGI(AAFwkTag::DELEGATOR, "create 1.2 testrunner"); + auto& runtime = application_->GetRuntime(AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_2); + auto testRunner = TestRunner::Create(runtime, args, false); + auto delegator = IAbilityDelegator::Create(runtime, application_->GetAppContext(), + std::move(testRunner), record->observer); + AbilityDelegatorRegistry::RegisterInstance(delegator, args, AbilityRuntime::Runtime::Language::STS); + delegator->SetApiTargetVersion(targetVersion); + delegator->Prepare(); + } } else { // FA model TAG_LOGD(AAFwkTag::APPKIT, "FA model"); AbilityRuntime::Runtime::Options options; @@ -2208,8 +2347,10 @@ bool MainThread::PrepareAbilityDelegator(const std::shared_ptr & return false; } bool isFaJsModel = entryHapModuleInfo.abilityInfos.front().srcLanguage == "js" ? true : false; - static auto runtime = AbilityRuntime::Runtime::Create(options); - auto testRunner = TestRunner::Create(runtime, args, isFaJsModel); + options.langs.emplace(AbilityRuntime::Runtime::Language::JS, true); // default + static auto runtimes = AbilityRuntime::Runtime::CreateRuntimes(options); + for (const auto& runtime : runtimes) { + auto testRunner = TestRunner::Create(runtime, args, isFaJsModel); if (testRunner == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null testRunner"); return false; @@ -2220,9 +2361,10 @@ bool MainThread::PrepareAbilityDelegator(const std::shared_ptr & } auto delegator = std::make_shared( application_->GetAppContext(), std::move(testRunner), record->observer); - AbilityDelegatorRegistry::RegisterInstance(delegator, args); + AbilityDelegatorRegistry::RegisterInstance(delegator, args, runtime->GetLanguage()); delegator->SetApiTargetVersion(targetVersion); delegator->Prepare(); + } } return true; } @@ -2281,8 +2423,11 @@ void MainThread::HandleLaunchAbility(const std::shared_ptr & TAG_LOGE(AAFwkTag::APPKIT, "null application"); return; } - auto& runtime = application->GetRuntime(); - appThread->UpdateRuntimeModuleChecker(runtime); + // need vm support + auto& runtimes = application->GetRuntime(); + for (const auto& runtime : runtimes) { + appThread->UpdateRuntimeModuleChecker(runtime); + } #ifdef APP_ABILITY_USE_TWO_RUNNER AbilityThread::AbilityThreadMain(application, abilityRecord, stageContext); #else @@ -2308,8 +2453,10 @@ void MainThread::HandleLaunchAbility(const std::shared_ptr & return; } SetProcessExtensionType(abilityRecord); - auto& runtime = application_->GetRuntime(); - UpdateRuntimeModuleChecker(runtime); + auto& runtimes = application_->GetRuntime(); + for (const auto& runtime : runtimes) { + UpdateRuntimeModuleChecker(runtime); + } #ifdef APP_ABILITY_USE_TWO_RUNNER AbilityThread::AbilityThreadMain(application_, abilityRecord, stageContext); #else @@ -2671,12 +2818,14 @@ void MainThread::HandleDumpHeapPrepare() TAG_LOGE(AAFwkTag::APPKIT, "null app"); return; } - auto &runtime = app->GetRuntime(); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + auto& runtimes = app->GetRuntime(); + if (runtimes.empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "runtimes empty"); return; } - runtime->GetHeapPrepare(); + for (const auto& runtime : runtimes) { + runtime->GetHeapPrepare(); + } } void MainThread::HandleDumpHeap(bool isPrivate) @@ -2691,47 +2840,50 @@ void MainThread::HandleDumpHeap(bool isPrivate) TAG_LOGE(AAFwkTag::APPKIT, "null app"); return; } - auto &runtime = app->GetRuntime(); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + auto& runtimes = app->GetRuntime(); + if (runtimes.empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "runtimes empty"); return; } - auto taskFork = [&runtime, &isPrivate] { - TAG_LOGD(AAFwkTag::APPKIT, "HandleDump Heap taskFork start"); - time_t startTime = time(nullptr); - int pid = -1; - if ((pid = fork()) < 0) { - TAG_LOGE(AAFwkTag::APPKIT, "err:%{public}d", errno); - return; - } - if (pid == 0) { - runtime->AllowCrossThreadExecution(); - runtime->DumpHeapSnapshot(isPrivate); - TAG_LOGI(AAFwkTag::APPKIT, "HandleDumpHeap successful, now you can check some file"); - _exit(0); - } - while (true) { - int status = 0; - pid_t p = waitpid(pid, &status, 0); - if (p < 0) { - TAG_LOGE(AAFwkTag::APPKIT, "HandleDumpHeap waitpid return p=%{public}d, err:%{public}d", p, errno); - break; + + for (const auto& runtime : runtimes) { + auto taskFork = [&runtime, &isPrivate] { + TAG_LOGD(AAFwkTag::APPKIT, "HandleDump Heap taskFork start"); + time_t startTime = time(nullptr); + int pid = -1; + if ((pid = fork()) < 0) { + TAG_LOGE(AAFwkTag::APPKIT, "err:%{public}d", errno); + return; } - if (p == pid) { - TAG_LOGE(AAFwkTag::APPKIT, "HandleDumpHeap dump process exited status: %{public}d", status); - break; + if (pid == 0) { + runtime->AllowCrossThreadExecution(); + runtime->DumpHeapSnapshot(isPrivate); + TAG_LOGI(AAFwkTag::APPKIT, "HandleDumpHeap successful, now you can check some file"); + _exit(0); } - if (time(nullptr) > startTime + TIME_OUT) { - TAG_LOGE(AAFwkTag::APPKIT, "time out to wait childprocess, killing forkpid %{public}d", pid); - kill(pid, SIGKILL); - break; + while (true) { + int status = 0; + pid_t p = waitpid(pid, &status, 0); + if (p < 0) { + TAG_LOGE(AAFwkTag::APPKIT, "HandleDumpHeap waitpid return p=%{public}d, err:%{public}d", p, errno); + break; + } + if (p == pid) { + TAG_LOGE(AAFwkTag::APPKIT, "HandleDumpHeap dump process exited status: %{public}d", status); + break; + } + if (time(nullptr) > startTime + TIME_OUT) { + TAG_LOGE(AAFwkTag::APPKIT, "time out to wait childprocess, killing forkpid %{public}d", pid); + kill(pid, SIGKILL); + break; + } + usleep(DEFAULT_SLEEP_TIME); } - usleep(DEFAULT_SLEEP_TIME); - } - }; + }; - ffrt::submit(taskFork, {}, {}, ffrt::task_attr().qos(ffrt::qos_user_initiated)); - runtime->DumpCpuProfile(); + ffrt::submit(taskFork, {}, {}, ffrt::task_attr().qos(ffrt::qos_user_initiated)); + runtime->DumpCpuProfile(); + } } void MainThread::DestroyHeapProfiler() @@ -2744,11 +2896,14 @@ void MainThread::DestroyHeapProfiler() auto task = [] { auto app = applicationForDump_.lock(); - if (app == nullptr || app->GetRuntime() == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + if (app == nullptr || app->GetRuntime().empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "runtimes empty"); return; } - app->GetRuntime()->DestroyHeapProfiler(); + auto& runtimes = app->GetRuntime(); + for (const auto& runtime : runtimes) { + runtime->DestroyHeapProfiler(); + } }; mainHandler_->PostTask(task, "MainThread:DestroyHeapProfiler"); } @@ -2763,11 +2918,14 @@ void MainThread::ForceFullGC() auto task = [] { auto app = applicationForDump_.lock(); - if (app == nullptr || app->GetRuntime() == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + if (app == nullptr || app->GetRuntime().empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "runtimes empty"); return; } - app->GetRuntime()->ForceFullGC(); + auto& runtimes = app->GetRuntime(); + for (const auto& runtime : runtimes) { + runtime->ForceFullGC(); + } }; mainHandler_->PostTask(task, "MainThread:ForceFullGC"); } @@ -3472,16 +3630,18 @@ int32_t MainThread::ChangeAppGcState(int32_t state) TAG_LOGE(AAFwkTag::APPKIT, "null application_"); return ERR_INVALID_VALUE; } - auto &runtime = application_->GetRuntime(); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + auto& runtimes = application_->GetRuntime(); + if (runtimes.empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "runtimes empty"); return ERR_INVALID_VALUE; } - if (runtime->GetLanguage() == AbilityRuntime::Runtime::Language::CJ) { - return NO_ERROR; + + for (const auto& runtime : runtimes) { + if (runtime->GetLanguage() == AbilityRuntime::Runtime::Language::JS) { + auto& nativeEngine = (static_cast(*runtime)).GetNativeEngine(); + nativeEngine.NotifyForceExpandState(state); + } } - auto& nativeEngine = (static_cast(*runtime)).GetNativeEngine(); - nativeEngine.NotifyForceExpandState(state); return NO_ERROR; } @@ -3519,12 +3679,16 @@ int32_t MainThread::OnAttachLocalDebug(bool isDebugFromLocal) TAG_LOGE(AAFwkTag::APPKIT, "null application_"); return ERR_INVALID_VALUE; } - auto &runtime = application_->GetRuntime(); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + + auto& runtimes = application_->GetRuntime(); + if (runtimes.empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "runtimes empty"); return ERR_INVALID_VALUE; } - runtime->StartLocalDebugMode(isDebugFromLocal); + + for (const auto& runtime : runtimes) { + runtime->StartLocalDebugMode(isDebugFromLocal); + } return NO_ERROR; } @@ -3741,12 +3905,25 @@ void MainThread::HandleCacheProcess() // force gc if (application_ != nullptr) { - auto &runtime = application_->GetRuntime(); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + auto& runtimes = application_->GetRuntime(); + if (runtimes.empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "runtimes empty"); return; } - runtime->ForceFullGC(); + for (const auto& runtime : runtimes) { + runtime->ForceFullGC(); + } + } +} + +void MainThread::AddRuntimeLang(ApplicationInfo& appInfo, AbilityRuntime::Runtime::Options& options) +{ + if (appInfo.codeLanguage == AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_2) { + options.langs.emplace(AbilityRuntime::Runtime::Language::STS, true); + } else if (appInfo.codeLanguage == AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_HYBRID) { + options.langs.emplace(AbilityRuntime::Runtime::Language::STS, true); + } else { + options.langs.emplace(AbilityRuntime::Runtime::Language::JS, true); } } } // namespace AppExecFwk diff --git a/frameworks/native/appkit/app/native_lib_util.cpp b/frameworks/native/appkit/app/native_lib_util.cpp index 152562ab11f7eba6fc876e7a0c996eb0e4585624..92935d11bd9c9af57780a8b2e327310bdeb4e209 100644 --- a/frameworks/native/appkit/app/native_lib_util.cpp +++ b/frameworks/native/appkit/app/native_lib_util.cpp @@ -20,6 +20,8 @@ namespace OHOS { namespace AppExecFwk { +constexpr char APP_ABC_LIB_PATH_KEY_PREFIX[] = "/data/storage/el1/bundle/"; +constexpr char APP_ABC_LIB_PATH_KEY_SUFFIX[] = "/ets/modules_static.abc"; std::string GetLibPath(const std::string &hapPath, bool isPreInstallApp) { std::string libPath = AbilityBase::Constants::LOCAL_CODE_PATH; @@ -30,7 +32,8 @@ std::string GetLibPath(const std::string &hapPath, bool isPreInstallApp) return libPath; } -void GetHapSoPath(const HapModuleInfo &hapInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp) +void GetHapSoPath(const HapModuleInfo &hapInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp, + AppLibPathMap &appAbcLibPaths) { if (hapInfo.nativeLibraryPath.empty()) { TAG_LOGD(AAFwkTag::APPKIT, "Lib path of %{public}s is empty, lib isn't isolated or compressed", @@ -49,9 +52,13 @@ void GetHapSoPath(const HapModuleInfo &hapInfo, AppLibPathMap &appLibPaths, bool TAG_LOGD( AAFwkTag::APPKIT, "appLibPathKey: %{private}s, lib path: %{private}s", appLibPathKey.c_str(), libPath.c_str()); appLibPaths[appLibPathKey].emplace_back(libPath); + + std::string appLibAbcPathKey = APP_ABC_LIB_PATH_KEY_PREFIX + hapInfo.moduleName + APP_ABC_LIB_PATH_KEY_SUFFIX; + appAbcLibPaths[appLibAbcPathKey].emplace_back(libPath); } -void GetHspNativeLibPath(const BaseSharedBundleInfo &hspInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp) +void GetHspNativeLibPath(const BaseSharedBundleInfo &hspInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp, + const std::string &appBundleName, AppLibPathMap &appAbcLibPaths) { if (hspInfo.nativeLibraryPath.empty()) { return; @@ -75,10 +82,17 @@ void GetHspNativeLibPath(const BaseSharedBundleInfo &hspInfo, AppLibPathMap &app TAG_LOGD( AAFwkTag::APPKIT, "appLibPathKey: %{private}s, libPath: %{private}s", appLibPathKey.c_str(), libPath.c_str()); appLibPaths[appLibPathKey].emplace_back(libPath); + + if (!appBundleName.empty()) { + const bool isInternalHsp = (hspInfo.moduleName == appBundleName); + const std::string name = isInternalHsp ? hspInfo.moduleName : hspInfo.bundleName + "/" + hspInfo.moduleName; + const std::string appLibAbcPathKey = APP_ABC_LIB_PATH_KEY_PREFIX + name + APP_ABC_LIB_PATH_KEY_SUFFIX; + appAbcLibPaths[appLibAbcPathKey].emplace_back(libPath); + } } void GetPatchNativeLibPath(const HapModuleInfo &hapInfo, std::string &patchNativeLibraryPath, - AppLibPathMap &appLibPaths) + AppLibPathMap &appLibPaths, AppLibPathMap &appAbcLibPaths) { if (hapInfo.isLibIsolated) { patchNativeLibraryPath = hapInfo.hqfInfo.nativeLibraryPath; @@ -101,6 +115,9 @@ void GetPatchNativeLibPath(const HapModuleInfo &hapInfo, std::string &patchNativ TAG_LOGD(AAFwkTag::APPKIT, "appLibPathKey: %{public}s, patch lib path: %{private}s", appLibPathKey.c_str(), patchLibPath.c_str()); appLibPaths[appLibPathKey].emplace_back(patchLibPath); + + std::string appLibAbcPathKey = APP_ABC_LIB_PATH_KEY_PREFIX + hapInfo.moduleName + APP_ABC_LIB_PATH_KEY_SUFFIX; + appAbcLibPaths[appLibAbcPathKey].emplace_back(patchLibPath); } } // AppExecFwk } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/appkit/app/ohos_application.cpp b/frameworks/native/appkit/app/ohos_application.cpp index 02c7a93acec6baa44301e5e07d7b83f7029a69e3..61e2a4025ae8ce1279db1dba6488aed43d40cdcf 100644 --- a/frameworks/native/appkit/app/ohos_application.cpp +++ b/frameworks/native/appkit/app/ohos_application.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -28,6 +28,7 @@ #include "application_context.h" #include "application_cleaner.h" #include "application_impl.h" +#include "application_context_manager.h" #include "bundle_mgr_helper.h" #include "configuration_convertor.h" #include "configuration_utils.h" @@ -46,11 +47,13 @@ #include "display_manager.h" #include "window.h" #endif +#include "ets_application_context_utils.h" namespace OHOS { namespace AppExecFwk { namespace { constexpr const char* PERSIST_DARKMODE_KEY = "persist.ace.darkmode"; + constexpr const char* STS_CONTEXT_CLASS_NAME = "Lapplication/Context/Context;"; } REGISTER_APPLICATION(OHOSApplication, OHOSApplication) constexpr int32_t APP_ENVIRONMENT_OVERWRITE = 1; @@ -77,11 +80,14 @@ void OHOSApplication::OnForeground() abilityRuntimeContext_->NotifyApplicationForeground(); } - if (runtime_ == nullptr) { - TAG_LOGD(AAFwkTag::APPKIT, "NotifyApplicationState, runtime_ is nullptr"); - return; + for (const auto& runtime : runtimes_) { + if (runtime == nullptr) { + TAG_LOGD(AAFwkTag::APPKIT, "NotifyApplicationState, runtime is nullptr"); + continue; + } + runtime->NotifyApplicationState(false); } - runtime_->NotifyApplicationState(false); + TAG_LOGD(AAFwkTag::APPKIT, "NotifyApplicationState::OnForeground end"); } @@ -97,11 +103,13 @@ void OHOSApplication::OnBackground() abilityRuntimeContext_->NotifyApplicationBackground(); } - if (runtime_ == nullptr) { - TAG_LOGD(AAFwkTag::APPKIT, "runtime_ is nullptr"); - return; + for (const auto& runtime : runtimes_) { + if (runtime == nullptr) { + TAG_LOGD(AAFwkTag::APPKIT, "runtime is nullptr"); + continue; + } + runtime->NotifyApplicationState(true); } - runtime_->NotifyApplicationState(true); } void OHOSApplication::DumpApplication() @@ -149,18 +157,18 @@ void OHOSApplication::DumpApplication() } /** - * @brief Set Runtime + * @brief Add Runtime * * @param runtime Runtime instance. */ -void OHOSApplication::SetRuntime(std::unique_ptr&& runtime) +void OHOSApplication::AddRuntime(std::unique_ptr&& runtime) { TAG_LOGD(AAFwkTag::APPKIT, "begin"); if (runtime == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); return; } - runtime_ = std::move(runtime); + runtimes_.push_back(std::move(runtime)); } /** @@ -176,6 +184,7 @@ void OHOSApplication::SetApplicationContext( TAG_LOGE(AAFwkTag::APPKIT, "null context"); return; } + AbilityRuntime::EtsApplicationContextUtils::SetApplicationContextToEts(abilityRuntimeContext); abilityRuntimeContext_ = abilityRuntimeContext; auto application = std::static_pointer_cast(shared_from_this()); std::weak_ptr applicationWptr = application; @@ -208,6 +217,44 @@ void OHOSApplication::SetApplicationContext( #endif } +void OHOSApplication::InitAniApplicationContext() +{ + auto& runtime = GetRuntime(AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_2); + auto aniEnv = static_cast(*runtime).GetAniEnv(); + AbilityRuntime::EtsApplicationContextUtils::CreateEtsApplicationContext(aniEnv); +} + +void OHOSApplication::InitAniContext() +{ + TAG_LOGD(AAFwkTag::APPKIT, "called"); + auto& runtime = GetRuntime(AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_2); + auto aniEnv = static_cast(*runtime).GetAniEnv(); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + ani_class contextCls = nullptr; + if (aniEnv->FindClass(STS_CONTEXT_CLASS_NAME, &contextCls) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "FindClass Context failed"); + return; + } + std::array contextFunctions = { + ani_native_function {"getApplicationContextSync", ":Lapplication/ApplicationContext/ApplicationContext;", + reinterpret_cast(AbilityRuntime::ContextUtil::GetApplicationContextSync)}, + ani_native_function {"createModuleResourceManagerSync", "Lstd/core/String;Lstd/core/String;" + ":L@ohos/resourceManager/resourceManager/ResourceManager;", + reinterpret_cast(AbilityRuntime::ContextUtil::CreateModuleResourceManagerSync)}, + ani_native_function {"nativeGetGroupDir", nullptr, + reinterpret_cast(AbilityRuntime::ContextUtil::NativeGetGroupDir)}, + ani_native_function {"switchArea", nullptr, + reinterpret_cast(AbilityRuntime::ContextUtil::SwitchArea)}, + ani_native_function {"getArea", nullptr, + reinterpret_cast(AbilityRuntime::ContextUtil::GetArea)}, + }; + aniEnv->Class_BindNativeMethods(contextCls, contextFunctions.data(), + contextFunctions.size()); +} + /** * * @brief Set the abilityRecordMgr to the OHOSApplication. @@ -367,6 +414,25 @@ void OHOSApplication::SetAppEnv(const std::vector& appEnvironmen return; } +void OHOSApplication::PreloadHybridModule(const HapModuleInfo &hapModuleInfo) const +{ + if (hapModuleInfo.codeLanguage != Constants::CODE_LANGUAGE_HYBRID) { + TAG_LOGD(AAFwkTag::APPKIT, "not hybrid runtime"); + return; + } + for (const auto& runtime : runtimes_) { + bool isEsmode = hapModuleInfo.compileMode == CompileMode::ES_MODULE; + bool useCommonTrunk = false; + for (const auto& md : hapModuleInfo.metadata) { + if (md.name == "USE_COMMON_CHUNK") { + useCommonTrunk = md.value == "true"; + break; + } + } + runtime->PreloadModule(hapModuleInfo.moduleName, hapModuleInfo.hapPath, isEsmode, useCommonTrunk); + } +} + std::shared_ptr OHOSApplication::AddAbilityStage( const std::shared_ptr &abilityRecord, const std::function &)> &callback, bool &isAsyncCallback) @@ -395,8 +461,10 @@ std::shared_ptr OHOSApplication::AddAbilityStage( TAG_LOGE(AAFwkTag::APPKIT, "null hapModuleInfo"); return nullptr; } - if (runtime_ && (runtime_->GetLanguage() == AbilityRuntime::Runtime::Language::JS)) { - static_cast(*runtime_).SetPkgContextInfoJson( + PreloadHybridModule(*hapModuleInfo); + auto& runtime = GetRuntime(abilityInfo->codeLanguage); + if (runtime && (runtime->GetLanguage() == AbilityRuntime::Runtime::Language::JS)) { + static_cast(*runtime).SetPkgContextInfoJson( hapModuleInfo->moduleName, hapModuleInfo->hapPath, hapModuleInfo->packageName); } SetAppEnv(hapModuleInfo->appEnvironments); @@ -407,7 +475,8 @@ std::shared_ptr OHOSApplication::AddAbilityStage( stageContext->SetResourceManager(rm); } - abilityStage = AbilityRuntime::AbilityStage::Create(runtime_, *hapModuleInfo); + auto& runtimeStage = GetRuntime(hapModuleInfo->abilityStageCodeLanguage); + abilityStage = AbilityRuntime::AbilityStage::Create(runtimeStage, *hapModuleInfo); if (abilityStage == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null abilityStage"); return nullptr; @@ -589,8 +658,8 @@ bool OHOSApplication::AddAbilityStage( return false; } - if (runtime_ == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime_"); + if (runtimes_.empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "runtimes empty"); return false; } @@ -614,7 +683,8 @@ bool OHOSApplication::AddAbilityStage( stageContext->SetResourceManager(rm); } - auto abilityStage = AbilityRuntime::AbilityStage::Create(runtime_, *moduleInfo); + auto& runtime = GetRuntime(moduleInfo->abilityStageCodeLanguage); + auto abilityStage = AbilityRuntime::AbilityStage::Create(runtime, *moduleInfo); if (abilityStage == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null abilityStage"); return false; @@ -669,11 +739,6 @@ std::shared_ptr OHOSApplication::GetAppContext() const return abilityRuntimeContext_; } -const std::unique_ptr& OHOSApplication::GetRuntime() const -{ - return runtime_; -} - void OHOSApplication::SetConfiguration(const Configuration &config) { if (!configuration_) { @@ -759,32 +824,62 @@ void OHOSApplication::SetExtensionTypeMap(std::map map) bool OHOSApplication::NotifyLoadRepairPatch(const std::string &hqfFile, const std::string &hapPath) { - if (runtime_ == nullptr) { - TAG_LOGD(AAFwkTag::APPKIT, "null runtime"); + // need vm support + if (runtimes_.empty()) { + TAG_LOGD(AAFwkTag::APPKIT, "runtimes empty"); return true; } - return runtime_->LoadRepairPatch(hqfFile, hapPath); + for (const auto& runtime : runtimes_) { + if (runtime == nullptr) { + TAG_LOGD(AAFwkTag::APPKIT, "null runtime"); + continue; + } + if (!runtime->LoadRepairPatch(hqfFile, hapPath)) { + return false; + } + } + return true; } bool OHOSApplication::NotifyHotReloadPage() { - if (runtime_ == nullptr) { - TAG_LOGD(AAFwkTag::APPKIT, "null runtime"); + if (runtimes_.empty()) { + TAG_LOGD(AAFwkTag::APPKIT, "runtimes empty"); return true; } - return runtime_->NotifyHotReloadPage(); + for (const auto& runtime : runtimes_) { + if (runtime == nullptr) { + TAG_LOGD(AAFwkTag::APPKIT, "null runtime"); + continue; + } + if (!runtime->NotifyHotReloadPage()) { + return false; + } + } + return true; } bool OHOSApplication::NotifyUnLoadRepairPatch(const std::string &hqfFile) { - if (runtime_ == nullptr) { - TAG_LOGD(AAFwkTag::APPKIT, "null runtime"); + // need vm support + if (runtimes_.empty()) { + TAG_LOGD(AAFwkTag::APPKIT, "runtimes empty"); return true; } - return runtime_->UnLoadRepairPatch(hqfFile); + for (const auto& runtime : runtimes_) { + if (runtime == nullptr) { + TAG_LOGD(AAFwkTag::APPKIT, "null runtime"); + continue; + } + if (!runtime->UnLoadRepairPatch(hqfFile)) { + return false; + } + } + + return true; } void OHOSApplication::CleanAppTempData(bool isLastProcess) @@ -994,5 +1089,35 @@ bool OHOSApplication::GetDisplayConfig(uint64_t displayId, float &density, std:: return true; } #endif + +const std::unique_ptr& OHOSApplication::GetRuntime(const std::string& language) const +{ + for (auto& runtime : runtimes_) { + if (runtime->GetLanguage() == ConvertLangToCode(language)) { + return runtime; + } + } + return runtimeNullptr_; +} + +void OHOSApplication::SetCJApplication(bool isCJApplication) +{ + isCJApplication_ = isCJApplication; +} + +AbilityRuntime::Runtime::Language OHOSApplication::ConvertLangToCode(const std::string& language) const +{ + if (language == AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_0) { + if (isCJApplication_) { + return AbilityRuntime::Runtime::Language::CJ; + } else { + return AbilityRuntime::Runtime::Language::JS; + } + } else if (language == AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_2) { + return AbilityRuntime::Runtime::Language::STS; + } else { + return AbilityRuntime::Runtime::Language::UNKNOWN; + } +} } // namespace AppExecFwk } // namespace OHOS diff --git a/frameworks/native/insight_intent/insight_intent_context/BUILD.gn b/frameworks/native/insight_intent/insight_intent_context/BUILD.gn index 972a829e85edba6c6fd1cdfaec822b239cc3e0d3..861c541ec88b997a07ae6caac63eeb7d79de938f 100644 --- a/frameworks/native/insight_intent/insight_intent_context/BUILD.gn +++ b/frameworks/native/insight_intent/insight_intent_context/BUILD.gn @@ -23,6 +23,7 @@ config("insight_intent_context_public_config") { ohos_shared_library("insightintentcontext") { sources = [ + "ets_insight_intent_context.cpp", "insight_intent_context.cpp", "js_insight_intent_context.cpp", ] @@ -38,6 +39,7 @@ ohos_shared_library("insightintentcontext") { "${ability_runtime_innerkits_path}/runtime:runtime", "${ability_runtime_napi_path}/inner/napi_common:napi_common", "${ability_runtime_native_path}/ability/native:ability_business_error", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", ] external_deps = [ @@ -49,6 +51,7 @@ ohos_shared_library("insightintentcontext") { "ipc:ipc_core", "ipc:ipc_single", "napi:ace_napi", + "runtime_core:ani", ] subsystem_name = "ability" diff --git a/frameworks/native/insight_intent/insight_intent_context/ets_insight_intent_context.cpp b/frameworks/native/insight_intent/insight_intent_context/ets_insight_intent_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b262b4c90111704409ed60d9349fa213459b1494 --- /dev/null +++ b/frameworks/native/insight_intent/insight_intent_context/ets_insight_intent_context.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ets_insight_intent_context.h" + +#include "ability_window_configuration.h" +#include "hilog_tag_wrapper.h" +#include "hitrace_meter.h" +#include "ani_common_want.h" +#include "sts_error_utils.h" + +namespace OHOS { +namespace AbilityRuntime { + +void EtsInsightIntentContext::Finalizer(ani_env *env, void* data, void* hint) +{ + TAG_LOGI(AAFwkTag::INTENT, "EtsInsightIntentContext::Finalizer called"); + std::unique_ptr(static_cast(data)); +} + +ani_object EtsInsightIntentContext::StartAbiitySync([[maybe_unused]] ani_env *env, + [[maybe_unused]] ani_object aniObj, ani_object wantObj) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + auto context = GetContext(env, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "get context failed."); + return CreateStsInvalidParamError(env, "context null"); + } + + AAFwk::Want want; + if (!OHOS::AppExecFwk::UnwrapWant(env, wantObj, want)) { + TAG_LOGE(AAFwkTag::INTENT, "parse wantParam failed"); + return CreateStsInvalidParamError(env, "Parse param want failed, want must be Want."); + } + + return context->StartAbilityInner(env, want); +} + +std::shared_ptr EtsInsightIntentContext::GetContext(ani_env *env, ani_object aniObj) +{ + ani_long nativeContextLong; + ani_class cls {}; + ani_field contextField = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null env"); + return nullptr; + } + + if ((status = env->FindClass("L@ohos/app/ability/InsightIntentContext/InsightIntentContext;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + + if ((status = env->Class_FindField(cls, "nativeContext", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_GetField_Long(aniObj, contextField, &nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return nullptr; + } + auto weakContext = reinterpret_cast*>(nativeContextLong); + return weakContext != nullptr ? weakContext->lock() : nullptr; +} + +ani_object EtsInsightIntentContext::StartAbilityInner(ani_env *env, AAFwk::Want &want) +{ + TAG_LOGD(AAFwkTag::INTENT, "EtsInsightIntentContext::StartAbilityInner called"); + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + + auto context = context_.lock(); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null context"); + return CreateStsError(env, AbilityErrorCode::ERROR_CODE_INNER); + } + + // verify if bundleName is empty or invalid + auto bundleNameFromWant = want.GetElement().GetBundleName(); + if (bundleNameFromWant.empty() || bundleNameFromWant != context->GetBundleName()) { + TAG_LOGE(AAFwkTag::INTENT, "bundleName empty or invalid"); + return CreateStsError(env, AbilityErrorCode::ERROR_CODE_OPERATION_NOT_SUPPORTED); + } + // modify windowmode setting + auto windowMode = context->GetCurrentWindowMode(); + if (windowMode == AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY || + windowMode == AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY) { + want.SetParam(AAFwk::Want::PARAM_RESV_WINDOW_MODE, windowMode); + } + + auto innerErrCode = context->StartAbilityByInsightIntent(want); + if (innerErrCode == ERR_OK) { + return CreateStsError(env, AbilityErrorCode::ERROR_OK); + } else { + return CreateStsErrorByNativeErr(env, innerErrCode); + } +} + +std::unique_ptr CreateEtsInsightIntentContext(ani_env *env, + const std::shared_ptr& context) +{ + TAG_LOGD(AAFwkTag::INTENT, "CreateEtsInsightIntentContext called"); + ani_class cls {}; + ani_status status = ANI_ERROR; + ani_object contextObj = nullptr; + ani_method method {}; + ani_field field = nullptr; + ani_ref contextObjtRef = nullptr; + if (context == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null context"); + return std::make_unique(); + } + if ((status = env->FindClass("L@ohos/app/ability/InsightIntentContext/InsightIntentContext;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return std::make_unique(); + } + std::array functions = { + ani_native_function { "nativeStartAbilitySync", nullptr, + reinterpret_cast(EtsInsightIntentContext::StartAbiitySync) }, + }; + if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { + if (status != ANI_ALREADY_BINDED) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return std::make_unique(); + } + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return std::make_unique(); + } + if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return std::make_unique(); + } + if ((status = env->Class_FindField(cls, "nativeContext", &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + return std::make_unique(); + } + auto workContext = new (std::nothrow) std::weak_ptr(context); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::INTENT, "null workContext"); + return std::make_unique(); + } + ani_long nativeContextLong = (ani_long)workContext; + if ((status = env->Object_SetField_Long(contextObj, field, nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + delete workContext; + return std::make_unique(); + } + if ((status = env->GlobalReference_Create(contextObj, &contextObjtRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::INTENT, "status: %{public}d", status); + delete workContext; + return std::make_unique(); + } + auto nativeReference = std::make_unique(); + nativeReference->aniCls = cls; + nativeReference->aniObj = contextObj; + nativeReference->aniRef = contextObjtRef; + return nativeReference; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/runtime/cj_runtime.cpp b/frameworks/native/runtime/cj_runtime.cpp index 296c36f758f0b22c959df867f193b045f2f931a5..0f4536dbcdd3c05cba8a233254b3f47b883da426 100644 --- a/frameworks/native/runtime/cj_runtime.cpp +++ b/frameworks/native/runtime/cj_runtime.cpp @@ -28,11 +28,6 @@ using namespace OHOS::AbilityRuntime; - -namespace { -const std::string DEBUGGER = "@Debugger"; -} // namespace - #define LIB_NAME "libcj_environment.z.so" #define GET_ENV_INS_NAME "OHOS_GetCJEnvInstance" @@ -115,16 +110,6 @@ bool CJRuntime::Initialize(const Options& options) return true; } -void CJRuntime::RegisterUncaughtExceptionHandler(const CJUncaughtExceptionInfo& uncaughtExceptionInfo) -{ - auto cjEnv = OHOS::CJEnv::LoadInstance(); - if (cjEnv == nullptr) { - TAG_LOGE(AAFwkTag::CJRUNTIME, "null cjEnv"); - return; - } - cjEnv->registerCJUncaughtExceptionHandler(uncaughtExceptionInfo); -} - bool CJRuntime::IsCJAbility(const std::string& info) { // in cj application, the srcEntry format should be packageName.AbilityClassName. @@ -275,3 +260,12 @@ void CJRuntime::UnLoadCJAppLibrary() { TAG_LOGI(AAFwkTag::CJRUNTIME, "UnLoadCJAppLibrary not support yet"); } +void CJRuntime::RegisterUncaughtExceptionHandler(void* uncaughtExceptionInfo) +{ + auto cjEnv = OHOS::CJEnv::LoadInstance(); + if (cjEnv == nullptr) { + TAG_LOGE(AAFwkTag::CJRUNTIME, "null cjEnv"); + return; + } + cjEnv->registerCJUncaughtExceptionHandler(*static_cast(uncaughtExceptionInfo)); +} \ No newline at end of file diff --git a/frameworks/native/runtime/js_module_reader.cpp b/frameworks/native/runtime/js_module_reader.cpp index 51a872a9d3128a0b2c6684263ba4df3820dc9273..73df8714a305b180a350b77893fad25a060b49f4 100755 --- a/frameworks/native/runtime/js_module_reader.cpp +++ b/frameworks/native/runtime/js_module_reader.cpp @@ -42,27 +42,51 @@ JsModuleReader::JsModuleReader(const std::string& bundleName, const std::string& } } -bool JsModuleReader::operator()(const std::string& inputPath, uint8_t **buff, - size_t *buffSize, std::string& errorMsg) const +std::shared_ptr JsModuleReader::GetExtractor( + const std::string& inputPath, bool isHybrid, std::string& errorMsg) const { - TAG_LOGD(AAFwkTag::JSRUNTIME, "called start: %{private}s", inputPath.c_str()); - HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - if (inputPath.empty() || buff == nullptr || buffSize == nullptr) { - TAG_LOGE(AAFwkTag::JSRUNTIME, "Invalid param"); - return false; + auto realHapPath = GetAppPath(inputPath, SHARED_FILE_SUFFIX); + if (realHapPath.empty()) { + TAG_LOGE(AAFwkTag::JSRUNTIME, "empty realHapPath"); + return nullptr; + } + bool newCreate = false; + std::shared_ptr extractor = ExtractorUtil::GetExtractor(realHapPath, newCreate); + if (extractor != nullptr) { + return extractor; + } + if (!isHybrid) { + errorMsg = "hap path error: " + realHapPath; + TAG_LOGE(AAFwkTag::JSRUNTIME, "realHapPath %{private}s GetExtractor failed", realHapPath.c_str()); + return nullptr; } - auto realHapPath = GetAppHspPath(inputPath); + realHapPath = GetAppPath(inputPath, ABILITY_FILE_SUFFIX); if (realHapPath.empty()) { TAG_LOGE(AAFwkTag::JSRUNTIME, "empty realHapPath"); + return nullptr; + } + extractor = ExtractorUtil::GetExtractor(realHapPath, newCreate); + if (extractor == nullptr) { + errorMsg = "hap path error: " + inputPath; + TAG_LOGE(AAFwkTag::JSRUNTIME, "inputPath %{private}s GetExtractor failed", inputPath.c_str()); + return nullptr; + } + return extractor; +} + +bool JsModuleReader::operator()(const std::string& inputPath, bool isHybrid, + uint8_t **buff, size_t *buffSize, std::string& errorMsg) const +{ + TAG_LOGD(AAFwkTag::JSRUNTIME, "called start: %{private}s", inputPath.c_str()); + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (inputPath.empty() || buff == nullptr || buffSize == nullptr) { + TAG_LOGE(AAFwkTag::JSRUNTIME, "Invalid param"); return false; } - bool newCreate = false; - std::shared_ptr extractor = ExtractorUtil::GetExtractor(realHapPath, newCreate); + std::shared_ptr extractor = GetExtractor(inputPath, isHybrid, errorMsg); if (extractor == nullptr) { - errorMsg = "hap path error: " + realHapPath; - TAG_LOGE(AAFwkTag::JSRUNTIME, "realHapPath %{private}s GetExtractor failed", realHapPath.c_str()); return false; } @@ -77,18 +101,17 @@ bool JsModuleReader::operator()(const std::string& inputPath, uint8_t **buff, return true; } -std::string JsModuleReader::GetAppHspPath(const std::string& inputPath) const +std::string JsModuleReader::GetAppPath(const std::string& inputPath, const std::string& suffix) const { if (isFormRender_) { - return GetFormAppHspPath(inputPath); + return GetFormAppPath(inputPath, suffix); } - return GetCommonAppHspPath(inputPath); + return GetCommonAppPath(inputPath, suffix); } -std::string JsModuleReader::GetFormAppHspPath(const std::string& inputPath) const +std::string JsModuleReader::GetFormAppPath(const std::string& inputPath, const std::string& suffix) const { std::string realHapPath; - std::string suffix = std::string(SHARED_FILE_SUFFIX); realHapPath.append("/data/bundles/") .append(bundleName_).append("/") .append(GetModuleName(inputPath)) @@ -109,9 +132,8 @@ std::string JsModuleReader::GetModuleName(const std::string& inputPath) const return inputPath.substr(inputPath.find_last_of("/") + 1); } -std::string JsModuleReader::GetCommonAppHspPath(const std::string& inputPath) const +std::string JsModuleReader::GetCommonAppPath(const std::string& inputPath, const std::string& suffix) const { - std::string suffix = std::string(SHARED_FILE_SUFFIX); std::string realHapPath = GetPresetAppHapPath(inputPath, bundleName_); if ((realHapPath.find(ABS_DATA_CODE_PATH) == 0) || (realHapPath == inputPath)) { realHapPath = std::string(ABS_CODE_PATH) + inputPath + suffix; diff --git a/frameworks/native/runtime/js_module_reader.h b/frameworks/native/runtime/js_module_reader.h index affe228e869ad94fd7237c058685aa725bc7cb3e..582fd98f4a4ef0955333671e7fae23a37bd6ad4c 100755 --- a/frameworks/native/runtime/js_module_reader.h +++ b/frameworks/native/runtime/js_module_reader.h @@ -34,6 +34,7 @@ public: static constexpr char MERGE_ABC_PATH[] = "ets/modules.abc"; static constexpr char SYS_ABS_CODE_PATH[] = "/system/app/appServiceFwk/"; static constexpr char SHARED_FILE_SUFFIX[] = ".hsp"; + static constexpr char ABILITY_FILE_SUFFIX[] = ".hap"; JsModuleReader(const std::string& bundleName, const std::string& hapPath, bool isFormRender = false); ~JsModuleReader() = default; @@ -42,15 +43,17 @@ public: JsModuleReader& operator=(const JsModuleReader&) = default; JsModuleReader& operator=(JsModuleReader&&) = default; - bool operator()(const std::string& inputPath, uint8_t **buff, size_t *buffSize, std::string& errorMsg) const; + bool operator()(const std::string& inputPath, bool isHybrid, + uint8_t **buff, size_t *buffSize, std::string& errorMsg) const; static std::string GetPresetAppHapPath(const std::string& inputPath, const std::string& bundleName); static void GetHapPathList(const std::string &bundleName, std::vector &hapList); private: - std::string GetAppHspPath(const std::string& inputPath) const; - std::string GetCommonAppHspPath(const std::string& inputPath) const; - std::string GetFormAppHspPath(const std::string& inputPath) const; + std::string GetAppPath(const std::string& inputPath, const std::string& suffix) const; + std::string GetCommonAppPath(const std::string& inputPath, const std::string& suffix) const; + std::string GetFormAppPath(const std::string& inputPath, const std::string& suffix) const; std::string GetModuleName(const std::string& inputPath) const; + std::shared_ptr GetExtractor(const std::string& inputPath, bool isHybrid, std::string& errorMsg) const; static std::string GetOtherHspPath(const std::string& bundleName, const std::string& moduleName, const std::string& inputPath); diff --git a/frameworks/native/runtime/js_runtime.cpp b/frameworks/native/runtime/js_runtime.cpp index 7a083c5a1a28077ee9ec238b6e33dd88573df02e..dff76364e4d1b41fd337e34009b4f6636399beed 100644 --- a/frameworks/native/runtime/js_runtime.cpp +++ b/frameworks/native/runtime/js_runtime.cpp @@ -82,7 +82,6 @@ constexpr int32_t DEFAULT_INTER_VAL = 500; constexpr int32_t API8 = 8; const std::string SANDBOX_ARK_CACHE_PATH = "/data/storage/ark-cache/"; const std::string SANDBOX_ARK_PROIFILE_PATH = "/data/storage/ark-profile"; -const std::string DEBUGGER = "@Debugger"; constexpr char MERGE_ABC_PATH[] = "/ets/modules.abc"; constexpr char BUNDLE_INSTALL_PATH[] = "/data/storage/el1/bundle/"; @@ -161,8 +160,8 @@ void JsRuntime::StartDebugMode(const DebugOption dOption) { HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); TAG_LOGD(AAFwkTag::JSRUNTIME, "localDebug %{public}d", dOption.isDebugFromLocal); - if (!dOption.isDebugFromLocal && !dOption.isDeveloperMode) { - TAG_LOGE(AAFwkTag::JSRUNTIME, "developer Mode false"); + if (!ShouldSkipDebugMode(dOption)) { + TAG_LOGE(AAFwkTag::JSRUNTIME, "not start debug"); return; } CHECK_POINTER(jsEnv_); @@ -207,10 +206,16 @@ void JsRuntime::StartDebugMode(const DebugOption dOption) TAG_LOGE(AAFwkTag::JSRUNTIME, "not support release app"); return; } + auto callback = [weak, isDebugApp, isStartWithDebug](int32_t tid, const DebuggerPostTask& task) { + panda::JSNApi::DebugOption debugOption = {ARK_DEBUGGER_LIB_PATH, isDebugApp ? isStartWithDebug : false}; + if (weak != nullptr) { + panda::JSNApi::StoreDebugInfo(tid, weak->GetVM(), debugOption, task, isDebugApp); + } + }; if (option.find(DEBUGGER) == std::string::npos) { // if has old connect server, stop it ConnectServerManager::Get().StopConnectServer(false); - ConnectServerManager::Get().SendDebuggerInfo(isStartWithDebug, isDebugApp); + ConnectServerManager::Get().SendInstanceMessageAll(callback); ConnectServerManager::Get().StartConnectServer(bundleName, socketFd, false); } else { if (appProvisionType == AppExecFwk::Constants::APP_PROVISION_TYPE_RELEASE) { @@ -229,6 +234,19 @@ void JsRuntime::StartDebugMode(const DebugOption dOption) DebuggerConnectionHandler(isDebugApp, isStartWithDebug); } +bool JsRuntime::ShouldSkipDebugMode(const DebugOption dOption) +{ + if (!dOption.isDebugFromLocal && !dOption.isDeveloperMode) { + TAG_LOGE(AAFwkTag::JSRUNTIME, "developer Mode false"); + return false; + } + if (!(dOption.codeLanguage == AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_0)) { + TAG_LOGE(AAFwkTag::JSRUNTIME, "developer register in sts"); + return false; + } + return true; +} + void JsRuntime::DebuggerConnectionHandler(bool isDebugApp, bool isStartWithDebug) { ConnectServerManager::Get().StoreInstanceMessage(getproctid(), instanceId_); @@ -1692,5 +1710,11 @@ void JsRuntime::StartLocalDebugMode(bool isDebugFromLocal) debugOption_.isDebugFromLocal = isDebugFromLocal; StartDebugMode(debugOption_); } +void JsRuntime::RegisterUncaughtExceptionHandler(void* uncaughtExceptionInfo) +{ + HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); + CHECK_POINTER(jsEnv_); + jsEnv_->RegisterUncaughtExceptionHandler(*static_cast(uncaughtExceptionInfo)); +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/native/runtime/ohos_sts_environment_impl.cpp b/frameworks/native/runtime/ohos_sts_environment_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7967a7c2aaf4003fd0d7dc669c2bc9b780ffcc5c --- /dev/null +++ b/frameworks/native/runtime/ohos_sts_environment_impl.cpp @@ -0,0 +1,174 @@ +/* + * 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 "ohos_sts_environment_impl.h" +#include "hilog_tag_wrapper.h" +#include "ohos_loop_handler.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { + std::shared_ptr g_eventHandler = nullptr; +} +void OHOSStsEnvironmentImpl::PostTaskToHandler(const char* taskName, uv_io_cb func, void* work, int status, + int priority) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + if (!func || !work) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Invalid parameters"); + return; + } + + auto task = [func, work, status]() { + TAG_LOGD(AAFwkTag::STSRUNTIME, "Do uv work"); + func(work, status); + TAG_LOGD(AAFwkTag::STSRUNTIME, "Do uv work end"); + }; + + AppExecFwk::EventQueue::Priority prio = AppExecFwk::EventQueue::Priority::IMMEDIATE; + switch (priority) { + case uv_qos_t::uv_qos_user_initiated: + prio = AppExecFwk::EventQueue::Priority::IMMEDIATE; + break; + case uv_qos_t::uv_qos_utility: + prio = AppExecFwk::EventQueue::Priority::LOW; + break; + case uv_qos_t::uv_qos_background: + prio = AppExecFwk::EventQueue::Priority::IDLE; + break; + default: + prio = AppExecFwk::EventQueue::Priority::HIGH; + break; + } + + if (g_eventHandler == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Invalid parameters"); + return; + } + g_eventHandler->PostTask(task, "uv_io_cb", 0, prio); +} +OHOSStsEnvironmentImpl::OHOSStsEnvironmentImpl() +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); +} + +OHOSStsEnvironmentImpl::OHOSStsEnvironmentImpl(const std::shared_ptr& eventRunner) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + if (eventRunner != nullptr) { + TAG_LOGD(AAFwkTag::STSRUNTIME, "Create event handler"); + eventHandler_ = std::make_shared(eventRunner); + if (eventRunner.get() == AppExecFwk::EventRunner::GetMainEventRunner().get()) { + g_eventHandler = std::make_shared(eventRunner); + } + } +} + +OHOSStsEnvironmentImpl::~OHOSStsEnvironmentImpl() +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); +} + +void OHOSStsEnvironmentImpl::PostTask(const std::function& task, const std::string& name, int64_t delayTime) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + if (eventHandler_ != nullptr) { + eventHandler_->PostTask(task, name, delayTime); + } +} + +void OHOSStsEnvironmentImpl::PostSyncTask(const std::function& task, const std::string& name) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + if (eventHandler_ != nullptr) { + eventHandler_->PostSyncTask(task, name); + } +} + +void OHOSStsEnvironmentImpl::RemoveTask(const std::string& name) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + if (eventHandler_ != nullptr) { + eventHandler_->RemoveTask(name); + } +} + +bool OHOSStsEnvironmentImpl::InitLoop(bool isStage) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + loop_ = new (std::nothrow)uv_loop_t; + if (loop_ == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "failed to create uv_loop, async task interface would not work"); + return false; + } + if (uv_loop_init(loop_) != ERR_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "failed to init uv_loop, async task interface would not work"); + delete loop_; + loop_ = nullptr; + return false; + } + auto fd = loop_ != nullptr ? uv_backend_fd(loop_) : -1; + if (fd < 0) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "get fd failed"); + return false; + } + uv_run(loop_, UV_RUN_NOWAIT); + + if (eventHandler_ != nullptr) { + uint32_t events = AppExecFwk::FILE_DESCRIPTOR_INPUT_EVENT | AppExecFwk::FILE_DESCRIPTOR_OUTPUT_EVENT; + eventHandler_->AddFileDescriptorListener(fd, events, std::make_shared(loop_), "uvLoopTask"); + TAG_LOGD(AAFwkTag::STSRUNTIME, "uv_register_task_to_event, isStage: %{public}d", isStage); + if (isStage && (eventHandler_->GetEventRunner()).get() == AppExecFwk::EventRunner::GetMainEventRunner().get()) { + uv_register_task_to_event(loop_, PostTaskToHandler, nullptr); + } + } + + return true; +} + +void OHOSStsEnvironmentImpl::DeInitLoop() +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + auto fd = loop_ != nullptr ? uv_backend_fd(loop_) : -1; + if (fd >= 0 && eventHandler_ != nullptr) { + eventHandler_->RemoveFileDescriptorListener(fd); + } + uv_unregister_task_to_event(loop_); + RemoveTask(TIMER_TASK); +} + +bool OHOSStsEnvironmentImpl::ReInitUVLoop() +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + if (loop_ != nullptr) { + delete loop_; + loop_ = nullptr; + } + + loop_ = new (std::nothrow)uv_loop_t; + if (loop_ == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "failed to create uv_loop, async task interface would not work"); + return false; + } + if (uv_loop_init(loop_) != ERR_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "failed to init uv_loop, async task interface would not work"); + delete loop_; + loop_ = nullptr; + return false; + } + return true; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/runtime/ohos_sts_environment_impl.h b/frameworks/native/runtime/ohos_sts_environment_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..c71d6ecbfdb7dec6a0d7ace2b069a7467327236a --- /dev/null +++ b/frameworks/native/runtime/ohos_sts_environment_impl.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_OHOS_STS_ENVIRONMENT_IMPL_H +#define OHOS_ABILITY_RUNTIME_OHOS_STS_ENVIRONMENT_IMPL_H + +#include + +#include "sts_environment_impl.h" + +namespace OHOS { +namespace AbilityRuntime { +class OHOSStsEnvironmentImpl : public StsEnv::StsEnvironmentImpl { +public: + OHOSStsEnvironmentImpl(); + explicit OHOSStsEnvironmentImpl(const std::shared_ptr& eventRunner); + ~OHOSStsEnvironmentImpl() override; + + void PostTask(const std::function& task, const std::string& name, int64_t delayTime) override; + + void PostSyncTask(const std::function& task, const std::string& name) override; + + void RemoveTask(const std::string& name) override; + + bool InitLoop(bool isStage) override; + + void DeInitLoop() override; + + bool ReInitUVLoop() override; + +private: + static void PostTaskToHandler(const char* taskName, uv_io_cb func, void* work, int status, int priority); + std::shared_ptr eventHandler_; + uv_loop_t* loop_ = nullptr; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_OHOS_STS_ENVIRONMENT_IMPL_H diff --git a/frameworks/native/runtime/runtime.cpp b/frameworks/native/runtime/runtime.cpp index 26362dd0dbbe6724c623e7a42581ceee0bdb3892..74c2eae6477caad85adb331e09872cab1491081a 100644 --- a/frameworks/native/runtime/runtime.cpp +++ b/frameworks/native/runtime/runtime.cpp @@ -19,14 +19,44 @@ #include "cj_runtime.h" #endif #include "js_runtime.h" +#include "sts_runtime.h" namespace OHOS { namespace AbilityRuntime { namespace { -std::unique_ptr g_preloadedInstance; +std::map> g_preloadedInstances; } -std::unique_ptr Runtime::Create(const Runtime::Options& options) +std::vector> Runtime::CreateRuntimes(Runtime::Options& options) +{ + std::vector> runtimes; + for (auto lang : options.langs) { + switch (lang.first) { + case Runtime::Language::JS: + options.lang = Runtime::Language::JS; + runtimes.push_back(JsRuntime::Create(options)); + break; +#ifdef CJ_FRONTEND + case Runtime::Language::CJ: + options.lang = Runtime::Language::CJ; + runtimes.push_back(CJRuntime::Create(options)); + break; +#endif + case Runtime::Language::STS: + options.lang = Runtime::Language::JS; + runtimes.push_back(JsRuntime::Create(options)); + options.lang = Runtime::Language::STS; + runtimes.push_back(STSRuntime::Create(options, &static_cast(*runtimes[0]))); + break; + default: + runtimes.push_back(std::unique_ptr()); + break; + } + } + return runtimes; +} + +std::unique_ptr Runtime::Create(Runtime::Options& options) { switch (options.lang) { case Runtime::Language::JS: @@ -35,22 +65,34 @@ std::unique_ptr Runtime::Create(const Runtime::Options& options) case Runtime::Language::CJ: return CJRuntime::Create(options); #endif + case Runtime::Language::STS: + return STSRuntime::PreFork(options); default: return std::unique_ptr(); } } -void Runtime::SavePreloaded(std::unique_ptr&& instance) +void Runtime::SavePreloaded(std::unique_ptr&& instance, Language key) { if (instance) { instance->FinishPreload(); } - g_preloadedInstance = std::move(instance); + + auto it = g_preloadedInstances.find(key); + if (it != g_preloadedInstances.end()) { + g_preloadedInstances.erase(it); + } + g_preloadedInstances.emplace(key, std::move(instance)); } -std::unique_ptr Runtime::GetPreloaded() +std::unique_ptr Runtime::GetPreloaded(Language key) { - return std::move(g_preloadedInstance); + auto it = g_preloadedInstances.find(key); + if (it == g_preloadedInstances.end()) { + return nullptr; + } + auto instance = std::move(it->second); + return instance; } } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/native/runtime/sts_data_struct_converter.cpp b/frameworks/native/runtime/sts_data_struct_converter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a55492e4e4f3766f2e11994baf6102c216e8bdaa --- /dev/null +++ b/frameworks/native/runtime/sts_data_struct_converter.cpp @@ -0,0 +1,142 @@ +/* + * 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 "sts_data_struct_converter.h" + +#include "common_func.h" +#include "configuration_convertor.h" +#include "hilog_tag_wrapper.h" +#include "ani_enum_convert.h" +namespace OHOS { +namespace AbilityRuntime { +using namespace OHOS::AppExecFwk; + +namespace { +constexpr const char* LAUNCH_PARAM_IMPL_CLASS_NAME = "L@ohos/app/ability/AbilityConstant/LaunchParamImpl;"; +constexpr const char* LAUNCH_REASON_ENUM_NAME = "L@ohos/app/ability/AbilityConstant/AbilityConstant/LaunchReason;"; +constexpr const char* LAST_EXIT_REASON_ENUM_NAME = + "L@ohos/app/ability/AbilityConstant/AbilityConstant/LastExitReason;"; +constexpr const char* LAST_EXIT_DETAIL_INFO_IMPL_CLASS_NAME = + "L@ohos/app/ability/AbilityConstant/LastExitDetailInfoImpl;"; +} + +ani_string GetAniString(ani_env *env, const std::string &str) +{ + ani_string aniStr = nullptr; + ani_status status = env->String_NewUTF8(str.c_str(), str.size(), &aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return nullptr; + } + return aniStr; +} + +ani_object CreateStsLastExitDetailInfo(ani_env* env, const AAFwk::LastExitDetailInfo& lastExitDetailInfo) +{ + ani_method method = nullptr; + ani_field field = nullptr; + ani_string string = nullptr; + ani_status status = ANI_ERROR; + ani_object object = nullptr; + ani_class cls = nullptr; + if ((status = env->FindClass(LAST_EXIT_DETAIL_INFO_IMPL_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "null cls"); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + return nullptr; + } + if (method == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "null method"); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "status: %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "null object"); + return nullptr; + } + env->Object_SetPropertyByName_Ref(object, "pid", GetAniString(env, std::to_string(lastExitDetailInfo.pid))); + env->Object_SetPropertyByName_Ref(object, "processName", GetAniString(env, lastExitDetailInfo.processName)); + env->Object_SetPropertyByName_Ref(object, "uid", GetAniString(env, std::to_string(lastExitDetailInfo.uid))); + env->Object_SetPropertyByName_Ref(object, "exitSubReason", + GetAniString(env, std::to_string(lastExitDetailInfo.exitSubReason))); + env->Object_SetPropertyByName_Ref(object, "exitMsg", GetAniString(env, lastExitDetailInfo.exitMsg)); + env->Object_SetPropertyByName_Ref(object, "rss", GetAniString(env, std::to_string(lastExitDetailInfo.rss))); + env->Object_SetPropertyByName_Ref(object, "pss", GetAniString(env, std::to_string(lastExitDetailInfo.pss))); + env->Object_SetPropertyByName_Ref(object, "timestamp", + GetAniString(env, std::to_string(lastExitDetailInfo.timestamp))); + + return object; +} + +ani_object CreateStsLaunchParam(ani_env* env, const AAFwk::LaunchParam& launchParam) +{ + ani_method method = nullptr; + ani_field field = nullptr; + ani_string string = nullptr; + ani_status status = ANI_ERROR; + ani_object object = nullptr; + ani_class cls = nullptr; + if ((status = env->FindClass(LAUNCH_PARAM_IMPL_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return nullptr; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null cls"); + return nullptr; + } + + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return nullptr; + } + if (method == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null method"); + return nullptr; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "status: %{public}d", status); + return nullptr; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null object"); + return nullptr; + } + env->Object_SetPropertyByName_Ref(object, "lastExitMessage", GetAniString(env, launchParam.lastExitMessage)); + + ani_enum_item launchReasonItem {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvertNativeToSts(env, + LAUNCH_REASON_ENUM_NAME, launchParam.launchReason, launchReasonItem); + env->Object_SetPropertyByName_Ref(object, "launchReason", launchReasonItem); + + ani_enum_item lastExitReasonItem {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvertNativeToSts(env, + LAST_EXIT_REASON_ENUM_NAME, launchParam.lastExitReason, lastExitReasonItem); + env->Object_SetPropertyByName_Ref(object, "lastExitReason", lastExitReasonItem); + env->Object_SetPropertyByName_Ref(object, "lastExitDetailInfo", + CreateStsLastExitDetailInfo(env, launchParam.lastExitDetailInfo)); + + return object; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/runtime/sts_error_utils.cpp b/frameworks/native/runtime/sts_error_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1906230a922d3b7f8cfd71f9022a7a6cd638b0a1 --- /dev/null +++ b/frameworks/native/runtime/sts_error_utils.cpp @@ -0,0 +1,198 @@ +/* + * 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 "sts_error_utils.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* ERR_MSG_TOO_FEW_PARAM = "Parameter error. Too few parameters."; +constexpr const char* ERR_MSG_NOT_MAINTHREAD = "Caller error. Caller from non-main thread."; +constexpr const char* ERR_MSG_INVALID_NUM_PARAMS = "Parameter error. The number of parameters is invalid."; +constexpr const char* NOT_SYSTEM_APP = "The application is not system-app, can not use system-api."; + +constexpr const char* BUSINESS_ERROR_CLASS = "L@ohos/base/BusinessError;"; +constexpr const char* ERROR_CLASS_NAME = "Lescompat/Error;"; +constexpr const char* ERROR_MSG_TRANSFER_CLASS_NOT_FOUND = "Unable to find the class for transferring."; +constexpr int32_t ERROR_CODE_TRANSFER_CLASS_NOT_FOUND = 10200067; +} // namespace + +void ThrowStsError(ani_env *env, ani_object err) +{ + if (err == nullptr) { + return; + } + env->ThrowError(static_cast(err)); +} + +void ThrowStsError(ani_env *env, int32_t errCode, const std::string &errorMsg) +{ + ThrowStsError(env, CreateStsError(env, errCode, errorMsg)); +} + +void ThrowStsError(ani_env *env, const AbilityErrorCode &err) +{ + ThrowStsError(env, CreateStsError(env, static_cast(err), GetErrorMsg(err))); +} + +void ThrowStsInvalidCallerError(ani_env *env) +{ + ThrowStsError(env, CreateStsError(env, + static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CALLER), + ERR_MSG_NOT_MAINTHREAD)); +} + +void ThrowStsTooFewParametersError(ani_env *env) +{ + ThrowStsError(env, CreateStsError(env, + static_cast(AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + ERR_MSG_TOO_FEW_PARAM)); +} + +void ThrowStsInvalidNumParametersError(ani_env *env) +{ + ThrowStsError(env, CreateStsError(env, + static_cast(AbilityErrorCode::ERROR_CODE_INVALID_PARAM), + ERR_MSG_INVALID_NUM_PARAMS)); +} + +void ThrowStsNoPermissionError(ani_env *env, const std::string &permission) +{ + ThrowStsError(env, CreateStsError(env, + static_cast(AbilityErrorCode::ERROR_CODE_PERMISSION_DENIED), + GetNoPermissionErrorMsg(permission))); +} + +void ThrowStsNotSystemAppError(ani_env *env) +{ + ThrowStsError(env, CreateStsError(env, + static_cast(AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP), + NOT_SYSTEM_APP)); +} + +void ThrowStsInvalidParamError(ani_env *env, const std::string &message) +{ + ThrowStsError(env, CreateStsInvalidParamError(env, message)); +} + +void ThrowStsErrorByNativeErr(ani_env *env, int32_t err) +{ + ThrowStsError(env, CreateStsErrorByNativeErr(env, err)); +} + +void ThrowStsTransferClassError(ani_env *env) +{ + ThrowStsError(env, CreateStsError(env, ERROR_CODE_TRANSFER_CLASS_NOT_FOUND, ERROR_MSG_TRANSFER_CLASS_NOT_FOUND)); +} + +ani_object CreateStsError(ani_env *env, const AbilityErrorCode &err) +{ + return CreateStsError(env, static_cast(err), GetErrorMsg(err)); +} + +ani_object CreateStsInvalidParamError(ani_env *env, const std::string &message) +{ + return CreateStsError(env, static_cast(AbilityErrorCode::ERROR_CODE_INVALID_PARAM), message); +} + +ani_object CreateStsNoPermissionError(ani_env *env, const std::string &permission) +{ + return CreateStsError(env, + static_cast(AbilityErrorCode::ERROR_CODE_PERMISSION_DENIED), + GetNoPermissionErrorMsg(permission)); +} + +ani_object CreateStsErrorByNativeErr(ani_env *env, int32_t err, const std::string &permission) +{ + auto errCode = GetJsErrorCodeByNativeError(err); + auto errMsg = (errCode == AbilityErrorCode::ERROR_CODE_PERMISSION_DENIED && !permission.empty()) ? + GetNoPermissionErrorMsg(permission) : GetErrorMsg(errCode); + return CreateStsError(env, static_cast(errCode), errMsg); +} + +ani_object WrapStsError(ani_env *env, const std::string &msg) +{ + ani_class cls {}; + ani_method method {}; + ani_object obj = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "null env"); + return nullptr; + } + + ani_string aniMsg = nullptr; + if ((status = env->String_NewUTF8(msg.c_str(), msg.size(), &aniMsg)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "String_NewUTF8 failed %{public}d", status); + return nullptr; + } + + ani_ref undefRef; + if ((status = env->GetUndefined(&undefRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "GetUndefined failed %{public}d", status); + return nullptr; + } + + if ((status = env->FindClass(ERROR_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "FindClass failed %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", "Lstd/core/String;Lescompat/ErrorOptions;:V", &method)) != + ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "Class_FindMethod failed %{public}d", status); + return nullptr; + } + + if ((status = env->Object_New(cls, method, &obj, aniMsg, undefRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "Object_New failed %{public}d", status); + return nullptr; + } + return obj; +} + +ani_object CreateStsError(ani_env *env, ani_int code, const std::string &msg) +{ + ani_class cls {}; + ani_method method {}; + ani_object obj = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "null env"); + return nullptr; + } + if ((status = env->FindClass(BUSINESS_ERROR_CLASS, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "FindClass failed %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", "DLescompat/Error;:V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "Class_FindMethod failed %{public}d", status); + return nullptr; + } + ani_object error = WrapStsError(env, msg); + if (error == nullptr) { + TAG_LOGE(AAFwkTag::ABILITY, "error nulll"); + return nullptr; + } + ani_double dCode(code); + if ((status = env->Object_New(cls, method, &obj, dCode, error)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "Object_New failed %{public}d", status); + return nullptr; + } + return obj; +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/runtime/sts_runtime.cpp b/frameworks/native/runtime/sts_runtime.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c9eaf0bcc830b4883b9e20b8076b6919688ea39e --- /dev/null +++ b/frameworks/native/runtime/sts_runtime.cpp @@ -0,0 +1,756 @@ +/* + * 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 "sts_runtime.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "accesstoken_kit.h" +#include "bundle_constants.h" +#include "config_policy_utils.h" +#include "connect_server_manager.h" +#include "constants.h" +#include "extract_resource_manager.h" +#include "extractor.h" +#include "file_ex.h" +#include "file_mapper.h" +#include "file_path_utils.h" +#include "hdc_register.h" +#include "hilog_tag_wrapper.h" +#include "hitrace_meter.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "js_runtime.h" +#include "js_utils.h" +#include "module_checker_delegate.h" +#include "ohos_sts_environment_impl.h" +#include "parameters.h" +#include "source_map.h" +#include "source_map_operator.h" +#include "static_core/runtime/tooling/inspector/debugger_arkapi.h" +#include "sts_environment.h" +#include "syscap_ts.h" +#include "system_ability_definition.h" +#include "ets_ani_expo.h" +#include "static_core/plugins/ets/runtime/ets_namespace_manager.h" + +#ifdef SUPPORT_SCREEN +#include "ace_forward_compatibility.h" +#include "declarative_module_preloader.h" +#include "hot_reloader.h" +#endif //SUPPORT_SCREEN + +using namespace OHOS::AbilityBase; +using Extractor = OHOS::AbilityBase::Extractor; + +namespace OHOS { +namespace AbilityRuntime { +namespace { +#ifdef APP_USE_ARM64 +const std::string SANDBOX_LIB_PATH = "/system/lib64"; +const std::string STS_RT_PATH = SANDBOX_LIB_PATH; +const std::string STS_SYSLIB_PATH = "/system/lib64:/system/lib64/platformsdk:/" + "system/lib64/module:/system/lib64/ndk"; +const std::string STS_CHIPSDK_PATH = "/system/lib64/chipset-pub-sdk"; +#else +const std::string SANDBOX_LIB_PATH = "/system/lib"; +const std::string STS_RT_PATH = SANDBOX_LIB_PATH; +const std::string STS_SYSLIB_PATH = + "/system/lib:/system/lib/platformsdk:/system/lib/module:/system/lib/ndk"; +const std::string STS_CHIPSDK_PATH = "/system/lib/chipset-pub-sdk"; +#endif +constexpr char BUNDLE_INSTALL_PATH[] = "/data/storage/el1/bundle/"; +constexpr char SANDBOX_ARK_CACHE_PATH[] = "/data/storage/ark-cache/"; +constexpr char MERGE_ABC_PATH[] = "/ets/modules_static.abc"; +constexpr char ENTRY_PATH_MAP_FILE[] = "/system/framework/entrypath.json"; +constexpr char ENTRY_PATH_MAP_KEY[] = "entryPath"; +constexpr char DEFAULT_ENTRY_ABILITY_CLASS[] = "entry/src/main/ets/entryability/EntryAbility/EntryAbility"; +constexpr const char* STRING_CLASS_NAME = "Lstd/core/String;"; +constexpr const char* ABC_RUNTIME_LINKER_CLASS_NAME = "Lstd/core/AbcRuntimeLinker;"; +const int NUMBER_ZERO = 0; +const int NUMBER_TWO = 2; + +class EntryPathManager { +public: + static EntryPathManager &GetInstance() + { + static EntryPathManager instance; + return instance; + } + + bool Init() + { + std::ifstream inFile; + inFile.open(ENTRY_PATH_MAP_FILE, std::ios::in); + if (!inFile.is_open()) { + TAG_LOGD(AAFwkTag::STSRUNTIME, "no entrypath file"); + return false; + } + nlohmann::json filePathsJson; + inFile >> filePathsJson; + if (filePathsJson.is_discarded()) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "json discarded error"); + inFile.close(); + return false; + } + + if (filePathsJson.is_null() || filePathsJson.empty()) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "invalid json"); + inFile.close(); + return false; + } + + if (!filePathsJson.contains(ENTRY_PATH_MAP_KEY)) { + TAG_LOGD(AAFwkTag::STSRUNTIME, "no entrypath key"); + return false; + } + const auto &entryPathMap = filePathsJson[ENTRY_PATH_MAP_KEY]; + if (!entryPathMap.is_object()) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "entrypath is not object"); + return false; + } + + for (const auto &entryPath: entryPathMap.items()) { + std::string key = entryPath.key(); + if (!entryPath.value().is_string()) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "val is not string, key: %{public}s", key.c_str()); + continue; + } + std::string val = entryPath.value(); + TAG_LOGD(AAFwkTag::STSRUNTIME, "key: %{public}s, value: %{public}s", key.c_str(), val.c_str()); + entryPathMap_.emplace(key, val); + } + inFile.close(); + return true; + } + + std::string GetEntryPath(const std::string &srcEntry) + { + auto const &iter = entryPathMap_.find(srcEntry); + if (iter == entryPathMap_.end()) { + if (StartsWithDotSlash(srcEntry)) { + TAG_LOGD(AAFwkTag::STSRUNTIME, "not found srcEntry: %{public}s", srcEntry.c_str()); + return DEFAULT_ENTRY_ABILITY_CLASS; + } + TAG_LOGD(AAFwkTag::STSRUNTIME, "srcEntry as class: %{public}s", srcEntry.c_str()); + return HandleOhmUrlSrcEntry(srcEntry); + } + TAG_LOGD(AAFwkTag::STSRUNTIME, "found srcEntry: %{public}s, output: %{public}s", + srcEntry.c_str(), iter->second.c_str()); + return iter->second; + } + +private: + EntryPathManager() = default; + + ~EntryPathManager() = default; + + static bool StartsWithDotSlash(const std::string &str) + { + if (str.length() < NUMBER_TWO) { + return false; + } + std::string prefix = str.substr(NUMBER_ZERO, NUMBER_TWO); + return prefix == "./"; + } + + static std::string HandleOhmUrlSrcEntry(const std::string &srcEntry) + { + size_t lastSlashPos = srcEntry.rfind('/'); + if (lastSlashPos == std::string::npos) { + std::string fileName = srcEntry; + // If there is no slash, the entire string is processed directly. + HandleOhmUrlFileName(fileName); + return fileName; + } + std::string base = srcEntry.substr(0, lastSlashPos + 1); + std::string fileName = srcEntry.substr(lastSlashPos + 1); + HandleOhmUrlFileName(fileName); + return base + fileName; + } + + static void HandleOhmUrlFileName(std::string &fileName) + { + size_t colonPos = fileName.rfind(':'); + if (colonPos != std::string::npos) { + // : => / + fileName.replace(colonPos, 1, "/"); + } else { + // => / + fileName = fileName + "/" + fileName; + } + } + + std::map entryPathMap_{}; +}; +} // namespace + +AppLibPathVec STSRuntime::appLibPaths_; + +std::unique_ptr STSRuntime::PreFork(const Options& options) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "PreFork begin"); + std::unique_ptr instance = std::make_unique(); + if (!instance->Initialize(options)) { + return std::unique_ptr(); + } + EntryPathManager::GetInstance().Init(); + return instance; +} + +void STSRuntime::PostFork(const Options &options, std::vector& aniOptions, JsRuntime* jsRuntime) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "PostFork begin"); + isBundle_ = options.isBundle; + bundleName_ = options.bundleName; + codePath_ = options.codePath; + ReInitStsEnvImpl(options); + pkgContextInfoJsonStringMap_ = options.pkgContextInfoJsonStringMap; + packageNameList_ = options.packageNameList; + ReInitUVLoop(); + + // interop + const std::string optionPrefix = "--ext:"; + std::string interop = optionPrefix + "interop"; + ani_option interopOption = {interop.data(), (void*)jsRuntime->GetNapiEnv()}; + aniOptions.push_back(interopOption); + + // aot + std::string aotFileString = ""; + if (!options.arkNativeFilePath.empty()) { + std::string aotFilePath = SANDBOX_ARK_CACHE_PATH + options.arkNativeFilePath + options.moduleName + ".an"; + aotFileString = "--ext:--aot-file=" + aotFilePath; + aniOptions.push_back(ani_option{aotFileString.c_str(), nullptr}); + TAG_LOGI(AAFwkTag::STSRUNTIME, "aotFileString: %{public}s", aotFileString.c_str()); + aniOptions.push_back(ani_option{"--ext:--enable-an", nullptr}); + } + + ani_env* aniEnv = GetAniEnv(); + ark::ets::ETSAni::Postfork(aniEnv, aniOptions); +} + +std::unique_ptr STSRuntime::Create(const Options& options, JsRuntime* jsRuntime) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "create ets runtime"); + std::unique_ptr instance; + auto preloadedInstance = Runtime::GetPreloaded(options.lang); +#ifdef SUPPORT_SCREEN + // reload ace if compatible mode changes + if (Ace::AceForwardCompatibility::PipelineChanged() && preloadedInstance) { + preloadedInstance.reset(); + } +#endif + if (preloadedInstance && preloadedInstance->GetLanguage() == Runtime::Language::STS) { + instance.reset(static_cast(preloadedInstance.release())); + } else { + instance = PreFork(options); + } + + std::vector aniOptions; + instance->PostFork(options, aniOptions, jsRuntime); + return instance; +} + +void STSRuntime::SetAppLibPath(const AppLibPathMap& appLibPaths, const AppLibPathMap& appAbcLibPaths) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + std::string appPath = ""; + for (const auto& kv : appLibPaths) { + for (const auto& libPath : kv.second) { + TAG_LOGD(AAFwkTag::STSRUNTIME, "SetSTSAppLibPath: %{public}s.", libPath.c_str()); + STSRuntime::appLibPaths_.emplace_back(libPath); + appPath += appPath.empty() ? libPath : ":" + libPath; + } + } + + StsEnv::STSEnvironment::InitSTSChipSDKNS(STS_CHIPSDK_PATH); + StsEnv::STSEnvironment::InitSTSAppNS(appPath); + StsEnv::STSEnvironment::InitSTSSDKNS(STS_RT_PATH); + StsEnv::STSEnvironment::InitSTSSysNS(STS_SYSLIB_PATH); + + ark::ets::EtsNamespaceManager::SetAppLibPaths(appAbcLibPaths); +} + +bool STSRuntime::Initialize(const Options& options) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + if (options.lang != GetLanguage()) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "language mismatch"); + return false; + } + + if (!CreateStsEnv(options)) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Create stsEnv failed"); + return false; + } + + apiTargetVersion_ = options.apiTargetVersion; + TAG_LOGD(AAFwkTag::STSRUNTIME, "Initialize: %{public}d", apiTargetVersion_); + + if (!stsEnv_->InitLoop(options.isStageModel)) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Init loop failed"); + return false; + } + + return true; +} + +bool STSRuntime::LoadSTSAppLibrary(const AppLibPathVec& appLibPaths) +{ + if (stsEnv_ == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "null stsEnv_"); + return false; + } + + appLibLoaded_ = true; + return true; +} + +void STSRuntime::StartDebugMode(const DebugOption dOption) +{ + HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::STSRUNTIME, "localDebug %{public}d", dOption.isDebugFromLocal); + if (!dOption.isDebugFromLocal && !dOption.isDeveloperMode) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "developer Mode false"); + return; + } + // Set instance id to tid after the first instance. + instanceId_ = static_cast(getproctid()); + + bool isStartWithDebug = dOption.isStartWithDebug; + bool isDebugApp = dOption.isDebugApp; + std::string appProvisionType = dOption.appProvisionType; + TAG_LOGD(AAFwkTag::STSRUNTIME, "Ark VM is starting debug mode [%{public}s]", isStartWithDebug ? "break" : "normal"); + const std::string bundleName = bundleName_; + uint32_t instanceId = instanceId_; + std::string inputProcessName = bundleName_ != dOption.processName ? dOption.processName : ""; + HdcRegister::DebugRegisterMode debugMode = HdcRegister::DebugRegisterMode::HDC_DEBUG_REG; + auto weak = stsEnv_; + HdcRegister::Get().StartHdcRegister(bundleName_, inputProcessName, isDebugApp, debugMode, + [bundleName, isStartWithDebug, instanceId, weak, isDebugApp, appProvisionType] + (int socketFd, std::string option) { + TAG_LOGI(AAFwkTag::STSRUNTIME, "HdcRegister msg, fd= %{public}d, option= %{public}s", socketFd, option.c_str()); + // system is debuggable when const.secure is false and const.debuggable is true + bool isSystemDebuggable = system::GetBoolParameter("const.secure", true) == false && + system::GetBoolParameter("const.debuggable", false) == true; + // Don't start any server if (system not in debuggable mode) and app is release version + // Starting ConnectServer in release app on debuggable system is only for debug mode, not for profiling mode. + if ((!isSystemDebuggable) && appProvisionType == AppExecFwk::Constants::APP_PROVISION_TYPE_RELEASE) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "not support release app"); + return; + } + if (option.find(DEBUGGER) == std::string::npos) { + // if has old connect server, stop it + ConnectServerManager::Get().SendInstanceMessageAll(nullptr); + ConnectServerManager::Get().StartConnectServer(bundleName, socketFd, false); + } else { + if (appProvisionType == AppExecFwk::Constants::APP_PROVISION_TYPE_RELEASE) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "not support release app"); + return; + } + if (weak == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "null weak"); + return; + } + int32_t identifierId = weak->ParseHdcRegisterOption(option); + if (identifierId == -1) { + TAG_LOGE(AAFwkTag::JSENV, "Abnormal parsing of tid results"); + return; + } + weak->debugMode_ = ark::ArkDebugNativeAPI::StartDebuggerForSocketPair(identifierId, socketFd); + } + }); + DebuggerConnectionHandler(isDebugApp, isStartWithDebug); +} + +void STSRuntime::DebuggerConnectionHandler(bool isDebugApp, bool isStartWithDebug) +{ + ConnectServerManager::Get().StoreInstanceMessage(getproctid(), instanceId_, "Debugger"); + if (stsEnv_ == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "null stsEnv"); + return; + } + ark::ArkDebugNativeAPI::NotifyDebugMode(getproctid(), instanceId_, isStartWithDebug); +} + +void STSRuntime::UnLoadSTSAppLibrary() +{ + TAG_LOGI(AAFwkTag::STSRUNTIME, "UnLoadSTSAppLibrary not support yet"); +} + +void STSRuntime::RegisterUncaughtExceptionHandler(void* uncaughtExceptionInfo) +{ + if (stsEnv_ == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "null stsEnv_"); + return; + } + + if (uncaughtExceptionInfo == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "null uncaughtExceptionInfo"); + return; + } + + auto handle = static_cast(uncaughtExceptionInfo); + if (handle != nullptr) { + stsEnv_->RegisterUncaughtExceptionHandler(*handle); + } +} + +STSRuntime::~STSRuntime() +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + Deinitialize(); + StopDebugMode(); +} + +void STSRuntime::PostTask(const std::function& task, const std::string& name, int64_t delayTime) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + if (stsEnv_ != nullptr) { + stsEnv_->PostTask(task, name, delayTime); + } +} + +void STSRuntime::PostSyncTask(const std::function& task, const std::string& name) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + if (stsEnv_ != nullptr) { + stsEnv_->PostSyncTask(task, name); + } +} + +void STSRuntime::RemoveTask(const std::string& name) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + if (stsEnv_ != nullptr) { + stsEnv_->RemoveTask(name); + } +} + +void STSRuntime::Deinitialize() +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + for (auto it = modules_.begin(); it != modules_.end(); it = modules_.erase(it)) { + delete it->second; + it->second = nullptr; + } + + if (stsEnv_ != nullptr) { + stsEnv_->DeInitLoop(); + } +} + +bool STSRuntime::CreateStsEnv(const Options& options) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + stsEnv_ = std::make_shared(std::make_unique(options.eventRunner)); + std::vector aniOptions; + + std::string interpreerMode = "--ext:--interpreter-type=cpp"; + std::string debugEnalbeMode = "--ext:--debugger-enable=true"; + std::string debugLibraryPathMode = "--ext:--debugger-library-path=/system/lib64/libarkinspector.so"; + std::string breadonstartMode = "--ext:--debugger-break-on-start"; + if (options.isStartWithDebug) { + ani_option interpreterModeOption = {interpreerMode.data(), nullptr}; + aniOptions.push_back(interpreterModeOption); + ani_option debugEnalbeModeOption = {debugEnalbeMode.data(), nullptr}; + aniOptions.push_back(debugEnalbeModeOption); + ani_option debugLibraryPathModeOption = {debugLibraryPathMode.data(), nullptr}; + aniOptions.push_back(debugLibraryPathModeOption); + ani_option breadonstartModeOption = {breadonstartMode.data(), nullptr}; + aniOptions.push_back(breadonstartModeOption); + } + + if (stsEnv_ == nullptr || !stsEnv_->StartRuntime(aniOptions)) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Init StsEnv failed"); + return false; + } + + return true; +} + +void STSRuntime::ReInitStsEnvImpl(const Options& options) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + if (stsEnv_ == nullptr) { + return; + } + stsEnv_->ReInitStsEnvImpl(std::make_unique(options.eventRunner)); +} + +void STSRuntime::ReInitUVLoop() +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + if (stsEnv_ == nullptr) { + return; + } + stsEnv_->ReInitUVLoop(); +} + +ani_env* STSRuntime::GetAniEnv() +{ + if (stsEnv_ == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "null stsEnv_"); + return nullptr; + } + return stsEnv_->GetAniEnv(); +} + +void STSRuntime::PreloadModule(const std::string& moduleName, const std::string& hapPath, + bool isEsMode, bool useCommonTrunk) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "moduleName: %{public}s", moduleName.c_str()); + ani_env* aniEnv = GetAniEnv(); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "GetAniEnv failed"); + return; + } + ani_class stringCls = nullptr; + if (aniEnv->FindClass(STRING_CLASS_NAME, &stringCls) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "FindClass Lstd/core/String Failed"); + return; + } + std::string modulePath = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_PATH; + ani_string ani_str; + if (aniEnv->String_NewUTF8(modulePath.c_str(), modulePath.size(), &ani_str) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "String_NewUTF8 modulePath Failed"); + return; + } + ani_ref undefined_ref; + if (aniEnv->GetUndefined(&undefined_ref) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "GetUndefined failed"); + return; + } + ani_array_ref refArray; + if (aniEnv->Array_New_Ref(stringCls, 1, undefined_ref, &refArray) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Array_New_Ref Failed"); + return; + } + if (aniEnv->Array_Set_Ref(refArray, 0, ani_str) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Array_Set_Ref Failed"); + return; + } + ani_class cls = nullptr; + if (aniEnv->FindClass(ABC_RUNTIME_LINKER_CLASS_NAME, &cls) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "FindClass AbcRuntimeLinker failed"); + return; + } + ani_method method = nullptr; + if (aniEnv->Class_FindMethod(cls, "", "Lstd/core/RuntimeLinker;[Lstd/core/String;:V", &method) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Class_FindMethod ctor failed"); + return; + } + ani_object object = nullptr; + if (aniEnv->Object_New(cls, method, &object, undefined_ref, refArray) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Object_New AbcRuntimeLinker failed"); + } +} + +std::unique_ptr STSRuntime::LoadModule(const std::string& moduleName, + const std::string& modulePath, const std::string& hapPath, bool esmodule, bool useCommonChunk, + const std::string& srcEntrance) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "Load module(%{public}s, %{public}s, %{public}s, %{public}s)", + moduleName.c_str(), modulePath.c_str(), hapPath.c_str(), esmodule ? "true" : "false"); + + std::string path = moduleName; + auto pos = path.find("::"); + if (pos != std::string::npos) { + path.erase(pos, path.size() - pos); + moduleName_ = path; + } + TAG_LOGD(AAFwkTag::STSRUNTIME, "moduleName_(%{public}s, path %{public}s", + moduleName_.c_str(), path.c_str()); + + std::string fileName; + if (!hapPath.empty()) { + fileName.append(codePath_).append(Constants::FILE_SEPARATOR).append(modulePath); + std::regex pattern(std::string(Constants::FILE_DOT) + std::string(Constants::FILE_SEPARATOR)); + fileName = std::regex_replace(fileName, pattern, ""); + } else { + if (!MakeFilePath(codePath_, modulePath, fileName)) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "make module file path: %{public}s failed", modulePath.c_str()); + return nullptr; + } + } + std::unique_ptr stsNativeReference = LoadStsModule(moduleName, fileName, hapPath, srcEntrance); + return stsNativeReference; +} + +std::unique_ptr STSRuntime::LoadStsModule(const std::string& moduleName, + const std::string& path, const std::string& hapPath, const std::string& srcEntrance) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "Load sts module(%{public}s, %{public}s, %{public}s, %{public}s)", + moduleName.c_str(), path.c_str(), hapPath.c_str(), srcEntrance.c_str()); + auto stsNativeReference = std::make_unique(); + ani_env* aniEnv = GetAniEnv(); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "GetAniEnv failed"); + return std::make_unique(); + } + + ani_class stringCls = nullptr; + if (aniEnv->FindClass(STRING_CLASS_NAME, &stringCls) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "FindClass Lstd/core/String Failed"); + return std::make_unique(); + } + + std::string modulePath = BUNDLE_INSTALL_PATH + moduleName_ + MERGE_ABC_PATH; + ani_string ani_str; + if (aniEnv->String_NewUTF8(modulePath.c_str(), modulePath.size(), &ani_str) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "String_NewUTF8 modulePath Failed"); + return std::make_unique(); + } + + ani_ref undefined_ref; + if (aniEnv->GetUndefined(&undefined_ref) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "GetUndefined failed"); + return std::make_unique(); + } + ani_array_ref refArray; + if (aniEnv->Array_New_Ref(stringCls, 1, undefined_ref, &refArray) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Array_New_Ref Failed"); + return std::make_unique(); + } + if (aniEnv->Array_Set_Ref(refArray, 0, ani_str) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Array_Set_Ref Failed"); + return std::make_unique(); + } + + ani_class cls = nullptr; + if (aniEnv->FindClass(ABC_RUNTIME_LINKER_CLASS_NAME, &cls) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "FindClass AbcRuntimeLinker failed"); + return std::make_unique(); + } + ani_method method = nullptr; + if (aniEnv->Class_FindMethod(cls, "", "Lstd/core/RuntimeLinker;[Lstd/core/String;:V", &method) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Class_FindMethod ctor failed"); + return std::make_unique(); + } + ani_object object = nullptr; + aniEnv->ResetError(); + if (aniEnv->Object_New(cls, method, &object, undefined_ref, refArray) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Object_New AbcRuntimeLinker failed"); + HandleUncaughtError(); + return std::make_unique(); + } + ani_method loadClassMethod = nullptr; + if (aniEnv->Class_FindMethod(cls, "loadClass", nullptr, &loadClassMethod) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Class_FindMethod loadClass failed"); + return std::make_unique(); + } + std::string entryPath = EntryPathManager::GetInstance().GetEntryPath(srcEntrance); + ani_string entryClassStr; + aniEnv->String_NewUTF8(entryPath.c_str(), entryPath.length(), &entryClassStr); + ani_class entryClass = nullptr; + ani_ref entryClassRef = nullptr; + ani_boolean isInit = false; + TAG_LOGI(AAFwkTag::STSRUNTIME, "load class: %{public}s", entryPath.c_str()); + if (aniEnv->Object_CallMethod_Ref(object, loadClassMethod, &entryClassRef, entryClassStr, isInit) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Object_CallMethod_Ref loadClassMethod failed"); + return std::make_unique(); + } else { + entryClass = static_cast(entryClassRef); + } + + ani_method entryMethod = nullptr; + if (aniEnv->Class_FindMethod(entryClass, "", ":V", &entryMethod) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Class_FindMethod ctor failed"); + return std::make_unique(); + } + + ani_object entryObject = nullptr; + if (aniEnv->Object_New(entryClass, entryMethod, &entryObject) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Object_New AbcRuntimeLinker failed"); + return std::make_unique(); + } + + ani_ref entryObjectRef = nullptr; + if (aniEnv->GlobalReference_Create(entryObject, &entryObjectRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "GlobalReference_Create failed"); + return std::make_unique(); + } + stsNativeReference->aniCls = entryClass; + stsNativeReference->aniObj = entryObject; + stsNativeReference->aniRef = entryObjectRef; + return stsNativeReference; +} + +bool STSRuntime::RunScript(ani_env* aniEnv, const std::string& moduleName, const std::string& abcPath, + const std::string& hapPath, const std::string& srcEntrance) +{ + bool newCreate = false; + std::string loadPath = ExtractorUtil::GetLoadFilePath(hapPath); + TAG_LOGE(AAFwkTag::STSRUNTIME, "hapPath[%{public}s], loadPath:%{public}s", hapPath.c_str(), loadPath.c_str()); + // need vm support Aot. + return true; +} + +void STSRuntime::HandleUncaughtError() +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + if (stsEnv_ == nullptr) { + return; + } + stsEnv_->HandleUncaughtError(); +} + +void STSRuntime::StopDebugMode() +{ + CHECK_POINTER(stsEnv_); + if (stsEnv_->debugMode_) { + ConnectServerManager::Get().RemoveInstance(instanceId_); + ark::ArkDebugNativeAPI::StopDebugger(); + } +} + +void STSRuntime::FinishPreload() +{ + ani_env* env = GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Failed: ANI env nullptr"); + return; + } + ark::ets::ETSAni::Prefork(env); +} + +void STSRuntime::PreloadClass(const char *className) +{ + ani_env* env = GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "GetAniEnv failed"); + return; + } + + ani_class cls = nullptr; + if (env->FindClass(className, &cls) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Find preload class failed"); + return; + } +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/simulator/BUILD.gn b/frameworks/simulator/BUILD.gn index fe4510fae1e6e38952fe7676fdff55994d69f75f..ef4dc70c41b77a9269b4e59eda791f69596dcce6 100644 --- a/frameworks/simulator/BUILD.gn +++ b/frameworks/simulator/BUILD.gn @@ -16,8 +16,10 @@ import("//foundation/ability/ability_runtime/ability_runtime.gni") if (is_mac) { dylib_suffix = ".dylib" -} else { +} else if (is_mingw) { dylib_suffix = ".dll" +} else if (is_linux) { + dylib_suffix = ".so" } not_needed("*", [ "dylib_suffix" ]) diff --git a/frameworks/simulator/ability_simulator/BUILD.gn b/frameworks/simulator/ability_simulator/BUILD.gn index a4111ede3463af8d0bba32763eff0113ad82c389..f18a2ca4bb4b86cb0a368ce7102876b820156b38 100644 --- a/frameworks/simulator/ability_simulator/BUILD.gn +++ b/frameworks/simulator/ability_simulator/BUILD.gn @@ -21,7 +21,7 @@ config("ability_simulator_public_config") { } ohos_shared_library("ability_simulator_inner") { - if (is_mingw || is_mac) { + if (is_mingw || is_mac || is_linux) { if (is_mingw) { defines = [ "WINDOWS_PLATFORM", @@ -43,6 +43,7 @@ ohos_shared_library("ability_simulator_inner") { "${windowmanager_path}/interfaces/innerkits/wm", "${windowmanager_path}/interfaces/kits/napi/window_runtime/window_stage_napi", "include/bundle_parser", + "${resource_management_path}/interfaces/inner_api/include", ] sources = [ @@ -101,8 +102,10 @@ ohos_shared_library("ability_simulator_inner") { if (is_mingw) { external_deps += [ "resource_management:win_resmgr" ] - } else { + } else if (is_mac) { external_deps += [ "resource_management:mac_resmgr" ] + } else if (is_linux) { + external_deps += [ "resource_management:linux_resmgr" ] } } @@ -113,7 +116,7 @@ ohos_shared_library("ability_simulator_inner") { } group("ability_simulator") { - if (is_mingw || is_mac) { + if (is_mingw || is_mac || is_linux) { public_deps = [ ":ability_simulator_inner" ] } } diff --git a/frameworks/simulator/ability_simulator/include/bundle_parser/inner_bundle_info.h b/frameworks/simulator/ability_simulator/include/bundle_parser/inner_bundle_info.h index 2f8dead654c209f7996d6747a3a291fe1c79001b..23ec315115d42bf321f851a1f2bc75d4bd8e9fef 100644 --- a/frameworks/simulator/ability_simulator/include/bundle_parser/inner_bundle_info.h +++ b/frameworks/simulator/ability_simulator/include/bundle_parser/inner_bundle_info.h @@ -16,6 +16,8 @@ #ifndef OHOS_ABILITY_RUNTIME_SIMULATOR_INNER_BUNDLE_INFO_H #define OHOS_ABILITY_RUNTIME_SIMULATOR_INNER_BUNDLE_INFO_H +#include + #include "nocopyable.h" #include "ability_info.h" #include "bundle_constants.h" diff --git a/frameworks/simulator/ability_simulator/include/simulator.h b/frameworks/simulator/ability_simulator/include/simulator.h index d1cfb0bf2d5a3afe313af8ec7a1fea816810d693..3b33d633eb76c7fc32917af50bc0b220d5266c95 100644 --- a/frameworks/simulator/ability_simulator/include/simulator.h +++ b/frameworks/simulator/ability_simulator/include/simulator.h @@ -36,7 +36,7 @@ public: using TerminateCallback = std::function; using FormUpdateCallback = std::function; using ResolveBufferTrackerCallback = std::function; + const std::string&, bool, uint8_t **, size_t *, std::string& errorMsg)>; /** * Create a simulator instance. diff --git a/frameworks/simulator/ability_simulator/src/simulator.cpp b/frameworks/simulator/ability_simulator/src/simulator.cpp index ef34549f47424c19db19aeb5da9b9a0dccf3a651..5207a2b7e8dd6d67da7c95ea267f38ad841ed3dd 100644 --- a/frameworks/simulator/ability_simulator/src/simulator.cpp +++ b/frameworks/simulator/ability_simulator/src/simulator.cpp @@ -68,6 +68,8 @@ const std::string DEPENDENCY_ALIAS = "dependencyAlias"; constexpr char ARK_DEBUGGER_LIB_PATH[] = "libark_inspector.dll"; #elif defined(MAC_PLATFORM) constexpr char ARK_DEBUGGER_LIB_PATH[] = "libark_inspector.dylib"; +#elif defined(LINUX_PLATFORM) +constexpr char ARK_DEBUGGER_LIB_PATH[] = "libark_inspector.so"; #else #error "Unsupported platform" #endif diff --git a/frameworks/simulator/build/ability_simulator.gni b/frameworks/simulator/build/ability_simulator.gni index e7f52af63980c84d32660103be922f8e69b0944a..1225e393d9232539c13367329879bdd08fa45ab3 100644 --- a/frameworks/simulator/build/ability_simulator.gni +++ b/frameworks/simulator/build/ability_simulator.gni @@ -29,7 +29,7 @@ template("gen_js_src_binary") { gen_obj(target_name + "_js") { input = invoker.js_source - if (is_mac || is_mingw) { + if (is_mac || is_mingw || is_linux) { output = target_out_dir + "/" + invoker.target_name + "_js.c" } else { output = target_out_dir + "/" + invoker.target_name + "_js.o" @@ -43,7 +43,7 @@ template("gen_js_src_binary") { get_label_info(":gen_abc_" + invoker.target_name, "target_out_dir") + "/" + get_path_info(invoker.js_source, "name") + ".abc" - if (is_mac || is_mingw) { + if (is_mac || is_mingw || is_linux) { output = target_out_dir + "/" + invoker.target_name + "_abc.c" } else { output = target_out_dir + "/" + invoker.target_name + "_abc.o" diff --git a/interfaces/inner_api/ability_manager/include/ability_state.h b/interfaces/inner_api/ability_manager/include/ability_state.h index e1dc60c851caec9a2cc250ee72ff6e073c547b65..13e842873485f919db23b92ffdaf7a3bd566897a 100644 --- a/interfaces/inner_api/ability_manager/include/ability_state.h +++ b/interfaces/inner_api/ability_manager/include/ability_state.h @@ -61,7 +61,8 @@ enum Reason { REASON_UPGRADE, REASON_USER_REQUEST, REASON_SIGNAL, - REASON_MAX = REASON_SIGNAL, + REASON_STS_ERROR, + REASON_MAX = REASON_STS_ERROR, }; enum UserStatus { diff --git a/interfaces/inner_api/ability_manager/include/mission_info.h b/interfaces/inner_api/ability_manager/include/mission_info.h index 999f679838ee5c93060fac075fa2ab709d7a8fab..70d80a71efb05dcadc9e43c47319538ba9275173 100644 --- a/interfaces/inner_api/ability_manager/include/mission_info.h +++ b/interfaces/inner_api/ability_manager/include/mission_info.h @@ -65,6 +65,12 @@ struct MissionValidResult : public Parcelable { int32_t missionId = -1; bool isValid = false; }; +// enum ContinueState { +// ACTIVE = 0, +// INACTIVE = 1 +// } +[[maybe_unused]] static ContinueState ContinueState_ConvertStsToNative(const int32_t index); +[[maybe_unused]] static int32_t ContinueState_ConvertNativeToSts(const ContinueState index); } // namespace AAFwk } // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_MISSION_INFO_H diff --git a/interfaces/inner_api/ability_manager/include/process_options.h b/interfaces/inner_api/ability_manager/include/process_options.h index 97f3ddc315bf09b7990f100346e4475b54e09d93..8f07e2668f11daa678009eeff9a7c4865c53f115 100644 --- a/interfaces/inner_api/ability_manager/include/process_options.h +++ b/interfaces/inner_api/ability_manager/include/process_options.h @@ -47,7 +47,11 @@ public: static ProcessOptions *Unmarshalling(Parcel &parcel); static ProcessMode ConvertInt32ToProcessMode(int32_t value); + static ProcessMode ConvertStsToProcessMode(int32_t index); + static int32_t ConvertProcessModeToSts(const ProcessMode ProcessMode); static StartupVisibility ConvertInt32ToStartupVisibility(int32_t value); + static StartupVisibility ConvertStsToStartupVisibility(int32_t index); + static int32_t ConvertStartupVisibilityToSts(const StartupVisibility value); static bool IsNewProcessMode(ProcessMode value); static bool IsAttachToStatusBarMode(ProcessMode value); static bool IsValidProcessMode(ProcessMode value); diff --git a/interfaces/inner_api/ani_base_context/BUILD.gn b/interfaces/inner_api/ani_base_context/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..c3788b3fe9ad8232638ece8f66e58713c2ec7800 --- /dev/null +++ b/interfaces/inner_api/ani_base_context/BUILD.gn @@ -0,0 +1,56 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +config("ani_context_base_public_config") { + visibility = [ ":*" ] + include_dirs = [ + "include" , + "${ability_runtime_services_path}/common/include", + ] +} + +ohos_shared_library("ani_base_context") { + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "include", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "${ability_runtime_services_path}/common/include", + ] + + sources = [ "src/ani_base_context.cpp" ] + + configs = [] + + public_configs = [ ":ani_context_base_public_config" ] + + external_deps = [ + "ability_base:configuration", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "hilog:libhilog", + "runtime_core:ani", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} diff --git a/interfaces/inner_api/ani_base_context/include/ani_base_context.h b/interfaces/inner_api/ani_base_context/include/ani_base_context.h new file mode 100644 index 0000000000000000000000000000000000000000..d9baa5b802154defb20bc581ee3c557d100229b0 --- /dev/null +++ b/interfaces/inner_api/ani_base_context/include/ani_base_context.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ANI_BASE_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_ANI_BASE_CONTEXT_H + +#include "ani.h" + +#include +#include +#include +#include +#include "context.h" + +namespace OHOS { +namespace AppExecFwk { +class Ability; +} + +namespace AbilityRuntime { + /** + * @brief Get "stageMode" value of object. + * + * @param env NAPI environment. + * @param object Native value contains "stageMode" object. + * @param stageMode The value of "stageMode" object. + * @return napi_status + */ + ani_status IsStageContext(ani_env* env, ani_object object, ani_boolean& stageMode); + + /** + * @brief Get stage mode context. + * + * @param env NAPI environment. + * @param object Native value of context. + * @return The stage mode context. + */ + class Context; + std::shared_ptr GetStageModeContext(ani_env* env, ani_object object); + + /** + * @brief Get current ability. + * + * @param env NAPI environment. + * @return The pointer of current ability. + */ + AppExecFwk::Ability* GetCurrentAbility(ani_env* env); +} +} +#endif // OHOS_ABILITY_RUNTIME_ANI_BASE_CONTEXT_H diff --git a/interfaces/inner_api/ani_base_context/src/ani_base_context.cpp b/interfaces/inner_api/ani_base_context/src/ani_base_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ebfee017eaa300f57f4d6e4a89b1402aab89c90a --- /dev/null +++ b/interfaces/inner_api/ani_base_context/src/ani_base_context.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_base_context.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +ani_status IsStageContext(ani_env* env, ani_object object, ani_boolean& stageMode) +{ + // arkTS 1.2 only supported stage mode + stageMode = true; + return ANI_OK; +} + +std::shared_ptr GetStageModeContext(ani_env* env, ani_object object) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "env is nullptr"); + return nullptr; + } + + ani_long nativeContextLong; + ani_status status = env->Object_GetFieldByName_Long(object, "nativeContext", &nativeContextLong); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "Object_GetField_Long failed, status : %{public}d", status); + return nullptr; + } + + auto weakContext = reinterpret_cast*>(nativeContextLong); + return weakContext != nullptr ? weakContext->lock() : nullptr; +} + +AppExecFwk::Ability* GetCurrentAbility(ani_env* env) +{ + return nullptr; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/interfaces/inner_api/app_manager/include/appmgr/app_mem_info.h b/interfaces/inner_api/app_manager/include/appmgr/app_mem_info.h index 82f2bad284002250901616ac21610d8d247e52b1..2ff17ae71586887ace70bb5217e368605fd9882d 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/app_mem_info.h +++ b/interfaces/inner_api/app_manager/include/appmgr/app_mem_info.h @@ -23,6 +23,14 @@ enum MemoryLevel { MEMORY_LEVEL_LOW = 1, MEMORY_LEVEL_CRITICAL = 2, }; +[[maybe_unused]] static MemoryLevel MemoryLevel_ConvertStsToNative(const int index) +{ + return static_cast(index); +} +[[maybe_unused]] static MemoryLevel MemoryLevel_ConvertNativeToSts(const MemoryLevel value) +{ + return value; +} } // namespace AppExecFwk } // namespace OHOS diff --git a/interfaces/inner_api/app_manager/include/appmgr/fault_data.h b/interfaces/inner_api/app_manager/include/appmgr/fault_data.h index 6ab902f3c5f904e1b8036a7cca42d22fc3f42c30..ffa8415e0507fde8bb2b5a674b5c719ab15a595d 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/fault_data.h +++ b/interfaces/inner_api/app_manager/include/appmgr/fault_data.h @@ -1,101 +1,102 @@ -/* - * Copyright (c) 2023 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_FAULT_DATA_H -#define OHOS_ABILITY_RUNTIME_FAULT_DATA_H - -#include - -#include "ierror_observer.h" -#include "iremote_object.h" -#include "parcel.h" - -namespace OHOS { -namespace AppExecFwk { - -/** - * @enum FaultDataType - * FaultDataType defines the type of FaultData. - */ -enum class FaultDataType { - UNKNOWN = -1, - CPP_CRASH, - JS_ERROR, - CJ_ERROR, - APP_FREEZE, - PERFORMANCE_CONTROL, - RESOURCE_CONTROL -}; - -class AppFreezeType { -public: - static constexpr char LIFECYCLE_HALF_TIMEOUT[] = "LIFECYCLE_HALF_TIMEOUT"; - static constexpr char LIFECYCLE_TIMEOUT[] = "LIFECYCLE_TIMEOUT"; - static constexpr char APP_LIFECYCLE_TIMEOUT[] = "APP_LIFECYCLE_TIMEOUT"; - static constexpr char THREAD_BLOCK_3S[] = "THREAD_BLOCK_3S"; - static constexpr char THREAD_BLOCK_6S[] = "THREAD_BLOCK_6S"; - static constexpr char APP_INPUT_BLOCK[] = "APP_INPUT_BLOCK"; - static constexpr char BUSSINESS_THREAD_BLOCK_3S[] = "BUSSINESS_THREAD_BLOCK_3S"; - static constexpr char BUSSINESS_THREAD_BLOCK_6S[] = "BUSSINESS_THREAD_BLOCK_6S"; -}; -/** - * @struct FaultData - * FaultData is used to save information about faultdata. - */ -struct FaultData : public Parcelable { - bool ReadFromParcel(Parcel &parcel); - bool WriteContent(Parcel &parcel) const; - virtual bool Marshalling(Parcel &parcel) const override; - static FaultData *Unmarshalling(Parcel &parcel); - // error object - ErrorObject errorObject; - FaultDataType faultType = FaultDataType::UNKNOWN; - std::string timeoutMarkers; - bool waitSaveState = false; - bool notifyApp = false; - bool forceExit = false; - bool needKillProcess = true; - uint32_t state = 0; - int32_t eventId = -1; - int32_t tid = -1; - uint32_t stuckTimeout = 0; - sptr token = nullptr; -}; - -/** - * @struct AppFaultDataBySA - * AppFaultDataBySA is used to save information about faultdata notified by SA. - */ -struct AppFaultDataBySA : public Parcelable { - bool ReadFromParcel(Parcel &parcel); - bool waitSaveState = false; - bool notifyApp = false; - bool forceExit = false; - bool needKillProcess = true; - bool WriteErrorObject(Parcel &parcel) const; - virtual bool Marshalling(Parcel &parcel) const override; - static AppFaultDataBySA *Unmarshalling(Parcel &parcel); - // error object - ErrorObject errorObject; - FaultDataType faultType = FaultDataType::UNKNOWN; - int32_t pid = -1; - uint32_t state = 0; - int32_t eventId = -1; - sptr token = nullptr; - std::string timeoutMarkers; -}; -} // namespace AppExecFwk -} // namespace OHOS +/* + * Copyright (c) 2023 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_FAULT_DATA_H +#define OHOS_ABILITY_RUNTIME_FAULT_DATA_H + +#include + +#include "ierror_observer.h" +#include "iremote_object.h" +#include "parcel.h" + +namespace OHOS { +namespace AppExecFwk { + +/** + * @enum FaultDataType + * FaultDataType defines the type of FaultData. + */ +enum class FaultDataType { + UNKNOWN = -1, + CPP_CRASH, + JS_ERROR, + CJ_ERROR, + APP_FREEZE, + PERFORMANCE_CONTROL, + RESOURCE_CONTROL, + STS_ERROR +}; + +class AppFreezeType { +public: + static constexpr char LIFECYCLE_HALF_TIMEOUT[] = "LIFECYCLE_HALF_TIMEOUT"; + static constexpr char LIFECYCLE_TIMEOUT[] = "LIFECYCLE_TIMEOUT"; + static constexpr char APP_LIFECYCLE_TIMEOUT[] = "APP_LIFECYCLE_TIMEOUT"; + static constexpr char THREAD_BLOCK_3S[] = "THREAD_BLOCK_3S"; + static constexpr char THREAD_BLOCK_6S[] = "THREAD_BLOCK_6S"; + static constexpr char APP_INPUT_BLOCK[] = "APP_INPUT_BLOCK"; + static constexpr char BUSSINESS_THREAD_BLOCK_3S[] = "BUSSINESS_THREAD_BLOCK_3S"; + static constexpr char BUSSINESS_THREAD_BLOCK_6S[] = "BUSSINESS_THREAD_BLOCK_6S"; +}; +/** + * @struct FaultData + * FaultData is used to save information about faultdata. + */ +struct FaultData : public Parcelable { + bool ReadFromParcel(Parcel &parcel); + bool WriteContent(Parcel &parcel) const; + virtual bool Marshalling(Parcel &parcel) const override; + static FaultData *Unmarshalling(Parcel &parcel); + // error object + ErrorObject errorObject; + FaultDataType faultType = FaultDataType::UNKNOWN; + std::string timeoutMarkers; + bool waitSaveState = false; + bool notifyApp = false; + bool forceExit = false; + bool needKillProcess = true; + uint32_t state = 0; + int32_t eventId = -1; + int32_t tid = -1; + uint32_t stuckTimeout = 0; + sptr token = nullptr; +}; + +/** + * @struct AppFaultDataBySA + * AppFaultDataBySA is used to save information about faultdata notified by SA. + */ +struct AppFaultDataBySA : public Parcelable { + bool ReadFromParcel(Parcel &parcel); + bool waitSaveState = false; + bool notifyApp = false; + bool forceExit = false; + bool needKillProcess = true; + bool WriteErrorObject(Parcel &parcel) const; + virtual bool Marshalling(Parcel &parcel) const override; + static AppFaultDataBySA *Unmarshalling(Parcel &parcel); + // error object + ErrorObject errorObject; + FaultDataType faultType = FaultDataType::UNKNOWN; + int32_t pid = -1; + uint32_t state = 0; + int32_t eventId = -1; + sptr token = nullptr; + std::string timeoutMarkers; +}; +} // namespace AppExecFwk +} // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_FAULT_DATA_H \ No newline at end of file diff --git a/interfaces/inner_api/app_manager/include/appmgr/running_process_info.h b/interfaces/inner_api/app_manager/include/appmgr/running_process_info.h index 6c96641868d6290c8f876c9b8ad9ec5abd818a11..c062b273dd615692a1d7c12db7ca0dbc0ec04ef1 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/running_process_info.h +++ b/interfaces/inner_api/app_manager/include/appmgr/running_process_info.h @@ -78,6 +78,8 @@ struct RunningProcessInfo : public Parcelable { ProcessType processType_ = ProcessType::NORMAL; ExtensionAbilityType extensionType_ = ExtensionAbilityType::UNSPECIFIED; }; +[[maybe_unused]] static AppProcessState AppProcessState_ConvertStsToNative(const int32_t index); +[[maybe_unused]] static int32_t AppProcessState_ConvertNativeToSts(const AppProcessState value); } // namespace AppExecFwk } // namespace OHOS diff --git a/interfaces/inner_api/app_manager/src/appmgr/running_process_info.cpp b/interfaces/inner_api/app_manager/src/appmgr/running_process_info.cpp index 496197617cd366f2583e498060d49ccec9d79741..079b5102c3a779e830fbe488f7bc28ee89cb5f51 100644 --- a/interfaces/inner_api/app_manager/src/appmgr/running_process_info.cpp +++ b/interfaces/inner_api/app_manager/src/appmgr/running_process_info.cpp @@ -113,5 +113,20 @@ bool RunningProcessInfo::Marshalling(Parcel &parcel) const WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, static_cast(pssValue)); return true; } +// enum ProcessState { +// STATE_CREATE, +// STATE_FOREGROUND, +// STATE_ACTIVE, +// STATE_BACKGROUND, +// STATE_DESTROY +// } +AppProcessState AppProcessState_ConvertStsToNative(const int32_t index) +{ + return static_cast(index); +} +int32_t AppProcessState_ConvertNativeToSts(const AppProcessState value) +{ + return static_cast(value); //todo wlh +} } // namespace AppExecFwk } // namespace OHOS diff --git a/interfaces/inner_api/connect_server_manager/BUILD.gn b/interfaces/inner_api/connect_server_manager/BUILD.gn index c2c684462c3aa841d1cc7b8b242102147ddd9f05..3f285a6fd25b1ad26c81bf7144635517eb4127d8 100644 --- a/interfaces/inner_api/connect_server_manager/BUILD.gn +++ b/interfaces/inner_api/connect_server_manager/BUILD.gn @@ -53,6 +53,7 @@ ohos_shared_library("connect_server_manager") { external_deps = [ "ets_runtime:libark_jsruntime", "hilog:libhilog", + "runtime_core:libarkruntime", ] configs = [ diff --git a/interfaces/inner_api/connect_server_manager/include/connect_server_manager.h b/interfaces/inner_api/connect_server_manager/include/connect_server_manager.h index 07ccd38995ab7dbe10fd3a01c45e62a22fe72fec..5cdeb4fbc5d8267f8a0b2e1da68d1f1826df25c4 100644 --- a/interfaces/inner_api/connect_server_manager/include/connect_server_manager.h +++ b/interfaces/inner_api/connect_server_manager/include/connect_server_manager.h @@ -52,6 +52,7 @@ public: void SetConnectedCallback(); bool SendInstanceMessage(int32_t tid, int32_t instanceId, const std::string& instanceName); void SendDebuggerInfo(bool needBreakPoint, bool isDebugApp); + void SendInstanceMessageAll(std::function callback); void LoadConnectServerDebuggerSo(); DebuggerPostTask GetDebuggerPostTask(int32_t tid); bool SetRecordCallback(const std::function &startRecordFunc, diff --git a/interfaces/inner_api/connect_server_manager/src/connect_server_manager.cpp b/interfaces/inner_api/connect_server_manager/src/connect_server_manager.cpp index bd7678ce0488ae1a442330c6a394c6e4be44079c..60d5971645fdf2ca1a42384f6ba93a01fd49715d 100644 --- a/interfaces/inner_api/connect_server_manager/src/connect_server_manager.cpp +++ b/interfaces/inner_api/connect_server_manager/src/connect_server_manager.cpp @@ -188,6 +188,26 @@ void ConnectServerManager::SendDebuggerInfo(bool needBreakPoint, bool isDebugApp } } +void ConnectServerManager::SendInstanceMessageAll(std::function callback) +{ + ConnectServerManager::Get().SetConnectedCallback(); + std::lock_guard lock(mutex_); + for (const auto& instance : instanceMap_) { + auto instanceId = instance.first; + auto instanceName = instance.second.first; + auto tid = instance.second.second; + std::lock_guard lock(g_debuggerMutex); + ConnectServerManager::Get().SendInstanceMessage(tid, instanceId, instanceName); + const auto &debuggerPostTask = g_debuggerInfo[tid].second; + if (!debuggerPostTask) { + continue; + } + if (callback != nullptr) { + callback(tid, debuggerPostTask); + } + } +} + void ConnectServerManager::SetConnectedCallback() { LoadConnectServerDebuggerSo(); diff --git a/interfaces/inner_api/insight_intent/insight_intent_context/ets_insight_intent_context.h b/interfaces/inner_api/insight_intent/insight_intent_context/ets_insight_intent_context.h new file mode 100644 index 0000000000000000000000000000000000000000..da3469860a7afe7357bcdc6ee32e4acdd3bfe06b --- /dev/null +++ b/interfaces/inner_api/insight_intent/insight_intent_context/ets_insight_intent_context.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_CONTEXT_H + +#include "sts_runtime.h" +#include "insight_intent_context.h" +namespace OHOS { +namespace AbilityRuntime { +/** + * @class EtsInsightIntentContext + * EtsInsightIntentContext provides a context for insightintent to execute certain tasks. + */ +class EtsInsightIntentContext final { +public: + + explicit EtsInsightIntentContext(const std::shared_ptr& context) : context_(context) {} + ~EtsInsightIntentContext() = default; + + static void Finalizer(ani_env *env, void* data, void* hint); + + /** + * Starts a new ability. Only such ability in the same application with the + * caller can be started. + * + * @param env, the ani environment. + * @param info, the params passed from ets caller. + * + * @return result of StartAbility. + */ + static ani_object StartAbiitySync([[maybe_unused]] ani_env *env, + [[maybe_unused]] ani_object aniObj, ani_object wantObj); + static std::shared_ptr GetContext(ani_env *env, ani_object aniObj); + + private: + ani_object StartAbilityInner(ani_env *env, AAFwk::Want &want); + std::weak_ptr context_; +}; + +std::unique_ptr CreateEtsInsightIntentContext(ani_env *env, + const std::shared_ptr& context); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_CONTEXT_H diff --git a/interfaces/inner_api/runtime/BUILD.gn b/interfaces/inner_api/runtime/BUILD.gn index 0732f3424759411e55fcb3413394b5ed795cdbe9..4d21a38c5c46fe630a8f5ed2fa12cf0dea4549c2 100644 --- a/interfaces/inner_api/runtime/BUILD.gn +++ b/interfaces/inner_api/runtime/BUILD.gn @@ -40,6 +40,7 @@ config("runtime_public_config") { visibility += [ "${ability_runtime_napi_path}/inner/napi_common:napi_common" ] include_dirs = [ "${ability_runtime_path}/interfaces/kits/native/ability/native/ability_business_error", + "${ability_runtime_path}/sts_environment/interfaces/inner_api", "include", ] } @@ -54,6 +55,8 @@ ohos_shared_library("runtime") { include_dirs = [ "${ability_runtime_path}/services/abilitymgr/include", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_bundle_manager_helper", + "${ability_runtime_path}/sts_environment/interfaces/inner_api", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", "${ability_runtime_utils_path}/global/constant", ] @@ -72,7 +75,11 @@ ohos_shared_library("runtime") { "${ability_runtime_native_path}/runtime/ohos_js_env_logger.cpp", "${ability_runtime_native_path}/runtime/ohos_js_environment_impl.cpp", "${ability_runtime_native_path}/runtime/ohos_loop_handler.cpp", + "${ability_runtime_native_path}/runtime/ohos_sts_environment_impl.cpp", "${ability_runtime_native_path}/runtime/runtime.cpp", + "${ability_runtime_native_path}/runtime/sts_data_struct_converter.cpp", + "${ability_runtime_native_path}/runtime/sts_error_utils.cpp", + "${ability_runtime_native_path}/runtime/sts_runtime.cpp", ] configs = [ ":runtime_config" ] @@ -87,6 +94,7 @@ ohos_shared_library("runtime") { "${ability_runtime_native_path}/ability/native:ability_business_error", "${ability_runtime_native_path}/appkit:appkit_manager_helper", "${ability_runtime_path}/js_environment/frameworks/js_environment:js_environment", + "${ability_runtime_path}/sts_environment/frameworks/sts_environment:sts_environment", "${ability_runtime_services_path}/common:app_util", ] @@ -116,6 +124,8 @@ ohos_shared_library("runtime") { "jsoncpp:jsoncpp", "napi:ace_napi", "resource_management:global_resmgr", + "runtime_core:ani", + "runtime_core:libarkruntime", "samgr:samgr_proxy", "zlib:shared_libz", ] diff --git a/interfaces/inner_api/runtime/include/cj_runtime.h b/interfaces/inner_api/runtime/include/cj_runtime.h index 518ef719567ec3418c5f5e1b4b59c12486aef724..c1f3f6f0faf94ed4c5f75296249b61071be55904 100644 --- a/interfaces/inner_api/runtime/include/cj_runtime.h +++ b/interfaces/inner_api/runtime/include/cj_runtime.h @@ -54,6 +54,8 @@ public: const std::string& hapPath, bool isEsMode, const std::string& srcEntrance) override {} void PreloadModule(const std::string& moduleName, const std::string& srcPath, const std::string& hapPath, bool isEsMode, bool useCommonTrunk) override {} + void PreloadModule(const std::string& moduleName, const std::string& hapPath, + bool isEsMode, bool useCommonTrunk) override {} void FinishPreload() override {} bool LoadRepairPatch(const std::string& patchFile, const std::string& baseFile) override { return false; } bool NotifyHotReloadPage() override { return false; } @@ -71,9 +73,8 @@ public: void DumpCpuProfile() override {}; void AllowCrossThreadExecution() override {}; void GetHeapPrepare() override {}; - void RegisterUncaughtExceptionHandler(const CJUncaughtExceptionInfo& uncaughtExceptionInfo); static bool RegisterCangjieCallback(); - + void RegisterUncaughtExceptionHandler(void* uncaughtExceptionInfo) override; private: bool StartDebugger(); bool LoadCJAppLibrary(const AppLibPathVec& appLibPaths); diff --git a/interfaces/inner_api/runtime/include/js_runtime.h b/interfaces/inner_api/runtime/include/js_runtime.h index f7e97f55d7b0e8d51606f757747901f750a1643d..fbf74d0440fe7f680d6d775854aa89803f73fa24 100644 --- a/interfaces/inner_api/runtime/include/js_runtime.h +++ b/interfaces/inner_api/runtime/include/js_runtime.h @@ -50,6 +50,13 @@ struct UncaughtExceptionInfo; using AppLibPathMap = std::map>; +#ifdef APP_USE_ARM +constexpr char ARK_DEBUGGER_LIB_PATH[] = "libark_inspector.z.so"; +#elif defined(APP_USE_X86_64) +constexpr char ARK_DEBUGGER_LIB_PATH[] = "libark_inspector.z.so"; +#else +constexpr char ARK_DEBUGGER_LIB_PATH[] = "libark_inspector.z.so"; +#endif namespace AbilityRuntime { class TimerTask; @@ -101,8 +108,11 @@ public: const std::string& hapPath, bool isEsMode, const std::string& srcEntrance) override; void PreloadModule(const std::string& moduleName, const std::string& srcPath, const std::string& hapPath, bool isEsMode, bool useCommonTrunk) override; + void PreloadModule(const std::string& moduleName, const std::string& hapPath, + bool isEsMode, bool useCommonTrunk) override {} bool PopPreloadObj(const std::string& key, std::unique_ptr& obj); void StartDebugMode(const DebugOption debugOption) override; + bool ShouldSkipDebugMode(const DebugOption debugOption); void SetDebugOption(const DebugOption debugOption) override; void StartLocalDebugMode(bool isDebugFromLocal) override; void DebuggerConnectionHandler(bool isDebugApp, bool isStartWithDebug); @@ -148,6 +158,7 @@ public: void SetPkgContextInfoJson(std::string moduleName, std::string hapPath, std::string packageName); void UpdatePkgContextInfoJson(const std::string& moduleName, const std::string& hapPath, const std::string& packageName); + void RegisterUncaughtExceptionHandler(void* uncaughtExceptionInfo) override; private: void FinishPreload() override; diff --git a/interfaces/inner_api/runtime/include/runtime.h b/interfaces/inner_api/runtime/include/runtime.h index 4352d27ba869975340d5c9b4b8d58a6b7879b7fe..1701d3bc643d9b2343153ec7ca00629be6892894 100644 --- a/interfaces/inner_api/runtime/include/runtime.h +++ b/interfaces/inner_api/runtime/include/runtime.h @@ -27,14 +27,24 @@ namespace AppExecFwk { class EventRunner; } // namespace AppExecFwk namespace AbilityRuntime { +namespace { +const std::string APPLICAITON_CODE_LANGUAGE_ARKTS_1_0 = "1.1"; +const std::string APPLICAITON_CODE_LANGUAGE_ARKTS_1_2 = "1.2"; +const std::string APPLICAITON_CODE_LANGUAGE_ARKTS_HYBRID = "hybrid"; +const std::string DEBUGGER = "@Debugger"; +} // namespace + class Runtime { public: enum class Language { JS = 0, - CJ + CJ, + STS, + UNKNOWN, }; struct Options { + std::map langs; Language lang = Language::JS; std::string bundleName; std::string moduleName; @@ -65,6 +75,7 @@ public: std::map pkgContextInfoJsonStringMap; std::map packageNameList; std::map aotCompileStatusMap; + bool isStartWithDebug = false; }; struct DebugOption { @@ -77,11 +88,13 @@ public: bool isStartWithNative = false; bool isDebugFromLocal = false; bool isDeveloperMode; + std::string codeLanguage = APPLICAITON_CODE_LANGUAGE_ARKTS_1_2; }; - static std::unique_ptr Create(const Options& options); - static void SavePreloaded(std::unique_ptr&& instance); - static std::unique_ptr GetPreloaded(); + static std::vector> CreateRuntimes(Options& options); + static std::unique_ptr Create(Options& options); + static void SavePreloaded(std::unique_ptr&& instance, Language key = Language::JS); + static std::unique_ptr GetPreloaded(Language key = Language::JS); Runtime() = default; virtual ~Runtime() = default; @@ -107,6 +120,8 @@ public: const std::string& hapPath, bool isEsMode, const std::string& srcEntrance) = 0; virtual void PreloadModule(const std::string& moduleName, const std::string& srcPath, const std::string& hapPath, bool isEsMode, bool useCommonTrunk) = 0; + virtual void PreloadModule(const std::string& moduleName, const std::string& hapPath, + bool isEsMode, bool useCommonTrunk) {} virtual void FinishPreload() = 0; virtual bool LoadRepairPatch(const std::string& patchFile, const std::string& baseFile) = 0; virtual bool NotifyHotReloadPage() = 0; @@ -121,6 +136,8 @@ public: Runtime(Runtime&&) = delete; Runtime& operator=(const Runtime&) = delete; Runtime& operator=(Runtime&&) = delete; + virtual void RegisterUncaughtExceptionHandler(void* uncaughtExceptionInfo) {} + virtual void PreloadClass(const char *className) {} }; } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/inner_api/runtime/include/sts_data_struct_converter.h b/interfaces/inner_api/runtime/include/sts_data_struct_converter.h new file mode 100644 index 0000000000000000000000000000000000000000..432fd44ff3ed444bfb7f0eff42d68d585d51144f --- /dev/null +++ b/interfaces/inner_api/runtime/include/sts_data_struct_converter.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_STS_DATA_STRUCT_CONVERTER_H +#define OHOS_ABILITY_RUNTIME_STS_DATA_STRUCT_CONVERTER_H + +#include "ability_info.h" +#include "application_info.h" +#include "launch_param.h" +#include "hap_module_info.h" +#include "want.h" +#include "configuration.h" + +#include "sts_runtime.h" + +namespace OHOS { +namespace AbilityRuntime { +ani_object CreateStsLaunchParam(ani_env *env, const AAFwk::LaunchParam& launchParam); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_DATA_STRUCT_CONVERTER_H diff --git a/interfaces/inner_api/runtime/include/sts_error_utils.h b/interfaces/inner_api/runtime/include/sts_error_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..3f8d2b930ddb0d0be88f5268f5b2895797c9fb4e --- /dev/null +++ b/interfaces/inner_api/runtime/include/sts_error_utils.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_STS_ERROR_UTILS_H +#define OHOS_ABILITY_RUNTIME_STS_ERROR_UTILS_H + +#include "ability_business_error.h" +#include "ani.h" + +namespace OHOS { +namespace AbilityRuntime { + +void ThrowStsError(ani_env *env, ani_object err); +void ThrowStsError(ani_env *env, int32_t errCode, const std::string &errorMsg = ""); +void ThrowStsError(ani_env *env, const AbilityErrorCode &err); +void ThrowStsInvalidCallerError(ani_env *env); +void ThrowStsTooFewParametersError(ani_env *env); +void ThrowStsInvalidNumParametersError(ani_env *env); +void ThrowStsNoPermissionError(ani_env *env, const std::string &permission); +void ThrowStsInvalidParamError(ani_env *env, const std::string &message); +void ThrowStsErrorByNativeErr(ani_env *env, int32_t err); +void ThrowStsNotSystemAppError(ani_env *env); +void ThrowStsTransferClassError(ani_env *env); + +ani_object CreateStsError(ani_env *env, const AbilityErrorCode &err); +ani_object CreateStsError(ani_env *env, ani_int code, const std::string &msg); +ani_object CreateStsInvalidParamError(ani_env *env, const std::string &message); +ani_object CreateStsNoPermissionError(ani_env *env, const std::string &permission); +ani_object CreateStsErrorByNativeErr(ani_env *env, int32_t err, const std::string &permission = ""); +ani_object WrapStsError(ani_env *env, const std::string &msg); +} // namespace AbilityRuntime +} // namespace OHOS + +#endif // OHOS_ABILITY_RUNTIME_STS_ERROR_UTILS_H diff --git a/interfaces/inner_api/runtime/include/sts_runtime.h b/interfaces/inner_api/runtime/include/sts_runtime.h new file mode 100644 index 0000000000000000000000000000000000000000..7cbc591acc30ed22c5b033c31a8aacc9041499d0 --- /dev/null +++ b/interfaces/inner_api/runtime/include/sts_runtime.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_STS_RUNTIME_H +#define OHOS_ABILITY_RUNTIME_STS_RUNTIME_H + +#include +#include +#include +#include +#include +#include +#include + +#include "runtime.h" +#include "js_runtime.h" +#include "sts_envsetup.h" +#include "ani.h" + +using AppLibPathMap = std::map>; +using AppLibPathVec = std::vector; + +namespace OHOS { +namespace StsEnv { +class STSEnvironment; +} // namespace StsEnv +struct STSUncaughtExceptionInfo; + +namespace AbilityRuntime { + +struct STSNativeReference { + ani_class aniCls = nullptr; + ani_object aniObj = nullptr; + ani_ref aniRef = nullptr; +}; + +class STSNativeReferenceWrapper : public NativeReference { +public: + uint32_t Ref() override { return 0; }; + uint32_t Unref() override { return 0; }; + napi_value Get() override { return nullptr; }; + operator napi_value() override { return nullptr; }; + void SetDeleteSelf() override { return; }; + uint32_t GetRefCount() override { return 0; }; + bool GetFinalRun() override { return false; }; + napi_value GetNapiValue() override { return 0; }; + std::shared_ptr ref_; +}; + +class STSRuntime : public Runtime { +public: + static std::unique_ptr Create(const Options& options, JsRuntime* jsRuntime); + static void SetAppLibPath(const AppLibPathMap& appLibPaths, const AppLibPathMap& appAbcLibPaths); + ~STSRuntime() override; + Language GetLanguage() const override + { + return Language::STS; + } + + void StartDebugMode(const DebugOption debugOption) override; + void DumpHeapSnapshot(bool isPrivate) override {} + void NotifyApplicationState(bool isBackground) override {} + bool SuspendVM(uint32_t tid) override { return false; } + void ResumeVM(uint32_t tid) override {} + void PreloadSystemModule(const std::string& moduleName) override {} + void PreloadMainAbility(const std::string& moduleName, const std::string& srcPath, + const std::string& hapPath, bool isEsMode, const std::string& srcEntrance) override {} + void PreloadModule(const std::string& moduleName, const std::string& srcPath, + const std::string& hapPath, bool isEsMode, bool useCommonTrunk) override {} + void PreloadModule( + const std::string& moduleName, const std::string& hapPath, bool isEsMode, bool useCommonTrunk) override; + void FinishPreload() override; + bool LoadRepairPatch(const std::string& patchFile, const std::string& baseFile) override { return false; } + bool NotifyHotReloadPage() override { return false; } + bool UnLoadRepairPatch(const std::string& patchFile) override { return false; } + void RegisterQuickFixQueryFunc(const std::map& moduleAndPath) override {}; + void StartProfiler(const DebugOption debugOption) override {}; + void SetModuleLoadChecker(const std::shared_ptr moduleCheckerDelegate) const override {} + void SetDeviceDisconnectCallback(const std::function &cb) override {}; + bool IsAppLibLoaded() const { return appLibLoaded_; } + void UnLoadSTSAppLibrary(); + void DestroyHeapProfiler() override {}; + void ForceFullGC() override {}; + void ForceFullGC(uint32_t tid) override {}; + void DumpHeapSnapshot(uint32_t tid, bool isFullGC, bool isBinary = false) override {}; + void DumpCpuProfile() override {}; + void AllowCrossThreadExecution() override {}; + void GetHeapPrepare() override {}; + void RegisterUncaughtExceptionHandler(void* uncaughtExceptionInfo) override; + void PostTask(const std::function& task, const std::string& name, int64_t delayTime); + void PostSyncTask(const std::function& task, const std::string& name); + void RemoveTask(const std::string& name); + ani_env* GetAniEnv(); + std::unique_ptr LoadModule(const std::string& moduleName, const std::string& modulePath, + const std::string& hapPath, bool esmodule, bool useCommonChunk, const std::string& srcEntrance); + std::unique_ptr LoadStsModule(const std::string& moduleName, const std::string& path, + const std::string& hapPath, const std::string& srcEntrance); + bool RunScript(ani_env* aniEnv, const std::string& moduleName, const std::string& abcPath, + const std::string& hapPath, const std::string& srcEntrance); + void HandleUncaughtError(); + static std::unique_ptr PreFork(const Options& options); + void PreloadClass(const char *className) override; + +private: + bool LoadSTSAppLibrary(const AppLibPathVec& appLibPaths); + bool Initialize(const Options& options); + void Deinitialize(); + bool CreateStsEnv(const Options& options); + void ReInitStsEnvImpl(const Options& options); + void ReInitUVLoop(); + void PostFork(const Options &options, std::vector& aniOptions, JsRuntime* jsRuntime); + std::shared_ptr stsEnv_; + int32_t apiTargetVersion_ = 0; + bool isBundle_ = true; + std::string codePath_; + std::map pkgContextInfoJsonStringMap_; + std::map packageNameList_; + bool appLibLoaded_ = false; + bool debugModel_ = false; + std::string bundleName_; + static AppLibPathVec appLibPaths_; + std::string moduleName_; + std::unordered_map modules_; + uint32_t instanceId_ = 0; + void DebuggerConnectionHandler(bool isDebugApp, bool isStartWithDebug); + void StopDebugMode(); + +public: + bool debugMode_ = false; +// std::mutex mutex_; +}; +} // namespace AbilityRuntime +} // namespace OHOS + +#endif // OHOS_ABILITY_RUNTIME_STS_RUNTIME_H diff --git a/interfaces/kits/native/ability/ability_runtime/ability_context.h b/interfaces/kits/native/ability/ability_runtime/ability_context.h index 9910230c7e180bad3ff6c24ea430b3a09bc04af5..a274c05424e01254e5fb1e46ff3b9f63b79b234f 100644 --- a/interfaces/kits/native/ability/ability_runtime/ability_context.h +++ b/interfaces/kits/native/ability/ability_runtime/ability_context.h @@ -173,6 +173,8 @@ public: virtual ErrCode RestoreWindowStage(napi_env env, napi_value contentStorage) = 0; + virtual ErrCode RestoreWindowStage(NativeReference* contentStorage) = 0; + virtual void OnAbilityResult(int requestCode, int resultCode, const AAFwk::Want &resultData) = 0; virtual ErrCode RequestModalUIExtension(const AAFwk::Want& want) = 0; @@ -369,6 +371,15 @@ public: virtual void SetAbilityConfiguration(const AppExecFwk::Configuration &config) = 0; virtual void SetAbilityColorMode(int32_t colorMode) = 0; virtual void SetAbilityResourceManager(std::shared_ptr abilityResourceMgr) = 0; + void SetScreenMode(int32_t screenMode) + { + screenMode_ = screenMode; + } + + int32_t GetScreenMode() const + { + return screenMode_; + } virtual std::shared_ptr GetWant() = 0; @@ -435,6 +446,9 @@ protected: { return contextTypeId == CONTEXT_TYPE_ID || Context::IsContext(contextTypeId); } + +private: + int32_t screenMode_ = AAFwk::ScreenMode::IDLE_SCREEN_MODE; }; } // namespace AbilityRuntime } // namespace OHOS 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 0f9837e34ad5209d0a8665bb462e0ee687af298b..c7be7990b6c03e235a8420976c977ed8a75b50ab 100644 --- a/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h +++ b/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h @@ -119,6 +119,8 @@ public: ErrCode RestoreWindowStage(napi_env env, napi_value contentStorage) override; + ErrCode RestoreWindowStage(NativeReference* contentStorage) override; + void SetStageContext(const std::shared_ptr &stageContext); /** diff --git a/interfaces/kits/native/ability/ability_runtime/ets_extension_context.h b/interfaces/kits/native/ability/ability_runtime/ets_extension_context.h new file mode 100644 index 0000000000000000000000000000000000000000..eccb984ecbeda95fa9e91237d87225698aa114be --- /dev/null +++ b/interfaces/kits/native/ability/ability_runtime/ets_extension_context.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_STS_EXTENSION_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_STS_EXTENSION_CONTEXT_H + +#include "extension_context.h" +#include "ani.h" + +namespace OHOS { +namespace AbilityRuntime { +void CreatEtsExtensionContext(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context, + std::shared_ptr abilityInfo); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_EXTENSION_CONTEXT_H \ No newline at end of file diff --git a/interfaces/kits/native/ability/native/ability_loader.h b/interfaces/kits/native/ability/native/ability_loader.h index 23947ec898c2169a47b0bfab43365a590337d66b..d6835e99624c15cf3bde5cb8eb6c142e89919f8b 100644 --- a/interfaces/kits/native/ability/native/ability_loader.h +++ b/interfaces/kits/native/ability/native/ability_loader.h @@ -28,9 +28,9 @@ namespace OHOS { namespace AppExecFwk { -using CreateExtension = std::function; +using CreateExtension = std::function; using CreateAblity = std::function; -using CreateUIAbility = std::function; +using CreateUIAbility = std::function; #ifdef ABILITY_WINDOW_SUPPORT using CreateSlice = std::function; #endif @@ -90,14 +90,15 @@ public: * * @return return Ability address */ - AbilityRuntime::Extension *GetExtensionByName(const std::string &abilityName); + AbilityRuntime::Extension *GetExtensionByName(const std::string &abilityName, + const std::string &language = AbilityRuntime::APPLICAITON_CODE_LANGUAGE_ARKTS_1_0); /** * @brief Get UIAbility address * @param abilityName UIAbility classname * @return return UIAbility address */ - AbilityRuntime::UIAbility *GetUIAbilityByName(const std::string &abilityName); + AbilityRuntime::UIAbility* GetUIAbilityByName(const std::string &abilityName, const std::string &language); #ifdef ABILITY_WINDOW_SUPPORT void RegisterAbilitySlice(const std::string &sliceName, const CreateSlice &createFunc); diff --git a/interfaces/kits/native/ability/native/ability_runtime/js_ui_ability.h b/interfaces/kits/native/ability/native/ability_runtime/js_ui_ability.h index 311461333289ddf27a84b6d540c49319580559c6..284b3965978eb48998fe345e2f41eb88f893357f 100644 --- a/interfaces/kits/native/ability/native/ability_runtime/js_ui_ability.h +++ b/interfaces/kits/native/ability/native/ability_runtime/js_ui_ability.h @@ -60,6 +60,11 @@ public: const std::shared_ptr application, std::shared_ptr &handler, const sptr &token) override; + static void CreateAndBindContext(const std::shared_ptr application, + const std::shared_ptr record, + const std::shared_ptr abilityContext, + const std::unique_ptr& runtime); + /** * @brief OnStart,Start JsUIability * @param want Indicates the {@link Want} structure containing startup information about the ability @@ -381,7 +386,6 @@ private: JsRuntime &jsRuntime_; std::shared_ptr shellContextRef_; std::shared_ptr jsAbilityObj_; - std::shared_ptr screenModePtr_; sptr remoteCallee_; }; } // namespace AbilityRuntime diff --git a/interfaces/kits/native/ability/native/ability_runtime/sts_ability_context.h b/interfaces/kits/native/ability/native/ability_runtime/sts_ability_context.h new file mode 100644 index 0000000000000000000000000000000000000000..b174b1cfa603c29dc9194e01fa78b035c52f7cbd --- /dev/null +++ b/interfaces/kits/native/ability/native/ability_runtime/sts_ability_context.h @@ -0,0 +1,103 @@ +/* + * 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_SIMULATOR_STS_ABILITY_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_SIMULATOR_STS_ABILITY_CONTEXT_H + +#include +#include +#include + +#include "ability_context.h" +#include "configuration.h" +#include "sts_runtime.h" +#include "ohos_application.h" +#include "sts_free_install_observer.h" +#include "open_link_options.h" + +class STSNativeReference; + +namespace OHOS { +namespace AbilityRuntime { +using OHOSApplication = AppExecFwk::OHOSApplication; +class StsAbilityContext final { +public: + static StsAbilityContext &GetInstance() + { + static StsAbilityContext instance; + return instance; + } + static void StartAbility1( + [[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, ani_object wantObj, ani_object call); + static void StartAbility2([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, ani_object wantObj, + ani_object opt, ani_object call); + static void StartAbilityForResult1(ani_env *env, ani_object aniObj, ani_object wantObj, ani_object callback); + static void StartAbilityForResult2( + ani_env *env, ani_object aniObj, ani_object wantObj, ani_object startOptionsObj, ani_object callback); + static void TerminateSelf(ani_env *env, ani_object aniObj, ani_object callback); + static void TerminateSelfWithResult(ani_env *env, ani_object aniObj, ani_object abilityResult, ani_object callback); + static void reportDrawnCompletedSync( + [[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, ani_object call); + static ani_object StartAbilityByTypeSync([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object aniObj, + ani_string aniType, ani_ref aniWantParam, ani_object startCallback); + + static ani_object SetAbilityContext(ani_env *env, const std::shared_ptr &context); + static std::shared_ptr GetAbilityContext(ani_env *env, ani_object aniObj); + static void StartServiceExtensionAbilitySync([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + [[maybe_unused]] ani_object wantObj, [[maybe_unused]] ani_object callbackobj); + static ani_object StartAbilityByCall(ani_env *env, ani_object aniObj, ani_object wantObj); + static void NativeOpenLinkSync(ani_env *env, ani_object aniObj, ani_string aniLink, + ani_object myCallbackobj, ani_object optionsObj, ani_object callbackobj); + static void NativeRestoreWindowStage(ani_env *env, ani_object aniObj, ani_object localStorage); + static void NativeSetMissionContinueState(ani_env *env, ani_object aniObj, ani_object stateObj, + ani_object callBack); + static bool NativeIsTerminating(ani_env *env, ani_object aniObj); + static void NativeMoveAbilityToBackground(ani_env *env, ani_object aniObj, ani_object callBack); + static void NativeRequestModalUIExtension(ani_env *env, ani_object aniObj, ani_string pickerWantObj, + ani_object callBackObj); + static ani_object NativeTransferStatic(ani_env *env, ani_object aniObj, ani_object input); + static ani_object NativeTransferDynamic(ani_env *env, ani_object aniObj, ani_object input); + +private: + static void InheritWindowMode(ani_env *env, ani_object aniObj, AAFwk::Want &want); + void StartAbilityInner([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, + ani_object wantObj, ani_object opt, ani_object call); + static void StartAbilityForResultInner(ani_env *env, ani_object aniObj, ani_object wantObj, + ani_object startOptionsObj, ani_object callback); + static int32_t GenerateRequestCode(); + void AddFreeInstallObserver(ani_env *env, const AAFwk::Want &want, ani_object callback, + const std::shared_ptr &context, bool isOpenLink = false); + void UnWrapOpenLinkOptions(ani_env *env, ani_object optionsObj, + AAFwk::OpenLinkOptions &openLinkOptions, AAFwk::Want &want); + void OpenLinkInner(ani_env *env, ani_object aniObj, ani_string aniLink, ani_object myCallbackobj, + ani_object optionsObj, ani_object callbackobj, bool haveOptionsParm, bool haveCallBackParm); + void CreateOpenLinkTask(ani_env *env, const ani_object callbackobj, + std::shared_ptr context, AAFwk::Want &want, int &requestCode); + static bool IsInstanceOf(ani_env *env, ani_object aniObj); + + sptr freeInstallObserver_ = nullptr; + static std::mutex requestCodeMutex_; +}; + +bool BindNativeMethods(ani_env *env, ani_class &cls); +bool SetAbilityInfo(ani_env *env, ani_class cls, ani_object contextObj, const std::shared_ptr &context); +bool SetConfiguration( + ani_env *env, ani_class cls, ani_object contextObj, const std::shared_ptr &context); +bool SetHapModuleInfo( + ani_env *env, ani_class cls, ani_object contextObj, const std::shared_ptr &context); +ani_ref CreateStsAbilityContext(ani_env *env, const std::shared_ptr &context); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_SIMULATOR_STS_ABILITY_CONTEXT_H diff --git a/interfaces/kits/native/ability/native/ability_runtime/sts_caller_complex.h b/interfaces/kits/native/ability/native/ability_runtime/sts_caller_complex.h new file mode 100644 index 0000000000000000000000000000000000000000..e59a57caa537ff6566c14ea5d627fdc421714000 --- /dev/null +++ b/interfaces/kits/native/ability/native/ability_runtime/sts_caller_complex.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_SIMULATOR_STS_CALLER_COMPLEX_H +#define OHOS_ABILITY_RUNTIME_SIMULATOR_STS_CALLER_COMPLEX_H + +#include +#include + +#include "caller_callback.h" +#include "sts_runtime.h" + +namespace OHOS { +namespace AbilityRuntime { +using ReleaseCallFunc = std::function)>; + +ani_object CreateEtsCaller(ani_env *env, ReleaseCallFunc releaseCallFunc, + sptr callee, std::shared_ptr callback); +ani_object CreateEtsCallee(ani_env *env); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_SIMULATOR_STS_CALLER_COMPLEX_H diff --git a/interfaces/kits/native/ability/native/ability_runtime/sts_ui_ability.h b/interfaces/kits/native/ability/native/ability_runtime/sts_ui_ability.h new file mode 100644 index 0000000000000000000000000000000000000000..1c7d9f6f8b434f9ef9e73c5cb890415a033cbd8a --- /dev/null +++ b/interfaces/kits/native/ability/native/ability_runtime/sts_ui_ability.h @@ -0,0 +1,332 @@ +/* + * 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_STS_UI_ABILITY_H +#define OHOS_ABILITY_RUNTIME_STS_UI_ABILITY_H + +#include "ability_delegator_infos.h" +#include "freeze_util.h" +#include "ui_ability.h" +#include "sts_runtime.h" + +class STSNativeReference; +namespace OHOS { +namespace AbilityRuntime { +class STSRuntime; +struct InsightIntentExecutorInfo; +using AbilityHandler = AppExecFwk::AbilityHandler; +using AbilityInfo = AppExecFwk::AbilityInfo; +using OHOSApplication = AppExecFwk::OHOSApplication; +using Want = AppExecFwk::Want; +using AbilityStartSetting = AppExecFwk::AbilityStartSetting; +using Configuration = AppExecFwk::Configuration; +using InsightIntentExecuteResult = AppExecFwk::InsightIntentExecuteResult; +using InsightIntentExecuteParam = AppExecFwk::InsightIntentExecuteParam; +using InsightIntentExecutorAsyncCallback = AppExecFwk::InsightIntentExecutorAsyncCallback; + +class StsUIAbility : public UIAbility { +public: + /** + * @brief Create a StsUIAbility instance through the singleton pattern + * @param runtime The runtime of the ability + * @return Returns the JsUIability Instance point + */ + static UIAbility *Create(const std::unique_ptr &runtime); + + explicit StsUIAbility(STSRuntime &stsRuntime); + ~StsUIAbility() override; + + /** + * @brief Init the UIability + * @param abilityInfo Indicate the Ability information + * @param application Indicates the main process + * @param handler the UIability EventHandler object + * @param token the remote token + */ + void Init(std::shared_ptr record, + const std::shared_ptr application, + std::shared_ptr &handler, const sptr &token) override; + + /** + * @brief OnStart,Start JsUIability + * @param want Indicates the {@link Want} structure containing startup information about the ability + * @param sessionInfo Indicates the sessionInfo + */ + void OnStart(const Want &want, sptr sessionInfo = nullptr) override; + + /** + * @brief Called when this ability enters the STATE_STOP state. + * The ability in the STATE_STOP is being destroyed. + * You can override this function to implement your own processing logic. + */ + void OnStop() override; + + /** + * @brief Called when this ability enters the STATE_STOP state. + * The ability in the STATE_STOP is being destroyed. + * You can override this function to implement your own processing logic. + * @param callbackInfo Indicates the lifecycle transaction callback information + * @param isAsyncCallback Indicates whether it is an asynchronous lifecycle callback + */ + void OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback) override; + + /** + * @brief The callback of OnStop. + */ + void OnStopCallback() override; + + /** + * @brief Prepare user data of local Ability. + * @param wantParams Indicates the user data to be saved. + * @return If the ability is willing to continue and data saved successfully, it returns 0; + * otherwise, it returns errcode. + */ + int32_t OnContinue(WantParams &wantParams, bool &isAsyncOnContinue, + const AppExecFwk::AbilityInfo &abilityInfo) 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. + * @param want Indicates the new Want containing information about the ability. + */ + void OnNewWant(const Want &want) override; + + /** + * @brief Prepare user data of local Ability. + * @param reason the reason why framework invoke this function + * @param wantParams Indicates the user data to be saved. + * @return result code defined in abilityConstants + */ + int32_t OnSaveState(int32_t reason, WantParams &wantParams) override; + + /** + * @brief Called when startAbilityForResult(ohos.aafwk.content.Want,int) is called to start an ability and the + * result is returned. This method is called only on Page abilities. You can start a new ability to perform some + * calculations and use setResult (int,ohos.aafwk.content.Want) to return the calculation result. Then the system + * calls back the current method to use the returned data to execute its own logic. + * @param requestCode Indicates the request code returned after the ability is started. You can define the request + * code to identify the results returned by abilities. The value ranges from 0 to 65535. + * @param resultCode Indicates the result code returned after the ability is started. You can define the result code + * to identify an error. + * @param want Indicates the data returned after the ability is started. You can define the data returned. The + * value can be null. + */ + void OnAbilityResult(int requestCode, int resultCode, const Want &resultData) override; + + /** + * @brief request a remote object of callee from this ability. + * @return Returns the remote object of callee. + */ + sptr CallRequest() override; + + /** + * @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; + + void OnAfterFocusedCommon(bool isFocused) override; + + /** + * @brief Get JsAbility + * @return Return the JsAbility + */ + std::shared_ptr GetStsAbility(); + + /** + * @brief Callback when the ability is shared.You can override this function to implement your own sharing logic. + * @param wantParams Indicates the user data to be saved. + * @return the result of OnShare + */ + int32_t OnShare(WantParams &wantParams) override; + + static void CreateAndBindContext(const std::shared_ptr application, + const std::shared_ptr record, + const std::shared_ptr abilityContext, + const std::unique_ptr& runtime); + +#ifdef SUPPORT_SCREEN +public: + /** + * @brief Called after instantiating WindowScene. + * You can override this function to implement your own processing logic. + */ + void OnSceneCreated() override; + + /** + * @brief Called after ability stoped. + * You can override this function to implement your own processing logic. + */ + void OnSceneWillDestroy() override; + + /** + * @brief Called after ability stoped. + * You can override this function to implement your own processing logic. + */ + void onSceneDestroyed() override; + + /** + * @brief Called after ability restored. + * You can override this function to implement your own processing logic. + */ + void OnSceneRestored() override; + + /** + * @brief Called when this ability enters the STATE_FOREGROUND state. + * The ability in the STATE_FOREGROUND state is visible. + * You can override this function to implement your own processing logic. + */ + void OnForeground(const Want &want) override; + + /** + * @brief Call "onForeground" js function barely. + * + * @param want Want + */ + void CallOnForegroundFunc(const Want &want) override; + + /** + * @brief Request focus for current window, can be override. + * + * @param want Want + */ + void RequestFocus(const Want &want) override; + + /** + * @brief Called when this ability enters the STATE_BACKGROUND state. + * The ability in the STATE_BACKGROUND state is invisible. + * You can override this function to implement your own processing logic. + */ + void OnBackground() override; + + /** + * Called when back press is dispatched. + * Return true if ability will be moved to background; return false if will be terminated + */ + bool OnBackPress() override; + + /** + * @brief Get JsWindow Stage + * @return Returns the current STSNativeReference + */ + std::shared_ptr GetJsWindowStage(); + + /** + * @brief Get STSRuntime + * @return Returns the current STSRuntime + */ + const STSRuntime &GetSTSRuntime(); + + /** + * @brief Execute insight intent when an ability is in foreground, schedule it to foreground repeatly. + * + * @param want Want. + * @param executeParam insight intent execute param. + * @param callback insight intent async callback. + */ + void ExecuteInsightIntentRepeateForeground(const Want &want, + const std::shared_ptr &executeParam, + std::unique_ptr callback) override; + + /** + * @brief Execute insight intent when an ability didn't started or in background, schedule it to foreground. + * + * @param want Want. + * @param executeParam insight intent execute param. + * @param callback insight intent async callback. + */ + void ExecuteInsightIntentMoveToForeground(const Want &want, + const std::shared_ptr &executeParam, + std::unique_ptr callback) override; + + /** + * @brief Execute insight intent when an ability didn't started, schedule it to background. + * + * @param want Want. + * @param executeParam insight intent execute param. + * @param callback insight intent async callback. + */ + virtual void ExecuteInsightIntentBackground(const AAFwk::Want &want, + const std::shared_ptr &executeParam, + std::unique_ptr callback) override; + + // /** + // * @brief Called when distributed system trying to collaborate remote ability. + // * @param want want with collaborative info. + // */ + // void HandleCollaboration(const Want &want) override; + +protected: + void DoOnForeground(const Want &want) override; + void ContinuationRestore(const Want &want) override; + +private: + bool IsRestorePageStack(const Want &want); + void RestorePageStack(const Want &want); + void GetPageStackFromWant(const Want &want, std::string &pageStack); + void AbilityContinuationOrRecover(const Want &want); + void UpdateStsWindowStage(ani_ref windowStage); + inline bool GetInsightIntentExecutorInfo(const Want &want, + const std::shared_ptr &executeParam, + InsightIntentExecutorInfo& executeInfo); + int32_t OnCollaborate(WantParams &wantParams); + + std::shared_ptr stsWindowStageObj_; + int32_t windowMode_ = 0; +#endif + +private: + bool CallObjectMethod(bool withResult, const char* name, const char* signature, ...); + ani_object CreateAppWindowStage(); + std::shared_ptr CreateADelegatorAbilityProperty(); + void SetAbilityContext(std::shared_ptr abilityInfo, std::shared_ptr want, + const std::string &moduleName, const std::string &srcPath); + void DoOnForegroundForSceneIsNull(const Want &want); + void AddLifecycleEventBeforeJSCall(FreezeUtil::TimeoutState state, const std::string &methodName) const; + void AddLifecycleEventAfterJSCall(FreezeUtil::TimeoutState state, const std::string &methodName) const; + bool CheckSatisfyTargetAPIVersion(int32_t targetAPIVersion); + bool BackPressDefaultValue(); + void UpdateAbilityObj(std::shared_ptr abilityInfo, + const std::string &moduleName, const std::string &srcPath); + void CreateAniContext(ani_env *env, ani_ref contextGlobalRef, int32_t screenMode); + bool BindNativeMethods(); + + STSRuntime &stsRuntime_; + std::shared_ptr shellContextRef_; + std::shared_ptr stsAbilityObj_; + std::shared_ptr screenModePtr_; + static std::once_flag singletonFlag_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_UI_ABILITY_H 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 0000000000000000000000000000000000000000..0f4b559224ef5a47138604a08e1f98fb036e4b2f --- /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 "sts_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/insight_intent_executor/ets_insight_intent_executor.h b/interfaces/kits/native/ability/native/insight_intent_executor/ets_insight_intent_executor.h new file mode 100644 index 0000000000000000000000000000000000000000..dea980d2846852069c51f3f5848cec68dd99ea5f --- /dev/null +++ b/interfaces/kits/native/ability/native/insight_intent_executor/ets_insight_intent_executor.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_EXECUTOR_H +#define OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_EXECUTOR_H + +#include "insight_intent_executor.h" +#include "sts_runtime.h" +#include "ets_insight_intent_context.h" + +class STSNativeReference; + +namespace OHOS { +namespace AppExecFwk { + struct InsightIntentExecuteResult; +} // namespace AAFwk +namespace AbilityRuntime { +class STSRuntime; + +class EtsInsightIntentExecutor final : public InsightIntentExecutor { +public: + static std::shared_ptr Create(STSRuntime& runtime); + enum class State { + INVALID, + CREATED, + INITIALIZED, + EXECUTING, + EXECUTATION_DONE, + DESTROYED + }; + + explicit EtsInsightIntentExecutor(STSRuntime& runtime); +public: + EtsInsightIntentExecutor(const EtsInsightIntentExecutor&) = delete; + EtsInsightIntentExecutor(const EtsInsightIntentExecutor&&) = delete; + EtsInsightIntentExecutor& operator=(const EtsInsightIntentExecutor&) = delete; + EtsInsightIntentExecutor& operator=(const EtsInsightIntentExecutor&&) = delete; + ~EtsInsightIntentExecutor() override; + + bool Init(const InsightIntentExecutorInfo& insightIntentInfo) override; + + bool HandleExecuteIntent( + InsightIntentExecuteMode mode, + const std::string& name, + const AAFwk::WantParams& param, + const std::shared_ptr& pageLoader, + std::unique_ptr callback, + bool& isAsync) override { return false; }; + + bool HandleExecuteEtsIntent( + InsightIntentExecuteMode mode, + const std::string& name, + const AAFwk::WantParams& param, + const std::shared_ptr& pageLoader, + std::unique_ptr callback, + bool& isAsync); + + inline State GetState() const + { + return state_; + } + +private: + static std::unique_ptr LoadEtsCode( + const InsightIntentExecutorInfo& insightIntentInfo, + STSRuntime& runtime); + + ani_ref CallObjectMethod(bool withResult, const char* name, const char* signature, ...); + + static void ReplyFailed(InsightIntentExecutorAsyncCallback* callback, + InsightIntentInnerErr innerErr = InsightIntentInnerErr::INSIGHT_INTENT_EXECUTE_REPLY_FAILED); + static void ReplySucceeded(InsightIntentExecutorAsyncCallback* callback, + std::shared_ptr resultCpp); + void ReplyFailedInner(InsightIntentInnerErr innerErr = InsightIntentInnerErr::INSIGHT_INTENT_EXECUTE_REPLY_FAILED); + void ReplySucceededInner(std::shared_ptr resultCpp); + bool ExecuteIntentCheckError(); + + bool HandleResultReturnedFromEtsFunc(ani_env *env, ani_ref result, bool isAsync); + + static bool CheckParametersUIAbilityForeground(const std::shared_ptr& windowStage); + bool ExecuteInsightIntentUIAbilityForeground( + const std::string& name, + const AAFwk::WantParams& param, + const std::shared_ptr& windowStage); + + static bool CheckParametersUIAbilityBackground(); + bool ExecuteInsightIntentUIAbilityBackground( + const std::string& name, + const AAFwk::WantParams& param); + + static bool CheckParametersUIExtension(const std::shared_ptr& UIExtensionContentSession); + bool ExecuteInsightIntentUIExtension( + const std::string& name, + const AAFwk::WantParams& param, + const std::shared_ptr& UIExtensionContentSession); + + static bool CheckParametersServiceExtension(); + bool ExecuteInsightIntentServiceExtension( + const std::string& name, + const AAFwk::WantParams& param); + + static void OnExecuteResult(ani_env *env, [[maybe_unused]]ani_object aniObj, ani_object result); + + STSRuntime& runtime_; + State state_ = State::CREATED; + std::unique_ptr etsObj_ = nullptr; + std::unique_ptr contextObj_ = nullptr; + std::shared_ptr contextCpp_ = nullptr; + std::unique_ptr callback_; + bool isAsync_ = false; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_INSIGHT_INTENT_EXECUTOR_H diff --git a/interfaces/kits/native/ability/native/js_service_extension.h b/interfaces/kits/native/ability/native/js_service_extension.h index 6305fc1ae7c77a67b76e48f47f9115bd21afa79a..7370c16b2389f444d2c1bf2b52a1996da9c020ef 100644 --- a/interfaces/kits/native/ability/native/js_service_extension.h +++ b/interfaces/kits/native/ability/native/js_service_extension.h @@ -180,12 +180,6 @@ private: void ListenWMS(); - bool GetInsightIntentExecutorInfo(const Want &want, - const std::shared_ptr &executeParam, - InsightIntentExecutorInfo &executorInfo); - - bool OnInsightIntentExecuteDone(uint64_t intentId, const AppExecFwk::InsightIntentExecuteResult &result) override; - JsRuntime& jsRuntime_; std::unique_ptr jsObj_; std::shared_ptr shellContextRef_ = nullptr; diff --git a/interfaces/kits/native/ability/native/recovery/recovery_param.h b/interfaces/kits/native/ability/native/recovery/recovery_param.h index 67db772c8eaa16d34ab8fc717fcd6653fe62972c..8b4482eeb32b9e20abf23eacb30e964bd89b2f3a 100644 --- a/interfaces/kits/native/ability/native/recovery/recovery_param.h +++ b/interfaces/kits/native/ability/native/recovery/recovery_param.h @@ -45,6 +45,7 @@ enum RestartFlag { RESTART_WHEN_JS_CRASH = 0x0001, RESTART_WHEN_APP_FREEZE = 0x0002, RESTART_WHEN_CJ_CRASH = 0x0004, + RESTART_WHEN_STS_CRASH = 0x0008, NO_RESTART = 0xFFFF, }; @@ -67,8 +68,12 @@ enum StateReason { JS_ERROR, APP_FREEZE, CJ_ERROR, + STS_ERROR, }; - +[[maybe_unused]] static OnSaveResult OnSaveResult_ConvertStsToNative(const int32_t index); +[[maybe_unused]] static OnSaveResult OnSaveResult_ConvertNativeToSts(const OnSaveResult value); +[[maybe_unused]] static StateType StateType_ConvertStsToNative(const int32_t index); +[[maybe_unused]] static int32_t StateType_ConvertNativeToSts(const StateType value); } // namespace AAFwk } // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_ABILITY_RECOVERY_PARAM_H \ No newline at end of file diff --git a/interfaces/kits/native/ability/native/service_extension.h b/interfaces/kits/native/ability/native/service_extension.h index 81d50fababc24960ff6f64a867d9975dc4f00f64..f0e992f389a55c1fd3c87f9befcd3246843c0328 100644 --- a/interfaces/kits/native/ability/native/service_extension.h +++ b/interfaces/kits/native/ability/native/service_extension.h @@ -19,11 +19,16 @@ #include "extension_base.h" namespace OHOS { +namespace AppExecFwk { +class InsightIntentExecuteParam; +struct InsightIntentExecuteResult; +} namespace AbilityRuntime { class ServiceExtensionContext; class Runtime; class ServiceExtension; using CreatorFunc = std::function& runtime)>; +struct InsightIntentExecutorInfo; /** * @brief Basic service components. */ @@ -82,6 +87,27 @@ public: */ void OnConfigurationUpdated(const AppExecFwk::Configuration &configuration) override; + /** + * @brief Get the executor info. + * + * @param want The want. + * @param executeParam The execute param. + * @param executorInfo The executor info. + * @return True if success, otherwise false. + */ + virtual bool GetInsightIntentExecutorInfo(const Want &want, + const std::shared_ptr &executeParam, + InsightIntentExecutorInfo &executorInfo); + + /** + * @brief On execute done. + * + * @param intentId The intent id. + * @param result The execute result. + * @return True if success, otherwise false. + */ + bool OnInsightIntentExecuteDone(uint64_t intentId, + const AppExecFwk::InsightIntentExecuteResult &result) override; private: static CreatorFunc creator_; }; diff --git a/interfaces/kits/native/ability/native/sts_free_install_observer.h b/interfaces/kits/native/ability/native/sts_free_install_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..184a47ceefd69378d8fe0e093e1632b5679a1b8b --- /dev/null +++ b/interfaces/kits/native/ability/native/sts_free_install_observer.h @@ -0,0 +1,64 @@ +/* +* 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_STS_FREE_INSTALL_OBSERVER_H +#define OHOS_ABILITY_RUNTIME_STS_FREE_INSTALL_OBSERVER_H + +#include +#include +#include + +#include "native_engine/native_engine.h" +#include "sts_runtime.h" +#include "sts_error_utils.h" +#include "free_install_observer_stub.h" + +namespace OHOS { +namespace AbilityRuntime { +struct StsFreeInstallObserverObject { + std::string bundleName; + std::string abilityName; + std::string startTime; + std::string url; + ani_object callBack; + bool isAbilityResult = false; +}; + +class StsFreeInstallObserver : public FreeInstallObserverStub { +public: + explicit StsFreeInstallObserver(ani_vm *etsVm); + virtual ~StsFreeInstallObserver(); + + void OnInstallFinished(const std::string &bundleName, const std::string &abilityName, const std::string &startTime, + const int &resultCode) override; + void OnInstallFinishedByUrl(const std::string &startTime, const std::string& url, const int &resultCode) override; + void AddStsObserverObject(ani_env *env, const std::string &bundleName, const std::string &abilityName, + const std::string &startTime, ani_object callBack); + void AddStsObserverObject(ani_env *env, const std::string &startTime, const std::string &url, ani_object callBack); + +private: + void CallCallback(ani_object callback, int32_t resultCode); + void HandleOnInstallFinished(const std::string &bundleName, const std::string &abilityName, + const std::string &startTime, const int &resultCode); + void HandleOnInstallFinishedByUrl(const std::string &startTime, const std::string& url, const int &resultCode); + void AddStsObserverCommon(ani_env *env, StsFreeInstallObserverObject &object, ani_object callBack); + + ani_vm *etsVm_; + std::mutex stsObserverObjectListLock_; + std::vector stsObserverObjectList_; +}; +} // namespace AbilityRuntime +} // namespace OHOS + +#endif // OHOS_ABILITY_RUNTIME_STS_FREE_INSTALL_OBSERVER_H \ No newline at end of file diff --git a/interfaces/kits/native/ability/native/sts_ui_extension_callback.h b/interfaces/kits/native/ability/native/sts_ui_extension_callback.h new file mode 100644 index 0000000000000000000000000000000000000000..36d28119228f9f80ed8faa0921860cf79315803b --- /dev/null +++ b/interfaces/kits/native/ability/native/sts_ui_extension_callback.h @@ -0,0 +1,49 @@ +/* + * 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_STS_UI_EXTENSION_CALLBACK_H +#define OHOS_ABILITY_RUNTIME_STS_UI_EXTENSION_CALLBACK_H + +#include "js_ui_extension_callback.h" +#include "sts_runtime.h" + +namespace OHOS { +namespace Ace { +class UIContent; +} +namespace AbilityRuntime { +class StsUIExtensionCallback : public JsUIExtensionCallback, + public std::enable_shared_from_this { +public: + StsUIExtensionCallback(); + virtual ~StsUIExtensionCallback(); + virtual void OnError(int32_t number); + virtual void OnRelease(int32_t code); + virtual void OnResult(int32_t resultCode, const AAFwk::Want &want); + virtual void SetSessionId(int32_t sessionId); + virtual void SetUIContent(Ace::UIContent* uiContent); + virtual void SetStsCallbackObject(ani_vm* aniVM, ani_object aniObject); + +private: + ani_env* GetAniEnv(); + void CloseModalUIExtension(); + ani_vm* aniVM_ = nullptr; + ani_ref startAbilityAniCallback_ = nullptr; + int32_t aniSessionId_ = 0; + Ace::UIContent* aniUIContent_ = nullptr; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_UI_EXTENSION_CALLBACK_H \ No newline at end of file diff --git a/interfaces/kits/native/ability/native/ui_ability.h b/interfaces/kits/native/ability/native/ui_ability.h index 38dd8c2e630b97524c503d49e71d31da6509fd6c..59ede4873f0f51c3db3f70efccc64e2d19511c3f 100644 --- a/interfaces/kits/native/ability/native/ui_ability.h +++ b/interfaces/kits/native/ability/native/ui_ability.h @@ -327,6 +327,9 @@ public: */ virtual int32_t OnShare(AAFwk::WantParams &wantParams); + void BindHybridContext(const std::shared_ptr application, + const std::shared_ptr record); + bool CheckIsSilentForeground() const; void SetIsSilentForeground(bool isSilentForeground); @@ -354,6 +357,10 @@ private: void SetLaunchParam(const AAFwk::LaunchParam &launchParam); void InitConfigurationProperties(const AppExecFwk::Configuration &changeConfiguration, ResourceConfigHelper &resourceConfig); + void BindStsContext(const std::shared_ptr application, + const std::shared_ptr record); + void BindJsContext(const std::shared_ptr application, + const std::shared_ptr record); std::shared_ptr continuationHandler_ = nullptr; std::shared_ptr continuationManager_ = 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 f748657bd6616f39f28d6953bd43a82764d7ab98..192fb7e6c36454fe31ac69afb25849fc77b21baa 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 @@ -25,7 +25,6 @@ #include "insight_intent_executor_info.h" #include "js_ui_extension_content_session.h" #include "ui_extension.h" -#include #include class NativeReference; @@ -108,9 +107,6 @@ public: */ virtual void OnCommand(const AAFwk::Want &want, bool restart, int startId) override; - virtual void OnCommandWindow(const AAFwk::Want &want, const sptr &sessionInfo, - AAFwk::WindowCommand winCmd) override; - /** * @brief Called when this ui extension enters the STATE_STOP state. * @@ -192,18 +188,14 @@ private: napi_value CallOnDisconnect(const AAFwk::Want &want, bool withResult = false); - void ForegroundWindow(const AAFwk::Want &want, const sptr &sessionInfo); - void BackgroundWindow(const sptr &sessionInfo); - void DestroyWindow(const sptr &sessionInfo); - - void OnCommandWindowDone(const sptr &sessionInfo, AAFwk::WindowCommand winCmd) override; + void ForegroundWindow(const AAFwk::Want &want, const sptr &sessionInfo) override; + void BackgroundWindow(const sptr &sessionInfo) override; + void DestroyWindow(const sptr &sessionInfo) override; bool ForegroundWindowInitInsightIntentExecutorInfo(const AAFwk::Want &want, const sptr &sessionInfo, InsightIntentExecutorInfo &executorInfo); bool ForegroundWindowWithInsightIntent(const AAFwk::Want &want, const sptr &sessionInfo, - bool needForeground); + bool needForeground) override; bool HandleSessionCreate(const AAFwk::Want &want, const sptr &sessionInfo); - void OnInsightIntentExecuteDone(const sptr &sessionInfo, - const AppExecFwk::InsightIntentExecuteResult &result) override; void PostInsightIntentExecuted(const sptr &sessionInfo, const AppExecFwk::InsightIntentExecuteResult &result, bool needForeground); std::unique_ptr CreateAppWindowStage(sptr uiWindow, @@ -215,9 +207,6 @@ private: JsRuntime& jsRuntime_; std::shared_ptr jsObj_ = nullptr; std::shared_ptr shellContextRef_ = nullptr; - std::mutex uiWindowMutex_; - std::map> uiWindowMap_; - std::set foregroundWindows_; std::map> contentSessions_; std::shared_ptr abilityResultListeners_ = nullptr; int32_t screenMode_ = AAFwk::IDLE_SCREEN_MODE; 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 5f14369e4d6d99aef78663546121de36ab9465fc..eb24d9411801450a491e171dfe1f3e116b092406 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 @@ -17,8 +17,11 @@ #define OHOS_ABILITY_RUNTIME_UI_EXTENSION_H #include "extension_base.h" - +#include namespace OHOS { +namespace AppExecFwk { +struct InsightIntentExecuteResult; +} namespace AbilityRuntime { class UIExtensionContext; class Runtime; @@ -65,6 +68,70 @@ public: * @return The ui extension instance. */ static UIExtension* Create(const std::unique_ptr& runtime); + + /** + * @brief On command window. + * + * @param want The want. + * @param sessionInfo The sessionInfo. + * @param winCmd The window command. + */ + void OnCommandWindow(const AAFwk::Want &want, const sptr &sessionInfo, + AAFwk::WindowCommand winCmd) override; + + /** + * @brief On command window done. + * + * @param sessionInfo The sessionInfo. + * @param winCmd The window command. + */ + void OnCommandWindowDone(const sptr &sessionInfo, AAFwk::WindowCommand winCmd) override; + + /** + * @brief On insight intent execute done. + * + * @param sessionInfo The sessionInfo. + * @param result The execute result. + */ + void OnInsightIntentExecuteDone(const sptr &sessionInfo, + const AppExecFwk::InsightIntentExecuteResult &result) override; + + /** + * @brief Excute foreground window. + * + * @param want The want. + * @param sessionInfo The sessionInfo. + */ + virtual void ForegroundWindow(const AAFwk::Want &want, const sptr &sessionInfo) {}; + + /** + * @brief Excute background window. + * + * @param sessionInfo The sessionInfo. + */ + virtual void BackgroundWindow(const sptr &sessionInfo) {}; + + /** + * @brief Excute destroy window. + * + * @param sessionInfo The sessionInfo. + */ + virtual void DestroyWindow(const sptr &sessionInfo) {}; + + /** + * @brief Excute foreground window with insight intent. + * + * @param want The want. + * @param sessionInfo The sessionInfo. + * @param needForeground If need foreground. + */ + virtual bool ForegroundWindowWithInsightIntent(const AAFwk::Want &want, const sptr &sessionInfo, + bool needForeground) { return false; }; + +protected: + std::mutex uiWindowMutex_; + std::map> uiWindowMap_; + std::set foregroundWindows_; }; } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/kits/native/appkit/ability_delegator/ability_delegator.h b/interfaces/kits/native/appkit/ability_delegator/ability_delegator.h index 19f5e0cc52d31c6dd92d0b02307f26b08bbbe684..1a894f9c02f6389590f6498d8a66e66a316c5cc1 100644 --- a/interfaces/kits/native/appkit/ability_delegator/ability_delegator.h +++ b/interfaces/kits/native/appkit/ability_delegator/ability_delegator.h @@ -69,7 +69,7 @@ public: /** * Definition of cleanup function. */ - using ClearFunc = std::function &)>; + using ClearFunc = std::function &)>; public: static std::shared_ptr Create(const std::shared_ptr& context, @@ -143,7 +143,7 @@ public: * @param monitor, Indicates the specified monitor object. * @return the obtained ability. */ - std::shared_ptr WaitAbilityMonitor(const std::shared_ptr &monitor); + std::shared_ptr WaitAbilityMonitor(const std::shared_ptr &monitor); /** * Waits for the specified monitor and return the obtained abilityStage. @@ -151,7 +151,7 @@ public: * @param monitor, Indicates the specified stage monitor object. * @return the obtained abilityStage. */ - std::shared_ptr WaitAbilityStageMonitor( + std::shared_ptr WaitAbilityStageMonitor( const std::shared_ptr &monitor); /** @@ -161,7 +161,7 @@ public: * @param timeoutMs, Indicates the specified time out time, in milliseconds. * @return the obtained ability. */ - std::shared_ptr WaitAbilityMonitor( + std::shared_ptr WaitAbilityMonitor( const std::shared_ptr &monitor, const int64_t timeoutMs); /** @@ -171,7 +171,7 @@ public: * @param timeoutMs, Indicates the specified time out time, in milliseconds. * @return the obtained abilityStage. */ - std::shared_ptr WaitAbilityStageMonitor( + std::shared_ptr WaitAbilityStageMonitor( const std::shared_ptr &monitor, const int64_t timeoutMs); /** @@ -194,7 +194,7 @@ public: * * @return the ability that is currently being displayed. */ - std::shared_ptr GetCurrentTopAbility(); + std::shared_ptr GetCurrentTopAbility(); /** * Obtains the name of the thread. @@ -259,56 +259,56 @@ public: * * @param ability, Indicates the ability properties. */ - void PostPerformStart(const std::shared_ptr &ability); + void PostPerformStart(const std::shared_ptr &ability); /** * Saves abilityStage properties when abilityStage is started and notify monitors. * * @param abilityStage , Indicates the abilityStage properties. */ - void PostPerformStageStart(const std::shared_ptr &abilityStage); + void PostPerformStageStart(const std::shared_ptr &abilityStage); /** * Saves ability properties when scence is created and notify monitors of state changes. * * @param ability, Indicates the ability properties. */ - void PostPerformScenceCreated(const std::shared_ptr &ability); + void PostPerformScenceCreated(const std::shared_ptr &ability); /** * Saves ability properties when scence is restored and notify monitors of state changes. * * @param ability, Indicates the ability properties. */ - void PostPerformScenceRestored(const std::shared_ptr &ability); + void PostPerformScenceRestored(const std::shared_ptr &ability); /** * Saves ability properties when scence is destroyed and notify monitors of state changes. * * @param ability, Indicates the ability properties. */ - void PostPerformScenceDestroyed(const std::shared_ptr &ability); + void PostPerformScenceDestroyed(const std::shared_ptr &ability); /** * Saves ability properties when ability is in the foreground and notify monitors of state changes. * * @param ability, Indicates the ability properties. */ - void PostPerformForeground(const std::shared_ptr &ability); + void PostPerformForeground(const std::shared_ptr &ability); /** * Saves ability properties when ability is in the background and notify monitors of state changes. * * @param ability, Indicates the ability properties. */ - void PostPerformBackground(const std::shared_ptr &ability); + void PostPerformBackground(const std::shared_ptr &ability); /** * Saves ability properties when ability is stopped and notify monitors of state changes. * * @param ability, Indicates the ability properties. */ - void PostPerformStop(const std::shared_ptr &ability); + void PostPerformStop(const std::shared_ptr &ability); /** * Finishes user test. @@ -328,11 +328,11 @@ public: private: AbilityDelegator::AbilityState ConvertAbilityState(const AbilityLifecycleExecutor::LifecycleState lifecycleState); - void ProcessAbilityProperties(const std::shared_ptr &ability); - void RemoveAbilityProperty(const std::shared_ptr &ability); - std::shared_ptr FindPropertyByToken(const sptr &token); - std::shared_ptr FindPropertyByName(const std::string &name); - inline void CallClearFunc(const std::shared_ptr &ability); + void ProcessAbilityProperties(const std::shared_ptr &ability); + void RemoveAbilityProperty(const std::shared_ptr &ability); + std::shared_ptr FindPropertyByToken(const sptr &token); + std::shared_ptr FindPropertyByName(const std::string &name); + inline void CallClearFunc(const std::shared_ptr &ability); private: static constexpr size_t INFORMATION_MAX_LENGTH {1000}; @@ -345,7 +345,7 @@ private: sptr observer_; std::unique_ptr delegatorThread_; - std::list> abilityProperties_; + std::list> abilityProperties_; std::vector> abilityMonitors_; std::vector> abilityStageMonitors_; diff --git a/interfaces/kits/native/appkit/ability_delegator/ability_delegator_infos.h b/interfaces/kits/native/appkit/ability_delegator/ability_delegator_infos.h index 3f649fb32ca560401bec844e17ba2aa09b7759c7..3fe7bde55f2734511b3ee6ad32dd86ddd1a0e612 100644 --- a/interfaces/kits/native/appkit/ability_delegator/ability_delegator_infos.h +++ b/interfaces/kits/native/appkit/ability_delegator/ability_delegator_infos.h @@ -19,12 +19,14 @@ #include #include "ability_lifecycle_executor.h" #include "iremote_object.h" +#include "sts_runtime.h" class NativeReference; namespace OHOS { namespace AppExecFwk { -struct ADelegatorAbilityProperty { + +struct BaseDelegatorAbilityProperty { // token of ability sptr token_; // name of ability @@ -35,15 +37,27 @@ struct ADelegatorAbilityProperty { std::string fullName_; // lifecycle state of ability AbilityLifecycleExecutor::LifecycleState lifecycleState_ {AbilityLifecycleExecutor::LifecycleState::UNINITIALIZED}; - // ability object in jsruntime +}; +struct ADelegatorAbilityProperty : public BaseDelegatorAbilityProperty { std::weak_ptr object_; }; -struct DelegatorAbilityStageProperty { +struct ETSDelegatorAbilityProperty : public BaseDelegatorAbilityProperty { + std::weak_ptr object_; +}; + +struct BaseDelegatorAbilityStageProperty { std::string moduleName_; std::string srcEntrance_; +}; + +struct DelegatorAbilityStageProperty : public BaseDelegatorAbilityStageProperty { std::weak_ptr object_; }; + +struct ETSDelegatorAbilityStageProperty : public BaseDelegatorAbilityStageProperty { + std::weak_ptr object_; +}; } // namespace AppExecFwk } // namespace OHOS diff --git a/interfaces/kits/native/appkit/ability_delegator/ability_delegator_registry.h b/interfaces/kits/native/appkit/ability_delegator/ability_delegator_registry.h index 1fd257b82310397e327403373df4e0ca6800e3ff..57f9c383be7d8d3bf41457d9cfe902ea43a2a0f5 100644 --- a/interfaces/kits/native/appkit/ability_delegator/ability_delegator_registry.h +++ b/interfaces/kits/native/appkit/ability_delegator/ability_delegator_registry.h @@ -24,6 +24,7 @@ #include "cj_ability_delegator_impl.h" #endif #include "iability_delegator.h" +#include "runtime.h" namespace OHOS { namespace AppExecFwk { @@ -34,7 +35,8 @@ public: * * @return the AbilityDelegator object initialized when the application is started. */ - static std::shared_ptr GetAbilityDelegator(); + static std::shared_ptr GetAbilityDelegator( + const AbilityRuntime::Runtime::Language &language = AbilityRuntime::Runtime::Language::JS); #ifdef CJ_FRONTEND /** @@ -60,10 +62,11 @@ public: * @param args, Indicates the AbilityDelegatorArgs object. */ static void RegisterInstance( - const std::shared_ptr& delegator, const std::shared_ptr& args); + const std::shared_ptr &delegator, const std::shared_ptr &args, + const AbilityRuntime::Runtime::Language &language); private: - static std::shared_ptr abilityDelegator_; + static std::map> abilityDelegator_; static std::shared_ptr abilityDelegatorArgs_; }; } // namespace AppExecFwk diff --git a/interfaces/kits/native/appkit/ability_delegator/iability_monitor.h b/interfaces/kits/native/appkit/ability_delegator/iability_monitor.h index 6a91fec773201b81359d67c387fe3365d2462038..f899604dd30c7cec97896334d12c7a1ff23cf87e 100644 --- a/interfaces/kits/native/appkit/ability_delegator/iability_monitor.h +++ b/interfaces/kits/native/appkit/ability_delegator/iability_monitor.h @@ -63,7 +63,7 @@ public: * @param isNotify Indicates whether to notify the matched ability to the object who waited. * @return true if match is successful; returns false otherwise. */ - virtual bool Match(const std::shared_ptr &ability, bool isNotify = false); + virtual bool Match(const std::shared_ptr &ability, bool isNotify = false); /** * Waits for and returns the started Ability object that matches the conditions specified in this monitor @@ -72,7 +72,7 @@ public: * * @return the Ability object if any object has started is matched within 5 seconds; returns null otherwise. */ - virtual std::shared_ptr WaitForAbility(); + virtual std::shared_ptr WaitForAbility(); /** * Waits for and returns the started Ability object that matches the conditions specified in this monitor @@ -84,61 +84,61 @@ public: * @return the Ability object if any object has started is matched within the specified time; * returns null otherwise. */ - virtual std::shared_ptr WaitForAbility(const int64_t timeoutMs); + virtual std::shared_ptr WaitForAbility(const int64_t timeoutMs); /** * Called when ability is started. * * @param abilityObj Indicates the ability object. */ - virtual void OnAbilityStart(const std::weak_ptr &abilityObj); + virtual void OnAbilityStart(const std::weak_ptr &abilityObj); /** * Called when ability is in foreground. * * @param abilityObj Indicates the ability object. */ - virtual void OnAbilityForeground(const std::weak_ptr &abilityObj); + virtual void OnAbilityForeground(const std::weak_ptr &abilityObj); /** * Called when ability is in background. * * @param abilityObj Indicates the ability object. */ - virtual void OnAbilityBackground(const std::weak_ptr &abilityObj); + virtual void OnAbilityBackground(const std::weak_ptr &abilityObj); /** * Called when ability is stopped. * * @param abilityObj Indicates the ability object. */ - virtual void OnAbilityStop(const std::weak_ptr &abilityObj); + virtual void OnAbilityStop(const std::weak_ptr &abilityObj); /** * Called when window stage is created. * * @param abilityObj Indicates the ability object. */ - virtual void OnWindowStageCreate(const std::weak_ptr &abilityObj); + virtual void OnWindowStageCreate(const std::weak_ptr &abilityObj); /** * Called when window stage is restored. * * @param abilityObj Indicates the ability object. */ - virtual void OnWindowStageRestore(const std::weak_ptr &abilityObj); + virtual void OnWindowStageRestore(const std::weak_ptr &abilityObj); /** * Called when window stage is destroyed. * * @param abilityObj Indicates the ability object. */ - virtual void OnWindowStageDestroy(const std::weak_ptr &abilityObj); + virtual void OnWindowStageDestroy(const std::weak_ptr &abilityObj); private: std::string abilityName_; std::string moduleName_; - std::shared_ptr matchedAbility_; + std::shared_ptr matchedAbility_; std::condition_variable cvMatch_; std::mutex mMatch_; diff --git a/interfaces/kits/native/appkit/ability_delegator/iability_stage_monitor.h b/interfaces/kits/native/appkit/ability_delegator/iability_stage_monitor.h index c1cd1251539015169bf1c9616c24d6bed292f161..59d2afa7562513d0bcd679b22b648f8ecf3018b2 100644 --- a/interfaces/kits/native/appkit/ability_delegator/iability_stage_monitor.h +++ b/interfaces/kits/native/appkit/ability_delegator/iability_stage_monitor.h @@ -53,7 +53,7 @@ public: * @param isNotify Indicates whether to notify the matched abilityStage to the object who waited. * @return true if match is successful; returns false otherwise. */ - virtual bool Match(const std::shared_ptr &abilityStage, bool isNotify = false); + virtual bool Match(const std::shared_ptr &abilityStage, bool isNotify = false); /** * Waits for and returns the started AbilityStage object that matches the conditions specified in this monitor @@ -65,7 +65,7 @@ public: * @return the AbilityStage object if any object has started is matched within the specified time; * returns null otherwise. */ - virtual std::shared_ptr WaitForAbilityStage(const int64_t timeoutMs); + virtual std::shared_ptr WaitForAbilityStage(const int64_t timeoutMs); /** * Waits for and returns the started AbilityStage object that matches the conditions specified in this monitor @@ -74,12 +74,12 @@ public: * * @return the AbilityStage object if any object has started is matched within 5 seconds; returns null otherwise. */ - virtual std::shared_ptr WaitForAbilityStage(); + virtual std::shared_ptr WaitForAbilityStage(); private: std::string moduleName_; std::string srcEntrance_; - std::shared_ptr matchedAbilityStage_; + std::shared_ptr matchedAbilityStage_; std::condition_variable cvMatch_; std::mutex mtxMatch_; diff --git a/interfaces/kits/native/appkit/ability_delegator/runner_runtime/sts_test_runner.h b/interfaces/kits/native/appkit/ability_delegator/runner_runtime/sts_test_runner.h new file mode 100644 index 0000000000000000000000000000000000000000..9a57af45ab3583bf2ba3fe97c793b7de404549e6 --- /dev/null +++ b/interfaces/kits/native/appkit/ability_delegator/runner_runtime/sts_test_runner.h @@ -0,0 +1,73 @@ +/* + * 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_STS_TEST_RUNNER_H +#define OHOS_ABILITY_RUNTIME_STS_TEST_RUNNER_H + +#include "bundle_info.h" +#include "sts_runtime.h" +#include "test_runner.h" + +class STSNativeReference; + +namespace OHOS { +namespace RunnerRuntime { +using namespace AppExecFwk; +using namespace AbilityRuntime; + +class STSTestRunner : public TestRunner { +public: + /** + * Creates a TestRunner instance with the input parameter passed. + * + * @param runtime Indicates the ability runtime. + * @param args Indicates the AbilityDelegatorArgs object. + * @param bundleInfo Indicates the bundle info. + * @return the TestRunner object if JsTestRunner object is created successfully; returns null otherwise. + */ + static std::unique_ptr Create(const std::unique_ptr &runtime, + const std::shared_ptr &args, const AppExecFwk::BundleInfo &bundleInfo); + + /** + * Default deconstructor used to deconstruct. + */ + ~STSTestRunner() override; + + /** + * Prepares the testing environment for running test code. + */ + void Prepare() override; + + /** + * Runs all test code. + */ + void Run() override; + + bool Initialize() override; + +private: + STSTestRunner(STSRuntime &STSRuntime, + const std::shared_ptr &args, const AppExecFwk::BundleInfo &bundleInfo); + void CallOnPrepareMethod(ani_env* aniEnv); + void CallOnRunMethod(ani_env* aniEnv); + + STSRuntime &stsRuntime_; + std::unique_ptr stsTestRunnerObj_; + std::string srcPath_; + std::string hapPath_; +}; +} // namespace RunnerRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_TEST_RUNNER_H diff --git a/interfaces/kits/native/appkit/ability_runtime/app/sts_ability_stage.h b/interfaces/kits/native/appkit/ability_runtime/app/sts_ability_stage.h new file mode 100644 index 0000000000000000000000000000000000000000..f46c1138b680a601e3e53fbd8f202fc5e7faac9e --- /dev/null +++ b/interfaces/kits/native/appkit/ability_runtime/app/sts_ability_stage.h @@ -0,0 +1,89 @@ +/* + * 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_STS_ABILITY_STAGE_H +#define OHOS_ABILITY_RUNTIME_STS_ABILITY_STAGE_H + +#include "ability_delegator_infos.h" + +#include +#include + +#include "ability_stage.h" +#include "configuration.h" +#include "js_startup_task.h" +#include "resource_manager.h" +#include "nlohmann/json.hpp" +#include "native_engine/native_value.h" +#include "sts_runtime.h" + +namespace OHOS { +namespace AbilityRuntime { +class STSAbilityStage : public AbilityStage { +public: + static std::shared_ptr Create( + const std::unique_ptr& runtime, const AppExecFwk::HapModuleInfo& hapModuleInfo); + + STSAbilityStage(STSRuntime& stsRuntime, std::unique_ptr&& stsAbilityStageObj); + ~STSAbilityStage() override; + + void Init(const std::shared_ptr &context, + const std::weak_ptr application) override; + + void OnCreate(const AAFwk::Want &want) const override; + + 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; + + int32_t RunAutoStartupTask(const std::function &callback, bool &isAsyncCallback, + const std::shared_ptr &stageContext) override; + +private: + + bool CallObjectMethod(bool withResult, const char* name, const char* signature, ...) const; + + std::shared_ptr CreateStageProperty() const; + + std::string GetHapModuleProp(const std::string &propName) const; + + static bool UseCommonChunk(const AppExecFwk::HapModuleInfo& hapModuleInfo); + + std::unique_ptr LoadJsOhmUrl(const std::string &srcEntry, const std::string &ohmUrl, + const std::string &moduleName, const std::string &hapPath, bool esmodule); + + std::unique_ptr LoadJsSrcEntry(const std::string &srcEntry); + + bool LoadJsStartupConfig(const std::string &srcEntry); + + int32_t RegisterAppStartupTask(const std::shared_ptr& hapModuleInfo); + + static int32_t RunAutoStartupTaskInner(const std::function &callback, bool &isAsyncCallback); + + STSRuntime& stsRuntime_; + + void SetJsAbilityStage(const std::shared_ptr &context); + std::unique_ptr stsAbilityStageObj_; + ani_object stageObj_ = nullptr; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_ABILITY_STAGE_H diff --git a/interfaces/kits/native/appkit/ability_runtime/app/sts_ability_stage_context.h b/interfaces/kits/native/appkit/ability_runtime/app/sts_ability_stage_context.h new file mode 100644 index 0000000000000000000000000000000000000000..6e46cf0715edbc42fc53f0acda345a5b654076d7 --- /dev/null +++ b/interfaces/kits/native/appkit/ability_runtime/app/sts_ability_stage_context.h @@ -0,0 +1,56 @@ +/* + * 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_STS_ABILITY_STAGE_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_STS_ABILITY_STAGE_CONTEXT_H + +#include "configuration.h" +#include "sts_runtime.h" + +namespace OHOS { +namespace AppExecFwk { +class OHOSApplication; +} +namespace AbilityRuntime { + +constexpr const char* STS_ABILITY_STAGE_CONTEXT_CLASS_NAME = "Lapplication/AbilityStageContext/AbilityStageContext;"; +constexpr const char* STS_ABILITY_STAGE_CLASS_NAME = "L@ohos/app/ability/AbilityStage/AbilityStage;"; + +class Context; +class STSAbilityStageContext final { +public: + explicit STSAbilityStageContext(const std::shared_ptr& context) : context_(context) {} + ~STSAbilityStageContext() = default; + + static void ConfigurationUpdated(ani_env* env, const std::shared_ptr &config); + + std::shared_ptr GetContext() + { + return context_.lock(); + } + static ani_object CreateStsAbilityStageContext(ani_env* env, std::shared_ptr context); + static void ResetEnv(ani_env* env); + +private: + static ani_object CreateHapModuleInfo(ani_env* env, const std::shared_ptr &context); + +private: + std::weak_ptr context_; + static ani_ref stsAbilityStageContextObj_; +}; + +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_ABILITY_STAGE_CONTEXT_H diff --git a/interfaces/kits/native/appkit/ability_runtime/context/application_context.h b/interfaces/kits/native/appkit/ability_runtime/context/application_context.h index 84365517a6c62eaae5d847dc98c7562848ef4429..fed2357efe19f77e4bfce390792a34a0579d20fa 100644 --- a/interfaces/kits/native/appkit/ability_runtime/context/application_context.h +++ b/interfaces/kits/native/appkit/ability_runtime/context/application_context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2024 Huawei Device Co., Ltd. + * Copyright (c) 2022-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 @@ -158,6 +158,16 @@ public: void SetCurrentAppMode(int32_t appIndex); void ProcessSecurityExit(const AAFwk::ExitReason &exitReason); + inline void* GetApplicationCtxObjRef() + { + return applicationContextObjRef_; + } + + inline void SetApplicationCtxObjRef(void* applicationContextObjRef) + { + applicationContextObjRef_ = applicationContextObjRef; + } + using SelfType = ApplicationContext; static const size_t CONTEXT_TYPE_ID; std::string GetDataDir(); @@ -184,6 +194,7 @@ private: int32_t appIndex_ = 0; int32_t appMode_ = 0; std::string instanceKey_; + void* applicationContextObjRef_ = nullptr; std::string dataDir_; std::mutex dataDirMutex_; }; diff --git a/interfaces/kits/native/appkit/ability_runtime/context/application_context_manager.h b/interfaces/kits/native/appkit/ability_runtime/context/application_context_manager.h index 4ce60e5b7036de6eb21576b6cbaf904165902683..a90b8bf30eaac6181311a6a21b324010e0c637c1 100644 --- a/interfaces/kits/native/appkit/ability_runtime/context/application_context_manager.h +++ b/interfaces/kits/native/appkit/ability_runtime/context/application_context_manager.h @@ -27,7 +27,7 @@ struct EnvData { napi_env env; EnvData(napi_env napienv) : env(napienv) {} }; - +struct STSNativeReference; class ApplicationContextManager { public: ApplicationContextManager(const ApplicationContextManager&) = delete; @@ -42,12 +42,17 @@ public: void RemoveGlobalObject(napi_env env); + void SetEtsGlobalObject(std::shared_ptr applicationContextObj); + + std::shared_ptr GetEtsGlobalObject(); + private: ApplicationContextManager(); ~ApplicationContextManager(); std::unordered_map> applicationContextMap_; + std::shared_ptr etsApplicationContextRef_; std::mutex applicationContextMutex_; }; } // namespace AbilityRuntime diff --git a/interfaces/kits/native/appkit/ability_runtime/context/bindable.h b/interfaces/kits/native/appkit/ability_runtime/context/bindable.h index 354431963ed50721a4f30f79ed6d1e34330091b1..a932ac1ffae0d7111610461b252d7fb81e28a209 100644 --- a/interfaces/kits/native/appkit/ability_runtime/context/bindable.h +++ b/interfaces/kits/native/appkit/ability_runtime/context/bindable.h @@ -17,38 +17,67 @@ #define OHOS_ABILITY_RUNTIME_BINDABLE_H #include +#include +class NativeReference; +typedef class __ani_ref *ani_ref; namespace OHOS { namespace AbilityRuntime { class Runtime; class BindingObject final { public: - template - BindingObject(Runtime& runtime, T* ptr) : runtime_(runtime), object_(ptr, SimpleRelease) {} + BindingObject() = default; ~BindingObject() = default; template - T* Get() + void Bind(Runtime& runtime, T* object) { - return static_cast(object_.get()); + static_assert(IsValidType(), "T must be ani_ref or NativeReference"); + const std::string typeName = GetTypeString(); + std::lock_guard guard(objectsMutex_); + std::unique_ptr obj(object, SimpleRelease); + objects_.emplace(typeName, std::move(obj)); } - void Reset() + template + void Bind(T* object) { - object_.reset(); + static_assert(IsValidType(), "T must be ani_ref or NativeReference"); + const std::string typeName = GetTypeString(); + std::lock_guard guard(objectsMutex_); + std::unique_ptr obj(object, SimpleRelease); + objects_.emplace(typeName, std::move(obj)); } - void Unbind() + template + T* Get() { - if (object_) { - object_.release(); + const std::string typeName = GetTypeString(); + std::lock_guard guard(objectsMutex_); + const auto& iter = objects_.find(typeName); + if (iter == objects_.end()) { + return nullptr; } + return static_cast(iter->second.get()); + } + + void Unbind() + { + // Consistency with previous behavior + Unbind(); } - Runtime& GetRuntime() + template + void Unbind() { - return runtime_; + const std::string typeName = GetTypeString(); + std::lock_guard guard(objectsMutex_); + const auto& iter = objects_.find(typeName); + if (iter == objects_.end()) { + return; + } + iter->second.release(); } BindingObject(const BindingObject&) = delete; @@ -63,8 +92,27 @@ private: delete static_cast(ptr); } - Runtime& runtime_; - std::unique_ptr object_; + template + static constexpr bool IsValidType() + { + if (std::is_same_v || std::is_same_v) { + return true; + } + return false; + } + + template + static std::string GetTypeString() + { + if (std::is_same_v) { + return "ani_ref"; + } else { + return "NativeReference"; + } + } + + std::map> objects_; + std::mutex objectsMutex_; }; class Bindable { @@ -74,16 +122,34 @@ public: template void Bind(Runtime& runtime, T* object) { - object_ = std::make_unique(runtime, object); + if (object_) { + object_->Bind(runtime, object); + } } - void Unbind() + template + void Bind(T* object) + { + if (object_) { + object_->Bind(object); + } + } + + void Unbind() const { if (object_) { object_->Unbind(); } } + template + void Unbind() const + { + if (object_) { + object_->Unbind(); + } + } + const std::unique_ptr& GetBindingObject() const { return object_; @@ -93,8 +159,8 @@ protected: Bindable() = default; private: - std::unique_ptr object_; + std::unique_ptr object_ = std::make_unique(); }; -} // namespace AbilityRuntime -} // namespace OHOS -#endif // OHOS_ABILITY_RUNTIME_BINDABLE_H +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_BINDABLE_H diff --git a/interfaces/kits/native/appkit/ability_runtime/context/ets_application_context_utils.h b/interfaces/kits/native/appkit/ability_runtime/context/ets_application_context_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..89422eeafc7238e025170028546a355a1eba9438 --- /dev/null +++ b/interfaces/kits/native/appkit/ability_runtime/context/ets_application_context_utils.h @@ -0,0 +1,76 @@ +/* + * 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_CONTEXT_UTILS_H +#define OHOS_ABILITY_RUNTIME_ETS_APPLICATION_CONTEXT_UTILS_H + +#include "ability_manager_client.h" +#include "ability_runtime_error_util.h" +#include "ani_common_util.h" +#include "ani_common_want.h" +#include "application_context.h" +#include "ets_enviroment_callback.h" +#include "ets_application_state_change_callback.h" +#include "sts_context_utils.h" +#include "sts_error_utils.h" +#include "sts_runtime.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsApplicationContextUtils { +public: + explicit EtsApplicationContextUtils() {} + virtual ~EtsApplicationContextUtils() = default; + static ani_string GetCurrentInstanceKey([[maybe_unused]]ani_env *env, + [[maybe_unused]]ani_object aniObj); + static ani_double GetCurrentAppCloneIndex([[maybe_unused]]ani_env *env, + [[maybe_unused]]ani_object aniObj); + static void RestartApp([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_object wantObj); + static void SetFont([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_string font); + static void SetColorMode([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_enum_item colorMode); + static void SetLanguage([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_string language); + static void SetFontSizeScale([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_double fontSizeScale); + static void ClearUpApplicationData([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_object callback); + static void GetRunningProcessInformation([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_object callback); + static ani_double NativeOnSync([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_string type, ani_object envCallback); + static void NativeOffSync([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_string type, ani_double callbackId, ani_object call); + static void NativeOnApplicationStateChangeSync([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_object callback); + static void NativeOffApplicationStateChangeSync([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_object callback); + static void killAllProcesses([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_boolean clearPageStack, ani_object call); + static void PreloadUIExtensionAbility([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_object wantObj, ani_object call); + static void SetSupportedProcessCacheSync([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_boolean value); + static void SetApplicationContextToEts(const std::shared_ptr &abilityRuntimeContext); + static void CreateEtsApplicationContext(ani_env* aniEnv); + static void BindApplicationContextFunc(ani_env* aniEnv, ani_class& contextClass); + static void SetAndBindApplicationObject(ani_env* aniEnv, ani_object applicationContextObject, + std::shared_ptr applicationContext); +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_APPLICATION_CONTEXT_UTILS_H \ No newline at end of file diff --git a/interfaces/kits/native/appkit/ability_runtime/context/ets_application_state_change_callback.h b/interfaces/kits/native/appkit/ability_runtime/context/ets_application_state_change_callback.h new file mode 100644 index 0000000000000000000000000000000000000000..989e30bf7489dffda16e3411afb99e45bd430fc8 --- /dev/null +++ b/interfaces/kits/native/appkit/ability_runtime/context/ets_application_state_change_callback.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_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_env *env); + virtual ~EtsApplicationStateChangeCallback() = default; + 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_env *env_ = nullptr; + std::set callbacks_; + mutable std::mutex mutex_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_APPLICATION_STATE_CHANGE_CALLBACK_H diff --git a/interfaces/kits/native/appkit/ability_runtime/context/ets_enviroment_callback.h b/interfaces/kits/native/appkit/ability_runtime/context/ets_enviroment_callback.h new file mode 100644 index 0000000000000000000000000000000000000000..72b0edef9f16d731587a1f3cc13fe82bd0fb168c --- /dev/null +++ b/interfaces/kits/native/appkit/ability_runtime/context/ets_enviroment_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_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_env *env); + 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_env *env_ = nullptr; + std::map enviromentAniCallbacks_; + int32_t serialNumber_ = 0; + std::mutex Mutex_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_ENVIRONMENT_CALLBACK_H \ No newline at end of file diff --git a/interfaces/kits/native/appkit/ability_runtime/context/sts_context_utils.h b/interfaces/kits/native/appkit/ability_runtime/context/sts_context_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..3ad0b3c455fac6be6ea4b371c2df7ca3979d1a4c --- /dev/null +++ b/interfaces/kits/native/appkit/ability_runtime/context/sts_context_utils.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_STS_CONTEXT_UTILS_H +#define OHOS_ABILITY_RUNTIME_STS_CONTEXT_UTILS_H + +#include "sts_runtime.h" +#include "context.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace ContextUtil { +void BindApplicationCtx(ani_env* aniEnv, ani_class contextClass, ani_object contextObj); + +void BindApplicationInfo(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context); + +void BindResourceManager(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context); + +void BindParentProperty(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context); + +void BindParentPropertyInner(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, + std::shared_ptr context); + +void StsCreatContext(ani_env* aniEnv, ani_class contextClass, ani_object contextObj, std::shared_ptr context); + +ani_object CreateModuleResourceManagerSync([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_string bundleName, ani_string moduleName); + +ani_object GetApplicationContextSync([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj); + +void NativeGetGroupDir([[maybe_unused]]ani_env *env, [[maybe_unused]]ani_object aniObj, + ani_string dataGroupIdObj, ani_object callBackObj); + +void SwitchArea(ani_env *env, ani_object obj, ani_enum_item areaModeItem); + +ani_enum_item GetArea(ani_env *env); +} +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_CONTEXT_UTILS_H diff --git a/interfaces/kits/native/appkit/app/application_data_manager.h b/interfaces/kits/native/appkit/app/application_data_manager.h index 3f8bb01b4e78f8521570be79cb8903df71347d6f..eed67a9aa3b2124658d18b686abedb0b3c260c3a 100644 --- a/interfaces/kits/native/appkit/app/application_data_manager.h +++ b/interfaces/kits/native/appkit/app/application_data_manager.h @@ -29,9 +29,11 @@ public: void AddErrorObserver(const std::shared_ptr &observer); bool NotifyUnhandledException(const std::string &errMsg); bool NotifyCJUnhandledException(const std::string &errMsg); + bool NotifySTSUnhandledException(const std::string &errMsg); void RemoveErrorObserver(); bool NotifyExceptionObject(const AppExecFwk::ErrorObject &errorObj); bool NotifyCJExceptionObject(const AppExecFwk::ErrorObject &errorObj); + bool NotifySTSExceptionObject(const AppExecFwk::ErrorObject &errorObj); private: ApplicationDataManager(); diff --git a/interfaces/kits/native/appkit/app/child_main_thread.h b/interfaces/kits/native/appkit/app/child_main_thread.h index 17b8d750d853d101897705a842bcf06523a5e619..4a35d6a0dddfb643f15ddf0d8136514c3e560ad3 100644 --- a/interfaces/kits/native/appkit/app/child_main_thread.h +++ b/interfaces/kits/native/appkit/app/child_main_thread.h @@ -56,7 +56,8 @@ private: void InitNativeLib(const BundleInfo &bundleInfo); void HandleExitProcessSafely(); void ExitProcessSafely(); - void GetNativeLibPath(const BundleInfo &bundleInfo, const HspList &hspList, AppLibPathMap &appLibPaths); + void GetNativeLibPath(const BundleInfo &bundleInfo, const HspList &hspList, AppLibPathMap &appLibPaths, + AppLibPathMap &appAbcLibPaths); void HandleRunNativeProc(const sptr &mainProcessCb); void UpdateNativeChildLibModuleName(const AppLibPathMap &appLibPaths, bool isSystemApp); diff --git a/interfaces/kits/native/appkit/app/main_thread.h b/interfaces/kits/native/appkit/app/main_thread.h index 4061b1ccbd10d1936600050e21a4729bb3bbe5c9..a6adaa4dfbe7eabb603cae93ea9b7ab0cc3e17d8 100644 --- a/interfaces/kits/native/appkit/app/main_thread.h +++ b/interfaces/kits/native/appkit/app/main_thread.h @@ -39,6 +39,7 @@ #include "resource_manager.h" #include "runtime.h" #include "watchdog.h" +#include "sts_envsetup.h" #ifdef CJ_FRONTEND #include "cj_envsetup.h" @@ -302,6 +303,10 @@ public: CJUncaughtExceptionInfo CreateCjExceptionInfo(const std::string &bundleName, uint32_t versionCode, const std::string &hapPath); #endif + JsEnv::UncaughtExceptionInfo CreateJsExceptionInfo(const std::string& bundleName, uint32_t versionCode, + const std::string& hapPath, std::string& appRunningId, int32_t pid, std::string& processName); + StsEnv::STSUncaughtExceptionInfo CreateStsExceptionInfo(const std::string& bundleName, uint32_t versionCode, + const std::string& hapPath, std::string& appRunningId, int32_t pid, std::string& processName); /** * @brief Notify NativeEngine GC of status change. * @@ -588,7 +593,8 @@ private: * */ bool PrepareAbilityDelegator(const std::shared_ptr &record, bool isStageBased, - const AppExecFwk::HapModuleInfo &entryHapModuleInfo, uint32_t targetVersion); + const AppExecFwk::HapModuleInfo &entryHapModuleInfo, uint32_t targetVersion, + const std::string &applicationCodeLanguage); /** * @brief Set current process extension type @@ -755,9 +761,12 @@ private: bool GetHqfFileAndHapPath(const std::string &bundleName, std::vector> &fileMap); - void GetNativeLibPath(const BundleInfo &bundleInfo, const HspList &hspList, AppLibPathMap &appLibPaths); + void GetNativeLibPath(const BundleInfo &bundleInfo, const HspList &hspList, AppLibPathMap &appLibPaths, + AppLibPathMap &appAbcLibPaths); void SetAppDebug(uint32_t modeFlag, bool isDebug); + void AddRuntimeLang(ApplicationInfo& appInfo, AbilityRuntime::Runtime::Options& options); + std::vector fileEntries_; std::vector nativeFileEntries_; std::vector handleAbilityLib_; // the handler of ACE Library. diff --git a/interfaces/kits/native/appkit/app/native_lib_util.h b/interfaces/kits/native/appkit/app/native_lib_util.h index 2bfd80626bb07ef662c3890ee3853f3e3a6c2c46..fae7086b1381eff4f417bc767921ede8ed1d2615 100644 --- a/interfaces/kits/native/appkit/app/native_lib_util.h +++ b/interfaces/kits/native/appkit/app/native_lib_util.h @@ -26,12 +26,14 @@ namespace OHOS { namespace AppExecFwk { std::string GetLibPath(const std::string &hapPath, bool isPreInstallApp); -void GetHapSoPath(const HapModuleInfo &hapInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp); +void GetHapSoPath(const HapModuleInfo &hapInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp, + AppLibPathMap &appAbcLibPaths); -void GetHspNativeLibPath(const BaseSharedBundleInfo &hspInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp); +void GetHspNativeLibPath(const BaseSharedBundleInfo &hspInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp, + const std::string &appBundleName, AppLibPathMap &appAbcLibPaths); void GetPatchNativeLibPath(const HapModuleInfo &hapInfo, std::string &patchNativeLibraryPath, - AppLibPathMap &appLibPaths); + AppLibPathMap &appLibPaths, AppLibPathMap &appAbcLibPaths); } // namespace AppExecFwk } // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_NATIVE_LIB_UTIL_H diff --git a/interfaces/kits/native/appkit/app/ohos_application.h b/interfaces/kits/native/appkit/app/ohos_application.h index 4e412b2453db0496c165662a1763cd8803374693..c1c2fb60a1dcc17d601fca1d0f5466ca7f0b8e59 100644 --- a/interfaces/kits/native/appkit/app/ohos_application.h +++ b/interfaces/kits/native/appkit/app/ohos_application.h @@ -26,7 +26,7 @@ #include "context.h" #include "ability_stage_context.h" #include "application_configuration_manager.h" - +#include "runtime.h" namespace OHOS { namespace AbilityRuntime { class Runtime; @@ -48,11 +48,11 @@ public: void DumpApplication(); /** - * @brief Set Runtime + * @brief Add Runtime * * @param runtime Runtime instance. */ - void SetRuntime(std::unique_ptr&& runtime); + void AddRuntime(std::unique_ptr&& runtime); /** * @brief Set ApplicationContext @@ -167,12 +167,22 @@ public: */ std::shared_ptr GetAppContext() const; + /** + * @brief return the application runtimes + * + * @param runtime + */ + const std::vector>& GetRuntime() const + { + return runtimes_; + } + /** * @brief return the application runtime * * @param runtime */ - const std::unique_ptr& GetRuntime() const; + const std::unique_ptr& GetRuntime(const std::string& language) const; /* * @@ -226,6 +236,10 @@ public: void CleanEmptyAbilityStage(); + void InitAniApplicationContext(); + + void InitAniContext(); + #ifdef SUPPORT_GRAPHICS bool GetDisplayConfig(uint64_t displayId, float &density, std::string &directionStr); #endif @@ -233,6 +247,13 @@ public: void PreloadAppStartup(const BundleInfo &bundleInfo, const HapModuleInfo &entryHapModuleInfo, const std::string &preloadModuleName); + inline void* GetApplicationCtxObjRef() + { + return applicationContextObjRef_; + } + + void SetCJApplication(bool isCJApplication = false); + private: void UpdateAppContextResMgr(const Configuration &config); bool IsUpdateColorNeeded(Configuration &config, AbilityRuntime::SetLevel level); @@ -247,14 +268,19 @@ private: const AppExecFwk::HapModuleInfo &hapModuleInfo, const std::function& callback); bool IsMainProcess(const std::string &bundleName, const std::string &process); + AbilityRuntime::Runtime::Language ConvertLangToCode(const std::string &language) const; + void PreloadHybridModule(const HapModuleInfo &hapModuleInfo) const; private: std::shared_ptr abilityRecordMgr_ = nullptr; std::shared_ptr abilityRuntimeContext_ = nullptr; std::unordered_map> abilityStages_; - std::unique_ptr runtime_; + std::vector> runtimes_; + std::unique_ptr runtimeNullptr_; std::shared_ptr configuration_ = nullptr; std::map extensionTypeMap_; + void* applicationContextObjRef_ = nullptr; + bool isCJApplication_ = false; }; } // namespace AppExecFwk } // namespace OHOS diff --git a/services/abilitymgr/src/mission/mission_info.cpp b/services/abilitymgr/src/mission/mission_info.cpp index 7d6d5fe17ba4fe6851e5acb3df9204ca9927900a..ea72c97033f92a1788436cc7add3a500cd3f525c 100644 --- a/services/abilitymgr/src/mission/mission_info.cpp +++ b/services/abilitymgr/src/mission/mission_info.cpp @@ -124,5 +124,19 @@ MissionValidResult *MissionValidResult::Unmarshalling(Parcel &parcel) } return info.release(); } +ContinueState ContinueState_ConvertStsToNative(const int32_t index) +{ + if (index <0 || index >1) { + return ContinueState::CONTINUESTATE_UNKNOWN; + } + return static_cast(index); +} +int32_t ContinueState_ConvertNativeToSts(const ContinueState value) +{ + if (value == ContinueState::CONTINUESTATE_ACTIVE || value == ContinueState::CONTINUESTATE_INACTIVE) { + return value; + } + return ContinueState::CONTINUESTATE_UNKNOWN; +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/pending_want_manager.cpp b/services/abilitymgr/src/pending_want_manager.cpp index 4bbceb6f8c871b0a31580b74195b81f6426e13c9..55e2fae3675170c62e46b0713bc4b1c8c23a4b27 100644 --- a/services/abilitymgr/src/pending_want_manager.cpp +++ b/services/abilitymgr/src/pending_want_manager.cpp @@ -20,6 +20,7 @@ #include "distributed_client.h" #include "hitrace_meter.h" #include "permission_constants.h" +#include "scene_board_judgement.h" #include "session_manager_lite.h" #include "utils/app_mgr_util.h" #include "wm_common.h" @@ -692,6 +693,10 @@ bool PendingWantManager::CheckCallerPermission() bool PendingWantManager::CheckWindowState(int32_t pid) { + if (!Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) { + TAG_LOGW(AAFwkTag::WANTAGENT, "scene board not enabled"); + return true; + } auto sceneSessionManager = Rosen::SessionManagerLite::GetInstance().GetSceneSessionManagerLiteProxy(); if (sceneSessionManager == nullptr) { TAG_LOGE(AAFwkTag::WANTAGENT, "null manager"); diff --git a/services/abilitymgr/src/process_options.cpp b/services/abilitymgr/src/process_options.cpp index 3a5f0efedc731ae18e3f4c490c2ba52024ad6241..ce80f46bbd1daf734d6d4801b8afa75fd200bfa6 100644 --- a/services/abilitymgr/src/process_options.cpp +++ b/services/abilitymgr/src/process_options.cpp @@ -19,6 +19,11 @@ namespace OHOS { namespace AAFwk { +const int NUMBER_ZERO = 0; +const int NUMBER_ONE = 1; +const int NUMBER_TWO = 2; +const int NUMBER_THREE = 3; + bool ProcessOptions::ReadFromParcel(Parcel &parcel) { processMode = static_cast(parcel.ReadInt32()); @@ -78,6 +83,22 @@ ProcessMode ProcessOptions::ConvertInt32ToProcessMode(int32_t value) return static_cast(value); } +ProcessMode ProcessOptions::ConvertStsToProcessMode(int32_t index) +{ + if (index < NUMBER_ZERO || index > NUMBER_TWO) { + return ProcessMode::UNSPECIFIED; + } + return static_cast(index + NUMBER_ONE); +} +int32_t ProcessOptions::ConvertProcessModeToSts(const ProcessMode mode) +{ + int32_t value = static_cast(mode); + if (value >= NUMBER_ONE && value <= NUMBER_THREE) { + return value - NUMBER_ONE; + } + return static_cast(ProcessMode::NEW_PROCESS_ATTACH_TO_PARENT); +} + StartupVisibility ProcessOptions::ConvertInt32ToStartupVisibility(int32_t value) { if (value <= static_cast(StartupVisibility::UNSPECIFIED) || @@ -87,6 +108,23 @@ StartupVisibility ProcessOptions::ConvertInt32ToStartupVisibility(int32_t value) return static_cast(value); } +StartupVisibility ConvertStsToStartupVisibility(int32_t index) +{ + if (index < NUMBER_ZERO || index > NUMBER_ONE) { + return StartupVisibility::UNSPECIFIED; + } + return static_cast(index); +} +int32_t ConvertStartupVisibilityToSts(const StartupVisibility value) +{ + if (value == StartupVisibility::STARTUP_HIDE) { + return NUMBER_ZERO; + } else if (value == StartupVisibility::STARTUP_SHOW) { + return NUMBER_ONE; + } + return NUMBER_ZERO; +} + bool ProcessOptions::IsNewProcessMode(ProcessMode value) { return (value == ProcessMode::NEW_PROCESS_ATTACH_TO_PARENT) || diff --git a/services/appmgr/src/app_mgr_service_inner.cpp b/services/appmgr/src/app_mgr_service_inner.cpp index 68b45db6376224cd49b2f5d77a3e92717cb12902..2aee2a2111097b1f77a07e879e990c7c66fa4663 100644 --- a/services/appmgr/src/app_mgr_service_inner.cpp +++ b/services/appmgr/src/app_mgr_service_inner.cpp @@ -6824,6 +6824,9 @@ std::string AppMgrServiceInner::FaultTypeToString(AppExecFwk::FaultDataType type case AppExecFwk::FaultDataType::JS_ERROR: typeStr = "JS_ERROR"; break; + case AppExecFwk::FaultDataType::STS_ERROR: + typeStr = "STS_ERROR"; + break; case AppExecFwk::FaultDataType::APP_FREEZE: typeStr = "APP_FREEZE"; break; diff --git a/services/common/include/hilog_tag_wrapper.h b/services/common/include/hilog_tag_wrapper.h index 2914871157419b5fed0f9a08249971dd5f35735c..7cfcc081750edc0bb2a6de0e79be7bde31387d71 100644 --- a/services/common/include/hilog_tag_wrapper.h +++ b/services/common/include/hilog_tag_wrapper.h @@ -58,6 +58,7 @@ enum class AAFwkLogTag : uint32_t { INTENT, JSNAPI, CJRUNTIME, + STSRUNTIME, DELEGATOR = DEFAULT + 0x30, // 0xD001330 CONTEXT, diff --git a/sts_environment/frameworks/sts_environment/BUILD.gn b/sts_environment/frameworks/sts_environment/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..4dde98c10a76ab3ab74c4773afaba85c3e4c378f --- /dev/null +++ b/sts_environment/frameworks/sts_environment/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") +import("../../sts_environment.gni") + +config("public_sts_environment_config") { + include_dirs = [ + "include", + "${ability_runtime_path}/sts_environment/interfaces/inner_api", + "${ability_runtime_services_path}/common/include", + "${ability_runtime_path}/interfaces/inner_api", + ] +} + +ohos_shared_library("sts_environment") { + branch_protector_ret = "pac_ret" + + public_configs = [ ":public_sts_environment_config" ] + + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + sources = [ + "src/dynamic_loader_ohos.cpp", + "src/sts_environment.cpp", + ] + + defines = [] + + external_deps = [ + "c_utils:utils", + "eventhandler:libeventhandler", + "faultloggerd:libunwinder", + "ffrt:libffrt", + "hilog:libhilog", + "json:nlohmann_json_static", + "libuv:uv", + "napi:ace_napi", + "runtime_core:ani", + ] + + if (ability_runtime_graphics) { + defines = [ "SUPPORT_GRAPHICS" ] + external_deps += [ "ace_engine:ace_uicontent" ] + } + + subsystem_name = "ability" + innerapi_tags = [ "platformsdk_indirect" ] + part_name = "ability_runtime" +} diff --git a/sts_environment/frameworks/sts_environment/include/sts_interface.h b/sts_environment/frameworks/sts_environment/include/sts_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..fe36569ffcbcfb70cbb09f041fce984a7e76072b --- /dev/null +++ b/sts_environment/frameworks/sts_environment/include/sts_interface.h @@ -0,0 +1,1547 @@ +/* + * 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_STS_ENVIRONMENT_STS_INTERFACE_H +#define OHOS_ABILITY_STS_ENVIRONMENT_STS_INTERFACE_H + +#include + +namespace OHOS { + +// Version Constants +#define ETS_NAPI_VERSION_1_0 0x00010000 + +// General return value constants +#define ETS_OK 0 // success +#define ETS_ERR (-1) // unknown error +#define ETS_ERR_VER (-2) // ETS version error +#define ETS_ERR_NOMEM (-3) // not enough memory +#define ETS_ERR_EXIST (-4) // VM already created +#define ETS_ERR_INVAL (-5) // invalid arguments + +// Boolean Constants +#define ETS_FALSE 0 +#define ETS_TRUE 1 + +// Mode Constants +#define ETS_COMMIT 1 +#define ETS_ABORT 2 + +// NOLINTEND(cppcoreguidelines-macro-usage) + +// Primitive Types +typedef uint8_t ets_boolean; +typedef int8_t ets_byte; +typedef uint16_t ets_char; +typedef int16_t ets_short; +typedef int32_t ets_int; +typedef int64_t ets_long; +typedef float ets_float; +typedef double ets_double; +typedef ets_int ets_size; + +// Reference Types +#ifdef __cplusplus +class __ets_object {}; +class __ets_class : public __ets_object {}; +class __ets_string : public __ets_object {}; +class __ets_array : public __ets_object {}; +class __ets_objectArray : public __ets_array {}; +class __ets_booleanArray : public __ets_array {}; +class __ets_byteArray : public __ets_array {}; +class __ets_charArray : public __ets_array {}; +class __ets_shortArray : public __ets_array {}; +class __ets_intArray : public __ets_array {}; +class __ets_longArray : public __ets_array {}; +class __ets_floatArray : public __ets_array {}; +class __ets_doubleArray : public __ets_array {}; +class __ets_error : public __ets_object {}; + +typedef __ets_object *ets_object; +typedef __ets_class *ets_class; +typedef __ets_string *ets_string; +typedef __ets_array *ets_array; +typedef __ets_objectArray *ets_objectArray; +typedef __ets_booleanArray *ets_booleanArray; +typedef __ets_byteArray *ets_byteArray; +typedef __ets_charArray *ets_charArray; +typedef __ets_shortArray *ets_shortArray; +typedef __ets_intArray *ets_intArray; +typedef __ets_longArray *ets_longArray; +typedef __ets_floatArray *ets_floatArray; +typedef __ets_doubleArray *ets_doubleArray; +typedef __ets_error *ets_error; +typedef __ets_object *ets_weak; + +#else // __cplusplus + +struct __ets_object; +typedef struct __ets_object *ets_object; +typedef ets_object ets_class; +typedef ets_object ets_string; +typedef ets_object ets_error; +typedef ets_object ets_weak; +typedef ets_object ets_array; +typedef ets_array ets_objectArray; +typedef ets_array ets_booleanArray; +typedef ets_array ets_byteArray; +typedef ets_array ets_charArray; +typedef ets_array ets_shortArray; +typedef ets_array ets_intArray; +typedef ets_array ets_longArray; +typedef ets_array ets_floatArray; +typedef ets_array ets_doubleArray; +#endif // __cplusplus + +struct __ets_deferred; +typedef struct __ets_deferred *ets_deferred; + +// Field and Method IDs +struct __ets_method; +struct __ets_field; +typedef struct __ets_method *ets_method; +typedef struct __ets_field *ets_field; + +// The Value Type +typedef union ets_value { + ets_boolean z; + ets_byte b; + ets_char c; + ets_short s; + ets_int i; + ets_long j; + ets_float f; + ets_double d; + ets_object l; +} ets_value; + +// Describe native method by name, signature and function pointer +typedef struct { + const char *name; + const char *signature; + void *func; +} EtsNativeMethod; + +// The object reference types +typedef enum { + ETS_INVALID_REF_TYPE = 0, + ETS_LOCAL_REF_TYPE = 1, + ETS_GLOBAL_REF_TYPE = 2, + ETS_WEAK_GLOBAL_REF_TYPE = 3 +} ets_objectRefType; + +#ifdef __cplusplus +typedef struct __EtsVM EtsVM; +typedef struct __EtsEnv ets_env; +#else +typedef const struct ETS_InvokeInterface *EtsVM; +typedef const struct ETS_NativeInterface *ets_env; +#endif + +// Deprecated types: +typedef ets_env EtsEnv; + +typedef enum { + ETS_OKAY, + ETS_INVALID_ARG, + ETS_GENERIC_FAILURE, + ETS_PENDING_EXCEPTION, + ETS_INVALID_VERSION, // NOTE(v.cherkashin): This status code doesn't match to napi interface. + // Should we probably delete this status code? +} ets_status; + +// clang-format off +// Interface Function Table +struct ETS_NativeInterface { + // NOTE(a.urakov): solve the "Array" naming problem + ets_int (*GetVersion)(EtsEnv *env); +#ifdef ETS_NAPI_DESIGN_FINISHED + ets_class (*DefineClass)(EtsEnv *env, const char *name, ets_object loader, const ets_byte *buf, ets_size bufLen); +#endif + ets_class (*FindClass)(EtsEnv *env, const char *name); +#ifdef ETS_NAPI_DESIGN_FINISHED + ets_method (*FromReflectedMethod)(EtsEnv *env, ets_object method); + ets_field (*FromReflectedField)(EtsEnv *env, ets_object field); + ets_object (*ToReflectedMethod)(EtsEnv *env, ets_class cls, ets_method p_method, ets_boolean isStatic); +#endif + ets_class (*GetSuperclass)(EtsEnv *env, ets_class cls); + ets_boolean (*IsAssignableFrom)(EtsEnv *env, ets_class cls1, ets_class cls2); +#ifdef ETS_NAPI_DESIGN_FINISHED + ets_object (*ToReflectedField)(EtsEnv *env, ets_class cls, ets_field p_field, ets_boolean isStatic); +#endif + ets_int (*ThrowError)(EtsEnv *env, ets_error obj); + ets_int (*ThrowErrorNew)(EtsEnv *env, ets_class cls, const char *message); + ets_error (*ErrorOccurred)(EtsEnv *env); + void (*ErrorDescribe)(EtsEnv *env); + void (*ErrorClear)(EtsEnv *env); + void (*FatalError)(EtsEnv *env, const char *message); + ets_int (*PushLocalFrame)(EtsEnv *env, ets_int capacity); + ets_object (*PopLocalFrame)(EtsEnv *env, ets_object result); + ets_object (*NewGlobalRef)(EtsEnv *env, ets_object obj); + void (*DeleteGlobalRef)(EtsEnv *env, ets_object globalRef); + void (*DeleteLocalRef)(EtsEnv *env, ets_object localRef); + ets_boolean (*IsSameObject)(EtsEnv *env, ets_object ref1, ets_object ref2); + ets_object (*NewLocalRef)(EtsEnv *env, ets_object ref); + ets_int (*EnsureLocalCapacity)(EtsEnv *env, ets_int capacity); + ets_object (*AllocObject)(EtsEnv *env, ets_class cls); + ets_object (*NewObject)(EtsEnv *env, ets_class cls, ets_method p_method, ...); + ets_object (*NewObjectList)(EtsEnv *env, ets_class cls, ets_method p_method, va_list args); + ets_object (*NewObjectArray)(EtsEnv *env, ets_class cls, ets_method p_method, const ets_value *args); + ets_class (*GetObjectClass)(EtsEnv *env, ets_object obj); + ets_boolean (*IsInstanceOf)(EtsEnv *env, ets_object obj, ets_class cls); + ets_method (*Getp_method)(EtsEnv *env, ets_class cls, const char *name, const char *sig); + ets_object (*CallObjectMethod)(EtsEnv *env, ets_object obj, ets_method p_method, ...); + ets_object (*CallObjectMethodList)(EtsEnv *env, ets_object obj, ets_method p_method, va_list args); + ets_object (*CallObjectMethodArray)(EtsEnv *env, ets_object obj, ets_method p_method, const ets_value *args); + ets_boolean (*CallBooleanMethod)(EtsEnv *env, ets_object obj, ets_method p_method, ...); + ets_boolean (*CallBooleanMethodList)(EtsEnv *env, ets_object obj, ets_method p_method, va_list args); + ets_boolean (*CallBooleanMethodArray)(EtsEnv *env, ets_object obj, ets_method p_method, const ets_value *args); + ets_byte (*CallByteMethod)(EtsEnv *env, ets_object obj, ets_method p_method, ...); + ets_byte (*CallByteMethodList)(EtsEnv *env, ets_object obj, ets_method p_method, va_list args); + ets_byte (*CallByteMethodArray)(EtsEnv *env, ets_object obj, ets_method p_method, const ets_value *args); + ets_char (*CallCharMethod)(EtsEnv *env, ets_object obj, ets_method p_method, ...); + ets_char (*CallCharMethodList)(EtsEnv *env, ets_object obj, ets_method p_method, va_list args); + ets_char (*CallCharMethodArray)(EtsEnv *env, ets_object obj, ets_method p_method, const ets_value *args); + ets_short (*CallShortMethod)(EtsEnv *env, ets_object obj, ets_method p_method, ...); + ets_short (*CallShortMethodList)(EtsEnv *env, ets_object obj, ets_method p_method, va_list args); + ets_short (*CallShortMethodArray)(EtsEnv *env, ets_object obj, ets_method p_method, const ets_value *args); + ets_int (*CallIntMethod)(EtsEnv *env, ets_object obj, ets_method p_method, ...); + ets_int (*CallIntMethodList)(EtsEnv *env, ets_object obj, ets_method p_method, va_list args); + ets_int (*CallIntMethodArray)(EtsEnv *env, ets_object obj, ets_method p_method, const ets_value *args); + ets_long (*CallLongMethod)(EtsEnv *env, ets_object obj, ets_method p_method, ...); + ets_long (*CallLongMethodList)(EtsEnv *env, ets_object obj, ets_method p_method, va_list args); + ets_long (*CallLongMethodArray)(EtsEnv *env, ets_object obj, ets_method p_method, const ets_value *args); + ets_float (*CallFloatMethod)(EtsEnv *env, ets_object obj, ets_method p_method, ...); + ets_float (*CallFloatMethodList)(EtsEnv *env, ets_object obj, ets_method p_method, va_list args); + ets_float (*CallFloatMethodArray)(EtsEnv *env, ets_object obj, ets_method p_method, const ets_value *args); + ets_double (*CallDoubleMethod)(EtsEnv *env, ets_object obj, ets_method p_method, ...); + ets_double (*CallDoubleMethodList)(EtsEnv *env, ets_object obj, ets_method p_method, va_list args); + ets_double (*CallDoubleMethodArray)(EtsEnv *env, ets_object obj, ets_method p_method, const ets_value *args); + void (*CallVoidMethod)(EtsEnv *env, ets_object obj, ets_method p_method, ...); + void (*CallVoidMethodList)(EtsEnv *env, ets_object obj, ets_method p_method, va_list args); + void (*CallVoidMethodArray)(EtsEnv *env, ets_object obj, ets_method p_method, const ets_value *args); + + ets_object (*CallNonvirtualObjectMethod)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, ...); + ets_object (*CallNonvirtualObjectMethodList)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + va_list args); + ets_object (*CallNonvirtualObjectMethodArray)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + const ets_value *args); + ets_boolean (*CallNonvirtualBooleanMethod)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, ...); + ets_boolean (*CallNonvirtualBooleanMethodList)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + va_list args); + ets_boolean (*CallNonvirtualBooleanMethodArray)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + const ets_value *args); + ets_byte (*CallNonvirtualByteMethod)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, ...); + ets_byte (*CallNonvirtualByteMethodList)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + va_list args); + ets_byte (*CallNonvirtualByteMethodArray)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + const ets_value *args); + ets_char (*CallNonvirtualCharMethod)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, ...); + ets_char (*CallNonvirtualCharMethodList)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + va_list args); + ets_char (*CallNonvirtualCharMethodArray)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + const ets_value *args); + ets_short (*CallNonvirtualShortMethod)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, ...); + ets_short (*CallNonvirtualShortMethodList)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + va_list args); + ets_short (*CallNonvirtualShortMethodArray)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + const ets_value *args); + ets_int (*CallNonvirtualIntMethod)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, ...); + ets_int (*CallNonvirtualIntMethodList)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + va_list args); + ets_int (*CallNonvirtualIntMethodArray)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + const ets_value *args); + ets_long (*CallNonvirtualLongMethod)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, ...); + ets_long (*CallNonvirtualLongMethodList)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + va_list args); + ets_long (*CallNonvirtualLongMethodArray)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + const ets_value *args); + ets_float (*CallNonvirtualFloatMethod)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, ...); + ets_float (*CallNonvirtualFloatMethodList)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + va_list args); + ets_float (*CallNonvirtualFloatMethodArray)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + const ets_value *args); + ets_double (*CallNonvirtualDoubleMethod)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, ...); + ets_double (*CallNonvirtualDoubleMethodList)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + va_list args); + ets_double (*CallNonvirtualDoubleMethodArray)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + const ets_value *args); + void (*CallNonvirtualVoidMethod)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, ...); + void (*CallNonvirtualVoidMethodList)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, va_list args); + void (*CallNonvirtualVoidMethodArray)(EtsEnv *env, ets_object obj, ets_class cls, ets_method p_method, + const ets_value *args); + ets_field (*Getp_field)(EtsEnv *env, ets_class cls, const char *name, const char *sig); + ets_object (*GetObjectField)(EtsEnv *env, ets_object obj, ets_field p_field); + ets_boolean (*GetBooleanField)(EtsEnv *env, ets_object obj, ets_field p_field); + ets_byte (*GetByteField)(EtsEnv *env, ets_object obj, ets_field p_field); + ets_char (*GetCharField)(EtsEnv *env, ets_object obj, ets_field p_field); + ets_short (*GetShortField)(EtsEnv *env, ets_object obj, ets_field p_field); + ets_int (*GetIntField)(EtsEnv *env, ets_object obj, ets_field p_field); + ets_long (*GetLongField)(EtsEnv *env, ets_object obj, ets_field p_field); + ets_float (*GetFloatField)(EtsEnv *env, ets_object obj, ets_field p_field); + ets_double (*GetDoubleField)(EtsEnv *env, ets_object obj, ets_field p_field); + void (*SetObjectField)(EtsEnv *env, ets_object obj, ets_field p_field, ets_object value); + void (*SetBooleanField)(EtsEnv *env, ets_object obj, ets_field p_field, ets_boolean value); + void (*SetByteField)(EtsEnv *env, ets_object obj, ets_field p_field, ets_byte value); + void (*SetCharField)(EtsEnv *env, ets_object obj, ets_field p_field, ets_char value); + void (*SetShortField)(EtsEnv *env, ets_object obj, ets_field p_field, ets_short value); + void (*SetIntField)(EtsEnv *env, ets_object obj, ets_field p_field, ets_int value); + void (*SetLongField)(EtsEnv *env, ets_object obj, ets_field p_field, ets_long value); + void (*SetFloatField)(EtsEnv *env, ets_object obj, ets_field p_field, ets_float value); + void (*SetDoubleField)(EtsEnv *env, ets_object obj, ets_field p_field, ets_double value); + ets_method (*GetStaticp_method)(EtsEnv *env, ets_class cls, const char *name, const char *sig); + ets_object (*CallStaticObjectMethod)(EtsEnv *env, ets_class cls, ets_method p_method, ...); + ets_object (*CallStaticObjectMethodList)(EtsEnv *env, ets_class cls, ets_method p_method, va_list args); + ets_object (*CallStaticObjectMethodArray)(EtsEnv *env, ets_class cls, ets_method p_method, ets_value *args); + ets_boolean (*CallStaticBooleanMethod)(EtsEnv *env, ets_class cls, ets_method p_method, ...); + ets_boolean (*CallStaticBooleanMethodList)(EtsEnv *env, ets_class cls, ets_method p_method, va_list args); + ets_boolean (*CallStaticBooleanMethodArray)(EtsEnv *env, ets_class cls, ets_method p_method, ets_value *args); + ets_byte (*CallStaticByteMethod)(EtsEnv *env, ets_class cls, ets_method p_method, ...); + ets_byte (*CallStaticByteMethodList)(EtsEnv *env, ets_class cls, ets_method p_method, va_list args); + ets_byte (*CallStaticByteMethodArray)(EtsEnv *env, ets_class cls, ets_method p_method, ets_value *args); + ets_char (*CallStaticCharMethod)(EtsEnv *env, ets_class cls, ets_method p_method, ...); + ets_char (*CallStaticCharMethodList)(EtsEnv *env, ets_class cls, ets_method p_method, va_list args); + ets_char (*CallStaticCharMethodArray)(EtsEnv *env, ets_class cls, ets_method p_method, ets_value *args); + ets_short (*CallStaticShortMethod)(EtsEnv *env, ets_class cls, ets_method p_method, ...); + ets_short (*CallStaticShortMethodList)(EtsEnv *env, ets_class cls, ets_method p_method, va_list args); + ets_short (*CallStaticShortMethodArray)(EtsEnv *env, ets_class cls, ets_method p_method, ets_value *args); + ets_int (*CallStaticIntMethod)(EtsEnv *env, ets_class cls, ets_method p_method, ...); + ets_int (*CallStaticIntMethodList)(EtsEnv *env, ets_class cls, ets_method p_method, va_list args); + ets_int (*CallStaticIntMethodArray)(EtsEnv *env, ets_class cls, ets_method p_method, ets_value *args); + ets_long (*CallStaticLongMethod)(EtsEnv *env, ets_class cls, ets_method p_method, ...); + ets_long (*CallStaticLongMethodList)(EtsEnv *env, ets_class cls, ets_method p_method, va_list args); + ets_long (*CallStaticLongMethodArray)(EtsEnv *env, ets_class cls, ets_method p_method, ets_value *args); + ets_float (*CallStaticFloatMethod)(EtsEnv *env, ets_class cls, ets_method p_method, ...); + ets_float (*CallStaticFloatMethodList)(EtsEnv *env, ets_class cls, ets_method p_method, va_list args); + ets_float (*CallStaticFloatMethodArray)(EtsEnv *env, ets_class cls, ets_method p_method, ets_value *args); + ets_double (*CallStaticDoubleMethod)(EtsEnv *env, ets_class cls, ets_method p_method, ...); + ets_double (*CallStaticDoubleMethodList)(EtsEnv *env, ets_class cls, ets_method p_method, va_list args); + ets_double (*CallStaticDoubleMethodArray)(EtsEnv *env, ets_class cls, ets_method p_method, ets_value *args); + void (*CallStaticVoidMethod)(EtsEnv *env, ets_class cls, ets_method p_method, ...); + void (*CallStaticVoidMethodList)(EtsEnv *env, ets_class cls, ets_method p_method, va_list args); + void (*CallStaticVoidMethodArray)(EtsEnv *env, ets_class cls, ets_method p_method, ets_value *args); + ets_field (*GetStaticp_field)(EtsEnv *env, ets_class cls, const char *name, const char *sig); + ets_object (*GetStaticObjectField)(EtsEnv *env, ets_class cls, ets_field p_field); + ets_boolean (*GetStaticBooleanField)(EtsEnv *env, ets_class cls, ets_field p_field); + ets_byte (*GetStaticByteField)(EtsEnv *env, ets_class cls, ets_field p_field); + ets_char (*GetStaticCharField)(EtsEnv *env, ets_class cls, ets_field p_field); + ets_short (*GetStaticShortField)(EtsEnv *env, ets_class cls, ets_field p_field); + ets_int (*GetStaticIntField)(EtsEnv *env, ets_class cls, ets_field p_field); + ets_long (*GetStaticLongField)(EtsEnv *env, ets_class cls, ets_field p_field); + ets_float (*GetStaticFloatField)(EtsEnv *env, ets_class cls, ets_field p_field); + ets_double (*GetStaticDoubleField)(EtsEnv *env, ets_class cls, ets_field p_field); + void (*SetStaticObjectField)(EtsEnv *env, ets_class cls, ets_field p_field, ets_object value); + void (*SetStaticBooleanField)(EtsEnv *env, ets_class cls, ets_field p_field, ets_boolean value); + void (*SetStaticByteField)(EtsEnv *env, ets_class cls, ets_field p_field, ets_byte value); + void (*SetStaticCharField)(EtsEnv *env, ets_class cls, ets_field p_field, ets_char value); + void (*SetStaticShortField)(EtsEnv *env, ets_class cls, ets_field p_field, ets_short value); + void (*SetStaticIntField)(EtsEnv *env, ets_class cls, ets_field p_field, ets_int value); + void (*SetStaticLongField)(EtsEnv *env, ets_class cls, ets_field p_field, ets_long value); + void (*SetStaticFloatField)(EtsEnv *env, ets_class cls, ets_field p_field, ets_float value); + void (*SetStaticDoubleField)(EtsEnv *env, ets_class cls, ets_field p_field, ets_double value); + ets_string (*NewString)(EtsEnv *env, const ets_char *unicodeChars, ets_size len); + ets_size (*GetStringLength)(EtsEnv *env, ets_string string); + const ets_char *(*GetStringChars)(EtsEnv *env, ets_string string, ets_boolean *isCopy); + void (*ReleaseStringChars)(EtsEnv *env, ets_string string, const ets_char *chars); + ets_string (*NewStringUTF)(EtsEnv *env, const char *bytes); + ets_size (*GetStringUTFLength)(EtsEnv *env, ets_string string); + const char *(*GetStringUTFChars)(EtsEnv *env, ets_string string, ets_boolean *isCopy); + void (*ReleaseStringUTFChars)(EtsEnv *env, ets_string string, const char *utf); + ets_size (*GetArrayLength)(EtsEnv *env, ets_array array); + ets_objectArray (*NewObjectsArray)(EtsEnv *env, ets_size length, ets_class element_class, + ets_object initial_element); + ets_object (*GetObjectArrayElement)(EtsEnv *env, ets_objectArray array, ets_size index); + void (*SetObjectArrayElement)(EtsEnv *env, ets_objectArray array, ets_size index, ets_object value); + ets_booleanArray (*NewBooleanArray)(EtsEnv *env, ets_size length); + ets_byteArray (*NewByteArray)(EtsEnv *env, ets_size length); + ets_charArray (*NewCharArray)(EtsEnv *env, ets_size length); + ets_shortArray (*NewShortArray)(EtsEnv *env, ets_size length); + ets_intArray (*NewIntArray)(EtsEnv *env, ets_size length); + ets_longArray (*NewLongArray)(EtsEnv *env, ets_size length); + ets_floatArray (*NewFloatArray)(EtsEnv *env, ets_size length); + ets_doubleArray (*NewDoubleArray)(EtsEnv *env, ets_size length); + ets_boolean *(*PinBooleanArray)(EtsEnv *env, ets_booleanArray array); + ets_byte *(*PinByteArray)(EtsEnv *env, ets_byteArray array); + ets_char *(*PinCharArray)(EtsEnv *env, ets_charArray array); + ets_short *(*PinShortArray)(EtsEnv *env, ets_shortArray array); + ets_int *(*PinIntArray)(EtsEnv *env, ets_intArray array); + ets_long *(*PinLongArray)(EtsEnv *env, ets_longArray array); + ets_float *(*PinFloatArray)(EtsEnv *env, ets_floatArray array); + ets_double *(*PinDoubleArray)(EtsEnv *env, ets_doubleArray array); + void (*UnpinBooleanArray)(EtsEnv *env, ets_booleanArray array); + void (*UnpinByteArray)(EtsEnv *env, ets_byteArray array); + void (*UnpinCharArray)(EtsEnv *env, ets_charArray array); + void (*UnpinShortArray)(EtsEnv *env, ets_shortArray array); + void (*UnpinIntArray)(EtsEnv *env, ets_intArray array); + void (*UnpinLongArray)(EtsEnv *env, ets_longArray array); + void (*UnpinFloatArray)(EtsEnv *env, ets_floatArray array); + void (*UnpinDoubleArray)(EtsEnv *env, ets_doubleArray array); + void (*GetBooleanArrayRegion)(EtsEnv *env, ets_booleanArray array, ets_size start, ets_size len, ets_boolean *buf); + void (*GetByteArrayRegion)(EtsEnv *env, ets_byteArray array, ets_size start, ets_size len, ets_byte *buf); + void (*GetCharArrayRegion)(EtsEnv *env, ets_charArray array, ets_size start, ets_size len, ets_char *buf); + void (*GetShortArrayRegion)(EtsEnv *env, ets_shortArray array, ets_size start, ets_size len, ets_short *buf); + void (*GetIntArrayRegion)(EtsEnv *env, ets_intArray array, ets_size start, ets_size len, ets_int *buf); + void (*GetLongArrayRegion)(EtsEnv *env, ets_longArray array, ets_size start, ets_size len, ets_long *buf); + void (*GetFloatArrayRegion)(EtsEnv *env, ets_floatArray array, ets_size start, ets_size len, ets_float *buf); + void (*GetDoubleArrayRegion)(EtsEnv *env, ets_doubleArray array, ets_size start, ets_size len, ets_double *buf); + void (*SetBooleanArrayRegion)(EtsEnv *env, ets_booleanArray array, ets_size start, ets_size len, + const ets_boolean *buf); + void (*SetByteArrayRegion)(EtsEnv *env, ets_byteArray array, ets_size start, ets_size len, const ets_byte *buf); + void (*SetCharArrayRegion)(EtsEnv *env, ets_charArray array, ets_size start, ets_size len, const ets_char *buf); + void (*SetShortArrayRegion)(EtsEnv *env, ets_shortArray array, ets_size start, ets_size len, const ets_short *buf); + void (*SetIntArrayRegion)(EtsEnv *env, ets_intArray array, ets_size start, ets_size len, const ets_int *buf); + void (*SetLongArrayRegion)(EtsEnv *env, ets_longArray array, ets_size start, ets_size len, const ets_long *buf); + void (*SetFloatArrayRegion)(EtsEnv *env, ets_floatArray array, ets_size start, ets_size len, const ets_float *buf); + void (*SetDoubleArrayRegion)(EtsEnv *env, ets_doubleArray array, ets_size start, ets_size len, + const ets_double *buf); + ets_int (*RegisterNatives)(EtsEnv *env, ets_class cls, const EtsNativeMethod *methods, ets_int nMethods); + ets_int (*UnregisterNatives)(EtsEnv *env, ets_class cls); + ets_int (*GetEtsVM)(EtsEnv *env, EtsVM **vm); + void (*GetStringRegion)(EtsEnv *env, ets_string str, ets_size start, ets_size len, ets_char *buf); + void (*GetStringUTFRegion)(EtsEnv *env, ets_string str, ets_size start, ets_size len, char *buf); + ets_weak (*NewWeakGlobalRef)(EtsEnv *env, ets_object obj); + void (*DeleteWeakGlobalRef)(EtsEnv *env, ets_weak obj); + ets_boolean (*ErrorCheck)(EtsEnv *env); +#ifdef ETS_NAPI_DESIGN_FINISHED + ets_object (*NewDirectByteBuffer)(EtsEnv *env, void *address, ets_long capacity); + void *(*GetDirectBufferAddress)(EtsEnv *env, ets_object buf); + ets_long (*GetDirectBufferCapacity)(EtsEnv *env, ets_object buf); +#endif + ets_objectRefType (*GetObjectRefType)(EtsEnv *env, ets_object obj); + + /* 227 methods */ + + // Promise API + ets_status (*PromiseCreate)(EtsEnv *env, ets_deferred *deferred, ets_object *promise); + ets_status (*DeferredResolve)(EtsEnv *env, ets_deferred deferred, ets_object resolution); + ets_status (*DeferredReject)(EtsEnv *env, ets_deferred deferred, ets_object rejection); +}; +// clang-format on + +// Invocation API Functions +typedef enum { + ETS_LOG_LEVEL, + ETS_MOBILE_LOG, + ETS_BOOT_FILE, + ETS_AOT_FILE, + ETS_ARK_FILE, + ETS_JIT, + ETS_NO_JIT, + ETS_AOT, + ETS_NO_AOT, + ETS_GC_TRIGGER_TYPE, + ETS_GC_TYPE, + ETS_RUN_GC_IN_PLACE, + ETS_INTERPRETER_TYPE, + ETS_NATIVE_LIBRARY_PATH, + ETS_VERIFICATION_MODE +} EtsOptionType; + +typedef struct EtsVMOption { + EtsOptionType option; + const void *extraInfo; +} EtsVMOption; + +typedef struct EtsVMInitArgs { + ets_int version; + ets_int nOptions; + EtsVMOption *options; +} EtsVMInitArgs; + +typedef enum { + ETS_MOBILE_LOG_LEVEL_UNKNOWN = 0, + ETS_MOBILE_LOG_LEVEL_DEFAULT, + ETS_MOBILE_LOG_LEVEL_VERBOSE, + ETS_MOBILE_LOG_LEVEL_DEBUG, + ETS_MOBILE_LOG_LEVEL_INFO, + ETS_MOBILE_LOG_LEVEL_WARN, + ETS_MOBILE_LOG_LEVEL_ERROR, + ETS_MOBILE_LOG_LEVEL_FATAL, + ETS_MOBILE_LOG_LEVEL_SILENT +} EtsMobileLogggerLevel; + +#ifdef __cplusplus +extern "C" { +#endif + +#define ETS_EXPORT __attribute__((visibility("default"))) +#define ETS_IMPORT +#define ETS_CALL + +ETS_EXPORT ets_int ETS_GetDefaultVMInitArgs(EtsVMInitArgs *vmArgs); +ETS_EXPORT ets_int ETS_GetCreatedVMs(EtsVM **vmBuf, ets_size bufLen, ets_size *nVms); +ETS_EXPORT ets_int ETS_CreateVM(EtsVM **pVm, EtsEnv **pEnv, EtsVMInitArgs *vmArgs); + +#ifdef __cplusplus +} +#endif + +struct ETS_InvokeInterface { + ets_int (*DestroyEtsVM)(EtsVM *vm); + ets_int (*GetEnv)(EtsVM *vm, EtsEnv **pEnv, ets_int version); + // CC-OFFNXT(G.NAM.03-CPP) project code style + ets_int (*AttachThread)(EtsVM *vm, EtsEnv **resultEnv, void **resultJsEnv); + ets_int (*DetachThread)(EtsVM *vm); +}; + +struct __EtsVM { + // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) + const struct ETS_InvokeInterface *invoke_interface; + +#ifdef __cplusplus + ets_int DestroyEtsVM() + { + return invoke_interface->DestroyEtsVM(this); + } + + ets_int GetEnv(EtsEnv **pEnv, ets_int version) + { + return invoke_interface->GetEnv(this, pEnv, version); + } + + ets_int AttachThread(EtsEnv **resultEnv, void **resultJsEnv) + { + return invoke_interface->AttachThread(this, resultEnv, resultJsEnv); + } + + ets_int DetachThread() + { + return invoke_interface->DetachThread(this); + } +#endif +}; + +struct __EtsEnv { + // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) + const struct ETS_NativeInterface *native_interface; + +#ifdef __cplusplus + + ets_int GetVersion() + { + return native_interface->GetVersion(this); + } + // DefineClass, + ets_class FindClass(const char *name) + { + return native_interface->FindClass(this, name); + } + // FromReflectedMethod, + // FromReflectedField, + // ToReflectedMethod, + ets_class GetSuperclass(ets_class cls) + { + return native_interface->GetSuperclass(this, cls); + } + ets_boolean IsAssignableFrom(ets_class cls1, ets_class cls2) + { + return native_interface->IsAssignableFrom(this, cls1, cls2); + } + // ToReflectedField, + ets_int ThrowError(ets_error obj) + { + return native_interface->ThrowError(this, obj); + } + ets_int ThrowErrorNew(ets_class cls, const char *message) + { + return native_interface->ThrowErrorNew(this, cls, message); + } + ets_error ErrorOccurred() + { + return native_interface->ErrorOccurred(this); + } + void ErrorDescribe() + { + native_interface->ErrorDescribe(this); + } + void ErrorClear() + { + native_interface->ErrorClear(this); + } + void FatalError(const char *message) + { + native_interface->FatalError(this, message); + } + ets_int PushLocalFrame(ets_int capacity) + { + return native_interface->PushLocalFrame(this, capacity); + } + ets_object PopLocalFrame(ets_object result) + { + return native_interface->PopLocalFrame(this, result); + } + ets_object NewGlobalRef(ets_object obj) + { + return native_interface->NewGlobalRef(this, obj); + } + void DeleteGlobalRef(ets_object globalRef) + { + native_interface->DeleteGlobalRef(this, globalRef); + } + void DeleteLocalRef(ets_object localRef) + { + native_interface->DeleteLocalRef(this, localRef); + } + ets_boolean IsSameObject(ets_object ref1, ets_object ref2) + { + return native_interface->IsSameObject(this, ref1, ref2); + } + ets_object NewLocalRef(ets_object ref) + { + return native_interface->NewLocalRef(this, ref); + } + ets_int EnsureLocalCapacity(ets_int capacity) + { + return native_interface->EnsureLocalCapacity(this, capacity); + } + ets_object AllocObject(ets_class cls) + { + return native_interface->AllocObject(this, cls); + } + ets_object NewObject(ets_class cls, ets_method p_method, ...) + { + va_list args; + va_start(args, p_method); + ets_object ret = native_interface->NewObjectList(this, cls, p_method, args); + va_end(args); + return ret; + } + ets_object NewObjectList(ets_class cls, ets_method p_method, va_list args) + { + return native_interface->NewObjectList(this, cls, p_method, args); + } + ets_object NewObjectArray(ets_class cls, ets_method p_method, const ets_value *args) + { + return native_interface->NewObjectArray(this, cls, p_method, args); + } + ets_class GetObjectClass(ets_object obj) + { + return native_interface->GetObjectClass(this, obj); + } + ets_boolean IsInstanceOf(ets_object obj, ets_class cls) + { + return native_interface->IsInstanceOf(this, obj, cls); + } + ets_method Getp_method(ets_class cls, const char *name, const char *sig) + { + return native_interface->Getp_method(this, cls, name, sig); + } + ets_object CallObjectMethod(ets_object obj, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_object res = native_interface->CallObjectMethodList(this, obj, method_id, args); + va_end(args); + return res; + } + ets_object CallObjectMethodList(ets_object obj, ets_method method_id, va_list args) + { + return native_interface->CallObjectMethodList(this, obj, method_id, args); + } + ets_object CallObjectMethodArray(ets_object obj, ets_method method_id, const ets_value *args) + { + return native_interface->CallObjectMethodArray(this, obj, method_id, args); + } + ets_boolean CallBooleanMethod(ets_object obj, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_boolean res = native_interface->CallBooleanMethodList(this, obj, method_id, args); + va_end(args); + return res; + } + ets_boolean CallBooleanMethodList(ets_object obj, ets_method method_id, va_list args) + { + return native_interface->CallBooleanMethodList(this, obj, method_id, args); + } + ets_boolean CallBooleanMethodArray(ets_object obj, ets_method method_id, const ets_value *args) + { + return native_interface->CallBooleanMethodArray(this, obj, method_id, args); + } + ets_byte CallByteMethod(ets_object obj, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_byte res = native_interface->CallByteMethodList(this, obj, method_id, args); + va_end(args); + return res; + } + ets_byte CallByteMethodList(ets_object obj, ets_method method_id, va_list args) + { + return native_interface->CallByteMethodList(this, obj, method_id, args); + } + ets_byte CallByteMethodArray(ets_object obj, ets_method method_id, const ets_value *args) + { + return native_interface->CallByteMethodArray(this, obj, method_id, args); + } + ets_char CallCharMethod(ets_object obj, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_char res = native_interface->CallCharMethodList(this, obj, method_id, args); + va_end(args); + return res; + } + ets_char CallCharMethodList(ets_object obj, ets_method method_id, va_list args) + { + return native_interface->CallCharMethodList(this, obj, method_id, args); + } + ets_char CallCharMethodArray(ets_object obj, ets_method method_id, const ets_value *args) + { + return native_interface->CallCharMethodArray(this, obj, method_id, args); + } + ets_short CallShortMethod(ets_object obj, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_short res = native_interface->CallShortMethodList(this, obj, method_id, args); + va_end(args); + return res; + } + ets_short CallShortMethodList(ets_object obj, ets_method method_id, va_list args) + { + return native_interface->CallShortMethodList(this, obj, method_id, args); + } + ets_short CallShortMethodArray(ets_object obj, ets_method method_id, const ets_value *args) + { + return native_interface->CallShortMethodArray(this, obj, method_id, args); + } + ets_int CallIntMethod(ets_object obj, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_int res = native_interface->CallIntMethodList(this, obj, method_id, args); + va_end(args); + return res; + } + ets_int CallIntMethodList(ets_object obj, ets_method method_id, va_list args) + { + return native_interface->CallIntMethodList(this, obj, method_id, args); + } + ets_int CallIntMethodArray(ets_object obj, ets_method method_id, const ets_value *args) + { + return native_interface->CallIntMethodArray(this, obj, method_id, args); + } + ets_long CallLongMethod(ets_object obj, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_long res = native_interface->CallLongMethodList(this, obj, method_id, args); + va_end(args); + return res; + } + ets_long CallLongMethodList(ets_object obj, ets_method method_id, va_list args) + { + return native_interface->CallLongMethodList(this, obj, method_id, args); + } + ets_long CallLongMethodArray(ets_object obj, ets_method method_id, const ets_value *args) + { + return native_interface->CallLongMethodArray(this, obj, method_id, args); + } + ets_float CallFloatMethod(ets_object obj, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_float res = native_interface->CallFloatMethodList(this, obj, method_id, args); + va_end(args); + return res; + } + ets_float CallFloatMethodList(ets_object obj, ets_method method_id, va_list args) + { + return native_interface->CallFloatMethodList(this, obj, method_id, args); + } + ets_float CallFloatMethodArray(ets_object obj, ets_method method_id, const ets_value *args) + { + return native_interface->CallFloatMethodArray(this, obj, method_id, args); + } + ets_double CallDoubleMethod(ets_object obj, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_double res = native_interface->CallDoubleMethodList(this, obj, method_id, args); + va_end(args); + return res; + } + ets_double CallDoubleMethodList(ets_object obj, ets_method method_id, va_list args) + { + return native_interface->CallDoubleMethodList(this, obj, method_id, args); + } + ets_double CallDoubleMethodArray(ets_object obj, ets_method method_id, const ets_value *args) + { + return native_interface->CallDoubleMethodArray(this, obj, method_id, args); + } + void CallVoidMethod(ets_object obj, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + native_interface->CallVoidMethodList(this, obj, method_id, args); + va_end(args); + } + void CallVoidMethodList(ets_object obj, ets_method method_id, va_list args) + { + native_interface->CallVoidMethodList(this, obj, method_id, args); + } + void CallVoidMethodArray(ets_object obj, ets_method method_id, const ets_value *args) + { + native_interface->CallVoidMethodArray(this, obj, method_id, args); + } + ets_object CallNonvirtualObjectMethod(ets_object obj, ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_object res = native_interface->CallNonvirtualObjectMethodList(this, obj, cls, method_id, args); + va_end(args); + return res; + } + ets_object CallNonvirtualObjectMethodList(ets_object obj, ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallNonvirtualObjectMethodList(this, obj, cls, method_id, args); + } + ets_object CallNonvirtualObjectMethodArray(ets_object obj, ets_class cls, ets_method method_id, + const ets_value *args) + { + return native_interface->CallNonvirtualObjectMethodArray(this, obj, cls, method_id, args); + } + ets_boolean CallNonvirtualBooleanMethod(ets_object obj, ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_boolean res = native_interface->CallNonvirtualBooleanMethodList(this, obj, cls, method_id, args); + va_end(args); + return res; + } + ets_boolean CallNonvirtualBooleanMethodList(ets_object obj, ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallNonvirtualBooleanMethodList(this, obj, cls, method_id, args); + } + ets_boolean CallNonvirtualBooleanMethodArray(ets_object obj, ets_class cls, ets_method method_id, + const ets_value *args) + { + return native_interface->CallNonvirtualBooleanMethodArray(this, obj, cls, method_id, args); + } + ets_byte CallNonvirtualByteMethod(ets_object obj, ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_byte res = native_interface->CallNonvirtualByteMethodList(this, obj, cls, method_id, args); + va_end(args); + return res; + } + ets_byte CallNonvirtualByteMethodList(ets_object obj, ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallNonvirtualByteMethodList(this, obj, cls, method_id, args); + } + ets_byte CallNonvirtualByteMethodArray(ets_object obj, ets_class cls, ets_method method_id, const ets_value *args) + { + return native_interface->CallNonvirtualByteMethodArray(this, obj, cls, method_id, args); + } + ets_char CallNonvirtualCharMethod(ets_object obj, ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_char res = native_interface->CallNonvirtualCharMethodList(this, obj, cls, method_id, args); + va_end(args); + return res; + } + ets_char CallNonvirtualCharMethodList(ets_object obj, ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallNonvirtualCharMethodList(this, obj, cls, method_id, args); + } + ets_char CallNonvirtualCharMethodArray(ets_object obj, ets_class cls, ets_method method_id, const ets_value *args) + { + return native_interface->CallNonvirtualCharMethodArray(this, obj, cls, method_id, args); + } + ets_short CallNonvirtualShortMethod(ets_object obj, ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_short res = native_interface->CallNonvirtualShortMethodList(this, obj, cls, method_id, args); + va_end(args); + return res; + } + ets_short CallNonvirtualShortMethodList(ets_object obj, ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallNonvirtualShortMethodList(this, obj, cls, method_id, args); + } + ets_short CallNonvirtualShortMethodArray(ets_object obj, ets_class cls, ets_method method_id, const ets_value *args) + { + return native_interface->CallNonvirtualShortMethodArray(this, obj, cls, method_id, args); + } + ets_int CallNonvirtualIntMethod(ets_object obj, ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_int res = native_interface->CallNonvirtualIntMethodList(this, obj, cls, method_id, args); + va_end(args); + return res; + } + ets_int CallNonvirtualIntMethodList(ets_object obj, ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallNonvirtualIntMethodList(this, obj, cls, method_id, args); + } + ets_int CallNonvirtualIntMethodArray(ets_object obj, ets_class cls, ets_method method_id, const ets_value *args) + { + return native_interface->CallNonvirtualIntMethodArray(this, obj, cls, method_id, args); + } + ets_long CallNonvirtualLongMethod(ets_object obj, ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_long res = native_interface->CallNonvirtualLongMethodList(this, obj, cls, method_id, args); + va_end(args); + return res; + } + ets_long CallNonvirtualLongMethodList(ets_object obj, ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallNonvirtualLongMethodList(this, obj, cls, method_id, args); + } + ets_long CallNonvirtualLongMethodArray(ets_object obj, ets_class cls, ets_method method_id, const ets_value *args) + { + return native_interface->CallNonvirtualLongMethodArray(this, obj, cls, method_id, args); + } + ets_float CallNonvirtualFloatMethod(ets_object obj, ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_float res = native_interface->CallNonvirtualFloatMethodList(this, obj, cls, method_id, args); + va_end(args); + return res; + } + ets_float CallNonvirtualFloatMethodList(ets_object obj, ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallNonvirtualFloatMethodList(this, obj, cls, method_id, args); + } + ets_float CallNonvirtualFloatMethodArray(ets_object obj, ets_class cls, ets_method method_id, const ets_value *args) + { + return native_interface->CallNonvirtualFloatMethodArray(this, obj, cls, method_id, args); + } + ets_double CallNonvirtualDoubleMethod(ets_object obj, ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_double res = native_interface->CallNonvirtualDoubleMethodList(this, obj, cls, method_id, args); + va_end(args); + return res; + } + ets_double CallNonvirtualDoubleMethodList(ets_object obj, ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallNonvirtualDoubleMethodList(this, obj, cls, method_id, args); + } + ets_double CallNonvirtualDoubleMethodArray(ets_object obj, ets_class cls, ets_method method_id, + const ets_value *args) + { + return native_interface->CallNonvirtualDoubleMethodArray(this, obj, cls, method_id, args); + } + void CallNonvirtualVoidMethod(ets_object obj, ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + native_interface->CallNonvirtualVoidMethodList(this, obj, cls, method_id, args); + va_end(args); + } + void CallNonvirtualVoidMethodList(ets_object obj, ets_class cls, ets_method method_id, va_list args) + { + native_interface->CallNonvirtualVoidMethodList(this, obj, cls, method_id, args); + } + void CallNonvirtualVoidMethodArray(ets_object obj, ets_class cls, ets_method method_id, const ets_value *args) + { + native_interface->CallNonvirtualVoidMethodArray(this, obj, cls, method_id, args); + } + ets_field Getp_field(ets_class cls, const char *name, const char *sig) + { + return native_interface->Getp_field(this, cls, name, sig); + } + ets_object GetObjectField(ets_object obj, ets_field p_field) + { + return native_interface->GetObjectField(this, obj, p_field); + } + ets_boolean GetBooleanField(ets_object obj, ets_field p_field) + { + return native_interface->GetBooleanField(this, obj, p_field); + } + ets_byte GetByteField(ets_object obj, ets_field p_field) + { + return native_interface->GetByteField(this, obj, p_field); + } + ets_char GetCharField(ets_object obj, ets_field p_field) + { + return native_interface->GetCharField(this, obj, p_field); + } + ets_short GetShortField(ets_object obj, ets_field p_field) + { + return native_interface->GetShortField(this, obj, p_field); + } + ets_int GetIntField(ets_object obj, ets_field p_field) + { + return native_interface->GetIntField(this, obj, p_field); + } + ets_long GetLongField(ets_object obj, ets_field p_field) + { + return native_interface->GetLongField(this, obj, p_field); + } + ets_float GetFloatField(ets_object obj, ets_field p_field) + { + return native_interface->GetFloatField(this, obj, p_field); + } + ets_double GetDoubleField(ets_object obj, ets_field p_field) + { + return native_interface->GetDoubleField(this, obj, p_field); + } + void SetObjectField(ets_object obj, ets_field p_field, ets_object value) + { + return native_interface->SetObjectField(this, obj, p_field, value); + } + void SetBooleanField(ets_object obj, ets_field p_field, ets_boolean value) + { + return native_interface->SetBooleanField(this, obj, p_field, value); + } + void SetByteField(ets_object obj, ets_field p_field, ets_byte value) + { + return native_interface->SetByteField(this, obj, p_field, value); + } + void SetCharField(ets_object obj, ets_field p_field, ets_char value) + { + return native_interface->SetCharField(this, obj, p_field, value); + } + void SetShortField(ets_object obj, ets_field p_field, ets_short value) + { + return native_interface->SetShortField(this, obj, p_field, value); + } + void SetIntField(ets_object obj, ets_field p_field, ets_int value) + { + return native_interface->SetIntField(this, obj, p_field, value); + } + void SetLongField(ets_object obj, ets_field p_field, ets_long value) + { + return native_interface->SetLongField(this, obj, p_field, value); + } + void SetFloatField(ets_object obj, ets_field p_field, ets_float value) + { + return native_interface->SetFloatField(this, obj, p_field, value); + } + void SetDoubleField(ets_object obj, ets_field p_field, ets_double value) + { + return native_interface->SetDoubleField(this, obj, p_field, value); + } + ets_method GetStaticp_method(ets_class cls, const char *name, const char *sig) + { + return native_interface->GetStaticp_method(this, cls, name, sig); + } + ets_object CallStaticObjectMethod(ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_object res = native_interface->CallStaticObjectMethodList(this, cls, method_id, args); + va_end(args); + return res; + } + ets_object CallStaticObjectMethodList(ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallStaticObjectMethodList(this, cls, method_id, args); + } + ets_object CallStaticObjectMethodArray(ets_class cls, ets_method method_id, ets_value *args) + { + return native_interface->CallStaticObjectMethodArray(this, cls, method_id, args); + } + ets_boolean CallStaticBooleanMethod(ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_boolean res = native_interface->CallStaticBooleanMethodList(this, cls, method_id, args); + va_end(args); + return res; + } + ets_boolean CallStaticBooleanMethodList(ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallStaticBooleanMethodList(this, cls, method_id, args); + } + ets_boolean CallStaticBooleanMethodArray(ets_class cls, ets_method method_id, ets_value *args) + { + return native_interface->CallStaticBooleanMethodArray(this, cls, method_id, args); + } + ets_byte CallStaticByteMethod(ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_byte res = native_interface->CallStaticByteMethodList(this, cls, method_id, args); + va_end(args); + return res; + } + ets_byte CallStaticByteMethodList(ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallStaticByteMethodList(this, cls, method_id, args); + } + ets_byte CallStaticByteMethodArray(ets_class cls, ets_method method_id, ets_value *args) + { + return native_interface->CallStaticByteMethodArray(this, cls, method_id, args); + } + ets_char CallStaticCharMethod(ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_char res = native_interface->CallStaticCharMethodList(this, cls, method_id, args); + va_end(args); + return res; + } + ets_char CallStaticCharMethodList(ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallStaticCharMethodList(this, cls, method_id, args); + } + ets_char CallStaticCharMethodArray(ets_class cls, ets_method method_id, ets_value *args) + { + return native_interface->CallStaticCharMethodArray(this, cls, method_id, args); + } + ets_short CallStaticShortMethod(ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_short res = native_interface->CallStaticShortMethodList(this, cls, method_id, args); + va_end(args); + return res; + } + ets_short CallStaticShortMethodList(ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallStaticShortMethodList(this, cls, method_id, args); + } + ets_short CallStaticShortMethodArray(ets_class cls, ets_method method_id, ets_value *args) + { + return native_interface->CallStaticShortMethodArray(this, cls, method_id, args); + } + ets_int CallStaticIntMethod(ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_int res = native_interface->CallStaticIntMethodList(this, cls, method_id, args); + va_end(args); + return res; + } + ets_int CallStaticIntMethodList(ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallStaticIntMethodList(this, cls, method_id, args); + } + ets_int CallStaticIntMethodArray(ets_class cls, ets_method method_id, ets_value *args) + { + return native_interface->CallStaticIntMethodArray(this, cls, method_id, args); + } + ets_long CallStaticLongMethod(ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_long res = native_interface->CallStaticLongMethodList(this, cls, method_id, args); + va_end(args); + return res; + } + ets_long CallStaticLongMethodList(ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallStaticLongMethodList(this, cls, method_id, args); + } + ets_long CallStaticLongMethodArray(ets_class cls, ets_method method_id, ets_value *args) + { + return native_interface->CallStaticLongMethodArray(this, cls, method_id, args); + } + ets_float CallStaticFloatMethod(ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_float res = native_interface->CallStaticFloatMethodList(this, cls, method_id, args); + va_end(args); + return res; + } + ets_float CallStaticFloatMethodList(ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallStaticFloatMethodList(this, cls, method_id, args); + } + ets_float CallStaticFloatMethodArray(ets_class cls, ets_method method_id, ets_value *args) + { + return native_interface->CallStaticFloatMethodArray(this, cls, method_id, args); + } + ets_double CallStaticDoubleMethod(ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + ets_double res = native_interface->CallStaticDoubleMethodList(this, cls, method_id, args); + va_end(args); + return res; + } + ets_double CallStaticDoubleMethodList(ets_class cls, ets_method method_id, va_list args) + { + return native_interface->CallStaticDoubleMethodList(this, cls, method_id, args); + } + ets_double CallStaticDoubleMethodArray(ets_class cls, ets_method method_id, ets_value *args) + { + return native_interface->CallStaticDoubleMethodArray(this, cls, method_id, args); + } + void CallStaticVoidMethod(ets_class cls, ets_method method_id, ...) + { + va_list args; + va_start(args, method_id); + native_interface->CallStaticVoidMethodList(this, cls, method_id, args); + va_end(args); + } + void CallStaticVoidMethodList(ets_class cls, ets_method method_id, va_list args) + { + native_interface->CallStaticVoidMethodList(this, cls, method_id, args); + } + void CallStaticVoidMethodArray(ets_class cls, ets_method method_id, ets_value *args) + { + native_interface->CallStaticVoidMethodArray(this, cls, method_id, args); + } + ets_field GetStaticp_field(ets_class cls, const char *name, const char *sig) + { + return native_interface->GetStaticp_field(this, cls, name, sig); + } + ets_object GetStaticObjectField(ets_class cls, ets_field p_field) + { + return native_interface->GetStaticObjectField(this, cls, p_field); + } + ets_boolean GetStaticBooleanField(ets_class cls, ets_field p_field) + { + return native_interface->GetStaticBooleanField(this, cls, p_field); + } + ets_byte GetStaticByteField(ets_class cls, ets_field p_field) + { + return native_interface->GetStaticByteField(this, cls, p_field); + } + ets_char GetStaticCharField(ets_class cls, ets_field p_field) + { + return native_interface->GetStaticCharField(this, cls, p_field); + } + ets_short GetStaticShortField(ets_class cls, ets_field p_field) + { + return native_interface->GetStaticShortField(this, cls, p_field); + } + ets_int GetStaticIntField(ets_class cls, ets_field p_field) + { + return native_interface->GetStaticIntField(this, cls, p_field); + } + ets_long GetStaticLongField(ets_class cls, ets_field p_field) + { + return native_interface->GetStaticLongField(this, cls, p_field); + } + ets_float GetStaticFloatField(ets_class cls, ets_field p_field) + { + return native_interface->GetStaticFloatField(this, cls, p_field); + } + ets_double GetStaticDoubleField(ets_class cls, ets_field p_field) + { + return native_interface->GetStaticDoubleField(this, cls, p_field); + } + void SetStaticObjectField(ets_class cls, ets_field p_field, ets_object value) + { + return native_interface->SetStaticObjectField(this, cls, p_field, value); + } + void SetStaticBooleanField(ets_class cls, ets_field p_field, ets_boolean value) + { + return native_interface->SetStaticBooleanField(this, cls, p_field, value); + } + void SetStaticByteField(ets_class cls, ets_field p_field, ets_byte value) + { + return native_interface->SetStaticByteField(this, cls, p_field, value); + } + void SetStaticCharField(ets_class cls, ets_field p_field, ets_char value) + { + return native_interface->SetStaticCharField(this, cls, p_field, value); + } + void SetStaticShortField(ets_class cls, ets_field p_field, ets_short value) + { + return native_interface->SetStaticShortField(this, cls, p_field, value); + } + void SetStaticIntField(ets_class cls, ets_field p_field, ets_int value) + { + return native_interface->SetStaticIntField(this, cls, p_field, value); + } + void SetStaticLongField(ets_class cls, ets_field p_field, ets_long value) + { + return native_interface->SetStaticLongField(this, cls, p_field, value); + } + void SetStaticFloatField(ets_class cls, ets_field p_field, ets_float value) + { + return native_interface->SetStaticFloatField(this, cls, p_field, value); + } + void SetStaticDoubleField(ets_class cls, ets_field p_field, ets_double value) + { + return native_interface->SetStaticDoubleField(this, cls, p_field, value); + } + ets_string NewString(const ets_char *unicode_chars, ets_size len) + { + return native_interface->NewString(this, unicode_chars, len); + } + ets_size GetStringLength(ets_string string) + { + return native_interface->GetStringLength(this, string); + } + const ets_char *GetStringChars(ets_string string, ets_boolean *is_copy) + { + return native_interface->GetStringChars(this, string, is_copy); + } + void ReleaseStringChars(ets_string string, const ets_char *chars) + { + native_interface->ReleaseStringChars(this, string, chars); + } + ets_string NewStringUTF(const char *bytes) + { + return native_interface->NewStringUTF(this, bytes); + } + ets_size GetStringUTFLength(ets_string string) + { + return native_interface->GetStringUTFLength(this, string); + } + const char *GetStringUTFChars(ets_string string, ets_boolean *is_copy) + { + return native_interface->GetStringUTFChars(this, string, is_copy); + } + void ReleaseStringUTFChars(ets_string string, const char *chars) + { + native_interface->ReleaseStringUTFChars(this, string, chars); + } + ets_size GetArrayLength(ets_array array) + { + return native_interface->GetArrayLength(this, array); + } + ets_objectArray NewObjectsArray(ets_size length, ets_class element_class, ets_object initial_element) + { + return native_interface->NewObjectsArray(this, length, element_class, initial_element); + } + ets_object GetObjectArrayElement(ets_objectArray array, ets_size index) + { + return native_interface->GetObjectArrayElement(this, array, index); + } + + void SetObjectArrayElement(ets_objectArray array, ets_size index, ets_object value) + { + native_interface->SetObjectArrayElement(this, array, index, value); + } + + // SetObjectArrayElement, + ets_booleanArray NewBooleanArray(ets_size length) + { + return native_interface->NewBooleanArray(this, length); + } + ets_byteArray NewByteArray(ets_size length) + { + return native_interface->NewByteArray(this, length); + } + ets_charArray NewCharArray(ets_size length) + { + return native_interface->NewCharArray(this, length); + } + ets_shortArray NewShortArray(ets_size length) + { + return native_interface->NewShortArray(this, length); + } + ets_intArray NewIntArray(ets_size length) + { + return native_interface->NewIntArray(this, length); + } + ets_longArray NewLongArray(ets_size length) + { + return native_interface->NewLongArray(this, length); + } + ets_floatArray NewFloatArray(ets_size length) + { + return native_interface->NewFloatArray(this, length); + } + ets_doubleArray NewDoubleArray(ets_size length) + { + return native_interface->NewDoubleArray(this, length); + } + ets_boolean *PinBooleanArray(ets_booleanArray array) + { + return native_interface->PinBooleanArray(this, array); + } + ets_byte *PinByteArray(ets_byteArray array) + { + return native_interface->PinByteArray(this, array); + } + ets_char *PinCharArray(ets_charArray array) + { + return native_interface->PinCharArray(this, array); + } + ets_short *PinShortArray(ets_shortArray array) + { + return native_interface->PinShortArray(this, array); + } + ets_int *PinIntArray(ets_intArray array) + { + return native_interface->PinIntArray(this, array); + } + ets_long *PinLongArray(ets_longArray array) + { + return native_interface->PinLongArray(this, array); + } + ets_float *PinFloatArray(ets_floatArray array) + { + return native_interface->PinFloatArray(this, array); + } + ets_double *PinDoubleArray(ets_doubleArray array) + { + return native_interface->PinDoubleArray(this, array); + } + void UnpinBooleanArray(ets_booleanArray array) + { + return native_interface->UnpinBooleanArray(this, array); + } + void UnpinByteArray(ets_byteArray array) + { + return native_interface->UnpinByteArray(this, array); + } + void UnpinCharArray(ets_charArray array) + { + return native_interface->UnpinCharArray(this, array); + } + void UnpinShortArray(ets_shortArray array) + { + return native_interface->UnpinShortArray(this, array); + } + void UnpinIntArray(ets_intArray array) + { + return native_interface->UnpinIntArray(this, array); + } + void UnpinLongArray(ets_longArray array) + { + return native_interface->UnpinLongArray(this, array); + } + void UnpinFloatArray(ets_floatArray array) + { + return native_interface->UnpinFloatArray(this, array); + } + void UnpinDoubleArray(ets_doubleArray array) + { + return native_interface->UnpinDoubleArray(this, array); + } + void GetBooleanArrayRegion(ets_booleanArray array, ets_size start, ets_size len, ets_boolean *buf) + { + return native_interface->GetBooleanArrayRegion(this, array, start, len, buf); + } + void GetByteArrayRegion(ets_byteArray array, ets_size start, ets_size len, ets_byte *buf) + { + return native_interface->GetByteArrayRegion(this, array, start, len, buf); + } + void GetCharArrayRegion(ets_charArray array, ets_size start, ets_size len, ets_char *buf) + { + return native_interface->GetCharArrayRegion(this, array, start, len, buf); + } + void GetShortArrayRegion(ets_shortArray array, ets_size start, ets_size len, ets_short *buf) + { + return native_interface->GetShortArrayRegion(this, array, start, len, buf); + } + void GetIntArrayRegion(ets_intArray array, ets_size start, ets_size len, ets_int *buf) + { + return native_interface->GetIntArrayRegion(this, array, start, len, buf); + } + void GetLongArrayRegion(ets_longArray array, ets_size start, ets_size len, ets_long *buf) + { + return native_interface->GetLongArrayRegion(this, array, start, len, buf); + } + void GetFloatArrayRegion(ets_floatArray array, ets_size start, ets_size len, ets_float *buf) + { + return native_interface->GetFloatArrayRegion(this, array, start, len, buf); + } + void GetDoubleArrayRegion(ets_doubleArray array, ets_size start, ets_size len, ets_double *buf) + { + return native_interface->GetDoubleArrayRegion(this, array, start, len, buf); + } + void SetBooleanArrayRegion(ets_booleanArray array, ets_size start, ets_size length, const ets_boolean *buf) + { + native_interface->SetBooleanArrayRegion(this, array, start, length, buf); + } + void SetByteArrayRegion(ets_byteArray array, ets_size start, ets_size length, const ets_byte *buf) + { + native_interface->SetByteArrayRegion(this, array, start, length, buf); + } + void SetCharArrayRegion(ets_charArray array, ets_size start, ets_size length, const ets_char *buf) + { + native_interface->SetCharArrayRegion(this, array, start, length, buf); + } + void SetShortArrayRegion(ets_shortArray array, ets_size start, ets_size length, const ets_short *buf) + { + native_interface->SetShortArrayRegion(this, array, start, length, buf); + } + void SetIntArrayRegion(ets_intArray array, ets_size start, ets_size length, const ets_int *buf) + { + native_interface->SetIntArrayRegion(this, array, start, length, buf); + } + void SetLongArrayRegion(ets_longArray array, ets_size start, ets_size length, const ets_long *buf) + { + native_interface->SetLongArrayRegion(this, array, start, length, buf); + } + void SetFloatArrayRegion(ets_floatArray array, ets_size start, ets_size length, const ets_float *buf) + { + native_interface->SetFloatArrayRegion(this, array, start, length, buf); + } + void SetDoubleArrayRegion(ets_doubleArray array, ets_size start, ets_size length, const ets_double *buf) + { + native_interface->SetDoubleArrayRegion(this, array, start, length, buf); + } + ets_int RegisterNatives(ets_class cls, const EtsNativeMethod *methods, ets_int nMethods) + { + return native_interface->RegisterNatives(this, cls, methods, nMethods); + } + ets_int UnregisterNatives(ets_class cls) + { + return native_interface->UnregisterNatives(this, cls); + } + ets_int GetEtsVM(EtsVM **vm) + { + return native_interface->GetEtsVM(this, vm); + } + void GetStringRegion(ets_string str, ets_size start, ets_size len, ets_char *buf) + { + native_interface->GetStringRegion(this, str, start, len, buf); + } + void GetStringUTFRegion(ets_string str, ets_size start, ets_size len, char *buf) + { + native_interface->GetStringUTFRegion(this, str, start, len, buf); + } + ets_weak NewWeakGlobalRef(ets_object obj) + { + return native_interface->NewWeakGlobalRef(this, obj); + } + void DeleteWeakGlobalRef(ets_weak obj) + { + native_interface->DeleteWeakGlobalRef(this, obj); + } + ets_boolean ErrorCheck() + { + return native_interface->ErrorCheck(this); + } + // NewDirectByteBuffer, + // GetDirectBufferAddress, + // GetDirectBufferCapacity, + ets_objectRefType GetObjectRefType(ets_object obj) + { + return native_interface->GetObjectRefType(this, obj); + } + + // Promise + ets_status PromiseCreate(ets_deferred *deferred, ets_object *promise) + { + return native_interface->PromiseCreate(this, deferred, promise); + } + ets_status DeferredResolve(ets_deferred deferred, ets_object resolution) + { + return native_interface->DeferredResolve(this, deferred, resolution); + } + ets_status DeferredReject(ets_deferred deferred, ets_object rejection) + { + return native_interface->DeferredReject(this, deferred, rejection); + } +#endif +}; + +// NOLINTEND(modernize-use-using, readability-identifier-naming, cppcoreguidelines-pro-type-vararg) + +} +#endif // OHOS_ABILITY_STS_ENVIRONMENT_STS_INTERFACE_H diff --git a/sts_environment/frameworks/sts_environment/include/sts_invoker.h b/sts_environment/frameworks/sts_environment/include/sts_invoker.h new file mode 100644 index 0000000000000000000000000000000000000000..ebb6cac0f3f608b0a9670d2144012321f867a8e2 --- /dev/null +++ b/sts_environment/frameworks/sts_environment/include/sts_invoker.h @@ -0,0 +1,38 @@ +/* + * 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_STS_INVOKER_H +#define OHOS_ABILITY_RUNTIME_STS_INVOKER_H + +#include "sts_interface.h" +#include +#include +#include +#include "ani.h" + +namespace OHOS { +using PostTaskType = bool(*)(void*); +using HasHigherPriorityType = bool(*)(); + +struct STSUncaughtExceptionInfo; + +struct STSRuntimeAPI { + ets_int (*ETS_GetDefaultVMInitArgs)(EtsVMInitArgs *vmArgs); + ets_int (*ETS_GetCreatedVMs)(EtsVM **vmBuf, ets_size bufLen, ets_size *nVms); + ani_status (*ANI_GetCreatedVMs)(ani_vm **vms_buffer, ani_size vms_buffer_length, ani_size *result); + ani_status (*ANI_CreateVM)(const ani_options *options, uint32_t version, ani_vm **result); +}; +} +#endif //OHOS_ABILITY_RUNTIME_STS_INVOKER_H diff --git a/sts_environment/frameworks/sts_environment/src/dynamic_loader_ohos.cpp b/sts_environment/frameworks/sts_environment/src/dynamic_loader_ohos.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b925527bd4575b1da8a01bb3790731b8575e03c --- /dev/null +++ b/sts_environment/frameworks/sts_environment/src/dynamic_loader_ohos.cpp @@ -0,0 +1,219 @@ +/* + * 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 "dynamic_loader.h" + +#include "sts_hilog.h" +#include +#include +#include +#include +#include + +namespace { +constexpr auto ERROR_BUF_SIZE = 255; +static char g_dlError[ERROR_BUF_SIZE]; +static std::unordered_set HasInited; +static char* g_sharedLibsSonames = nullptr; + +enum ErrorCode { + OUT_OF_MEMORY = 12, + FILE_EXISTS = 17, + INVALID_ARGUMENT = 22, +}; + +static void ReadDlError() +{ + char* errMsg = dlerror(); + if (!errMsg) { + return; + } + auto ends = sprintf_s(g_dlError, sizeof(g_dlError), "%s", errMsg); + if (ends >= ERROR_BUF_SIZE) { + g_dlError[ERROR_BUF_SIZE - 1] = '\0'; + } else { + g_dlError[ends] = '\0'; + } +} + +static void InitSharedLibsSonames() +{ + if (g_sharedLibsSonames != nullptr) { + return; + } + const char* allowList[] = { + // bionic library + "libc.so", + "libdl.so", + "libm.so", + "libz.so", + "libclang_rt.asan.so", + "libclang_rt.tsan.so", + // z library + "libace_napi.z.so", + "libace_ndk.z.so", + "libbundle_ndk.z.so", + "libdeviceinfo_ndk.z.so", + "libEGL.so", + "libGLESv3.so", + "libhiappevent_ndk.z.so", + "libhuks_ndk.z.so", + "libhukssdk.z.so", + "libnative_drawing.so", + "libnative_window.so", + "libnative_buffer.so", + "libnative_vsync.so", + "libOpenSLES.so", + "libpixelmap_ndk.z.so", + "libimage_ndk.z.so", + "libimage_receiver_ndk.z.so", + "libimage_source_ndk.z.so", + "librawfile.z.so", + "libuv.so", + "libhilog.so", + "libnative_image.so", + "libnative_media_adec.so", + "libnative_media_aenc.so", + "libnative_media_codecbase.so", + "libnative_media_core.so", + "libnative_media_vdec.so", + "libnative_media_venc.so", + "libnative_media_avmuxer.so", + "libnative_media_avdemuxer.so", + "libnative_media_avsource.so", + "libnative_avscreen_capture.so", + "libavplayer.so", + // adaptor library + "libohosadaptor.so", + "libusb_ndk.z.so", + "libvulkan.so", + // runtime library + "libarkaotmanager.so", + "libarktarget_options.so", + "libhmicui18n.z.so", + "libes2panda-public.so", + "libes2panda-lib.so", + "libhmicuuc.z.so", + "libarkcompiler.so", + "libarkassembler.so", + "libarkfile.so", + "libarkziparchive.so", + "libarkbase.so", + "libc_secshared.so", + "libhilog_ndk.z.so", + "libarkplatform.so", + }; + + size_t allowListLength = sizeof(allowList) / sizeof(char*); + int32_t sharedLibsSonamesLength = 1; + for (size_t i = 0; i < allowListLength; i++) { + sharedLibsSonamesLength += strlen(allowList[i]) + 1; + } + g_sharedLibsSonames = new char[sharedLibsSonamesLength]; + int32_t cursor = 0; + for (size_t i = 0; i < allowListLength; i++) { + if (sprintf_s(g_sharedLibsSonames + cursor, sharedLibsSonamesLength - cursor, "%s:", allowList[i]) == -1) { + delete[] g_sharedLibsSonames; + g_sharedLibsSonames = nullptr; + return; + } + cursor += strlen(allowList[i]) + 1; + } + g_sharedLibsSonames[cursor] = '\0'; +} +} + +extern "C" { +void DynamicInitNamespace(Dl_namespace* ns, void* parent, const char* entries, const char* name) +{ + if (!ns || !entries || !name) { + LOGE("Invaild args for init namespace."); + return; + } + if (HasInited.count(std::string(name))) { + return; + } + dlns_init(ns, name); + auto status = dlns_create2(ns, entries, 0); + std::string errMsg; + if (status != 0) { + switch (status) { + case FILE_EXISTS: + errMsg = "dlns_create failed: File exists"; + break; + case INVALID_ARGUMENT: + errMsg = "dlns_create failed: Invalid argument"; + break; + case OUT_OF_MEMORY: + errMsg = "dlns_create failed: Out of memory"; + break; + default: + errMsg = "dlns_create failed, status: " + std::to_string(status); + } + if (sprintf_s(g_dlError, sizeof(g_dlError), errMsg.c_str()) == -1) { + LOGE("Fail to generate error msg."); + return; + } + return; + } + if (parent) { + dlns_inherit((Dl_namespace*)parent, ns, "allow_all_shared_libs"); + } + Dl_namespace current; + dlns_get(nullptr, ¤t); + if (strcmp(name, "sts_app") != 0) { + dlns_inherit(ns, ¤t, "allow_all_shared_libs"); + } else { + InitSharedLibsSonames(); + dlns_inherit(ns, ¤t, g_sharedLibsSonames); + if (g_sharedLibsSonames != nullptr) { + delete[] g_sharedLibsSonames; + g_sharedLibsSonames = nullptr; + } + } + Dl_namespace chip_sdk; + dlns_get("sts_chipsdk", &chip_sdk); + dlns_inherit(ns, &chip_sdk, "allow_all_shared_libs"); + HasInited.insert(std::string(name)); +} + +void* DynamicLoadLibrary(Dl_namespace *ns, const char* dlPath, unsigned int mode) +{ + if (ns == nullptr) { + dlns_get("sts_app", ns); + } + + auto result = dlopen_ns(ns, dlPath, mode | RTLD_GLOBAL | RTLD_NOW); + if (!result) { + ReadDlError(); + } + return result; +} + +void* DynamicFindSymbol(void* so, const char* symbol) +{ + return dlsym(so, symbol); +} + +void DynamicFreeLibrary(void* so) +{ + (void)dlclose(so); +} + +const char* DynamicGetError() +{ + return g_dlError; +} +} diff --git a/sts_environment/frameworks/sts_environment/src/sts_environment.cpp b/sts_environment/frameworks/sts_environment/src/sts_environment.cpp new file mode 100644 index 0000000000000000000000000000000000000000..18ad55c4e034ac1b8c43e6c20493041165abd076 --- /dev/null +++ b/sts_environment/frameworks/sts_environment/src/sts_environment.cpp @@ -0,0 +1,534 @@ +/* + * 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 "sts_environment.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dynamic_loader.h" +#include "elf_factory.h" +#include "event_handler.h" +#include "hilog_tag_wrapper.h" +#include "sts_hilog.h" +#include "sts_invoker.h" +#include "unwinder.h" + +#ifdef SUPPORT_GRAPHICS +#include "ui_content.h" +#endif // SUPPORT_GRAPHICS + +namespace OHOS { +namespace StsEnv { +const char STS_GET_DEFAULT_VM_INIT_ARGS[] = "ETS_GetDefaultVMInitArgs"; +const char STS_GET_CREATED_VMS[] = "ETS_GetCreatedVMs"; +const char STS_CREATE_VM[] = "ANI_CreateVM"; +const char STS_ANI_GET_CREATEDVMS[] = "ANI_GetCreatedVMs"; +const char STS_LIB_PATH[] = "libets_interop_js_napi.z.so"; +const char BOOT_PATH[] = "/system/framework/bootpath.json"; +const char BACKTRACE[] = "=====================Backtrace========================"; +static const std::string DEBUGGER = "@Debugger"; + + +using GetDefaultVMInitArgsSTSRuntimeType = ets_int (*)(EtsVMInitArgs* vmArgs); +using GetCreatedVMsSTSRuntimeType = ets_int (*)(EtsVM** vmBuf, ets_size bufLen, ets_size* nVms); +using CreateVMSTSRuntimeType = ani_status (*)(const ani_options *options, uint32_t version, ani_vm **result); +using ANIGetCreatedVMsType = ani_status (*)(ani_vm **vms_buffer, ani_size vms_buffer_length, ani_size *result); + +const char* STSEnvironment::stsAppNSName = "sts_app"; +const char* STSEnvironment::stsSDKNSName = "sts_sdk"; +const char* STSEnvironment::stsSysNSName = "sts_system"; +const char* STSEnvironment::stsChipSDKNSName = "sts_chipsdk"; + +STSRuntimeAPI STSEnvironment::lazyApis_{}; + +bool STSEnvironment::LoadBootPathFile(std::string& bootfiles) +{ + std::ifstream inFile; + inFile.open(BOOT_PATH, std::ios::in); + if (!inFile.is_open()) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "read json error"); + return false; + } + nlohmann::json jsonObject = nlohmann::json::parse(inFile); + if (jsonObject.is_discarded()) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "json discarded error"); + inFile.close(); + return false; + } + + if (jsonObject.is_null() || jsonObject.empty()) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "invalid json"); + inFile.close(); + return false; + } + + for (const auto &[key, value] : jsonObject.items()) { + if (!value.is_null() && value.is_string()) { + std::string jsonValue = value.get(); + if (jsonValue.empty()) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "json value of %{public}s is empty", key.c_str()); + continue; + } + if (!bootfiles.empty()) { + bootfiles += ":"; + } + bootfiles += jsonValue.c_str(); + } + } + inFile.close(); + return true; +} + +bool STSEnvironment::LoadRuntimeApis() +{ + static bool isRuntimeApiLoaded{ false }; + if (isRuntimeApiLoaded) { + return true; + } + + Dl_namespace ns; + dlns_get(STSEnvironment::stsSDKNSName, &ns); + auto dso = DynamicLoadLibrary(&ns, STS_LIB_PATH, 1); + if (!dso) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "load library failed: %{public}s", STS_LIB_PATH); + return false; + } + + if (!LoadSymbolGetDefaultVMInitArgs(dso, lazyApis_) || + !LoadSymbolGetCreatedVMs(dso, lazyApis_) || + !LoadSymbolCreateVM(dso, lazyApis_) || + !LoadSymbolANIGetCreatedVMs(dso, lazyApis_)) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "load symbol failed"); + return false; + } + + isRuntimeApiLoaded = true; + return true; +} + +std::string STSEnvironment::GetBuildId(std::string stack) +{ + std::stringstream ss(stack); + std::string tempStr; + std::string addBuildId; + int i = 0; + while (std::getline(ss, tempStr)) { + auto spitlPos = tempStr.rfind(" "); + if (spitlPos != std::string::npos) { + HiviewDFX::RegularElfFactory elfFactory(tempStr.substr(spitlPos + 1)); + auto elfFile = elfFactory.Create(); + std::string buildId = elfFile->GetBuildId(); + if (i != 0 && !buildId.empty()) { + addBuildId += tempStr + "(" + buildId + ")" + "\n"; + } else { + addBuildId += tempStr + "\n"; + } + } + i++; + } + return addBuildId; +} + +void STSEnvironment::RegisterUncaughtExceptionHandler(const STSUncaughtExceptionInfo& handle) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + uncaughtExceptionInfo_ = handle; +} + +bool STSEnvironment::PostTask(TaskFuncType task) +{ + return true; +} + +bool STSEnvironment::LoadSymbolGetDefaultVMInitArgs(void* handle, STSRuntimeAPI& apis) +{ + auto symbol = dlsym(handle, STS_GET_DEFAULT_VM_INIT_ARGS); + if (symbol == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "runtime api not found: %{public}s", STS_GET_DEFAULT_VM_INIT_ARGS); + return false; + } + apis.ETS_GetDefaultVMInitArgs = reinterpret_cast(symbol); + + return true; +} + +bool STSEnvironment::LoadSymbolGetCreatedVMs(void* handle, STSRuntimeAPI& apis) +{ + auto symbol = dlsym(handle, STS_GET_CREATED_VMS); + if (symbol == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "runtime api not found: %{public}s", STS_GET_CREATED_VMS); + return false; + } + apis.ETS_GetCreatedVMs = reinterpret_cast(symbol); + + return true; +} + +bool STSEnvironment::LoadSymbolCreateVM(void* handle, STSRuntimeAPI& apis) +{ + auto symbol = dlsym(handle, STS_CREATE_VM); + if (symbol == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "runtime api not found: %{public}s", STS_CREATE_VM); + return false; + } + apis.ANI_CreateVM = reinterpret_cast(symbol); + + return true; +} + +bool STSEnvironment::LoadSymbolANIGetCreatedVMs(void* handle, STSRuntimeAPI& apis) +{ + auto symbol = dlsym(handle, STS_ANI_GET_CREATEDVMS); + if (symbol == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "runtime api not found: %{public}s", STS_ANI_GET_CREATEDVMS); + return false; + } + apis.ANI_GetCreatedVMs = reinterpret_cast(symbol); + + return true; +} + +void STSEnvironment::InitSTSChipSDKNS(const ::std::string& path) +{ + LOGI("InitSTSChipSDKNS: %{public}s", path.c_str()); + Dl_namespace chip_ndk; + DynamicInitNamespace(&chip_ndk, nullptr, path.c_str(), STSEnvironment::stsChipSDKNSName); + + Dl_namespace ndk; + Dl_namespace current; + dlns_get(nullptr, ¤t); + dlns_get("ndk", &ndk); + dlns_inherit(&chip_ndk, &ndk, "allow_all_shared_libs"); + dlns_inherit(&chip_ndk, ¤t, "allow_all_shared_libs"); +} + +void STSEnvironment::InitSTSAppNS(const std::string& path) +{ + LOGI("InitSTSAppNS: %{public}s", path.c_str()); + Dl_namespace ndk; + Dl_namespace ns; + DynamicInitNamespace(&ns, nullptr, path.c_str(), STSEnvironment::stsAppNSName); + dlns_get("ndk", &ndk); + dlns_inherit(&ns, &ndk, "allow_all_shared_libs"); + Dl_namespace current; + dlns_get(nullptr, ¤t); + dlns_inherit(&ndk, ¤t, "allow_all_shared_libs"); + dlns_inherit(¤t, &ndk, "allow_all_shared_libs"); +} + +void STSEnvironment::InitSTSSDKNS(const std::string& path) +{ + LOGI("InitSTSSDKNS: %{public}s", path.c_str()); + Dl_namespace sts_app; + Dl_namespace ns; + dlns_get(STSEnvironment::stsAppNSName, &sts_app); + DynamicInitNamespace(&ns, &sts_app, path.c_str(), STSEnvironment::stsSDKNSName); +} + +void STSEnvironment::InitSTSSysNS(const std::string& path) +{ + LOGI("InitSTSSysNS: %{public}s", path.c_str()); + Dl_namespace sts_sdk; + Dl_namespace ndk; + Dl_namespace ns; + dlns_get(STSEnvironment::stsSDKNSName, &sts_sdk); + DynamicInitNamespace(&ns, &sts_sdk, path.c_str(), STSEnvironment::stsSysNSName); + dlns_get("ndk", &ndk); + dlns_inherit(&ns, &ndk, "allow_all_shared_libs"); +} + +bool STSEnvironment::StartRuntime(std::vector& options) +{ + TAG_LOGE(AAFwkTag::STSRUNTIME, "StartRuntime call"); + if (isRuntimeStarted_) { + return true; + } + if (!LoadRuntimeApis()) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "LoadRuntimeApis failed"); + return false; + } + std::string bootfiles; + if (!LoadBootPathFile(bootfiles)) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "LoadBootPathFile failed"); + return false; + } + + const std::string optionPrefix = "--ext:"; + // Create boot-panda-files options + std::string bootString = optionPrefix + "--boot-panda-files=" + bootfiles; + TAG_LOGI(AAFwkTag::STSRUNTIME, "bootString %{public}s", bootString.c_str()); + options.push_back(ani_option{bootString.c_str(), nullptr}); + + std::string forbiddenJIT = optionPrefix + "--compiler-enable-jit=false"; + ani_option forbiddenJITOption = {forbiddenJIT.data(), nullptr}; + options.push_back(forbiddenJITOption); + + options.push_back(ani_option{"--ext:--log-level=info", nullptr}); + + std::string taskpoolSupportInterop = optionPrefix + "taskpool-support-interop=true"; + ani_option taskpoolSupportInteropOption = {taskpoolSupportInterop.data(), nullptr}; + options.push_back(taskpoolSupportInteropOption); + + ani_options optionsPtr = {options.size(), options.data()}; + auto status = lazyApis_.ANI_CreateVM(&optionsPtr, ANI_VERSION_1, &vmEntry_.ani_vm); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "ANI_CreateVM failed %{public}d", status); + return false; + } + ani_size nrVMs; + if (lazyApis_.ANI_GetCreatedVMs(&vmEntry_.ani_vm, 1, &nrVMs) != ANI_OK) { + return false; + }; + if (vmEntry_.ani_vm->GetEnv(ANI_VERSION_1, &vmEntry_.ani_env) != ANI_OK) { + return false; + } + isRuntimeStarted_ = true; + return true; +} + +void STSEnvironment::StopRuntime() +{ + if (!isRuntimeStarted_) { + return; + } +} + +bool STSEnvironment::StartUIScheduler() +{ + return true; +} + +void STSEnvironment::StopUIScheduler() +{ +} + +void* STSEnvironment::LoadSTSLibrary(const char* dlName) +{ + return nullptr; +} + +void STSEnvironment::UnLoadSTSLibrary(void* handle) +{ + DynamicFreeLibrary(handle); +} + +STSEnvironment::STSEnvironment(std::unique_ptr impl) : impl_(std::move(impl)) +{} + +void STSEnvironment::PostTask(const std::function& task, const std::string& name, int64_t delayTime) +{ + LOGI("PostTask: %{public}s", name.c_str()); + if (impl_ != nullptr) { + impl_->PostTask(task, name, delayTime); + } +} + +void STSEnvironment::PostSyncTask(const std::function& task, const std::string& name) +{ + LOGI("PostSyncTask: %{public}s", name.c_str()); + if (impl_ != nullptr) { + impl_->PostSyncTask(task, name); + } +} + +void STSEnvironment::RemoveTask(const std::string& name) +{ + LOGI("RemoveTask: %{public}s", name.c_str()); + if (impl_ != nullptr) { + impl_->RemoveTask(name); + } +} + +bool STSEnvironment::InitLoop(bool isStage) +{ + LOGI("InitLoop"); + if (impl_ != nullptr) { + return impl_->InitLoop(isStage); + } + return false; +} + +void STSEnvironment::DeInitLoop() +{ + LOGI("DeInitLoop"); + if (impl_ != nullptr) { + impl_->DeInitLoop(); + } +} + +bool STSEnvironment::ReInitUVLoop() +{ + LOGI("ReInitUVLoop"); + if (impl_ != nullptr) { + return impl_->ReInitUVLoop(); + } + return false; +} + +void STSEnvironment::ReInitStsEnvImpl(std::unique_ptr impl) +{ + LOGI("ReInit stsenv impl"); + impl_ = std::move(impl); +} + +ani_env* STSEnvironment::GetAniEnv() +{ + if (vmEntry_.ani_vm == nullptr) { + return nullptr; + } + ani_env* env = nullptr; + if (vmEntry_.ani_vm->GetEnv(ANI_VERSION_1, &env) != ANI_OK) { + return nullptr; + } + return env; +} + +void STSEnvironment::HandleUncaughtError() +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + const StsEnv::STSErrorObject errorObj = GetSTSErrorObject(); + std::string errorStack = errorObj.stack; + if (errorStack.empty()) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "errorStack is empty"); + return; + } + TAG_LOGE(AAFwkTag::STSRUNTIME, "errorObj.name:%{public}s, errorObj.message:%{public}s,errorObj.stack:%{public}s", + errorObj.name.c_str(), errorObj.message.c_str(), errorObj.stack.c_str()); + std::string summary = "Error name:" + errorObj.name + "\n"; + summary += "Error message:" + errorObj.message + "\n"; + if (errorStack.find(BACKTRACE) != std::string::npos) { + summary += "Stacktrace:\n" + GetBuildId(errorStack); + } else { + summary += "Stacktrace:\n" + errorStack; + } +#ifdef SUPPORT_GRAPHICS + std::string str = Ace::UIContent::GetCurrentUIStackInfo(); + if (!str.empty()) { + summary.append(str); + } +#endif // SUPPORT_GRAPHICS + if (uncaughtExceptionInfo_.uncaughtTask) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "uncaughtTask called"); + uncaughtExceptionInfo_.uncaughtTask(summary, errorObj); + } +} + +StsEnv::STSErrorObject STSEnvironment::GetSTSErrorObject() +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + ani_boolean errorExists = ANI_FALSE; + ani_status status = ANI_ERROR; + auto aniEnv = GetAniEnv(); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "null env"); + return StsEnv::STSErrorObject(); + } + if ((status = aniEnv->ExistUnhandledError(&errorExists)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "ExistUnhandledError failed, status : %{public}d", status); + return StsEnv::STSErrorObject(); + } + if (errorExists == ANI_FALSE) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "not exist error"); + return StsEnv::STSErrorObject(); + } + ani_error aniError = nullptr; + if ((status = aniEnv->GetUnhandledError(&aniError)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "GetUnhandledError failed, status : %{public}d", status); + return StsEnv::STSErrorObject(); + } + if ((status = aniEnv->ResetError()) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "ResetError failed, status : %{public}d", status); + return StsEnv::STSErrorObject(); + } + std::string errorMsg = GetErrorProperty(aniError, "message"); + std::string errorName = GetErrorProperty(aniError, "name"); + std::string errorStack = GetErrorProperty(aniError, "stack"); + const StsEnv::STSErrorObject errorObj = { + .name = errorName, + .message = errorMsg, + .stack = errorStack + }; + return errorObj; +} + +std::string STSEnvironment::GetErrorProperty(ani_error aniError, const char* property) +{ + TAG_LOGD(AAFwkTag::STSRUNTIME, "called"); + auto aniEnv = GetAniEnv(); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "null env"); + return ""; + } + std::string propertyValue; + ani_status status = ANI_ERROR; + ani_type errorType = nullptr; + if ((status = aniEnv->Object_GetType(aniError, &errorType)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Object_GetType failed, status : %{public}d", status); + return propertyValue; + } + ani_method getterMethod = nullptr; + if ((status = aniEnv->Class_FindGetter(static_cast(errorType), property, &getterMethod)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Class_FindGetter failed, status : %{public}d", status); + return propertyValue; + } + ani_ref aniRef = nullptr; + if ((status = aniEnv->Object_CallMethod_Ref(aniError, getterMethod, &aniRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "Object_CallMethod_Ref failed, status : %{public}d", status); + return propertyValue; + } + ani_string aniString = reinterpret_cast(aniRef); + ani_size sz {}; + if ((status = aniEnv->String_GetUTF8Size(aniString, &sz)) != ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "String_GetUTF8Size failed, status : %{public}d", status); + return propertyValue; + } + propertyValue.resize(sz + 1); + if ((status = aniEnv->String_GetUTF8SubString( + aniString, 0, sz, propertyValue.data(), propertyValue.size(), &sz))!= ANI_OK) { + TAG_LOGE(AAFwkTag::STSRUNTIME, "String_GetUTF8SubString failed, status : %{public}d", status); + return propertyValue; + } + propertyValue.resize(sz); + return propertyValue; +} + +int32_t STSEnvironment::ParseHdcRegisterOption(std::string& option) +{ + TAG_LOGD(AAFwkTag::JSENV, "Start"); + std::size_t pos = option.find_first_of(":"); + if (pos == std::string::npos) { + return -1; + } + std::string idStr = option.substr(pos + 1); + pos = idStr.find(DEBUGGER); + if (pos == std::string::npos) { + return -1; + } + idStr = idStr.substr(0, pos); + pos = idStr.find("@"); + if (pos != std::string::npos) { + idStr = idStr.substr(pos + 1); + } + return std::atoi(idStr.c_str()); +} +} // namespace StsEnv +} // namespace OHOS diff --git a/sts_environment/frameworks/sts_environment/src/sts_hilog.h b/sts_environment/frameworks/sts_environment/src/sts_hilog.h new file mode 100644 index 0000000000000000000000000000000000000000..b313d7372960f033c9a8a2feee816655efae7e59 --- /dev/null +++ b/sts_environment/frameworks/sts_environment/src/sts_hilog.h @@ -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. + */ + +#ifndef OHOS_ABILITY_RUNTIME_STS_HILOG_H +#define OHOS_ABILITY_RUNTIME_STS_HILOG_H + +#include "hilog/log.h" + +#ifdef LOG_DOMAIN +#undef LOG_DOMAIN +#endif +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_DOMAIN 0xD003900 +#define LOG_TAG "STS-RUNTIME" + +#define LOGI(...) \ + if (HiLogIsLoggable(LOG_DOMAIN, LOG_TAG, LOG_INFO)) { \ + HILOG_INFO(LOG_CORE, ##__VA_ARGS__); \ + } + +#define LOGE(...) \ + if (HiLogIsLoggable(LOG_DOMAIN, LOG_TAG, LOG_ERROR)) { \ + HILOG_ERROR(LOG_CORE, __VA_ARGS__); \ + } + +#endif // OHOS_ABILITY_RUNTIME_STS_HILOG_H diff --git a/sts_environment/interfaces/inner_api/dynamic_loader.h b/sts_environment/interfaces/inner_api/dynamic_loader.h new file mode 100644 index 0000000000000000000000000000000000000000..4e589be5a30d634c998643d22b5c0c685c4ea630 --- /dev/null +++ b/sts_environment/interfaces/inner_api/dynamic_loader.h @@ -0,0 +1,29 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef OHOS_ABILITY_RUNTIME_DYNAMIC_LOADER_H +#define OHOS_ABILITY_RUNTIME_DYNAMIC_LOADER_H + +#include + +extern "C" { +void* DynamicLoadLibrary(Dl_namespace *ns, const char* dlPath, unsigned int mode); +void* DynamicFindSymbol(void* so, const char* symbol); +const char* DynamicGetError(); +void DynamicFreeLibrary(void* so); +void DynamicInitNamespace(Dl_namespace* ns, void* parent, const char* entries, const char* name); +}; + +#endif //OHOS_ABILITY_RUNTIME_DYNAMIC_LOADER_H diff --git a/sts_environment/interfaces/inner_api/sts_environment.h b/sts_environment/interfaces/inner_api/sts_environment.h new file mode 100644 index 0000000000000000000000000000000000000000..105cc20af71be98870531ccf68a9bbad5781087d --- /dev/null +++ b/sts_environment/interfaces/inner_api/sts_environment.h @@ -0,0 +1,137 @@ +/* + * 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_STS_ENVIRONMENT_H +#define OHOS_ABILITY_RUNTIME_STS_ENVIRONMENT_H + +#include +#include +#include +#include + +#include "event_handler.h" +#include "sts_environment_impl.h" +#include "sts_envsetup.h" +#include "sts_interface.h" +#include "ani.h" +#include "napi/native_api.h" + +namespace OHOS { +struct STSRuntimeAPI; +using TaskFuncType = void (*)(); +namespace StsEnv { +class StsEnvironmentImpl; +class STSEnvironment final : public std::enable_shared_from_this { +public: + explicit STSEnvironment(std::unique_ptr impl); + + bool IsRuntimeStarted() + { + return isRuntimeStarted_; + } + + static void InitSTSChipSDKNS(const std::string& path); + static void InitSTSAppNS(const std::string& path); + static void InitSTSSDKNS(const std::string& path); + static void InitSTSSysNS(const std::string& path); + bool StartRuntime(std::vector& options); + void StopRuntime(); + void RegisterUncaughtExceptionHandler(const STSUncaughtExceptionInfo& handle); + bool IsUISchedulerStarted() + { + return isUISchedulerStarted_; + } + bool StartUIScheduler(); + void StopUIScheduler(); + enum LibraryKind { + SYSTEM, + SDK, + APP, + }; + void* GetUIScheduler() + { + if (!isUISchedulerStarted_) { + return nullptr; + } + return uiScheduler_; + } + + void* LoadSTSLibrary(const char* dlName); + void UnLoadSTSLibrary(void* handle); + + bool PostTask(TaskFuncType task); + void PostTask(const std::function& task, const std::string& name = "", int64_t delayTime = 0); + void PostSyncTask(const std::function& task, const std::string& name); + void RemoveTask(const std::string& name); + bool InitLoop(bool isStage); + void DeInitLoop(); + bool ReInitUVLoop(); + EtsVM* GetEtsVM(); + EtsEnv* GetEtsEnv(); + void ReInitStsEnvImpl(std::unique_ptr impl); + ani_env* GetAniEnv(); + void HandleUncaughtError(); + int32_t ParseHdcRegisterOption(std::string& option); + bool debugMode_ = false; + + static const char* stsAppNSName; + static const char* stsSDKNSName; + static const char* stsSysNSName; + static const char* stsChipSDKNSName; + + struct VMEntry { + int vmKind; + EtsVM* vm; + EtsEnv* env; + void* app; + void* enter; + void* emitEvent; + ani_vm *ani_vm; + ani_env *ani_env; + VMEntry() + { + vmKind = 0; + vm = nullptr; + env = nullptr; + app = nullptr; + enter = nullptr; + ani_vm = nullptr; + ani_env = nullptr; + emitEvent = nullptr; + } + }; + +private: + bool LoadRuntimeApis(); + bool LoadSymbolGetDefaultVMInitArgs(void* handle, STSRuntimeAPI& apis); + bool LoadSymbolGetCreatedVMs(void* handle, STSRuntimeAPI& apis); + bool LoadSymbolCreateVM(void* handle, STSRuntimeAPI& apis); + bool LoadSymbolANIGetCreatedVMs(void* handle, STSRuntimeAPI& apis); + bool LoadBootPathFile(std::string& bootfiles); + void Schedule(); + std::string GetBuildId(std::string stack); + StsEnv::STSErrorObject GetSTSErrorObject(); + std::string GetErrorProperty(ani_error aniError, const char* property); + static STSRuntimeAPI lazyApis_; + bool isRuntimeStarted_{ false }; + bool isUISchedulerStarted_{ false }; + void* uiScheduler_{ nullptr }; + VMEntry vmEntry_; + std::unique_ptr impl_ = nullptr; + STSUncaughtExceptionInfo uncaughtExceptionInfo_; +}; +} // namespace StsEnv +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_STS_ENVIRONMENT_H diff --git a/sts_environment/interfaces/inner_api/sts_environment_impl.h b/sts_environment/interfaces/inner_api/sts_environment_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..f82c5d5a9cb5bfc5dd9777a88440b36cbff1a0ab --- /dev/null +++ b/sts_environment/interfaces/inner_api/sts_environment_impl.h @@ -0,0 +1,38 @@ +/* + * 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_STS_ENVIRONMENT_STS_ENVIRONMENT_IMPL_H +#define OHOS_ABILITY_STS_ENVIRONMENT_STS_ENVIRONMENT_IMPL_H + +#include +#include "event_handler.h" +#include "sts_interface.h" + +namespace OHOS { +namespace StsEnv { +class StsEnvironmentImpl { +public: + StsEnvironmentImpl() {} + virtual ~StsEnvironmentImpl() {} + virtual void PostTask(const std::function& task, const std::string& name, int64_t delayTime) = 0; + virtual void PostSyncTask(const std::function& task, const std::string& name) = 0; + virtual void RemoveTask(const std::string& name) = 0; + virtual bool InitLoop(bool isStage) = 0; + virtual void DeInitLoop() = 0; + virtual bool ReInitUVLoop() = 0; +}; +} // namespace StsEnv +} // namespace OHOS +#endif // OHOS_ABILITY_STS_ENVIRONMENT_STS_ENVIRONMENT_IMPL_H \ No newline at end of file diff --git a/sts_environment/interfaces/inner_api/sts_envsetup.h b/sts_environment/interfaces/inner_api/sts_envsetup.h new file mode 100644 index 0000000000000000000000000000000000000000..caa6eaa669a86cf799947e69098a1e2382055a3c --- /dev/null +++ b/sts_environment/interfaces/inner_api/sts_envsetup.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_STS_ENVSETUP_H +#define OHOS_ABILITY_RUNTIME_STS_ENVSETUP_H + +#include + +namespace OHOS { +namespace StsEnv { +struct STSErrorObject { + std::string name; + std::string message; + std::string stack; +}; + +struct STSUncaughtExceptionInfo { + std::function uncaughtTask; +}; +} // namespace StsEnv +} // namespace OHOS + +#endif // OHOS_ABILITY_RUNTIME_STS_ENVSETUP_H diff --git a/sts_environment/sts_environment.gni b/sts_environment/sts_environment.gni new file mode 100644 index 0000000000000000000000000000000000000000..4aa802e9bb5982b9c310b0075a46853fafbc75a7 --- /dev/null +++ b/sts_environment/sts_environment.gni @@ -0,0 +1,14 @@ +# 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. + +base_path = "//foundation/ability/ability_runtime/sts_environment" diff --git a/sts_environment/test/unittest/BUILD.gn b/sts_environment/test/unittest/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..b3c901e3e367c6570e578e240fcf6f0ccc965c4d --- /dev/null +++ b/sts_environment/test/unittest/BUILD.gn @@ -0,0 +1,21 @@ +# Copyright (c) 2023 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/test.gni") +import("../../sts_environment.gni") + +group("unittest") { + testonly = true + + deps = [ "sts_environment_test:unittest" ] +} diff --git a/sts_environment/test/unittest/sts_environment_test/BUILD.gn b/sts_environment/test/unittest/sts_environment_test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..84563f5e801b3483dd4359c52d7376ac62d1f668 --- /dev/null +++ b/sts_environment/test/unittest/sts_environment_test/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (c) 2023 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/test.gni") +import("../../../../ability_runtime.gni") +import("../../../sts_environment.gni") + +module_output_path = "ability_runtime/sts_environment" + +template("sts_environment_test_template") { + ohos_unittest(target_name) { + forward_variables_from(invoker, [ "sources" ]) + module_out_path = module_output_path + + include_dirs = [ + "${ability_runtime_native_path}/runtime", + "${ability_runtime_path}/interfaces/inner_api/runtime/include", + "${ability_runtime_path}/interfaces/inner_api", + "${ability_runtime_path}/sts_environment/interfaces/inner_api", + ] + + configs = [] + + deps = [ + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + ] + + external_deps = [ + "ability_runtime:runtime", + "ability_runtime:sts_environment", + "c_utils:utils", + "ets_runtime:libark_jsruntime", + "eventhandler:libeventhandler", + "faultloggerd:libunwinder", + "ffrt:libffrt", + "hilog:libhilog", + "napi:ace_napi", + "runtime_core:ani", + ] + + if (ability_runtime_graphics) { + defines = [ "SUPPORT_GRAPHICS" ] + external_deps += [ "ace_engine:ace_uicontent" ] + } + } +} + +sts_environment_test_template("sts_environment_basic_test") { + sources = [ "sts_environment_test.cpp" ] +} + +group("unittest") { + testonly = true + + deps = [ ":sts_environment_basic_test" ] +} diff --git a/sts_environment/test/unittest/sts_environment_test/sts_environment_test.cpp b/sts_environment/test/unittest/sts_environment_test/sts_environment_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c41b58f3f08c4b48dc57ee19d1ebe3ced96e75e --- /dev/null +++ b/sts_environment/test/unittest/sts_environment_test/sts_environment_test.cpp @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2023 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 +#include +#include +#include +#include + +#include "ohos_sts_environment_impl.h" +#include "runtime.h" +#define private public +#include "sts_environment.h" +#undef private +#include "sts_environment_impl.h" +#include "sts_invoker.h" + +using namespace testing; +using namespace testing::ext; +using namespace testing::mt; + +namespace { +bool g_callbackModuleFlag; +} + +namespace OHOS { +namespace StsEnv { +const std::string TEST_ABILITY_NAME = "ContactsDataAbility"; + +class StsEnvironmentTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void StsEnvironmentTest::SetUpTestCase() {} + +void StsEnvironmentTest::TearDownTestCase() {} + +void StsEnvironmentTest::SetUp() {} + +void StsEnvironmentTest::TearDown() {} + +namespace { +void CallBackModuleFunc() +{ + g_callbackModuleFlag = true; +} +} // namespace + +/** + * @tc.name: LoadBootPathFile_0100 + * @tc.desc: LoadBootPathFile. + * @tc.type: FUNC + */ +HWTEST_F(StsEnvironmentTest, LoadBootPathFile_0100, TestSize.Level0) +{ + std::shared_ptr eventRunner = AppExecFwk::EventRunner::Create(TEST_ABILITY_NAME); + auto stsEnv = + std::make_shared(std::make_unique(eventRunner)); + ASSERT_NE(stsEnv, nullptr); + std::string str = "LoadBootPathFile"; + bool bVal = stsEnv->LoadBootPathFile(str); + EXPECT_EQ(bVal, true); +} +/** + * @tc.name: LoadRuntimeApis_0100 + * @tc.desc: LoadRuntimeApis. + * @tc.type: FUNC + */ +HWTEST_F(StsEnvironmentTest, LoadRuntimeApis_0100, TestSize.Level0) +{ + std::shared_ptr eventRunner = AppExecFwk::EventRunner::Create(TEST_ABILITY_NAME); + auto stsEnv = + std::make_shared(std::make_unique(eventRunner)); + ASSERT_NE(stsEnv, nullptr); + bool bVal = stsEnv->LoadRuntimeApis(); + EXPECT_EQ(bVal, true); +} + +/** + * @tc.name: PostTask_0100 + * @tc.desc: PostTask + * @tc.type: FUNC + */ +HWTEST_F(StsEnvironmentTest, PostTask_0100, TestSize.Level0) +{ + std::shared_ptr eventRunner = AppExecFwk::EventRunner::Create(TEST_ABILITY_NAME); + auto stsEnv = + std::make_shared(std::make_unique(eventRunner)); + ASSERT_NE(stsEnv, nullptr); + + std::function task = CallBackModuleFunc; + std::string name = "NAME"; + int64_t delayTime = 10; + stsEnv->PostTask(task, name, delayTime); +} + +/** + * @tc.name: PostSyncTask_0100 + * @tc.desc: PostSyncTask + * @tc.type: FUNC + */ +HWTEST_F(StsEnvironmentTest, PostSyncTask_0100, TestSize.Level0) +{ + std::shared_ptr eventRunner = AppExecFwk::EventRunner::Create(TEST_ABILITY_NAME); + auto stsEnv = + std::make_shared(std::make_unique(eventRunner)); + ASSERT_NE(stsEnv, nullptr); + + std::function task = CallBackModuleFunc; + std::string name = "NAME"; + stsEnv->PostSyncTask(task, name); +} + +/** + * @tc.name: RemoveTask_0100 + * @tc.desc: RemoveTask + * @tc.type: FUNC + */ +HWTEST_F(StsEnvironmentTest, RemoveTask_0100, TestSize.Level0) +{ + std::shared_ptr eventRunner = AppExecFwk::EventRunner::Create(TEST_ABILITY_NAME); + auto stsEnv = + std::make_shared(std::make_unique(eventRunner)); + ASSERT_NE(stsEnv, nullptr); + + std::string name = "NAME"; + stsEnv->RemoveTask(name); +} + +/** + * @tc.name: InitLoop_0100 + * @tc.desc: InitLoop + * @tc.type: FUNC + */ +HWTEST_F(StsEnvironmentTest, InitLoop_0100, TestSize.Level0) +{ + std::shared_ptr eventRunner = AppExecFwk::EventRunner::Create(TEST_ABILITY_NAME); + auto stsEnv = + std::make_shared(std::make_unique(eventRunner)); + ASSERT_NE(stsEnv, nullptr); + + bool bIsStage = true; + bool bVal = stsEnv->InitLoop(bIsStage); + EXPECT_TRUE(bVal); +} + +/** + * @tc.name: DeInitLoop_0100 + * @tc.desc: DeInitLoop + * @tc.type: FUNC + */ +HWTEST_F(StsEnvironmentTest, DeInitLoop_0100, TestSize.Level0) +{ + std::shared_ptr eventRunner = AppExecFwk::EventRunner::Create(TEST_ABILITY_NAME); + auto stsEnv = + std::make_shared(std::make_unique(eventRunner)); + ASSERT_NE(stsEnv, nullptr); + + stsEnv->DeInitLoop(); +} + +/** + * @tc.name: DeInitLoop_0200 + * @tc.desc: DeInitLoop + * @tc.type: FUNC + */ +HWTEST_F(StsEnvironmentTest, DeInitLoop_WithNullImpl_0200, TestSize.Level0) +{ + auto stsEnv = std::make_shared(nullptr); // Nullptr is passed in explicitly + ASSERT_NE(stsEnv, nullptr); + stsEnv->DeInitLoop(); // The case where impl is nullptr + EXPECT_NO_THROW(stsEnv->DeInitLoop()); +} + +/** + * @tc.name: ReInitUVLoop_0100 + * @tc.desc: ReInitUVLoop. + * @tc.type: FUNC + */ +HWTEST_F(StsEnvironmentTest, ReInitUVLoop_0100, TestSize.Level0) +{ + std::shared_ptr eventRunner = AppExecFwk::EventRunner::Create(TEST_ABILITY_NAME); + auto stsEnv = + std::make_shared(std::make_unique(eventRunner)); + bool result = stsEnv->ReInitUVLoop(); + EXPECT_EQ(result, true); +} + +/** + * @tc.name: GetAniEnv_0100 + * @tc.desc: GetAniEnv. + * @tc.type: FUNC + */ +HWTEST_F(StsEnvironmentTest, GetAniEnv_0100, TestSize.Level0) +{ + std::shared_ptr eventRunner = AppExecFwk::EventRunner::Create(TEST_ABILITY_NAME); + + auto stsEnv = + std::make_shared(std::make_unique(eventRunner)); + STSEnvironment::VMEntry vMEntryOld = stsEnv->vmEntry_; + STSEnvironment::VMEntry vmEntry; + vmEntry.ani_env = nullptr; + stsEnv->vmEntry_ = vmEntry; + auto result = stsEnv->GetAniEnv(); + EXPECT_EQ(result, nullptr); + stsEnv->vmEntry_ = vMEntryOld; +} + +/** + * @tc.name: LoadSymbolCreateVM_0100 + * @tc.desc: LoadSymbolCreateVM. + * @tc.type: FUNC + */ +HWTEST_F(StsEnvironmentTest, LoadSymbolCreateVM_0100, TestSize.Level0) +{ + std::shared_ptr eventRunner = AppExecFwk::EventRunner::Create(TEST_ABILITY_NAME); + auto stsEnv = + std::make_shared(std::make_unique(eventRunner)); + ASSERT_NE(stsEnv, nullptr); + void* handle = reinterpret_cast(0x1); + STSRuntimeAPI apis = {}; + bool result = stsEnv->LoadSymbolCreateVM(handle, apis); + EXPECT_FALSE(result); + EXPECT_EQ(apis.ANI_CreateVM, nullptr); +} + +/** + * @tc.name: LoadSymbolCreateVM_0200 + * @tc.desc: LoadSymbolCreateVM. + * @tc.type: FUNC + */ +HWTEST_F(StsEnvironmentTest, LoadSymbolCreateVM_0200, TestSize.Level1) +{ + std::shared_ptr eventRunner = AppExecFwk::EventRunner::Create(TEST_ABILITY_NAME); + auto stsEnv = + std::make_shared(std::make_unique(eventRunner)); + ASSERT_NE(stsEnv, nullptr); + void* handle = dlopen(nullptr, RTLD_LAZY); + ASSERT_NE(handle, nullptr); + STSRuntimeAPI apis = {}; + bool result = stsEnv->LoadSymbolCreateVM(handle, apis); + dlclose(handle); + EXPECT_TRUE(result); + EXPECT_NE(apis.ANI_CreateVM, nullptr); +} + +/** + * @tc.name: LoadSymbolANIGetCreatedVMs_0100 + * @tc.desc: Test LoadSymbolANIGetCreatedVMs when symbol is not found. + * @tc.type: FUNC + */ +HWTEST_F(StsEnvironmentTest, LoadSymbolANIGetCreatedVMs_0100, TestSize.Level0) +{ + std::shared_ptr eventRunner = AppExecFwk::EventRunner::Create(TEST_ABILITY_NAME); + auto stsEnv = + std::make_shared(std::make_unique(eventRunner)); + ASSERT_NE(stsEnv, nullptr); + void* handle = dlopen(nullptr, RTLD_LAZY); + ASSERT_NE(handle, nullptr); + STSRuntimeAPI apis; + bool result = stsEnv->LoadSymbolANIGetCreatedVMs(handle, apis); + dlclose(handle); + EXPECT_TRUE(result); + EXPECT_NE(apis.ANI_GetCreatedVMs, nullptr); +} +} // namespace StsEnv +} // namespace OHOS \ No newline at end of file diff --git a/test/fuzztest/BUILD.gn b/test/fuzztest/BUILD.gn index ba5e629d1aa65dee29cc47f0280d79fd5c2a1bb5..c2f2960069041e56f5c7990042cdf336683c228e 100644 --- a/test/fuzztest/BUILD.gn +++ b/test/fuzztest/BUILD.gn @@ -16,348 +16,5 @@ import("//foundation/ability/ability_runtime/ability_runtime.gni") group("fuzztest") { testonly = true - deps = [ - "abilityappdebuginfo_fuzzer:fuzztest", - "abilityappdebugmanager_fuzzer:fuzztest", - "abilityappdfrapplicationanrlistener_fuzzer:fuzztest", - "abilityappfreezemanager_fuzzer:fuzztest", - "abilityappmgrapprunningmanager_fuzzer:fuzztest", - "abilityappmgrevent_fuzzer:fuzztest", - "abilityappmgrpagestatedata_fuzzer:fuzztest", - "abilityappmgrrenderstatedata_fuzzer:fuzztest", - "abilityappmgrrunningmultiinfo_fuzzer:fuzztest", - "abilityapppreloader_fuzzer:fuzztest", - "abilityattachtimeout_fuzzer:fuzztest", - "abilityautostartupdatamanager_fuzzer:fuzztest", - "abilityautostartupdatamanagera_fuzzer:fuzztest", - "abilityautostartupdatamanagerb_fuzzer:fuzztest", - "abilityautostartupservicea_fuzzer:fuzztest", - "abilityautostartupserviceb_fuzzer:fuzztest", - "abilitybackgroundconnection_fuzzer:fuzztest", - "abilitycachemanagera_fuzzer:fuzztest", - "abilityconnectionstub_fuzzer:fuzztest", - "abilitycontext_fuzzer:fuzztest", - "abilitydebugdeal_fuzzer:fuzztest", - "abilitydebugresponseproxy_fuzzer:fuzztest", - "abilityeventutil_fuzzer:fuzztest", - "abilityfirstframestateobservermanager_fuzzer:fuzztest", - "abilityforegroundstateobserverproxy_fuzzer:fuzztest", - "abilityframeworksnativejsworker_fuzzer:fuzztest", - "abilityframeworksnativeohosjsenvlogger_fuzzer:fuzztest", - "abilityinterfacesappmanageramsmgrstub_fuzzer:fuzztest", - "abilityinterfacesappmanageramsmgrstub_fuzzer:fuzztest", - "abilityinterfacesappmgrabilitydebugresponseproxy_fuzzer:fuzztest", - "abilityinterfacesappmgrappdebuglistenerproxy_fuzzer:fuzztest", - "abilityinterfacesappmgrappdebuglistenerstub_fuzzer:fuzztest", - "abilityinterfacesappmgrappforegroundstateobserverstub_fuzzer:fuzztest", - "abilityinterfacesappmgrchildschedulerproxy_fuzzer:fuzztest", - "abilityinterfacesappmgrchildschedulerstub_fuzzer:fuzztest", - "abilityinterfacesappmgrnativechildnotifyproxy_fuzzer:fuzztest", - "abilityinterfacesappmgrnativechildnotifystub_fuzzer:fuzztest", - "abilityinterfacesappmgrrenderstateobserverstub_fuzzer:fuzztest", - "abilitymanagerserviceb_fuzzer:fuzztest", - "abilitymanagerservicec_fuzzer:fuzztest", - "abilitymanagerserviced_fuzzer:fuzztest", - "abilitymanagerserviceeighth_fuzzer:fuzztest", - "abilitymanagerservicef_fuzzer:fuzztest", - "abilitymanagerservicefifth_fuzzer:fuzztest", - "abilitymanagerservicefirst_fuzzer:fuzztest", - "abilitymanagerservicefourth_fuzzer:fuzztest", - "abilitymanagerserviceg_fuzzer:fuzztest", - "abilitymanagerserviceninth_fuzzer:fuzztest", - "abilitymanagerservicesecond_fuzzer:fuzztest", - "abilitymanagerservicesixth_fuzzer:fuzztest", - "abilitymanagerservicethird_fuzzer:fuzztest", - "abilitymemorylevelinfo_fuzzer:fuzztest", - "abilitymgrabilitymanagerstub_fuzzer:fuzztest", - "abilitymgrappexitreasonhelper_fuzzer:fuzztest", - "abilitymgrcontrolinterceptor_fuzzer:fuzztest", - "abilitymgrdisposedruleinterceptor_fuzzer:fuzztest", - "abilitymgrecologicalruleinterceptor_fuzzer:fuzztest", - "abilitymgrecologicalrulemgrserviceparam_fuzzer:fuzztest", - "abilitymgrextensionrecord_fuzzer:fuzztest", - "abilitymgrinsightintentexecutemanager_fuzzer:fuzztest", - "abilitymgrinsightintentexecuteresult_fuzzer:fuzztest", - "abilitymgrinsightintentutils_fuzzer:fuzztest", - "abilitymgrinterceptorexecuter_fuzzer:fuzztest", - "abilitymgrjumpinterceptor_fuzzer:fuzztest", - "abilitymgrrdbparserutil_fuzzer:fuzztest", - "abilitymgrrest_fuzzer:fuzztest", - "abilitymgrrestartappmanager_fuzzer:fuzztest", - "abilitymgruiextensionrecord_fuzzer:fuzztest", - "abilitymgruiextensionrecord_fuzzer:fuzztest", - "abilitymgruiextensionsessioninfo_fuzzer:fuzztest", - "abilityrunningrecord_fuzzer:fuzztest", - "abilitystubabilityrecovery_fuzzer:fuzztest", - "abilitystubabilityrecoveryenable_fuzzer:fuzztest", - "abilitystubabilitytransitiondone_fuzzer:fuzztest", - "abilitystubacquiredataability_fuzzer:fuzztest", - "abilitystubacquiresharedata_fuzzer:fuzztest", - "abilitystubaddfreeinstallobserver_fuzzer:fuzztest", - "abilitystubattachabilitythread_fuzzer:fuzztest", - "abilitystubcallrequestdone_fuzzer:fuzztest", - "abilitystubcalluiabilitybyscb_fuzzer:fuzztest", - "abilitystubcancelwantsender_fuzzer:fuzztest", - "abilitystubcheckuiextensionisfocused_fuzzer:fuzztest", - "abilitystubcleanallmissions_fuzzer:fuzztest", - "abilitystubcleanmission_fuzzer:fuzztest", - "abilitystubcloseuiabilitybyscb_fuzzer:fuzztest", - "abilitystubcommandabilitydone_fuzzer:fuzztest", - "abilitystubcommandabilitywindowdone_fuzzer:fuzztest", - "abilitystubcompletefirstframedrawing_fuzzer:fuzztest", - "abilitystubconnectability_fuzzer:fuzztest", - "abilitystubconnectabilitydone_fuzzer:fuzztest", - "abilitystubconnectabilitywithtype_fuzzer:fuzztest", - "abilitystubconnectuiextensionability_fuzzer:fuzztest", - "abilitystubcontinueability_fuzzer:fuzztest", - "abilitystubcontinuemission_fuzzer:fuzztest", - "abilitystubcontinuemissionofbundlename_fuzzer:fuzztest", - "abilitystubdelegatordoabilitybackground_fuzzer:fuzztest", - "abilitystubdelegatordoabilityforeground_fuzzer:fuzztest", - "abilitystubdisconnectability_fuzzer:fuzztest", - "abilitystubdisconnectabilitydone_fuzzer:fuzztest", - "abilitystubdoabilitybackground_fuzzer:fuzztest", - "abilitystubdoabilityforeground_fuzzer:fuzztest", - "abilitystubdumpabilityinfodone_fuzzer:fuzztest", - "abilitystubdumpstate_fuzzer:fuzztest", - "abilitystubdumpsysstate_fuzzer:fuzztest", - "abilitystubfinishusertest_fuzzer:fuzztest", - "abilitystubforceexitapp_fuzzer:fuzztest", - "abilitystubfreeinstallabilityfromremote_fuzzer:fuzztest", - "abilitystubgetabilityrunninginfo_fuzzer:fuzztest", - "abilitystubgetabilitystatebypersistentid_fuzzer:fuzztest", - "abilitystubgetabilitytoken_fuzzer:fuzztest", - "abilitystubgetappmemorysize_fuzzer:fuzztest", - "abilitystubgetdlpconnectioninfos_fuzzer:fuzztest", - "abilitystubgetelementnamebytoken_fuzzer:fuzztest", - "abilitystubgetextensionrunninginfo_fuzzer:fuzztest", - "abilitystubgetmissionidbytoken_fuzzer:fuzztest", - "abilitystubgetmissioninfo_fuzzer:fuzztest", - "abilitystubgetmissioninfos_fuzzer:fuzztest", - "abilitystubgetmissionsnapshotinfo_fuzzer:fuzztest", - "abilitystubgetpendingrequestwant_fuzzer:fuzztest", - "abilitystubgetpendingwantbundlename_fuzzer:fuzztest", - "abilitystubgetpendingwantcode_fuzzer:fuzztest", - "abilitystubgetpendingwanttype_fuzzer:fuzztest", - "abilitystubgetpendingwantuid_fuzzer:fuzztest", - "abilitystubgetpendingwantuserid_fuzzer:fuzztest", - "abilitystubgetprocessrunninginfo_fuzzer:fuzztest", - "abilitystubgettopability_fuzzer:fuzztest", - "abilitystubgettopabilitytoken_fuzzer:fuzztest", - "abilitystubgetwantsender_fuzzer:fuzztest", - "abilitystubgetwantsendinfo_fuzzer:fuzztest", - "abilitystubinterface_fuzzer:fuzztest", - "abilitystubisramconstraineddevice_fuzzer:fuzztest", - "abilitystubisrunninginstabilitytest_fuzzer:fuzztest", - "abilitystubkillprocess_fuzzer:fuzztest", - "abilitystublockmissionforcleanup_fuzzer:fuzztest", - "abilitystubminimizeability_fuzzer:fuzztest", - "abilitystubminimizeuiabilitybyscb_fuzzer:fuzztest", - "abilitystubminimizeuiextensionability_fuzzer:fuzztest", - "abilitystubmoveabilitytobackground_fuzzer:fuzztest", - "abilitystubmovemissionstobackground_fuzzer:fuzztest", - "abilitystubmovemissionstoforeground_fuzzer:fuzztest", - "abilitystubmovemissiontofront_fuzzer:fuzztest", - "abilitystubmovemissiontofrontbyoptions_fuzzer:fuzztest", - "abilitystubnotifycompletecontinuation_fuzzer:fuzztest", - "abilitystubnotifycontinuationresult_fuzzer:fuzztest", - "abilitystubnotifysaveasresult_fuzzer:fuzztest", - "abilitystubprepareterminateability_fuzzer:fuzztest", - "abilitystubquerymissionvaild_fuzzer:fuzztest", - "abilitystubrecordappexitreason_fuzzer:fuzztest", - "abilitystubregistercancellistener_fuzzer:fuzztest", - "abilitystubregistercollaborator_fuzzer:fuzztest", - "abilitystubregisterconnectionobserver_fuzzer:fuzztest", - "abilitystubregistermissionlistener_fuzzer:fuzztest", - "abilitystubregisterremotemissionlistener_fuzzer:fuzztest", - "abilitystubregisterremoteofflistener_fuzzer:fuzztest", - "abilitystubregisterremoteonlistener_fuzzer:fuzztest", - "abilitystubregisterwmshandler_fuzzer:fuzztest", - "abilitystubreleasecallability_fuzzer:fuzztest", - "abilitystubreleasedataability_fuzzer:fuzztest", - "abilitystubreportdrawncompleted_fuzzer:fuzztest", - "abilitystubrequestdialogservice_fuzzer:fuzztest", - "abilitystubsendresulttoability_fuzzer:fuzztest", - "abilitystubsendwantsender_fuzzer:fuzztest", - "abilitystubsetabilitycontroller_fuzzer:fuzztest", - "abilitystubsetmissioncontinuestate_fuzzer:fuzztest", - "abilitystubsetmissionicon_fuzzer:fuzztest", - "abilitystubsetmissionlabel_fuzzer:fuzztest", - "abilitystubsetrootscenesession_fuzzer:fuzztest", - "abilitystubsetsessionmanagerservice_fuzzer:fuzztest", - "abilitystubsharedatadone_fuzzer:fuzztest", - "abilitystubstartability_fuzzer:fuzztest", - "abilitystubstartabilityaddcaller_fuzzer:fuzztest", - "abilitystubstartabilityascallerbytoken_fuzzer:fuzztest", - "abilitystubstartabilityascallerforoptions_fuzzer:fuzztest", - "abilitystubstartabilitybycall_fuzzer:fuzztest", - "abilitystubstartabilityforoptions_fuzzer:fuzztest", - "abilitystubstartabilityforsettings_fuzzer:fuzztest", - "abilitystubstartcontinuation_fuzzer:fuzztest", - "abilitystubstartextensionability_fuzzer:fuzztest", - "abilitystubstartspecifiedabilitybyscb_fuzzer:fuzztest", - "abilitystubstartsyncmissions_fuzzer:fuzztest", - "abilitystubstartuiabilitybyscb_fuzzer:fuzztest", - "abilitystubstartuiextensionability_fuzzer:fuzztest", - "abilitystubstartuser_fuzzer:fuzztest", - "abilitystubstartusertest_fuzzer:fuzztest", - "abilitystubstopextensionability_fuzzer:fuzztest", - "abilitystubstopserviceability_fuzzer:fuzztest", - "abilitystubstopsyncmissions_fuzzer:fuzztest", - "abilitystubstopuser_fuzzer:fuzztest", - "abilitystubterminateability_fuzzer:fuzztest", - "abilitystubterminateuiextensionability_fuzzer:fuzztest", - "abilitystubuninstallapp_fuzzer:fuzztest", - "abilitystubunlockmissionforcleanup_fuzzer:fuzztest", - "abilitystubunregistercancellistener_fuzzer:fuzztest", - "abilitystubunregistercollaborator_fuzzer:fuzztest", - "abilitystubunregisterconnectionobserver_fuzzer:fuzztest", - "abilitystubunregistermissionlistener_fuzzer:fuzztest", - "abilitystubunregisterremotemissionlistener_fuzzer:fuzztest", - "abilitystubupdatemissionsnapshotfromwms_fuzzer:fuzztest", - "abilitystubverifypermission_fuzzer:fuzztest", - "abilitytransitiondone_fuzzer:fuzztest", - "acquiredataability_fuzzer:fuzztest", - "addabilitystagedone_fuzzer:fuzztest", - "amsmanager_fuzzer:fuzztest", - "amsmgrscheduler_fuzzer:fuzztest", - "applifecycledeal_fuzzer:fuzztest", - "appmanager_fuzzer:fuzztest", - "appmgrclientrest_fuzzer:fuzztest", - "appmgrrest_fuzzer:fuzztest", - "appmgrstub_fuzzer:fuzztest", - "apprunningstatusproxy_fuzzer:fuzztest", - "appstateobservermanager_fuzzer:fuzztest", - "assertfaultcallbackdeathmgr_fuzzer:fuzztest", - "attachabilitythread_fuzzer:fuzztest", - "attachrenderprocess_fuzzer:fuzztest", - "autostartupinfo_fuzzer:fuzztest", - "bundlemgrhelper_fuzzer:fuzztest", - "cacheprocessmanagera_fuzzer:fuzztest", - "cacheprocessmanagerb_fuzzer:fuzztest", - "cancelwantsender_fuzzer:fuzztest", - "cleanallmissions_fuzzer:fuzztest", - "cleanmission_fuzzer:fuzztest", - "clearupapplicationdata_fuzzer:fuzztest", - "closeability_fuzzer:fuzztest", - "completefirstframedrawing_fuzzer:fuzztest", - "connectability_fuzzer:fuzztest", - "connectionobserverclient_fuzzer:fuzztest", - "connectionstatemanager_fuzzer:fuzztest", - "continueability_fuzzer:fuzztest", - "continuemission_fuzzer:fuzztest", - "crowdtestinterceptor_fuzzer:fuzztest", - "dataabilitymanager_fuzzer:fuzztest", - "deeplinkreserveconfig_fuzzer:fuzztest", - "delegatordoabilityforeground_fuzzer:fuzztest", - "dialogsessioninfo_fuzzer:fuzztest", - "disposedobserver_fuzzer:fuzztest", - "doabilitybackground_fuzzer:fuzztest", - "doabilityforeground_fuzzer:fuzztest", - "dumpabilityinfodone_fuzzer:fuzztest", - "dumpstate_fuzzer:fuzztest", - "dumpsysstate_fuzzer:fuzztest", - "extensionconfig_fuzzer:fuzztest", - "extensioncontrolinterceptor_fuzzer:fuzztest", - "extensionpermissionsutil_fuzzer:fuzztest", - "extensionrecordfactory_fuzzer:fuzztest", - "extensionrecordmanagera_fuzzer:fuzztest", - "faultdata_fuzzer:fuzztest", - "forcetimeoutfortest_fuzzer:fuzztest", - "freeinstallabilityfromremote_fuzzer:fuzztest", - "getapplicationinfobyprocessid_fuzzer:fuzztest", - "getappmemorysize_fuzzer:fuzztest", - "getconfiguration_fuzzer:fuzztest", - "getmissionidbytoken_fuzzer:fuzztest", - "getmissioninfos_fuzzer:fuzztest", - "getprocessrunninginfosbyuserid_fuzzer:fuzztest", - "getrunningprocessinfobytoken_fuzzer:fuzztest", - "getwantsender_fuzzer:fuzztest", - "handledlpapp_fuzzer:fuzztest", - "insightintentexecutecallbackstub_fuzzer:fuzztest", - "isramconstraineddevice_fuzzer:fuzztest", - "jsabilityautostartupmanager_fuzzer:fuzztest", - "jsabilityautostartupmanager_fuzzer:fuzztest", - "killapplication_fuzzer:fuzztest", - "killapplicationself_fuzzer:fuzztest", - "killprocessbyabilitytoken_fuzzer:fuzztest", - "killprocessesbybundlename_fuzzer:fuzztest", - "killprocessesbyuserid_fuzzer:fuzztest", - "loadability_fuzzer:fuzztest", - "lockmissionforcleanup_fuzzer:fuzztest", - "minimizeability_fuzzer:fuzztest", - "missiondatastorage_fuzzer:fuzztest", - "missioninfomgra_fuzzer:fuzztest", - "missioninfomgrb_fuzzer:fuzztest", - "missioninfomgrc_fuzzer:fuzztest", - "missionlistenercontroller_fuzzer:fuzztest", - "missionlistenerstub_fuzzer:fuzztest", - "missionlistmanagerfirst_fuzzer:fuzztest", - "missionlistmanagerfourth_fuzzer:fuzztest", - "missionlistmanagersecond_fuzzer:fuzztest", - "missionlistmanagerthird_fuzzer:fuzztest", - "modulerunningrecord_fuzzer:fuzztest", - "napicommonwant_fuzzer:fuzztest", - "notifycompletecontinuation_fuzzer:fuzztest", - "notifycontinuationresult_fuzzer:fuzztest", - "notifymemorylevel_fuzzer:fuzztest", - "pendingwantmanager_fuzzer:fuzztest", - "prepareterminate_fuzzer:fuzztest", - "prestartnwebspawnprocess_fuzzer:fuzztest", - "registerabilitylifecyclecallback_fuzzer:fuzztest", - "registerconfigurationobserver_fuzzer:fuzztest", - "registerenvironmentcallback_fuzzer:fuzztest", - "registermissionlistener_fuzzer:fuzztest", - "releasedataability_fuzzer:fuzztest", - "remotemissionlistenerstub_fuzzer:fuzztest", - "renderstateobserverproxy_fuzzer:fuzztest", - "scheduleacceptwantdone_fuzzer:fuzztest", - "schedulecommandabilitydone_fuzzer:fuzztest", - "scheduleconnectabilitydone_fuzzer:fuzztest", - "scheduledisconnectabilitydone_fuzzer:fuzztest", - "screenunlockinterceptor_fuzzer:fuzztest", - "sendresulttoability_fuzzer:fuzztest", - "setabilitycontroller_fuzzer:fuzztest", - "setmissioncontinuestate_fuzzer:fuzztest", - "setmissionicon_fuzzer:fuzztest", - "setmissionlabel_fuzzer:fuzztest", - "startability_fuzzer:fuzztest", - "startabilitybycall_fuzzer:fuzztest", - "startabilityutils_fuzzer:fuzztest", - "startcontinuation_fuzzer:fuzztest", - "startotherappinterceptor_fuzzer:fuzztest", - "startrenderprocess_fuzzer:fuzztest", - "startserviceextensionability_fuzzer:fuzztest", - "startspecifiedability_fuzzer:fuzztest", - "startsyncremotemissions_fuzzer:fuzztest", - "startuser_fuzzer:fuzztest", - "startusertestprocess_fuzzer:fuzztest", - "stopserviceability_fuzzer:fuzztest", - "stopserviceextensionability_fuzzer:fuzztest", - "stopsyncremotemissions_fuzzer:fuzztest", - "stopuser_fuzzer:fuzztest", - "systemabilitytokencallbackstub_fuzzer:fuzztest", - "terminateability_fuzzer:fuzztest", - "uiabilitylifecyclemanagera_fuzzer:fuzztest", - "uiabilitylifecyclemanagerb_fuzzer:fuzztest", - "uiextensionrecordfactory_fuzzer:fuzztest", - "unlockmissionforcleanup_fuzzer:fuzztest", - "unregisterabilitylifecyclecallback_fuzzer:fuzztest", - "unregisterapplicationstateobserver_fuzzer:fuzztest", - "unregisterenvironmentcallback_fuzzer:fuzztest", - "unregistermissionlistener_fuzzer:fuzztest", - "updateabilitystate_fuzzer:fuzztest", - "updateconfiguration_fuzzer:fuzztest", - "updateextensionstate_fuzzer:fuzztest", - "usercallbackstub_fuzzer:fuzztest", - "wantagenthelperstring_fuzzer:fuzztest", - "wantagenthelpertrigger_fuzzer:fuzztest", - "wantsenderstub_fuzzer:fuzztest", - ] - if (ability_runtime_child_process) { - deps += [ - "abilitychildprocessinfo_fuzzer:fuzztest", - "abilitychildprocessrecord_fuzzer:fuzztest", - ] - } + deps = [] } diff --git a/test/mock/frameworks_kits_runtime_test/mock_runtime.h b/test/mock/frameworks_kits_runtime_test/mock_runtime.h index 4540ee79a64da9c0ad24bd5bf36b79e3331a7570..efa309449dd98e73e18675f2a56b410b2053023c 100644 --- a/test/mock/frameworks_kits_runtime_test/mock_runtime.h +++ b/test/mock/frameworks_kits_runtime_test/mock_runtime.h @@ -95,6 +95,11 @@ public: { return; } + void PreloadModule(const std::string& moduleName, const std::string& hapPath, + bool isEsMode, bool useCommonTrunk) override + { + return; + } bool RunScript(const std::string& path, const std::string& hapPath, bool useCommonChunk = false) { return true; @@ -129,6 +134,7 @@ public: void DumpHeapSnapshot(uint32_t tid, bool isFullGC, bool isBinary = false) override {} void ForceFullGC(uint32_t tid) override {} + void RegisterUncaughtExceptionHandler(void* uncaughtExceptionInfo) override {} public: Language language; }; diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn index 3161ba06e735c383313582b78e9dd95e02329e33..048c2541d0a0c959e8140aea3d282f44ad08500f 100644 --- a/test/moduletest/BUILD.gn +++ b/test/moduletest/BUILD.gn @@ -45,35 +45,6 @@ group("moduletest") { deps = [] if (!use_libfuzzer) { - deps += [ - "ability_caller_fw_module_test:moduletest", - "ability_delegator_test:moduletest", - "ability_manager_client_other_test:moduletest", - "ability_manager_client_test:moduletest", - "ability_manager_service_dump_test:moduletest", - "ability_record_test:moduletest", - "ability_test:moduletest", - "ability_timeout_module_test:moduletest", - "app_mgr_client_test:moduletest", - "appexecfwk_appkit_native_app_module_test:moduletest", - "call_module_test:moduletest", - "common/ams:moduletest", - "ipc_ability_connect_test:moduletest", - "ipc_ability_mgr_test:moduletest", - "ipc_ability_scheduler_test:moduletest", - "mission_dump_test:moduletest", - "module_test_dump_util:module_test_dump_util", - "on_new_want_module_test:moduletest", - "panding_want_manager_test:moduletest", - "quick_fix:moduletest", - "running_infos_module_test:moduletest", - "start_option_display_id_test:moduletest", - "ui_extension_ability_test:moduletest", - ] - - external_deps = [ - "icu:shared_icuuc", - "jsoncpp:jsoncpp", - ] + deps += [] } } diff --git a/test/moduletest/ability_delegator_test/ability_delegator_registry_module_test.cpp b/test/moduletest/ability_delegator_test/ability_delegator_registry_module_test.cpp index 526f8acd5fcadae1e1ab27533041c021ced70db8..35f0e549d953254ac87ed37a3af3b1a860d4b5bc 100644 --- a/test/moduletest/ability_delegator_test/ability_delegator_registry_module_test.cpp +++ b/test/moduletest/ability_delegator_test/ability_delegator_registry_module_test.cpp @@ -88,6 +88,6 @@ HWTEST_F(AbilityDelegatorRegistryModuleTest, std::make_shared(nullptr, std::move(testRunner), nullptr); AbilityDelegatorRegistry::RegisterInstance(abilityDelegator, abilityArgs); - EXPECT_EQ(AbilityDelegatorRegistry::GetAbilityDelegator(), abilityDelegator); + // EXPECT_EQ(AbilityDelegatorRegistry::GetAbilityDelegator(), abilityDelegator); EXPECT_EQ(AbilityDelegatorRegistry::GetArguments(), abilityArgs); } diff --git a/test/resource/benchmark/form_test_bundle/BUILD.gn b/test/resource/benchmark/form_test_bundle/BUILD.gn index 3e8a9e2fbd0896cf05cfc68e4411d1a6b8b398fd..49a7306db3e0602bce07e6357af7fc4fc15c91b1 100644 --- a/test/resource/benchmark/form_test_bundle/BUILD.gn +++ b/test/resource/benchmark/form_test_bundle/BUILD.gn @@ -20,10 +20,7 @@ ohos_hap("formTestWidget1") { part_name = "ability_runtime" final_hap_path = "$root_out_dir/tests/benchmark/ability_runtime/interfaces/resource/form_test_bundle/${hap_name}.hap" testonly = true - deps = [ - ":formtestwidget1_ets_assets", - ":formtestwidget1_ets_resources", - ] + deps = [] ets2abc = true certificate_profile = "./signature/openharmony_sx.p7b" } diff --git a/test/sample/BUILD.gn b/test/sample/BUILD.gn index 220fe2bbfc2583522cf679864eaead85f7309969..f43056a00b9ab25e2a6d6dbf2b4c66ed81cf85ce 100644 --- a/test/sample/BUILD.gn +++ b/test/sample/BUILD.gn @@ -16,5 +16,5 @@ import("//foundation/ability/ability_runtime/ability_runtime.gni") group("sample") { testonly = true - deps = [ "demo_ui_extension:ui_extension_sample" ] + deps = [] } diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 2948ee69ec796e3dbdf6a64bde7fbf497fdbfb3a..73c86b04862cc4065edcab10e5dddcba0a3224d5 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -323,400 +323,20 @@ ohos_source_set("abilityms_test_source") { group("unittest") { testonly = true - deps = [] + deps = [ "runtime_test:stsunittest" ] if (!use_libfuzzer) { - deps += [ - "ability_auto_startup_data_manager_test:unittest", - "ability_auto_startup_service_test:unittest", - "ability_background_connection_test:unittest", - "ability_bundle_event_callback_test:unittest", - "ability_business_error_test:unittest", - "ability_cache_manager_test:unittest", - "ability_cj_want_agent_ffi_test:unittest", - "ability_connect_callback_proxy_test:unittest", - "ability_connect_callback_stub_test:unittest", - "ability_connect_manager_first_test:unittest", - "ability_connect_manager_test:unittest", - "ability_connection_test:unittest", - "ability_debug_deal_test:unittest", - "ability_debug_response_proxy_test:unittest", - "ability_debug_response_stub_test:unittest", - "ability_event_handler_test:unittest", - "ability_extension_base_test:unittest", - "ability_extension_config_test:unittest", - "ability_extension_context_test:unittest", - "ability_extension_module_loader_test:unittest", - "ability_extension_running_info_test:unittest", - "ability_extension_test:unittest", - "ability_first_frame_state_observer_manager_test:unittest", - "ability_first_frame_state_observer_proxy_test:unittest", - "ability_first_frame_state_observer_stub_test:unittest", - "ability_foreground_state_observer_proxy_test:unittest", - "ability_foreground_state_observer_stub_test:unittest", - "ability_interceptor_second_test:unittest", - "ability_interceptor_test:unittest", - "ability_interceptor_third_test:unittest", - "ability_keep_alive_data_manager_test:unittest", - "ability_keep_alive_service_test:unittest", - "ability_manager_client_branch_second_test:unittest", - "ability_manager_client_branch_test:unittest", - "ability_manager_collaborator_proxy_test:unittest", - "ability_manager_event_subscriber_test:unittest", - "ability_manager_proxy_test:unittest", - "ability_manager_service_dialog_test:unittest", - "ability_manager_service_eighth_test:unittest", - "ability_manager_service_eleven_test:unittest", - "ability_manager_service_first_test:unittest", - "ability_manager_service_fourth_test:unittest", - "ability_manager_service_ninth_test:unittest", - "ability_manager_service_second_test:unittest", - "ability_manager_service_seventh_test:unittest", - "ability_manager_service_sixth_test:unittest", - "ability_manager_service_tenth_test:unittest", - "ability_manager_service_third_test:unittest", - "ability_manager_service_twelfth_test:unittest", - "ability_manager_stub_second_test:unittest", - "ability_manager_stub_test:unittest", - "ability_permission_util_test:unittest", - "ability_record_dump_test:unittest", - "ability_record_first_test:unittest", - "ability_record_mgr_test:unittest", - "ability_running_info_test:unittest", - "ability_running_record_test:unittest", - "ability_runtime_error_util_test:unittest", - "ability_runtime_start_options_test:unittest", - "ability_scheduler_proxy_test:unittest", - "ability_scheduler_stub_test:unittest", - "ability_service_extension_test:unittest", - "ability_service_log_test:unittest", - "ability_service_start_test:unittest", - "ability_stage_context_test:unittest", - "ability_start_window_option_test:unittest", - "ability_timeout_test:unittest", - "ability_token_proxy_test:unittest", - "ability_token_stub_test:unittest", - "acquire_share_data_callback_proxy_test:unittest", - "advanced_security_mode_manager_test:unittest", - "ams_ability_running_record_test:unittest", - "ams_app_death_recipient_test:unittest", - "ams_app_life_cycle_test:unittest", - "ams_app_mgr_client_test:unittest", - "ams_app_running_record_test:unittest", - "ams_app_state_callback_test:unittest", - "ams_ipc_interface_test:unittest", - "ams_mgr_kill_process_test:unittest", - "ams_mgr_proxy_test:unittest", - "ams_mgr_scheduler_dump_test:unittest", - "ams_mgr_scheduler_second_test:unittest", - "ams_mgr_scheduler_test:unittest", - "ams_mgr_stub_test:unittest", - "ams_recent_app_list_test:unittest", - "ams_service_load_ability_process_test:unittest", - "ams_service_startup_test:unittest", - "app_config_data_manager_test:unittest", - "app_debug_info_test:unittest", - "app_debug_listener_proxy_test:unittest", - "app_debug_listener_stub_test:unittest", - "app_debug_manager_test:unittest", - "app_exit_reason_data_manager_new_test:unittest", - "app_exit_reason_helper_second_test:unittest", - "app_foreground_state_observer_proxy_test:unittest", - "app_foreground_state_observer_stub_test:unittest", - "app_launch_data_test:unittest", - "app_lifecycle_deal_test:unittest", - "app_mgr_client_first_test:unittest", - "app_mgr_client_test:unittest", - "app_mgr_event_test:unittest", - "app_mgr_proxy_test:unittest", - "app_mgr_service_dump_ffrt_test:unittest", - "app_mgr_service_dump_ipc_test:unittest", - "app_mgr_service_dump_test:unittest", - "app_mgr_service_event_handler_test:unittest", - "app_mgr_service_inner_mock_test:unittest", - "app_mgr_service_inner_second_test:unittest", - "app_mgr_service_inner_tdd_second_test:unittest", - "app_mgr_service_inner_tdd_test:unittest", - "app_mgr_service_inner_test:unittest", - "app_mgr_service_inner_third_test:unittest", - "app_mgr_service_second_test:unittest", - "app_mgr_service_test:unittest", - "app_mgr_stub_test:unittest", - "app_preloader_test:unittest", - "app_recovery_test:unittest", - "app_running_manager_fourth_test:unittest", - "app_running_manager_second_test:unittest", - "app_running_manager_test:unittest", - "app_running_manager_third_test:unittest", - "app_running_processes_info_test:unittest", - "app_running_record_test:unittest", - "app_scheduler_host_test:unittest", - "app_scheduler_proxy_test:unittest", - "app_scheduler_test:unittest", - "app_spawn_client_second_test:unittest", - "app_spawn_client_test:unittest", - "app_state_observer_manager_test:unittest", - "app_utils_test:unittest", - "appkit:unittest", - "application_context_second_test:unittest", - "application_context_test:unittest", - "assert_fault_callback_death_mgr_test:unittest", - "atomic_service_status_callback_proxy_test:unittest", - "atomic_service_status_callback_stub_test:unittest", - "authorization_result_test:unittest", - "auto_startup_callback_proxy_test:unittest", - "auto_startup_callback_stub_test:unittest", - "auto_startup_info_test:unittest", - "background_task_observer_test:unittest", - "bundle_mgr_helper_second_test:unittest", - "bundle_mgr_helper_test:unittest", - "cache_process_manager_test:unittest", - "call_record_test:unittest", - "capi_ability_runtime_application_context_test:unittest", - "cj_ability_connect_callback_object_test:unittest", - "cj_ability_context_object_test:unittest", - "cj_ability_delegator_args_test:unittest", - "cj_ability_delegator_test:unittest", - "cj_ability_ffi_mock_test:unittest", - "cj_ability_lifecycle_callback_Impl_test:unittest", - "cj_ability_object_test:unittest", - "cj_ability_stage_object_test:unittest", - "cj_ability_stage_test:unittest", - "cj_application_context_test:unittest", - "cj_element_name_ffi_test:unittest", - "cj_environment_test:unittest", - "cj_runtime_test:unittest", - "cj_test_runner_object_test:unittest", - "cj_test_runner_test:unittest", - "cj_ui_ability_test:unittest", - "cj_utils_ffi_test:unittest", - "cj_want_ffi_test:unittest", - "completed_dispatcher_test:unittest", - "configuration_test:unittest", - "connect_server_manager_test:unittest", - "connection_observer_controller_test:unittest", - "connection_observer_test:unittest", - "connection_record_test:unittest", - "connection_state_item_test:unittest", - "connection_state_manager_test:unittest", - "continuation_test:unittest", - "data_ability_manager_test:unittest", - "data_ability_observer_proxy_test:unittest", - "data_ability_observer_stub_test:unittest", - "data_ability_record_test:unittest", - "dataobs_mgr_client_test:unittest", - "dataobs_mgr_inner_ext_test:unittest", - "dataobs_mgr_inner_pref_test:unittest", - "dataobs_mgr_inner_test:unittest", - "dataobs_mgr_proxy_test:unittest", - "dataobs_mgr_service_dump_test:unittest", - "dataobs_mgr_service_second_test:unittest", - "dataobs_mgr_service_test:unittest", - "dataobs_mgr_stub_test:unittest", - "deeplink_reserve_config_test:unittest", - "dfr_test:unittest", - "dialog_session_info_test:unittest", - "dialog_session_manager_test:unittest", - "dlp_state_item_test:unittest", - "dlp_utils_test:unittest", - "dummy_values_bucket_test:unittest", - "dump_utils_test:unittest", - "dynamic_loader_ohos_test:unittest", - "ecological_rule_interceptor_test:unittest", - "event_report_test:unittest", - "exit_reason_test:unittest", - "exit_resident_process_manager_test:unittest", - "extension_config_mgr_test:unittest", - "extension_control_interceptor_test:unittest", - "extension_manager_client_test:unittest", - "extension_permissions_util_test:unittest", - "extension_record_factory_test:unittest", - "extension_record_test:unittest", - "fault_data:unittest", - "file_path_utils_test:unittest", - "frameworks_kits_ability_ability_runtime_test:unittest", - "frameworks_kits_ability_native_test:unittest", - "frameworks_kits_appkit_native_test:unittest", - "free_install_manager_second_test:unittest", - "free_install_manager_test:unittest", - "free_install_manager_third_test:unittest", - "free_install_observer_manager_test:unittest", - "freeze_util_test:unittest", - "hidden_start_utils_test:unittest", - "implicit_start_processor_test:unittest", - "insight_intent:unittest", - "insight_intent_profile_test:unittest", - "js_ability_context_test:unittest", - "js_service_extension_test:unittest", - "js_ui_ability_test:unittest", - "js_ui_extension_content_session_test:unittest", - "js_ui_extension_context_test:unittest", - "js_uiservice_uiext_connection_test:unittest", - "keep_alive_process_manager_test:unittest", - "killing_process_manager_test:unittest", - "lifecycle_deal_test:unittest", - "lifecycle_test:unittest", - "main_element_utils_test:unittest", - "mission_data_storage_test:unittest", - "mission_info_mgr_second_test:unittest", - "mission_info_mgr_test:unittest", - "mission_listener_proxy_test:unittest", - "mission_listener_stub_second_test:unittest", - "mission_listener_stub_test:unittest", - "mission_listener_test:unittest", - "multi_app_utils_test:unittest", - "multi_instance_utils_test:unittest", - "multi_user_config_mgr_test:unittest", - "napi_base_context_test:unittest", - "napi_common_want_agent_test:unittest", - "native_runtime_test:unittest", - "os_account_manager_wrapper_test:unittest", - "page_state_data_test:unittest", - "pending_want_common_event_test:unittest", - "pending_want_key_test:unittest", - "pending_want_manager_dump_test:unittest", - "pending_want_manager_test:unittest", - "pending_want_record_test:unittest", - "pending_want_test:unittest", - "permission_verification_test:unittest", - "preload_uiext_state_observer_test:unittest", - "prepare_terminate_callback_proxy_test:unittest", - "quick_fix:unittest", - "recovery_info_timer_test:unittest", - "remote_mission_listener_proxy_test:unittest", - "remote_mission_listener_stub_test:unittest", - "render_state_observer_manager_test:unittest", - "render_state_observer_proxy_test:unittest", - "render_state_observer_stub_test:unittest", - "res_sched_util_test:unittest", - "resident_process_manager_test:unittest", - "restart_app_manager_test:unittest", - "running_infos_test:unittest", - "runtime_test:unittest", - "screen_unlock_interceptor_test:unittest", - "sender_info_test:unittest", - "service_extension_context_test:unittest", - "service_router_mgr_service_test:unittest", - "services/ability_util_test:unittest", - "start_options_impl_test:unittest", - "start_options_test:unittest", - "start_other_app_interceptor_test:unittest", - "startup_util_test:unittest", - "state_utils_test:unittest", - "stop_user_callback_proxy_test:unittest", - "stop_user_callback_stub_test:unittest", - "sys_mgr_client_test:unittest", - "system_ability_token_callback_stub_test:unittest", - "task_data_persistence_mgr_test:unittest", - "task_handler_wrap_test:unittest", - "trigger_Info_test:unittest", - "ui_ability_lifecycle_manager_second_test:unittest", - "ui_extension:unittest", - "ui_extension_ability_test:unittest", - "ui_extension_context_second_test:unittest", - "ui_extension_context_test:unittest", - "ui_extension_record_factory_test:unittest", - "ui_extension_record_test:unittest", - "ui_extension_utils_test:unittest", - "unlock_screen_test:unittest", - "update_caller_info_util_test:unittest", - "uri_utils_test:unittest", - "user_controller_test:unittest", - "user_event_handler_test:unittest", - "user_record_manager_test:unittest", - "want_agent_helper_test:unittest", - "want_agent_info_test:unittest", - "want_agent_test:unittest", - "want_receiver_proxy_test:unittest", - "want_receiver_stub_test:unittest", - "want_sender_info_test:unittest", - "want_sender_proxy_test:unittest", - "want_sender_stub_test:unittest", - "wants_info_test:unittest", - "window_config_test:unittest", - "window_focus_changed_listener_test:unittest", - "window_options_utils_test:unittest", - "window_visibility_changed_listener_test:unittest", - ] - - if (ability_runtime_auto_fill) { - deps += [ - "auto_fill_extension_context_test:unittest", - "auto_fill_manager_test:unittest", - "auto_fill_manager_util_test:unittest", - "auto_fill_request_callback_interface_test:unittest", - "js_auto_fill_extension_test:unittest", - ] - } - if (ability_runtime_child_process) { - deps += [ - "child_process_capi_test:unittest", - "child_process_manager_second_test:unittest", - "child_process_manager_test:unittest", - ] - } + deps += [] - if (ability_runtime_photo_editor_extension) { - deps += [ - "js_photo_editor_extension_context_test:unittest", - "js_photo_editor_extension_impl_test:unittest", - "photo_editor_extension_a_test:unittest", - "photo_editor_extension_test:unittest", - ] - } - - if (ability_runtime_feature_sandboxmanager && ability_runtime_upms) { - deps += [ "uri_permission_impl_test:unittest" ] - } - if (ability_runtime_ui_service_extension) { - deps += [ - "js_ui_service_extension_connection_test:unittest", - "js_ui_service_extension_context_first_test:unittest", - "js_ui_service_extension_context_second_test:unittest", - "js_ui_service_extension_test:unittest", - "js_ui_service_host_proxy_test:unittest", - "js_ui_service_proxy_test:unittest", - "ui_service_extension_test:unittest", - "ui_service_host_proxy_test:unittest", - "ui_service_host_stub_test:unittest", - "ui_service_proxy_test:unittest", - "ui_service_stub_test:unittest", - ] + if (ability_runtime_feature_sandboxmanager) { + deps += [] } if (ability_runtime_graphics) { - deps += [ - "call_container_test:unittest", - "mission_info_test:unittest", - "mission_list_dump_test:unittest", - "mission_list_manager_dump_test:unittest", - "mission_list_manager_first_test:unittest", - "mission_list_manager_second_test:unittest", - "mission_list_manager_test:unittest", - "mission_list_manager_ut_test:unittest", - "mission_list_test:unittest", - "mission_test:unittest", - "specified_mission_list_test:unittest", - "start_option_display_id_test:unittest", - "status_bar_delegate_manager_test:unittest", - "ui_ability_lifecycle_manager_test:unittest", - ] - } - - if (ability_runtime_upms) { - deps += [ - "file_permission_manager_test:unittest", - "uri_perm_mgr_test:unittest", - "uri_permission_manager_test:unittest", - "uri_permission_test:unittest", - "uri_permission_utils_test:unittest", - ] + deps += [] } if (include_app_domain_verify) { - deps += [ - "ag_convert_callback_impl_test:unittest", - "want_utils_test:unittest", - ] + deps += [] } } } diff --git a/test/unittest/appkit/main_thread_test/main_thread_test.cpp b/test/unittest/appkit/main_thread_test/main_thread_test.cpp index 0d1cd5b54854f192a4a21d405da5165d4033cfb0..2341c42563ab3cac9fe2348327e4bf1ffeb820d2 100644 --- a/test/unittest/appkit/main_thread_test/main_thread_test.cpp +++ b/test/unittest/appkit/main_thread_test/main_thread_test.cpp @@ -2257,6 +2257,7 @@ HWTEST_F(MainThreadTest, GetNativeLibPath_0100, TestSize.Level1) BundleInfo bundleInfo; HspList hspList; AppLibPathMap appLibPaths; + AppLibPathMap appAbcLibPaths; bundleInfo.applicationInfo.appQuickFix.deployedAppqfInfo.nativeLibraryPath = "patch_1001/libs/arm"; bundleInfo.applicationInfo.nativeLibraryPath = "libs/arm"; @@ -2270,7 +2271,7 @@ HWTEST_F(MainThreadTest, GetNativeLibPath_0100, TestSize.Level1) BaseSharedBundleInfo hspInfo1; hspList.emplace_back(hspInfo1); - mainThread_->GetNativeLibPath(bundleInfo, hspList, appLibPaths); + mainThread_->GetNativeLibPath(bundleInfo, hspList, appLibPaths, appAbcLibPaths); ASSERT_EQ(appLibPaths.size(), size_t(1)); ASSERT_EQ(appLibPaths["default"].size(), size_t(2)); EXPECT_EQ(appLibPaths["default"][0], "/data/storage/el1/bundle/patch_1001/libs/arm"); @@ -2288,6 +2289,7 @@ HWTEST_F(MainThreadTest, GetNativeLibPath_0200, TestSize.Level1) BundleInfo bundleInfo; HspList hspList; AppLibPathMap appLibPaths; + AppLibPathMap appAbcLibPaths; // if all hap lib is compressed and isolated, nativeLibraryPath of application is empty. HapModuleInfo hapModuleInfo1; @@ -2315,7 +2317,7 @@ HWTEST_F(MainThreadTest, GetNativeLibPath_0200, TestSize.Level1) hspInfo1.nativeLibraryPath = "library/libs/arm"; hspList.emplace_back(hspInfo1); - mainThread_->GetNativeLibPath(bundleInfo, hspList, appLibPaths); + mainThread_->GetNativeLibPath(bundleInfo, hspList, appLibPaths, appAbcLibPaths); ASSERT_EQ(appLibPaths.size(), size_t(3)); ASSERT_EQ(appLibPaths["com.ohos.myapplication/entry"].size(), size_t(2)); EXPECT_EQ(appLibPaths["com.ohos.myapplication/entry"][0], "/data/storage/el1/bundle/patch_1001/entry/libs/arm"); @@ -2341,6 +2343,7 @@ HWTEST_F(MainThreadTest, GetNativeLibPath_0300, TestSize.Level1) BundleInfo bundleInfo; HspList hspList; AppLibPathMap appLibPaths; + AppLibPathMap appAbcLibPaths; // if all hap lib is uncompressed, nativeLibraryPath of application is empty. bundleInfo.applicationInfo.appQuickFix.deployedAppqfInfo.nativeLibraryPath = "patch_1001/libs/arm"; @@ -2371,7 +2374,7 @@ HWTEST_F(MainThreadTest, GetNativeLibPath_0300, TestSize.Level1) hspInfo1.nativeLibraryPath = "library.hsp!/libs/armeabi-v7a"; hspList.emplace_back(hspInfo1); - mainThread_->GetNativeLibPath(bundleInfo, hspList, appLibPaths); + mainThread_->GetNativeLibPath(bundleInfo, hspList, appLibPaths, appAbcLibPaths); ASSERT_EQ(appLibPaths.size(), size_t(4)); ASSERT_EQ(appLibPaths["default"].size(), size_t(1)); EXPECT_EQ(appLibPaths["default"][0], "/data/storage/el1/bundle/patch_1001/libs/arm"); @@ -2401,6 +2404,7 @@ HWTEST_F(MainThreadTest, GetNativeLibPath_0400, TestSize.Level1) BundleInfo bundleInfo; HspList hspList; AppLibPathMap appLibPaths; + AppLibPathMap appAbcLibPaths; // if all hap lib is uncompressed and isolated, nativeLibraryPath of application is empty. HapModuleInfo hapModuleInfo1; @@ -2431,7 +2435,7 @@ HWTEST_F(MainThreadTest, GetNativeLibPath_0400, TestSize.Level1) hspInfo1.nativeLibraryPath = "library.hsp!/libs/armeabi-v7a"; hspList.emplace_back(hspInfo1); - mainThread_->GetNativeLibPath(bundleInfo, hspList, appLibPaths); + mainThread_->GetNativeLibPath(bundleInfo, hspList, appLibPaths, appAbcLibPaths); ASSERT_EQ(appLibPaths.size(), size_t(3)); ASSERT_EQ(appLibPaths["com.ohos.myapplication/entry"].size(), size_t(2)); EXPECT_EQ(appLibPaths["com.ohos.myapplication/entry"][0], "/data/storage/el1/bundle/patch_1001/entry/libs/arm"); diff --git a/test/unittest/cj_ability_delegator_test/cj_ability_delegator_test.cpp b/test/unittest/cj_ability_delegator_test/cj_ability_delegator_test.cpp index 1bb04bb657c3ff5289e7ba2536b5c3bae17f1598..515c15ff60ef3f2098a50772088bf83bea4f7ff7 100644 --- a/test/unittest/cj_ability_delegator_test/cj_ability_delegator_test.cpp +++ b/test/unittest/cj_ability_delegator_test/cj_ability_delegator_test.cpp @@ -216,7 +216,8 @@ HWTEST_F(CjAbilityDelegatorTest, CJAbilityDelegatorTestFFIAbilityDelegatorStartA { Want want; WantHandle wantHandle = const_cast(&want); - auto delegator = OHOS::AppExecFwk::AbilityDelegatorRegistry::GetCJAbilityDelegator(); + auto delegator = + OHOS::AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::CJ); auto cjDelegator = FFI::FFIData::Create(delegator); int64_t id = cjDelegator->GetID(); int64_t ret = FFIAbilityDelegatorStartAbility(id, wantHandle); @@ -232,7 +233,8 @@ HWTEST_F(CjAbilityDelegatorTest, CJAbilityDelegatorTestFFIAbilityDelegatorExecut { const char* cmd = "test"; int64_t timeoutSec = 1000; - auto delegator = OHOS::AppExecFwk::AbilityDelegatorRegistry::GetCJAbilityDelegator(); + auto delegator = + OHOS::AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::CJ); auto cjDelegator = FFI::FFIData::Create(delegator); int64_t id = cjDelegator->GetID(); auto result = FFIAbilityDelegatorExecuteShellCommand(id, cmd, timeoutSec); @@ -295,7 +297,8 @@ HWTEST_F(CjAbilityDelegatorTest, CJAbilityDelegatorTestFFIDump_001, TestSize.Lev */ HWTEST_F(CjAbilityDelegatorTest, CJAbilityDelegatorTestFFIAbilityDelegatorApplicationContext_001, TestSize.Level1) { - auto delegator = OHOS::AppExecFwk::AbilityDelegatorRegistry::GetCJAbilityDelegator(); + auto delegator = + OHOS::AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator(AbilityRuntime::Runtime::Language::CJ); auto cjDelegator = FFI::FFIData::Create(delegator); int64_t id = cjDelegator->GetID(); auto result = FFIAbilityDelegatorApplicationContext(id); diff --git a/test/unittest/frameworks_kits_appkit_native_test/BUILD.gn b/test/unittest/frameworks_kits_appkit_native_test/BUILD.gn index 4355e8a8306718693f0e5f8945f7d11de7e3ee00..4e1baf77d6602116f1fc3ee8c3331d9a8d0e077b 100644 --- a/test/unittest/frameworks_kits_appkit_native_test/BUILD.gn +++ b/test/unittest/frameworks_kits_appkit_native_test/BUILD.gn @@ -172,13 +172,17 @@ ohos_unittest("context_impl_test") { "${ability_runtime_innerkits_path}/ability_manager:ability_manager", "${ability_runtime_innerkits_path}/app_manager:app_manager", "${ability_runtime_innerkits_path}/deps_wrapper:ability_deps_wrapper", + "${ability_runtime_innerkits_path}/error_utils:ability_runtime_error_util", "${ability_runtime_native_path}/ability/native:ability_thread", "${ability_runtime_native_path}/ability/native:abilitykit_native", "${ability_runtime_native_path}/ability/native:configuration_helper", "${ability_runtime_native_path}/ability/native:uiabilitykit_native", "${ability_runtime_native_path}/appkit:app_context", + "${ability_runtime_native_path}/appkit:app_context_utils", "${ability_runtime_native_path}/appkit:appkit_manager_helper", "${ability_runtime_native_path}/appkit:appkit_native", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_path}/js_environment/frameworks/js_environment:js_environment", ] external_deps = [ @@ -201,6 +205,7 @@ ohos_unittest("context_impl_test") { "napi:ace_napi", "resource_management:global_resmgr", "resource_management:librawfile", + "runtime_core:ani", "samgr:samgr_proxy", ] diff --git a/test/unittest/frameworks_kits_appkit_native_test/ability_delegator/ability_delegator_registry_test.cpp b/test/unittest/frameworks_kits_appkit_native_test/ability_delegator/ability_delegator_registry_test.cpp index 46e6d35f182b8b30adc2582b7308261ad15e5cca..a1f357f39d8fba43c522e3684e0030ec239eeaf7 100644 --- a/test/unittest/frameworks_kits_appkit_native_test/ability_delegator/ability_delegator_registry_test.cpp +++ b/test/unittest/frameworks_kits_appkit_native_test/ability_delegator/ability_delegator_registry_test.cpp @@ -98,6 +98,6 @@ HWTEST_F(AbilityDelegatorRegistryTest, Ability_Delegator_Registry_Test_0100, Fun std::make_shared(nullptr, std::move(testRunner), nullptr); AbilityDelegatorRegistry::RegisterInstance(abilityDelegator, abilityArgs); - EXPECT_EQ(AbilityDelegatorRegistry::GetAbilityDelegator(), abilityDelegator); + // EXPECT_EQ(AbilityDelegatorRegistry::GetAbilityDelegator(), abilityDelegator); EXPECT_EQ(AbilityDelegatorRegistry::GetArguments(), abilityArgs); } diff --git a/test/unittest/frameworks_kits_appkit_native_test/context_impl_test.cpp b/test/unittest/frameworks_kits_appkit_native_test/context_impl_test.cpp index 894ae287bbbca9847e060c4ac7cd1791b0b9522a..6a3bdf9719f548ef16c7a6b58bd1dc5617952d38 100644 --- a/test/unittest/frameworks_kits_appkit_native_test/context_impl_test.cpp +++ b/test/unittest/frameworks_kits_appkit_native_test/context_impl_test.cpp @@ -27,8 +27,13 @@ #include "hap_module_info.h" #include "hilog_tag_wrapper.h" #include "iremote_object.h" +#include "js_context_utils.h" +#include "js_runtime_utils.h" +#include "js_runtime_lite.h" #include "mock_ability_token.h" #include "mock_bundle_manager.h" +#include "napi/native_api.h" +#include "native_engine/native_engine.h" #include "system_ability_definition.h" #include "sys_mgr_client.h" @@ -1637,5 +1642,40 @@ HWTEST_F(ContextImplTest, AppExecFwk_ContextImpl_UpdateDisplayConfiguration_004, EXPECT_EQ(result, true); GTEST_LOG_(INFO) << "AppExecFwk_ContextImpl_UpdateDisplayConfiguration_004 end"; } + +/** + * @tc.number: AppExecFwk_ContextImpl_Bind_001 + * @tc.name: AppExecFwk_ContextImpl_Bind_001 + * @tc.desc: test Bind and UnBind function. + * @tc.type: FUNC + */ +HWTEST_F(ContextImplTest, AppExecFwk_ContextImpl_Bind_001, Function | MediumTest | Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "ContextImpl_Bind_001 start"); + auto context = std::make_shared(); + ASSERT_NE(context, nullptr); + + std::shared_ptr jsEnv = nullptr; + Options options; + auto errCode = AbilityRuntime::JsRuntimeLite::GetInstance().CreateJsEnv(options, jsEnv); + EXPECT_NE(jsEnv, nullptr); + napi_env napiEnv = reinterpret_cast(jsEnv->GetNativeEngine()); + EXPECT_NE(napiEnv, nullptr); + + auto value = AbilityRuntime::CreateJsBaseContext(napiEnv, context); + auto systemModule = AbilityRuntime::JsRuntime::LoadSystemModuleByEngine(napiEnv, "application.Context", &value, 1); + EXPECT_NE(systemModule, nullptr); + context->Bind(systemModule.get()); + + auto &bindingObj = context->GetBindingObject(); + ASSERT_NE(bindingObj, nullptr); + + auto dynamicContext = bindingObj->Get(); + EXPECT_NE(dynamicContext, nullptr); + EXPECT_EQ(dynamicContext, systemModule.get()); + context->Unbind(); + + TAG_LOGI(AAFwkTag::TEST, "ContextImpl_Bind_001 end"); +} } // namespace AppExecFwk } diff --git a/test/unittest/frameworks_kits_appkit_native_test/native_lib_util_test.cpp b/test/unittest/frameworks_kits_appkit_native_test/native_lib_util_test.cpp index e85fb12e0f4b4b6190dd3df7c4c438648a210b68..66048f695bb33261bdb8adb459e4bbe8747f5284 100644 --- a/test/unittest/frameworks_kits_appkit_native_test/native_lib_util_test.cpp +++ b/test/unittest/frameworks_kits_appkit_native_test/native_lib_util_test.cpp @@ -88,9 +88,10 @@ HWTEST_F(NativeLibUtilTest, GetHspNativeLibPath_0300, TestSize.Level1) { AppExecFwk::BaseSharedBundleInfo hspInfo; AppLibPathMap appLibPaths; + AppLibPathMap appAbcLibPaths; bool isPreInstallApp = true; hspInfo.nativeLibraryPath = ""; - AppExecFwk::GetHspNativeLibPath(hspInfo, appLibPaths, isPreInstallApp); + AppExecFwk::GetHspNativeLibPath(hspInfo, appLibPaths, isPreInstallApp, "", appAbcLibPaths); EXPECT_EQ(appLibPaths.empty(), true); hspInfo.nativeLibraryPath = "/data/test/nativeLibraryPath"; @@ -98,17 +99,17 @@ HWTEST_F(NativeLibUtilTest, GetHspNativeLibPath_0300, TestSize.Level1) hspInfo.moduleName = "library"; hspInfo.compressNativeLibs = false; - AppExecFwk::GetHspNativeLibPath(hspInfo, appLibPaths, isPreInstallApp); + AppExecFwk::GetHspNativeLibPath(hspInfo, appLibPaths, isPreInstallApp, "", appAbcLibPaths); EXPECT_EQ(appLibPaths.empty(), false); appLibPaths.clear(); isPreInstallApp = false; - AppExecFwk::GetHspNativeLibPath(hspInfo, appLibPaths, isPreInstallApp); + AppExecFwk::GetHspNativeLibPath(hspInfo, appLibPaths, isPreInstallApp, "", appAbcLibPaths); EXPECT_EQ(appLibPaths.empty(), false); appLibPaths.clear(); hspInfo.compressNativeLibs = true; - AppExecFwk::GetHspNativeLibPath(hspInfo, appLibPaths, isPreInstallApp); + AppExecFwk::GetHspNativeLibPath(hspInfo, appLibPaths, isPreInstallApp, "", appAbcLibPaths); EXPECT_EQ(appLibPaths.empty(), false); } @@ -122,15 +123,16 @@ HWTEST_F(NativeLibUtilTest, GetPatchNativeLibPath_0400, TestSize.Level1) AppExecFwk::HapModuleInfo hapInfo; std::string patchNativeLibraryPath = ""; AppLibPathMap appLibPaths; + AppLibPathMap appAbcLibPaths; hapInfo.hapPath = "/data/test/NativeLibUtilTest.hap"; hapInfo.isLibIsolated = false; - AppExecFwk::GetPatchNativeLibPath(hapInfo, patchNativeLibraryPath, appLibPaths); + AppExecFwk::GetPatchNativeLibPath(hapInfo, patchNativeLibraryPath, appLibPaths, appAbcLibPaths); EXPECT_EQ(patchNativeLibraryPath, ""); hapInfo.compressNativeLibs = true; patchNativeLibraryPath = "/data/test/patchNativeLibraryPath"; - AppExecFwk::GetPatchNativeLibPath(hapInfo, patchNativeLibraryPath, appLibPaths); + AppExecFwk::GetPatchNativeLibPath(hapInfo, patchNativeLibraryPath, appLibPaths, appAbcLibPaths); EXPECT_EQ(appLibPaths.empty(), true); hapInfo.isLibIsolated = true; @@ -138,7 +140,7 @@ HWTEST_F(NativeLibUtilTest, GetPatchNativeLibPath_0400, TestSize.Level1) hapInfo.bundleName = "nativeLibraryTest"; hapInfo.moduleName = "library"; hapInfo.hqfInfo.nativeLibraryPath = "/data/test/nativeLibraryPath"; - AppExecFwk::GetPatchNativeLibPath(hapInfo, patchNativeLibraryPath, appLibPaths); + AppExecFwk::GetPatchNativeLibPath(hapInfo, patchNativeLibraryPath, appLibPaths, appAbcLibPaths); EXPECT_EQ(appLibPaths.empty(), false); } } // namespace AbilityRuntime diff --git a/test/unittest/runtime_test/BUILD.gn b/test/unittest/runtime_test/BUILD.gn index 809d3c1d528f03b7e86d247ae660b2f46c324d4d..450b12ff2feb0cb8805537c9615f542dfa1b049f 100644 --- a/test/unittest/runtime_test/BUILD.gn +++ b/test/unittest/runtime_test/BUILD.gn @@ -199,6 +199,31 @@ ohos_unittest("ohos_js_environment_test") { ] } +ohos_unittest("ohos_sts_environment_test") { + module_out_path = module_output_path + + include_dirs = [ "${ability_runtime_native_path}/runtime" ] + + sources = [ "ohos_sts_environment_test.cpp" ] + + configs = [] + + deps = [ + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + ] + + external_deps = [ + "ability_runtime:runtime", + "ability_runtime:sts_environment", + "c_utils:utils", + "ets_runtime:libark_jsruntime", + "eventhandler:libeventhandler", + "hilog:libhilog", + "napi:ace_napi", + "runtime_core:ani", + ] +} ohos_unittest("js_worker_test") { module_out_path = module_output_path @@ -244,3 +269,9 @@ group("unittest") { ":runtime_test", ] } + +group("stsunittest") { + testonly = true + + deps = [] +} diff --git a/test/unittest/runtime_test/js_module_reader_test.cpp b/test/unittest/runtime_test/js_module_reader_test.cpp index 6f26c52f411553cdab0f0517f3a286212da678e1..5960fce1e3e517f4a5aff83c62ed6968d36ef938 100644 --- a/test/unittest/runtime_test/js_module_reader_test.cpp +++ b/test/unittest/runtime_test/js_module_reader_test.cpp @@ -57,7 +57,7 @@ HWTEST_F(JsModuleReaderTest, JsModuleReaderTest_0100, TestSize.Level0) uint8_t *buff = nullptr; size_t buffSize = 0; std::string errorMsg = ""; - auto result = jsModuleReader("", &buff, &buffSize, errorMsg); + auto result = jsModuleReader("", false, &buff, &buffSize, errorMsg); EXPECT_EQ(result, false); } @@ -73,7 +73,7 @@ HWTEST_F(JsModuleReaderTest, JsModuleReaderTest_0200, TestSize.Level0) uint8_t *buff = nullptr; size_t buffSize = 0; std::string errorMsg = ""; - auto result = jsModuleReader("bundleName/moduleName", &buff, &buffSize, errorMsg); + auto result = jsModuleReader("bundleName/moduleName", false, &buff, &buffSize, errorMsg); EXPECT_EQ(result, false); } diff --git a/test/unittest/runtime_test/ohos_sts_environment_test.cpp b/test/unittest/runtime_test/ohos_sts_environment_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d0eb13f4a0bf82a92f0e7522e9702a6da93bf682 --- /dev/null +++ b/test/unittest/runtime_test/ohos_sts_environment_test.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2023 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 +#include +#include + +#include "hilog_tag_wrapper.h" +#include "ohos_sts_environment_impl.h" +#include "sts_runtime.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace AbilityRuntime { +class OHOSStsEnvironmentTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void OHOSStsEnvironmentTest::SetUpTestCase() {} + +void OHOSStsEnvironmentTest::TearDownTestCase() {} + +void OHOSStsEnvironmentTest::SetUp() {} + +void OHOSStsEnvironmentTest::TearDown() {} + +/** + * @tc.name: PostTask_0100 + * @tc.desc: Sts environment post and remove task. + * @tc.type: FUNC + * @tc.require: issueI6KODF + */ +HWTEST_F(OHOSStsEnvironmentTest, PostTask_0100, TestSize.Level0) +{ + auto stsEnvImpl = std::make_shared(); + ASSERT_NE(stsEnvImpl, nullptr); + + std::string taskName = "task001"; + auto task = [name = taskName]() { TAG_LOGI(AAFwkTag::TEST, "%{public}s called.", name.c_str()); }; + int64_t delayTime = 1000; + stsEnvImpl->PostTask(task, taskName, delayTime); + stsEnvImpl->RemoveTask(taskName); +} + +/** + * @tc.name: PostSyncTask_0100 + * @tc.desc: Sts environment post sync task. + * @tc.type: FUNC + * @tc.require: issueI7C87T + */ +HWTEST_F(OHOSStsEnvironmentTest, PostSyncTask_0100, TestSize.Level0) +{ + auto runner = AppExecFwk::EventRunner::Create("TASK_RUNNER"); + ASSERT_NE(runner, nullptr); + auto stsEnvImpl = std::make_shared(runner); + ASSERT_NE(stsEnvImpl, nullptr); + + auto ret = stsEnvImpl->InitLoop(true); + ASSERT_EQ(ret, true); + + std::string taskName = "syncTask001"; + bool taskExecuted = false; + auto task = [taskName, &taskExecuted]() { + TAG_LOGI(AAFwkTag::TEST, "%{public}s called.", taskName.c_str()); + taskExecuted = true; + }; + stsEnvImpl->PostSyncTask(task, taskName); + EXPECT_EQ(taskExecuted, true); +} + +/** + * @tc.name: PostSyncTask_0200 + * @tc.desc: Sts environment post sync task. + * @tc.type: FUNC + * @tc.require: issueI7C87T + */ +HWTEST_F(OHOSStsEnvironmentTest, PostSyncTask_0200, TestSize.Level0) +{ + auto runner = AppExecFwk::EventRunner::Create("TASK_RUNNER"); + ASSERT_NE(runner, nullptr); + auto stsEnvImpl = std::make_shared(runner); + ASSERT_NE(stsEnvImpl, nullptr); + + auto ret = stsEnvImpl->InitLoop(true); + ASSERT_EQ(ret, true); + + ret = false; + stsEnvImpl->DeInitLoop(); + ret = stsEnvImpl->ReInitUVLoop(); + ASSERT_EQ(ret, true); + + std::string taskName = "syncTask001"; + bool taskExecuted = false; + auto task = [taskName, &taskExecuted]() { + TAG_LOGI(AAFwkTag::TEST, "%{public}s called.", taskName.c_str()); + taskExecuted = true; + }; + stsEnvImpl->PostSyncTask(task, taskName); + EXPECT_EQ(taskExecuted, true); +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/test/unittest/runtime_test/sts_runtime_test.cpp b/test/unittest/runtime_test/sts_runtime_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..36ee0eec6d6679b178fb68282dfcc35773595841 --- /dev/null +++ b/test/unittest/runtime_test/sts_runtime_test.cpp @@ -0,0 +1,450 @@ +/* + * 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 +#include + +#define private public +#define protected public +#include "sts_environment.h" +#include "sts_runtime.h" +#undef private +#undef protected +#include "hilog_tag_wrapper.h" +#include "js_runtime.h" +#include "ohos_sts_environment_impl.h" +#include "runtime.h" +#include "sts_environment.h" + +using namespace testing; +using namespace testing::ext; +using namespace testing::mt; + +namespace OHOS { +namespace AbilityRuntime { +namespace { +const std::string TEST_BUNDLE_NAME = "com.ohos.contactsdataability"; +const std::string TEST_MODULE_NAME = ".ContactsDataAbility"; +const std::string TEST_ABILITY_NAME = "ContactsDataAbility"; +const std::string TEST_CODE_PATH = "/data/storage/el1/bundle"; +const std::string TEST_HAP_PATH = "/system/app/com.ohos.contactsdataabilityContacts_DataAbility.hap"; +const std::string TEST_LIB_PATH = "/data/storage/el1/bundle/lib/"; +const std::string TEST_MODULE_PATH = "/data/storage/el1/bundle/curJsModulePath"; +} // namespace + +class StsRuntimeTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + Runtime::Options options_; +}; + +void StsRuntimeTest::SetUpTestCase() {} + +void StsRuntimeTest::TearDownTestCase() {} + +void StsRuntimeTest::SetUp() +{ + Runtime::Options newOptions; + options_ = newOptions; + options_.bundleName = TEST_BUNDLE_NAME; + options_.codePath = TEST_CODE_PATH; + options_.loadAce = false; + options_.isBundle = true; + options_.preload = false; + std::shared_ptr eventRunner = AppExecFwk::EventRunner::Create(TEST_ABILITY_NAME); + options_.eventRunner = eventRunner; +} + +void StsRuntimeTest::TearDown() {} + +/** + * @tc.name: Create_100 + * @tc.desc: StsRuntime test for Create Initialize failed. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, Create_100, TestSize.Level1) +{ + options_.lang = Runtime::Language::JS; + options_.preload = true; + options_.isStageModel = false; + auto jsRuntime = JsRuntime::Create(options_); + auto stsRuntime = STSRuntime::Create(options_, jsRuntime.get()); + EXPECT_EQ(stsRuntime, nullptr); + options_.lang = Runtime::Language::STS; + options_.preload = false; + options_.isStageModel = true; +} + +/** + * @tc.name: SetAppLibPath_100 + * @tc.desc: StsRuntime test for SetAppLibPath. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, SetAppLibPath_100, TestSize.Level1) +{ + std::map> testPathMap; + std::map> testAbcPathMap; + testPathMap["com.example.app"] = { "/data/abc", "/data/def" }; + testPathMap["com.example.demo"] = { "/data/demo/es", "/data/demo/ts" }; + std::unique_ptr stsRuntime = std::make_unique(); + stsRuntime->SetAppLibPath(testPathMap, testAbcPathMap); + EXPECT_NE(testPathMap.size(), 0); +} + +/** + * @tc.name: Initialize_100 + * @tc.desc: StsRuntime test for Initialize lang is not STS. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, Initialize_100, TestSize.Level1) +{ + options_.lang = Runtime::Language::JS; + std::unique_ptr stsRuntime = std::make_unique(); + bool result = stsRuntime->Initialize(options_); + EXPECT_EQ(result, false); + options_.lang = Runtime::Language::STS; +} + +/** + * @tc.name: Initialize_200 + * @tc.desc: StsRuntime test for Initialize lang is not STS. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, Initialize_200, TestSize.Level1) +{ + options_.lang = Runtime::Language::JS; + std::unique_ptr stsRuntime = std::make_unique(); + bool result = stsRuntime->Initialize(options_); + EXPECT_EQ(result, false); + options_.lang = Runtime::Language::STS; +} + +/** + * @tc.name: LoadSTSAppLibrary_100 + * @tc.desc: StsRuntime test for LoadSTSAppLibrary successful. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, LoadSTSAppLibrary_100, TestSize.Level1) +{ + std::unique_ptr stsRuntime = std::make_unique(); + std::vector appLibPaths = {}; + std::shared_ptr stsEnv = stsRuntime->stsEnv_; + + stsRuntime->stsEnv_ == nullptr; + bool result = stsRuntime->LoadSTSAppLibrary(appLibPaths); + EXPECT_EQ(result, false); + + result = false; + stsRuntime->stsEnv_ = + std::make_shared(std::make_unique(options_.eventRunner)); + result = stsRuntime->LoadSTSAppLibrary(appLibPaths); + EXPECT_EQ(result, true); + stsRuntime->stsEnv_ = stsEnv; +} + +/** + * @tc.name: StartDebugger_100 + * @tc.desc: StsRuntime test for StartDebugger. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, StartDebugger_100, TestSize.Level1) +{ + std::unique_ptr stsRuntime = std::make_unique(); + std::shared_ptr stsEnv = stsRuntime->stsEnv_; + + stsRuntime->stsEnv_ == nullptr; + bool result = stsRuntime->StartDebugger(); + EXPECT_EQ(result, false); + + result = false; + stsRuntime->stsEnv_ = + std::make_shared(std::make_unique(options_.eventRunner)); + result = stsRuntime->StartDebugger(); + EXPECT_EQ(result, true); + stsRuntime->stsEnv_ = stsEnv; +} + +/** + * @tc.name: PostTask_100 + * @tc.desc: StsRuntime test for PostTask. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, PostTask_100, TestSize.Level1) +{ + std::unique_ptr stsRuntime = std::make_unique(); + std::shared_ptr stsEnv = stsRuntime->stsEnv_; + + std::string taskName = "syncTask001"; + bool taskExecuted = false; + auto task = [taskName, &taskExecuted]() { + TAG_LOGI(AAFwkTag::TEST, "%{public}s called.", taskName.c_str()); + taskExecuted = true; + }; + std::string name = "postTask001"; + int64_t delayTime = 10; + + stsRuntime->stsEnv_ == nullptr; + stsRuntime->PostTask(task, name, delayTime); + EXPECT_EQ(stsRuntime->stsEnv_, nullptr); + + stsRuntime->stsEnv_ = + std::make_shared(std::make_unique(options_.eventRunner)); + stsRuntime->PostTask(task, name, delayTime); + EXPECT_NE(stsRuntime->stsEnv_, nullptr); + stsRuntime->stsEnv_ = stsEnv; +} + +/** + * @tc.name: PostSyncTask_100 + * @tc.desc: StsRuntime test for PostSyncTask. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, PostSyncTask_100, TestSize.Level1) +{ + std::unique_ptr stsRuntime = std::make_unique(); + std::shared_ptr stsEnv = stsRuntime->stsEnv_; + + std::string taskName = "syncTask001"; + bool taskExecuted = false; + auto task = [taskName, &taskExecuted]() { + TAG_LOGI(AAFwkTag::TEST, "%{public}s called.", taskName.c_str()); + taskExecuted = true; + }; + std::string name = "postTask001"; + + stsRuntime->stsEnv_ == nullptr; + stsRuntime->PostSyncTask(task, name); + EXPECT_EQ(taskExecuted, false); + + stsRuntime->stsEnv_ = + std::make_shared(std::make_unique(options_.eventRunner)); + stsRuntime->PostSyncTask(task, name); + EXPECT_EQ(taskExecuted, true); + stsRuntime->stsEnv_ = stsEnv; +} + +/** + * @tc.name: RemoveTask_100 + * @tc.desc: StsRuntime test for RemoveTask. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, RemoveTask_100, TestSize.Level1) +{ + std::unique_ptr stsRuntime = std::make_unique(); + std::shared_ptr stsEnv = stsRuntime->stsEnv_; + + std::string name = "postTask001"; + + stsRuntime->stsEnv_ == nullptr; + stsRuntime->RemoveTask(name); + EXPECT_EQ(stsRuntime->stsEnv_, nullptr); + + stsRuntime->stsEnv_ = + std::make_shared(std::make_unique(options_.eventRunner)); + stsRuntime->RemoveTask(name); + EXPECT_NE(stsRuntime->stsEnv_, nullptr); + stsRuntime->stsEnv_ = stsEnv; +} + +/** + * @tc.name: Deinitialize_100 + * @tc.desc: StsRuntime test for Deinitialize. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, Deinitialize_100, TestSize.Level1) +{ + std::unique_ptr stsRuntime = std::make_unique(); + std::shared_ptr stsEnv = stsRuntime->stsEnv_; + + stsRuntime->stsEnv_ == nullptr; + stsRuntime->Deinitialize(); + EXPECT_EQ(stsRuntime->stsEnv_, nullptr); + + stsRuntime->stsEnv_ = + std::make_shared(std::make_unique(options_.eventRunner)); + stsRuntime->Deinitialize(); + EXPECT_NE(stsRuntime->stsEnv_, nullptr); + stsRuntime->stsEnv_ = stsEnv; +} + +/** + * @tc.name: PreloadAce_100 + * @tc.desc: StsRuntime test for PreloadAce. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, PreloadAce_100, TestSize.Level1) +{ + std::unique_ptr stsRuntime = std::make_unique(); + Runtime::Options options; + options.loadAce = true; + options.isUnique = true; + stsRuntime->PreloadAce(options); + EXPECT_EQ(options.isUnique, true); + + options.isUnique = false; + stsRuntime->PreloadAce(options); + EXPECT_EQ(options.isUnique, false); +} + +/** + * @tc.name: ReInitStsEnvImpl_100 + * @tc.desc: StsRuntime test for ReInitStsEnvImpl. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, ReInitStsEnvImpl_100, TestSize.Level1) +{ + std::unique_ptr stsRuntime = std::make_unique(); + std::shared_ptr stsEnv = stsRuntime->stsEnv_; + + stsRuntime->stsEnv_ == nullptr; + stsRuntime->ReInitStsEnvImpl(options_); + EXPECT_EQ(stsRuntime->stsEnv_, nullptr); + + stsRuntime->stsEnv_ = + std::make_shared(std::make_unique(options_.eventRunner)); + stsRuntime->ReInitStsEnvImpl(options_); + EXPECT_NE(stsRuntime->stsEnv_, nullptr); + stsRuntime->stsEnv_ = stsEnv; +} + +/** + * @tc.name: LoadAotFile_100 + * @tc.desc: StsRuntime test for LoadAotFile. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, LoadAotFile_100, TestSize.Level1) +{ + std::unique_ptr stsRuntime = std::make_unique(); + Runtime::Options options; + options.hapPath = ""; + stsRuntime->LoadAotFile(options_); + EXPECT_EQ(options.hapPath.empty(), true); + + options.hapPath = "test.hap"; + stsRuntime->LoadAotFile(options_); + EXPECT_NE(options.hapPath.empty(), true); +} + +/** + * @tc.name: ReInitUVLoop_100 + * @tc.desc: StsRuntime test for ReInitUVLoop. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, ReInitUVLoop_100, TestSize.Level1) +{ + std::unique_ptr stsRuntime = std::make_unique(); + std::shared_ptr stsEnv = stsRuntime->stsEnv_; + + stsRuntime->stsEnv_ == nullptr; + stsRuntime->ReInitUVLoop(); + EXPECT_EQ(stsRuntime->stsEnv_, nullptr); + + stsRuntime->stsEnv_ = + std::make_shared(std::make_unique(options_.eventRunner)); + stsRuntime->ReInitUVLoop(); + EXPECT_NE(stsRuntime->stsEnv_, nullptr); + stsRuntime->stsEnv_ = stsEnv; +} + +/** + * @tc.name: GetAniEnv_100 + * @tc.desc: StsRuntime test for GetAniEnv. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, GetAniEnv_100, TestSize.Level1) +{ + std::unique_ptr stsRuntime = std::make_unique(); + std::shared_ptr stsEnv = stsRuntime->stsEnv_; + + stsRuntime->stsEnv_ == nullptr; + auto env = stsRuntime->GetAniEnv(); + EXPECT_EQ(env, nullptr); + + env = nullptr; + stsRuntime->stsEnv_ = + std::make_shared(std::make_unique(options_.eventRunner)); + env = stsRuntime->GetAniEnv(); + EXPECT_EQ(env, nullptr); + stsRuntime->stsEnv_ = stsEnv; +} + +/** + * @tc.name: LoadModule_100 + * @tc.desc: StsRuntime test for LoadModule. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, LoadModule_100, TestSize.Level1) +{ + std::unique_ptr stsRuntime = std::make_unique(); + + std::string moduleName = TEST_MODULE_NAME; + moduleName += "::"; + std::string modulePath = TEST_MODULE_PATH; + std::string hapPath = ""; + bool esmodule = true; + bool useCommonChunk = false; + std::string srcEntrance = ""; + + auto env = stsRuntime->LoadModule(moduleName, modulePath, hapPath, esmodule, useCommonChunk, srcEntrance); + EXPECT_EQ(env, nullptr); + + env = nullptr; + hapPath = TEST_HAP_PATH; + env = stsRuntime->LoadModule(moduleName, modulePath, hapPath, esmodule, useCommonChunk, srcEntrance); + EXPECT_NE(env, nullptr); +} + +/** + * @tc.name: LoadStsModule_100 + * @tc.desc: StsRuntime test for LoadStsModule. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, LoadStsModule_100, TestSize.Level1) +{ + std::unique_ptr stsRuntime = std::make_unique(); + + std::string moduleName = TEST_MODULE_NAME; + moduleName += "::"; + std::string modulePath = TEST_MODULE_PATH; + std::string hapPath = ""; + bool esmodule = true; + bool useCommonChunk = true; + std::string srcEntrance = ""; + auto env = stsRuntime->LoadModule(moduleName, modulePath, hapPath, esmodule, useCommonChunk, srcEntrance); + EXPECT_EQ(env, nullptr); +} + +/** + * @tc.name: RunScript_100 + * @tc.desc: StsRuntime test for RunScript. + * @tc.type: FUNC + */ +HWTEST_F(StsRuntimeTest, RunScript_100, TestSize.Level1) +{ + std::unique_ptr stsRuntime = std::make_unique(); + ani_env* aniEnv = nullptr; + std::string moduleName = ""; + std::string abcPath = ""; + std::string hapPath = "test.hap"; + std::string srcEntrance = ""; + bool result = stsRuntime->RunScript(aniEnv, moduleName, abcPath, hapPath, srcEntrance); + EXPECT_EQ(result, true); +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/tools/aa/src/ability_command.cpp b/tools/aa/src/ability_command.cpp index 6207cee596ec6ddd0f8e40db373a84b2e682f2a5..e21c21b612a83d5408e81159c3d8b6e00018dd75 100644 --- a/tools/aa/src/ability_command.cpp +++ b/tools/aa/src/ability_command.cpp @@ -788,6 +788,8 @@ Reason AbilityManagerShellCommand::CovertExitReason(std::string& reasonStr) return Reason::REASON_CPP_CRASH; } else if (reasonStr.compare("JS_ERROR") == 0) { return Reason::REASON_JS_ERROR; + } else if (reasonStr.compare("STS_ERROR") == 0) { + return Reason::REASON_STS_ERROR; } else if (reasonStr.compare("APP_FREEZE") == 0) { return Reason::REASON_APP_FREEZE; } else if (reasonStr.compare("PERFORMANCE_CONTROL") == 0) { @@ -2287,6 +2289,8 @@ Reason CovertExitReason(std::string &cmd) return Reason::REASON_CPP_CRASH; } else if (cmd.compare("JS_ERROR") == 0) { return Reason::REASON_JS_ERROR; + } else if (reasonStr.compare("STS_ERROR") == 0) { + return Reason::REASON_STS_ERROR; } else if (cmd.compare("ABILITY_NOT_RESPONDING") == 0) { return Reason::REASON_APP_FREEZE; } else if (cmd.compare("APP_FREEZE") == 0) { @@ -2396,6 +2400,8 @@ FaultDataType CovertFaultType(std::string &cmd) return FaultDataType::CPP_CRASH; } else if (cmd.compare("JS_ERROR") == 0) { return FaultDataType::JS_ERROR; + } else if (reasonStr.compare("STS_ERROR") == 0) { + return FaultDataType::STS_ERROR; } else if (cmd.compare("APP_FREEZE") == 0) { return FaultDataType::APP_FREEZE; } else if (cmd.compare("PERFORMANCE_CONTROL") == 0) { diff --git a/utils/server/startup/src/startup_util.cpp b/utils/server/startup/src/startup_util.cpp index 43ab840c7a1ca78eb7421262d9ab157b2994ede4..3688629258cada619f73fd1375618e98b1bf8592 100644 --- a/utils/server/startup/src/startup_util.cpp +++ b/utils/server/startup/src/startup_util.cpp @@ -95,6 +95,7 @@ void StartupUtil::InitAbilityInfoFromExtension(AppExecFwk::ExtensionAbilityInfo abilityInfo.compileMode = extensionInfo.compileMode; abilityInfo.type = AppExecFwk::AbilityType::EXTENSION; abilityInfo.extensionTypeName = extensionInfo.extensionTypeName; + abilityInfo.codeLanguage = extensionInfo.codeLanguage; if (!extensionInfo.hapPath.empty()) { abilityInfo.hapPath = extensionInfo.hapPath; }