From aab5eb2dd2c286212d1be3aabb9f640cb19fd90e Mon Sep 17 00:00:00 2001 From: zhangzezhong Date: Mon, 9 Jun 2025 21:32:57 +0800 Subject: [PATCH 1/3] delegator run XTS Signed-off-by: zhangzezhong --- all.diff | 4890 +++++++++++++++++ bundle.json | 10 + ets_environment/ets_environment.gni | 14 + .../frameworks/ets_environment/BUILD.gn | 63 + .../ets_environment/src/dynamic_loader.cpp | 194 + .../ets_environment/src/ets_environment.cpp | 356 ++ .../interfaces/inner_api/dynamic_loader.h | 31 + .../interfaces/inner_api/ets_environment.h | 72 + .../inner_api/ets_exception_callback.h | 34 + frameworks/cj/ffi/BUILD.gn | 1 + .../ani/ani_common/src/ani_common_util.cpp | 6 +- .../ani/ani_common/src/ani_common_want.cpp | 4 + .../ets/ani/enum_convert/ani_enum_convert.h | 12 +- .../ets/@ohos.app.ability.AbilityConstant.ets | 107 + .../ets/@ohos.app.ability.StartOptions.ets | 18 + .../ets/ets/@ohos.app.ability.UIAbility.ets | 74 + frameworks/ets/ets/@ohos.app.ability.Want.ets | 232 + .../ets/@ohos.app.ability.wantConstant.ets | 66 + frameworks/ets/ets/BUILD.gn | 102 + frameworks/ets/ets/utils/AbilityUtils.ets | 64 + .../app/ability_delegator/ability_monitor.cpp | 84 +- .../app/ability_delegator/ability_monitor.h | 14 +- .../js_ability_delegator.cpp | 19 +- frameworks/native/ability/native/BUILD.gn | 5 + .../native/ability/native/ability_loader.cpp | 10 +- .../native/ability_runtime/ets_ui_ability.cpp | 694 +++ .../native/extension_ability_thread.cpp | 8 +- .../ability/native/ui_ability_thread.cpp | 6 +- frameworks/native/appkit/BUILD.gn | 4 + .../ability_delegator/ability_delegator.cpp | 63 +- .../ability_delegator_registry.cpp | 28 +- .../ability_delegator/iability_monitor.cpp | 20 +- .../appkit/app/application_data_manager.cpp | 19 + .../native/appkit/app/dump_runtime_helper.cpp | 6 +- frameworks/native/appkit/app/main_thread.cpp | 323 +- .../native/appkit/app/ohos_application.cpp | 144 +- frameworks/native/runtime/cj_runtime.cpp | 20 +- .../runtime/ets_data_struct_converter.cpp | 106 + frameworks/native/runtime/ets_runtime.cpp | 481 ++ frameworks/native/runtime/js_runtime.cpp | 7 + frameworks/native/runtime/runtime.cpp | 42 +- .../ability_simulator/src/js_runtime.cpp | 3 + interfaces/inner_api/runtime/BUILD.gn | 5 + .../inner_api/runtime/include/cj_runtime.h | 4 +- .../include/ets_data_struct_converter.h | 27 + .../inner_api/runtime/include/ets_runtime.h | 105 + .../inner_api/runtime/include/js_runtime.h | 3 + .../inner_api/runtime/include/runtime.h | 17 +- .../native/ability/native/ability_loader.h | 9 +- .../native/ability_runtime/ets_ui_ability.h | 168 + .../ability_delegator/ability_delegator.h | 34 +- .../ability_delegator_infos.h | 11 +- .../ability_delegator_registry.h | 9 +- .../ability_delegator/iability_monitor.h | 22 +- .../appkit/app/application_data_manager.h | 2 + .../kits/native/appkit/app/main_thread.h | 12 +- .../kits/native/appkit/app/ohos_application.h | 21 +- 57 files changed, 8642 insertions(+), 263 deletions(-) create mode 100644 all.diff create mode 100644 ets_environment/ets_environment.gni create mode 100644 ets_environment/frameworks/ets_environment/BUILD.gn create mode 100644 ets_environment/frameworks/ets_environment/src/dynamic_loader.cpp create mode 100644 ets_environment/frameworks/ets_environment/src/ets_environment.cpp create mode 100644 ets_environment/interfaces/inner_api/dynamic_loader.h create mode 100644 ets_environment/interfaces/inner_api/ets_environment.h create mode 100644 ets_environment/interfaces/inner_api/ets_exception_callback.h create mode 100644 frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.StartOptions.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.UIAbility.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.Want.ets create mode 100644 frameworks/ets/ets/@ohos.app.ability.wantConstant.ets create mode 100644 frameworks/ets/ets/utils/AbilityUtils.ets create mode 100644 frameworks/native/ability/native/ability_runtime/ets_ui_ability.cpp create mode 100644 frameworks/native/runtime/ets_data_struct_converter.cpp create mode 100644 frameworks/native/runtime/ets_runtime.cpp create mode 100644 interfaces/inner_api/runtime/include/ets_data_struct_converter.h create mode 100644 interfaces/inner_api/runtime/include/ets_runtime.h create mode 100644 interfaces/kits/native/ability/native/ability_runtime/ets_ui_ability.h diff --git a/all.diff b/all.diff new file mode 100644 index 00000000000..69cef01d987 --- /dev/null +++ b/all.diff @@ -0,0 +1,4890 @@ +diff --git a/bundle.json b/bundle.json +index 4c096e00742f53b3a363ec9cf51c5c0f44f802eb..3cce00df14d16eedee08485ca7446239fa74cc87 100644 +--- a/bundle.json ++++ b/bundle.json +@@ -135,6 +135,7 @@ + "//foundation/ability/ability_runtime/frameworks/js/napi:napi_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/ets_environment/frameworks/ets_environment:ets_environment", + "//foundation/ability/ability_runtime/js_environment/frameworks/js_environment:js_environment", + "//foundation/ability/ability_runtime/services/abilitymgr/etc:appfwk_etc", + "//foundation/ability/ability_runtime/services/dialog_ui/ams_system_dialog:dialog_hap", +@@ -261,6 +262,15 @@ + }, + "name": "//foundation/ability/ability_runtime/js_environment/frameworks/js_environment:js_environment" + }, ++ { ++ "header": { ++ "header_base": "//foundation/ability/ability_runtime/ets_environment/interfaces/inner_api", ++ "header_files": [ ++ "ets_environment.h" ++ ] ++ }, ++ "name": "//foundation/ability/ability_runtime/ets_environment/frameworks/ets_environment:ets_environment" ++ }, + { + "header": { + "header_base": "//foundation/ability/ability_runtime/cj_environment/interfaces/inner_api", +diff --git a/ets_environment/ets_environment.gni b/ets_environment/ets_environment.gni +new file mode 100644 +index 0000000000000000000000000000000000000000..b044edbd9d057f4000e0f620cea72d1567c63af0 +--- /dev/null ++++ b/ets_environment/ets_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/ets_environment" +diff --git a/ets_environment/frameworks/ets_environment/BUILD.gn b/ets_environment/frameworks/ets_environment/BUILD.gn +new file mode 100644 +index 0000000000000000000000000000000000000000..a3f1835114b196ff9b7335949951658505490076 +--- /dev/null ++++ b/ets_environment/frameworks/ets_environment/BUILD.gn +@@ -0,0 +1,63 @@ ++# Copyright (c) 2025 Huawei Device Co., Ltd. ++# Licensed under the Apache License, Version 2.0 (the "License"); ++# you may not use this file except in compliance with the License. ++# You may obtain a copy of the License at ++# ++# http://www.apache.org/licenses/LICENSE-2.0 ++# ++# Unless required by applicable law or agreed to in writing, software ++# distributed under the License is distributed on an "AS IS" BASIS, ++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++# See the License for the specific language governing permissions and ++# limitations under the License. ++ ++import("//build/ohos.gni") ++import("//foundation/ability/ability_runtime/ability_runtime.gni") ++import("../../ets_environment.gni") ++ ++config("public_ets_environment_config") { ++ include_dirs = [ ++ "include", ++ "${ability_runtime_path}/ets_environment/interfaces/inner_api", ++ "${ability_runtime_path}/interfaces/inner_api", ++ "${ability_runtime_services_path}/common/include", ++ ] ++} ++ ++ohos_shared_library("ets_environment") { ++ branch_protector_ret = "pac_ret" ++ ++ public_configs = [ ":public_ets_environment_config" ] ++ ++ sanitize = { ++ cfi = true ++ cfi_cross_dso = true ++ debug = false ++ } ++ ++ sources = [ ++ "src/dynamic_loader.cpp", ++ "src/ets_environment.cpp", ++ ] ++ ++ defines = [] ++ ++ external_deps = [ ++ "c_utils:utils", ++ "eventhandler:libeventhandler", ++ "faultloggerd:libunwinder", ++ "hilog:libhilog", ++ "json:nlohmann_json_static", ++ "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/ets_environment/frameworks/ets_environment/src/dynamic_loader.cpp b/ets_environment/frameworks/ets_environment/src/dynamic_loader.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..6b2934937440590733373c543d94982429321f8b +--- /dev/null ++++ b/ets_environment/frameworks/ets_environment/src/dynamic_loader.cpp +@@ -0,0 +1,194 @@ ++/* ++ * Copyright (c) 2025 Huawei Device Co., Ltd. ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT 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 ++#include ++#include ++#include ++#include ++ ++#include "hilog_tag_wrapper.h" ++ ++namespace OHOS { ++namespace EtsEnv { ++namespace { ++constexpr int32_t ERROR_BUF_SIZE = 255; ++static char g_dlError[ERROR_BUF_SIZE]; ++static std::unordered_set g_hasInited; ++static std::string g_sharedLibsSonames = ""; ++constexpr int32_t OUT_OF_MEMORY = 12; ++constexpr int32_t FILE_EXISTS = 17; ++constexpr int32_t 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.empty()) { ++ return; ++ } ++ g_sharedLibsSonames = ++ // 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"; ++} ++} // namespace ++ ++void DynamicInitNamespace(Dl_namespace *ns, void *parent, const char *entries, const char *name) ++{ ++ if (ns == nullptr || entries == nullptr || name == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Invaild args for init namespace."); ++ return; ++ } ++ if (g_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) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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, "ets_app") != 0) { ++ dlns_inherit(ns, ¤t, "allow_all_shared_libs"); ++ } else { ++ InitSharedLibsSonames(); ++ dlns_inherit(ns, ¤t, g_sharedLibsSonames.c_str()); ++ } ++ g_hasInited.insert(std::string(name)); ++} ++ ++void *DynamicLoadLibrary(Dl_namespace *ns, const char *dlPath, uint32_t mode) ++{ ++ if (ns == nullptr) { ++ dlns_get("ets_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; ++} ++} // namespace EtsEnv ++} // namespace OHOS +\ No newline at end of file +diff --git a/ets_environment/frameworks/ets_environment/src/ets_environment.cpp b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..ef09b6afd092495df3721d791a47ba284632af36 +--- /dev/null ++++ b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp +@@ -0,0 +1,356 @@ ++/* ++ * Copyright (c) 2025 Huawei Device Co., Ltd. ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT 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_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 "unwinder.h" ++ ++#ifdef SUPPORT_GRAPHICS ++#include "ui_content.h" ++#endif // SUPPORT_GRAPHICS ++ ++namespace OHOS { ++namespace EtsEnv { ++namespace { ++const char ETS_CREATE_VM[] = "ANI_CreateVM"; ++const char ETS_ANI_GET_CREATEDVMS[] = "ANI_GetCreatedVMs"; ++const char ETS_LIB_PATH[] = "libets_interop_js_napi.z.so"; ++const char BOOT_PATH[] = "/system/framework/bootpath.json"; ++const char BACKTRACE[] = "=====================Backtrace========================"; ++ ++using CreateVMETSRuntimeType = 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 ETS_SDK_NSNAME[] = "ets_sdk"; ++const char ETS_SYS_NSNAME[] = "ets_system"; ++} // namespace ++ ++ETSRuntimeAPI ETSEnvironment::lazyApis_ {}; ++ ++bool ETSEnvironment::LoadBootPathFile(std::string &bootfiles) ++{ ++ std::ifstream inFile; ++ inFile.open(BOOT_PATH, std::ios::in); ++ if (!inFile.is_open()) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "read json error"); ++ return false; ++ } ++ nlohmann::json jsonObject = nlohmann::json::parse(inFile); ++ if (jsonObject.is_discarded()) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "json discarded error"); ++ inFile.close(); ++ return false; ++ } ++ ++ if (jsonObject.is_null() || jsonObject.empty()) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "json value of %{public}s is empty", key.c_str()); ++ continue; ++ } ++ if (!bootfiles.empty()) { ++ bootfiles += ":"; ++ } ++ bootfiles += jsonValue.c_str(); ++ } ++ } ++ inFile.close(); ++ return true; ++} ++ ++bool ETSEnvironment::LoadRuntimeApis() ++{ ++ static bool isRuntimeApiLoaded { false }; ++ if (isRuntimeApiLoaded) { ++ return true; ++ } ++ ++ Dl_namespace ns; ++ dlns_get(ETS_SDK_NSNAME, &ns); ++ auto dso = DynamicLoadLibrary(&ns, ETS_LIB_PATH, 1); ++ if (!dso) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "load library failed: %{public}s", ETS_LIB_PATH); ++ return false; ++ } ++ ++ if (!LoadSymbolCreateVM(dso, lazyApis_) || ++ !LoadSymbolANIGetCreatedVMs(dso, lazyApis_)) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "load symbol failed"); ++ return false; ++ } ++ ++ isRuntimeApiLoaded = true; ++ return true; ++} ++ ++std::string ETSEnvironment::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(); ++ if (elfFile == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null elfFile"); ++ break; ++ } ++ std::string buildId = elfFile->GetBuildId(); ++ if (i != 0 && !buildId.empty()) { ++ addBuildId += tempStr + "(" + buildId + ")" + "\n"; ++ } else { ++ addBuildId += tempStr + "\n"; ++ } ++ } ++ i++; ++ } ++ return addBuildId; ++} ++ ++void ETSEnvironment::RegisterUncaughtExceptionHandler(const ETSUncaughtExceptionInfo &handle) ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "RegisterUncaughtExceptionHandler called"); ++ uncaughtExceptionInfo_ = handle; ++} ++ ++bool ETSEnvironment::LoadSymbolCreateVM(void *handle, ETSRuntimeAPI &apis) ++{ ++ auto symbol = dlsym(handle, ETS_CREATE_VM); ++ if (symbol == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "runtime api not found: %{public}s", ETS_CREATE_VM); ++ return false; ++ } ++ apis.ANI_CreateVM = reinterpret_cast(symbol); ++ ++ return true; ++} ++ ++bool ETSEnvironment::LoadSymbolANIGetCreatedVMs(void *handle, ETSRuntimeAPI &apis) ++{ ++ auto symbol = dlsym(handle, ETS_ANI_GET_CREATEDVMS); ++ if (symbol == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "runtime api not found: %{public}s", ETS_ANI_GET_CREATEDVMS); ++ return false; ++ } ++ apis.ANI_GetCreatedVMs = reinterpret_cast(symbol); ++ ++ return true; ++} ++ ++void ETSEnvironment::InitETSSDKNS(const std::string &path) ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "InitETSSDKNS: %{public}s", path.c_str()); ++ Dl_namespace ndk; ++ Dl_namespace ns; ++ DynamicInitNamespace(&ns, nullptr, path.c_str(), ETS_SDK_NSNAME); ++ dlns_get("ndk", &ndk); ++ dlns_inherit(&ns, &ndk, "allow_all_shared_libs"); ++} ++ ++void ETSEnvironment::InitETSSysNS(const std::string &path) ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "InitETSSysNS: %{public}s", path.c_str()); ++ Dl_namespace ets_sdk; ++ Dl_namespace ndk; ++ Dl_namespace ns; ++ dlns_get(ETS_SDK_NSNAME, &ets_sdk); ++ DynamicInitNamespace(&ns, &ets_sdk, path.c_str(), ETS_SYS_NSNAME); ++ dlns_get("ndk", &ndk); ++ dlns_inherit(&ns, &ndk, "allow_all_shared_libs"); ++} ++ ++bool ETSEnvironment::Initialize(napi_env napiEnv, std::vector &options) ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "StartRuntime called"); ++ if (!LoadRuntimeApis()) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "LoadRuntimeApis failed"); ++ return false; ++ } ++ std::string bootfiles; ++ if (!LoadBootPathFile(bootfiles)) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "bootString %{public}s", bootString.c_str()); ++ options.push_back(ani_option { bootString.c_str(), nullptr }); ++ std::string schedulingExternal = optionPrefix + "--coroutine-enable-external-scheduling=true"; ++ ani_option schedulingExternalOption = { schedulingExternal.data(), nullptr }; ++ options.push_back(schedulingExternalOption); ++ ++ 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 enableVerfication = optionPrefix + "--verification-enabled=true"; ++ ani_option enableVerficationOption = { enableVerfication.data(), nullptr }; ++ options.push_back(enableVerficationOption); ++ ++ std::string verificationMode = optionPrefix + "--verification-mode=on-the-fly"; ++ ani_option verificationModeOption = { verificationMode.data(), nullptr }; ++ options.push_back(verificationModeOption); ++ ++ std::string interop = optionPrefix + "interop"; ++ ani_option interopOption = { interop.data(), (void *)napiEnv }; ++ options.push_back(interopOption); ++ ani_options optionsPtr = { options.size(), options.data() }; ++ ani_status status = ANI_ERROR; ++ if ((status = lazyApis_.ANI_CreateVM(&optionsPtr, ANI_VERSION_1, &vmEntry_.aniVm_)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "ANI_CreateVM failed %{public}d", status); ++ return false; ++ } ++ if ((status = vmEntry_.aniVm_->GetEnv(ANI_VERSION_1, &vmEntry_.aniEnv_)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetEnv failed %{public}d", status); ++ return false; ++ } ++ return true; ++} ++ ++ani_env *ETSEnvironment::GetAniEnv() ++{ ++ return vmEntry_.aniEnv_; ++} ++ ++void ETSEnvironment::HandleUncaughtError() ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "HandleUncaughtError called"); ++ const EtsEnv::ETSErrorObject errorObj = GetETSErrorObject(); ++ std::string errorStack = errorObj.stack; ++ if (errorStack.empty()) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "errorStack is empty"); ++ return; ++ } ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "uncaughtTask called"); ++ uncaughtExceptionInfo_.uncaughtTask(summary, errorObj); ++ } ++} ++ ++EtsEnv::ETSErrorObject ETSEnvironment::GetETSErrorObject() ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "GetETSErrorObject called"); ++ ani_boolean errorExists = ANI_FALSE; ++ ani_status status = ANI_ERROR; ++ auto aniEnv = GetAniEnv(); ++ if (aniEnv == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env"); ++ return EtsEnv::ETSErrorObject(); ++ } ++ if ((status = aniEnv->ExistUnhandledError(&errorExists)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "ExistUnhandledError failed, status : %{public}d", status); ++ return EtsEnv::ETSErrorObject(); ++ } ++ if (errorExists == ANI_FALSE) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "not exist error"); ++ return EtsEnv::ETSErrorObject(); ++ } ++ ani_error aniError = nullptr; ++ if ((status = aniEnv->GetUnhandledError(&aniError)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetUnhandledError failed, status : %{public}d", status); ++ return EtsEnv::ETSErrorObject(); ++ } ++ if ((status = aniEnv->ResetError()) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "ResetError failed, status : %{public}d", status); ++ return EtsEnv::ETSErrorObject(); ++ } ++ std::string errorMsg = GetErrorProperty(aniError, "message"); ++ std::string errorName = GetErrorProperty(aniError, "name"); ++ std::string errorStack = GetErrorProperty(aniError, "stack"); ++ const EtsEnv::ETSErrorObject errorObj = { ++ .name = errorName, ++ .message = errorMsg, ++ .stack = errorStack ++ }; ++ return errorObj; ++} ++ ++std::string ETSEnvironment::GetErrorProperty(ani_error aniError, const char *property) ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "GetErrorProperty called"); ++ auto aniEnv = GetAniEnv(); ++ std::string propertyValue; ++ ani_status status = ANI_ERROR; ++ ani_type errorType = nullptr; ++ if ((status = aniEnv->Object_GetType(aniError, &errorType)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "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::ETSRUNTIME, "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::ETSRUNTIME, "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::ETSRUNTIME, "String_GetUTF8SubString failed, status : %{public}d", status); ++ return propertyValue; ++ } ++ propertyValue.resize(sz); ++ return propertyValue; ++} ++} // namespace EtsEnv ++} // namespace OHOS +diff --git a/ets_environment/interfaces/inner_api/dynamic_loader.h b/ets_environment/interfaces/inner_api/dynamic_loader.h +new file mode 100644 +index 0000000000000000000000000000000000000000..6155e797e8e59b1b312376065d856cd554f78d0e +--- /dev/null ++++ b/ets_environment/interfaces/inner_api/dynamic_loader.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_DYNAMIC_LOADER_H ++#define OHOS_ABILITY_RUNTIME_DYNAMIC_LOADER_H ++ ++#include ++#include ++ ++namespace OHOS { ++namespace EtsEnv { ++void *DynamicLoadLibrary(Dl_namespace *ns, const char *dlPath, uint32_t 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); ++} // namespace EtsEnv ++} // namespace OHOS ++#endif // OHOS_ABILITY_RUNTIME_DYNAMIC_LOADER_H +diff --git a/ets_environment/interfaces/inner_api/ets_environment.h b/ets_environment/interfaces/inner_api/ets_environment.h +new file mode 100644 +index 0000000000000000000000000000000000000000..2c37be0747a6ab938aaace948f8600d0f22bdb82 +--- /dev/null ++++ b/ets_environment/interfaces/inner_api/ets_environment.h +@@ -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. ++ */ ++ ++#ifndef OHOS_ABILITY_RUNTIME_ETS_ENVIRONMENT_H ++#define OHOS_ABILITY_RUNTIME_ETS_ENVIRONMENT_H ++ ++#include ++#include ++#include ++#include ++ ++#include "ani.h" ++#include "ets_exception_callback.h" ++#include "event_handler.h" ++#include "napi/native_api.h" ++ ++namespace OHOS { ++namespace EtsEnv { ++struct ETSRuntimeAPI { ++ 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); ++}; ++ ++class ETSEnvironment final : public std::enable_shared_from_this { ++public: ++ ETSEnvironment() {}; ++ ++ static void InitETSSDKNS(const std::string &path); ++ static void InitETSSysNS(const std::string &path); ++ ++ bool Initialize(napi_env napiEnv, std::vector &options); ++ void RegisterUncaughtExceptionHandler(const ETSUncaughtExceptionInfo &handle); ++ ani_env *GetAniEnv(); ++ void HandleUncaughtError(); ++ ++ struct VMEntry { ++ ani_vm *aniVm_; ++ ani_env *aniEnv_; ++ VMEntry() ++ { ++ aniVm_ = nullptr; ++ aniEnv_ = nullptr; ++ } ++ }; ++ ++private: ++ bool LoadRuntimeApis(); ++ bool LoadSymbolCreateVM(void *handle, ETSRuntimeAPI &apis); ++ bool LoadSymbolANIGetCreatedVMs(void *handle, ETSRuntimeAPI &apis); ++ bool LoadBootPathFile(std::string &bootfiles); ++ std::string GetBuildId(std::string stack); ++ EtsEnv::ETSErrorObject GetETSErrorObject(); ++ std::string GetErrorProperty(ani_error aniError, const char *property); ++ static ETSRuntimeAPI lazyApis_; ++ VMEntry vmEntry_; ++ ETSUncaughtExceptionInfo uncaughtExceptionInfo_; ++}; ++} // namespace EtsEnv ++} // namespace OHOS ++#endif // OHOS_ABILITY_RUNTIME_ETS_ENVIRONMENT_H +diff --git a/ets_environment/interfaces/inner_api/ets_exception_callback.h b/ets_environment/interfaces/inner_api/ets_exception_callback.h +new file mode 100644 +index 0000000000000000000000000000000000000000..2d935af7f1fd3cd58a70487b8d17801b3a91e8fc +--- /dev/null ++++ b/ets_environment/interfaces/inner_api/ets_exception_callback.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_EXCEPTION_CALLBACK_H ++#define OHOS_ABILITY_RUNTIME_ETS_EXCEPTION_CALLBACK_H ++ ++#include ++ ++namespace OHOS { ++namespace EtsEnv { ++struct ETSErrorObject { ++ std::string name; ++ std::string message; ++ std::string stack; ++}; ++ ++struct ETSUncaughtExceptionInfo { ++ std::function uncaughtTask; ++}; ++} // namespace EtsEnv ++} // namespace OHOS ++#endif // OHOS_ABILITY_RUNTIME_ETS_EXCEPTION_CALLBACK_H +diff --git a/frameworks/cj/ffi/BUILD.gn b/frameworks/cj/ffi/BUILD.gn +index 03df8fc4f901e9ed2625b89d0ed895e1b7ca304b..b9797aa47928e3073e7626a0c69d8642909fee08 100644 +--- a/frameworks/cj/ffi/BUILD.gn ++++ b/frameworks/cj/ffi/BUILD.gn +@@ -69,6 +69,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/ani_common/src/ani_common_util.cpp b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp +index d909518810b8d955c92bda96a4ac85f8fa1893ed..8d2a9961007957785d74ef7f94cca3fb0912d8a4 100644 +--- a/frameworks/ets/ani/ani_common/src/ani_common_util.cpp ++++ b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp +@@ -93,7 +93,7 @@ bool GetFieldBoolByName(ani_env *env, ani_object object, const char *name, bool + return false; + } + ani_boolean isUndefined = true; +- if ((status = env->Reference_IsUndefined(object, &isUndefined)) != ANI_OK) { ++ if ((status = env->Reference_IsUndefined(field, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } +@@ -103,7 +103,7 @@ bool GetFieldBoolByName(ani_env *env, ani_object object, const char *name, bool + } + ani_boolean aniValue = false; + if ((status = env->Object_CallMethodByName_Boolean( +- reinterpret_cast(object), "booleanValue", nullptr, &aniValue)) != ANI_OK) { ++ reinterpret_cast(field), "booleanValue", nullptr, &aniValue)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } +@@ -143,7 +143,7 @@ bool GetFieldStringByName(ani_env *env, ani_object object, const char *name, std + return false; + } + ani_boolean isUndefined = true; +- if ((status = env->Reference_IsUndefined(object, &isUndefined)) != ANI_OK) { ++ if ((status = env->Reference_IsUndefined(field, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); + return false; + } +diff --git a/frameworks/ets/ani/ani_common/src/ani_common_want.cpp b/frameworks/ets/ani/ani_common/src/ani_common_want.cpp +index 0f6f8ad80cbbba99916ca1bb186f24dcb14ef313..0fcacfbf24a0f9ecd0c6d9a4d0fe3bb239a6d063 100644 +--- a/frameworks/ets/ani/ani_common/src/ani_common_want.cpp ++++ b/frameworks/ets/ani/ani_common/src/ani_common_want.cpp +@@ -61,6 +61,10 @@ bool InnerUnwrapWantParams(ani_env* env, ani_object wantObject, AAFwk::WantParam + ani_object WrapWant(ani_env *env, const AAFwk::Want &want) + { + TAG_LOGD(AAFwkTag::ANI, "WrapWant called"); ++ if (env == nullptr) { ++ TAG_LOGE(AAFwkTag::ANI, "null env"); ++ return nullptr; ++ } + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + ani_method method = nullptr; +diff --git a/frameworks/ets/ani/enum_convert/ani_enum_convert.h b/frameworks/ets/ani/enum_convert/ani_enum_convert.h +index 6234c8bc88fa2631cee71c7abafbbfe85279ba1f..a61bbe0b3d7e02b3b5590b832bb0c42cf6acf98c 100644 +--- a/frameworks/ets/ani/enum_convert/ani_enum_convert.h ++++ b/frameworks/ets/ani/enum_convert/ani_enum_convert.h +@@ -47,7 +47,7 @@ static bool EnumConvert_EtsToNative(ani_env *env, ani_enum_item enumItem, T &res + ani_int intValue{}; + status = env->EnumItem_GetValue_Int(enumItem, &intValue); + if (ANI_OK != status) { +- TAG_LOGE(AAFwkTag::EtsRUNTIME, "EnumConvert_EtsToNative failed, status : %{public}d", status); ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "EnumConvert_EtsToNative failed, status : %{public}d", status); + return false; + } + result = static_cast(intValue); +@@ -56,12 +56,12 @@ static bool EnumConvert_EtsToNative(ani_env *env, ani_enum_item enumItem, T &res + ani_string strValue{}; + status = env->EnumItem_GetValue_String(enumItem, &strValue); + if (ANI_OK != status) { +- TAG_LOGE(AAFwkTag::EtsRUNTIME, "EnumItem_GetValue_String failed, status : %{public}d", status); ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "EnumItem_GetValue_String failed, status : %{public}d", status); + return false; + } + return GetStdString(env, strValue, result); + } else { +- TAG_LOGE(AAFwkTag::EtsRUNTIME, "Enum convert failed: type not supported"); ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Enum convert failed: type not supported"); + return false; + } + } +@@ -78,7 +78,7 @@ static bool EnumConvert_NativeToEts(ani_env *env, const char *enumName, const T + ani_enum aniEnum{}; + ani_status status = env->FindEnum(enumName, &aniEnum); + if (ANI_OK != status) { +- TAG_LOGE(AAFwkTag::EtsRUNTIME, "Enum convert FindEnum failed: %{public}s status: %{public}d", enumName, status); ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Enum convert FindEnum failed: %{public}s status: %{public}d", enumName, status); + return false; + } + constexpr int32_t loopMaxNum = 1000; +@@ -86,7 +86,7 @@ static bool EnumConvert_NativeToEts(ani_env *env, const char *enumName, const T + ani_enum_item enumItem{}; + status = env->Enum_GetEnumItemByIndex(aniEnum, index, &enumItem); + if (ANI_OK != status) { +- TAG_LOGE(AAFwkTag::EtsRUNTIME, ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, + "Enum convert Enum_GetEnumItemByIndex failed: enumName:%{public}s index:%{public}d status:%{public}d", + enumName, index, status); + return false; +@@ -98,7 +98,7 @@ static bool EnumConvert_NativeToEts(ani_env *env, const char *enumName, const T + return true; + } + } +- TAG_LOGE(AAFwkTag::EtsRUNTIME, "EnumConvert_NativeToEts failed enumName: %{public}s", enumName); ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "EnumConvert_NativeToEts failed enumName: %{public}s", enumName); + return false; + } + } +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..4c72a344a577c6744bbaabbb1d0bcf6438229369 +--- /dev/null ++++ b/frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets +@@ -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. ++ */ ++ ++namespace AbilityConstant { ++ export interface LaunchParam { ++ launchReason: LaunchReason; ++ launchReasonMessage?: string; ++ lastExitReason: LastExitReason; ++ lastExitMessage: string; ++ } ++ ++ 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 = ''; ++} ++ ++export default AbilityConstant; +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..c4a6565f60e989af6d6f36af74fd1bf0953087b9 +--- /dev/null ++++ b/frameworks/ets/ets/@ohos.app.ability.StartOptions.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 StartOptions { ++ displayId?: number; ++} +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..f53af8d5f3a52ec32b5a2d7f95d02ff0d5803e17 +--- /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 Want from '@ohos.app.ability.Want'; ++import window from '@ohos.window'; ++import { AbilityUtils } from './utils/AbilityUtils'; ++ ++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 isOverride = AbilityUtils.isOverride(derivedClassType, "onDestroyAsync", uiAbilityClassType); ++ if (isOverride) { ++ this.onDestroyAsync().then(() => this.nativeOnDestroyCallback()); ++ return true; ++ } ++ this.onDestroy(); ++ return false; ++ } ++ ++ launchWant: Want = new Want(); ++ lastRequestWant: Want = new Want(); ++ ++ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { ++ } ++ ++ onWindowStageCreate(windowStage: window.WindowStage): void { ++ } ++ ++ onWindowStageDestroy(): 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.Want.ets b/frameworks/ets/ets/@ohos.app.ability.Want.ets +new file mode 100644 +index 0000000000000000000000000000000000000000..c1a0ec876e06dda04f1f9587c7f8e5a831f6fdc1 +--- /dev/null ++++ b/frameworks/ets/ets/@ohos.app.ability.Want.ets +@@ -0,0 +1,232 @@ ++/* ++ * Copyright (c) 2025 Huawei Device Co., Ltd. ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT 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' ++ ++type valueType = NullishType; ++const DOMAIN_ID = 0xD001300; ++const TAG = 'WantSerializeTool'; ++ ++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)) { ++ // 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, 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 RecordSerializeTool.stringify(obj as Object as Record); ++ } catch (err) { ++ hilog.error(DOMAIN_ID, TAG, `RecordSerializeTool.stringify error: ${err}`); ++ return ''; ++ } ++ } ++ ++ public static parseNoThrow(text: string): Record { ++ try { ++ return RecordSerializeTool.parse(text) as Object as Record; ++ } catch (err) { ++ hilog.error(DOMAIN_ID, TAG, `RecordSerializeTool.parse error: ${err}`); ++ 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; ++} +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..721b9d7eed16e8db803946e9c4644a02f9667979 +--- /dev/null ++++ b/frameworks/ets/ets/@ohos.app.ability.wantConstant.ets +@@ -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. ++ */ ++ ++namespace wantConstant { ++ export enum Action { ++ ACTION_HOME = 'ohos.want.action.home', ++ ACTION_DIAL = 'ohos.want.action.dial', ++ ACTION_SEARCH = 'ohos.want.action.search', ++ ACTION_WIRELESS_SETTINGS = 'ohos.settings.wireless', ++ ACTION_MANAGE_APPLICATIONS_SETTINGS = 'ohos.settings.manage.applications', ++ ACTION_APPLICATION_DETAILS_SETTINGS = 'ohos.settings.application.details', ++ ACTION_SET_ALARM = 'ohos.want.action.setAlarm', ++ ACTION_SHOW_ALARMS = 'ohos.want.action.showAlarms', ++ ACTION_SNOOZE_ALARM = 'ohos.want.action.snoozeAlarm', ++ ACTION_DISMISS_ALARM = 'ohos.want.action.dismissAlarm', ++ ACTION_DISMISS_TIMER = 'ohos.want.action.dismissTimer', ++ ACTION_SEND_SMS = 'ohos.want.action.sendSms', ++ ACTION_CHOOSE = 'ohos.want.action.choose', ++ ACTION_IMAGE_CAPTURE = 'ohos.want.action.imageCapture', ++ ACTION_VIDEO_CAPTURE = 'ohos.want.action.videoCapture', ++ ACTION_SELECT = 'ohos.want.action.select', ++ ACTION_SEND_DATA = 'ohos.want.action.sendData', ++ ACTION_SEND_MULTIPLE_DATA = 'ohos.want.action.sendMultipleData', ++ ACTION_SCAN_MEDIA_FILE = 'ohos.want.action.scanMediaFile', ++ ACTION_VIEW_DATA = 'ohos.want.action.viewData', ++ ACTION_EDIT_DATA = 'ohos.want.action.editData', ++ INTENT_PARAMS_INTENT = 'ability.want.params.INTENT', ++ INTENT_PARAMS_TITLE = 'ability.want.params.TITLE', ++ ACTION_FILE_SELECT = 'ohos.action.fileSelect', ++ PARAMS_STREAM = 'ability.params.stream', ++ ACTION_APP_ACCOUNT_OAUTH = 'ohos.account.appAccount.action.oauth' ++ } ++ ++ export enum Flags { ++ FLAG_AUTH_READ_URI_PERMISSION = 0x00000001, ++ FLAG_AUTH_WRITE_URI_PERMISSION = 0x00000002, ++ FLAG_ABILITY_FORWARD_RESULT = 0x00000004, ++ FLAG_ABILITY_CONTINUATION = 0x00000008, ++ FLAG_NOT_OHOS_COMPONENT = 0x00000010, ++ FLAG_ABILITY_FORM_ENABLED = 0x00000020, ++ FLAG_AUTH_PERSISTABLE_URI_PERMISSION = 0x00000040, ++ FLAG_AUTH_PREFIX_URI_PERMISSION = 0x00000080, ++ FLAG_ABILITYSLICE_MULTI_DEVICE = 0x00000100, ++ FLAG_START_FOREGROUND_ABILITY = 0x00000200, ++ FLAG_ABILITY_CONTINUATION_REVERSIBLE = 0x00000400, ++ FLAG_INSTALL_ON_DEMAND = 0x00000800, ++ FLAG_INSTALL_WITH_BACKGROUND_MODE = 0x80000000, ++ FLAG_ABILITY_CLEAR_MISSION = 0x00008000, ++ FLAG_ABILITY_NEW_MISSION = 0x10000000, ++ FLAG_ABILITY_MISSION_TOP = 0x20000000 ++ } ++} ++ ++export default wantConstant; +diff --git a/frameworks/ets/ets/BUILD.gn b/frameworks/ets/ets/BUILD.gn +index 4c90291f2d28ac92432c2eef65f3b3e6cc5dee4d..26efc114b17d9134c8341923f9b935867e0a6ae8 100644 +--- a/frameworks/ets/ets/BUILD.gn ++++ b/frameworks/ets/ets/BUILD.gn +@@ -31,8 +31,110 @@ ohos_prebuilt_etc("ability_runtime_base_context_abc_etc") { + deps = [ ":ability_runtime_base_context_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_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_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_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_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" ] ++} ++ + group("ets_packages") { + deps = [ + ":ability_runtime_base_context_abc_etc", ++ # ":ability_runtime_ui_ability_abc_etc", ++ ":ability_runtime_ability_constant_abc_etc", ++ ":ability_runtime_ability_utils_abc_etc", ++ ":ability_runtime_start_options_abc_etc", ++ ":ability_runtime_want_abc_etc", ++ ":ability_runtime_want_constant_abc_etc", + ] + } +diff --git a/frameworks/ets/ets/utils/AbilityUtils.ets b/frameworks/ets/ets/utils/AbilityUtils.ets +new file mode 100644 +index 0000000000000000000000000000000000000000..573c5d3a20767a270ff0fff7f770c905f7817cd7 +--- /dev/null ++++ b/frameworks/ets/ets/utils/AbilityUtils.ets +@@ -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 hilog from '@ohos.hilog' ++ ++const DOMAIN_ID = 0xD001300; ++const TAG = 'AbilityUtils'; ++const LEVEL = 100; ++ ++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 isOverride(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 true; ++ } ++ } ++ } ++ let baseType = currType.getBaseType(); ++ if (baseType.equals(currType)) { ++ hilog.error(DOMAIN_ID, TAG, `isOverride: baseType equals currType (${currType.getName()})`); ++ return undefined; ++ } ++ level++; ++ if (level >= LEVEL) { ++ hilog.error(DOMAIN_ID, TAG, `isOverride: inheritance level >= ${LEVEL}, abort`); ++ return undefined; ++ } ++ currType = baseType; ++ } catch (err) { ++ hilog.error(DOMAIN_ID, TAG, `isOverride error: ${err}`); ++ return undefined; ++ } ++ } ++ return false; ++ } ++} +diff --git a/frameworks/native/ability/native/BUILD.gn b/frameworks/native/ability/native/BUILD.gn +index 52d727221b7f227bb5bed8c59e3ca21fceff1a4d..d21d8b1129d240a23ee1550d664ecd511bba9e73 100644 +--- a/frameworks/native/ability/native/BUILD.gn ++++ b/frameworks/native/ability/native/BUILD.gn +@@ -155,6 +155,7 @@ ohos_shared_library("abilitykit_utils") { + "${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", ++ "${ability_runtime_innerkits_path}/runtime/include", + "${ability_runtime_innerkits_path}/wantagent/include", + "${ability_runtime_services_path}/abilitymgr/include/utils", + "${ability_runtime_services_path}/abilitymgr/include", +@@ -764,6 +765,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", +@@ -771,6 +773,7 @@ ohos_shared_library("uiabilitykit_native") { + ] + + sources = [ ++ "${ability_runtime_native_path}/ability/native/ability_runtime/ets_ui_ability.cpp", + "${ability_runtime_native_path}/ability/native/ability_runtime/js_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", +@@ -802,6 +805,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", + ] +@@ -822,6 +826,7 @@ ohos_shared_library("uiabilitykit_native") { + "ipc:ipc_napi", + "json:nlohmann_json_static", + "resource_management:global_resmgr", ++ "runtime_core:ani", + "samgr:samgr_proxy", + ] + public_external_deps = [ +diff --git a/frameworks/native/ability/native/ability_loader.cpp b/frameworks/native/ability/native/ability_loader.cpp +index 1c26bd9c57a4b15d9a00a68a3e7fae84e03eb1b1..1a8f740a1c2e2bef0216900f7cb276eea9397081 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()); + 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/ets_ui_ability.cpp b/frameworks/native/ability/native/ability_runtime/ets_ui_ability.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..dac5f017eb87aa6839e24f030f7ed97935305a34 +--- /dev/null ++++ b/frameworks/native/ability/native/ability_runtime/ets_ui_ability.cpp +@@ -0,0 +1,694 @@ ++/* ++ * Copyright (c) 2025 Huawei Device Co., Ltd. ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#include "ets_ui_ability.h" ++ ++#include ++ ++#include "ani_common_want.h" ++#include "app_recovery.h" ++#include "connection_manager.h" ++#include "display_util.h" ++#include "ets_data_struct_converter.h" ++#include "hilog_tag_wrapper.h" ++#include "hitrace_meter.h" ++#include "string_wrapper.h" ++#ifdef SUPPORT_SCREEN ++// #include "ani_window_stage.h" ++#endif ++ ++namespace OHOS { ++namespace AbilityRuntime { ++std::once_flag EtsUIAbility::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 ++#ifdef SUPPORT_SCREEN ++constexpr int32_t BASE_DISPLAY_ID_NUM(10); ++#endif ++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 called"); ++ if (env == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); ++ return; ++ } ++ ani_long destroyCallbackPtr = 0; ++ ani_status status = ANI_ERROR; ++ if ((status = env->Object_GetFieldByName_Long(aniObj, "destroyCallbackPoint", &destroyCallbackPtr)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "Object_GetFieldByName_Long status: %{public}d", status); ++ return; ++ } ++ if (destroyCallbackPtr == 0) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null destroyCallbackPtr"); ++ return; ++ } ++ auto *callbackInfo = reinterpret_cast *>(destroyCallbackPtr); ++ if (callbackInfo == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null callbackInfo"); ++ return; ++ } ++ callbackInfo->Call(); ++ AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo); ++} ++} // namespace ++ ++UIAbility *EtsUIAbility::Create(const std::unique_ptr &runtime) ++{ ++ return new (std::nothrow) EtsUIAbility(static_cast(*runtime)); ++} ++ ++EtsUIAbility::EtsUIAbility(ETSRuntime &etsRuntime) : etsRuntime_(etsRuntime) ++{ ++ TAG_LOGD(AAFwkTag::UIABILITY, "EtsUIAbility called"); ++} ++ ++EtsUIAbility::~EtsUIAbility() ++{ ++ TAG_LOGI(AAFwkTag::UIABILITY, "~EtsUIAbility called"); ++ if (shellContextRef_ && shellContextRef_->aniRef) { ++ auto env = etsRuntime_.GetAniEnv(); ++ if (env != nullptr) { ++ env->GlobalReference_Delete(shellContextRef_->aniRef); ++ } ++ } ++ if (etsWindowStageObj_ && etsWindowStageObj_->aniRef) { ++ auto env = etsRuntime_.GetAniEnv(); ++ if (env != nullptr) { ++ env->GlobalReference_Delete(etsWindowStageObj_->aniRef); ++ } ++ } ++} ++ ++void EtsUIAbility::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); ++ std::string srcPath(abilityInfo->package); ++ if (!abilityInfo->isModuleJson) { ++ 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, "etsAbility srcPath: %{public}s", srcPath.c_str()); ++ } ++ ++ std::string moduleName(abilityInfo->moduleName); ++ moduleName.append("::").append(abilityInfo->name); ++ SetAbilityContext(abilityInfo, record->GetWant(), moduleName, srcPath, application); ++} ++ ++bool EtsUIAbility::BindNativeMethods() ++{ ++ auto env = etsRuntime_.GetAniEnv(); ++ if (env == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); ++ 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 EtsUIAbility::UpdateAbilityObj( ++ std::shared_ptr abilityInfo, const std::string &moduleName, const std::string &srcPath) ++{ ++ std::string key = moduleName + "::" + srcPath; ++ std::unique_ptr moduleObj = nullptr; ++ etsAbilityObj_ = etsRuntime_.LoadModule(moduleName, srcPath, abilityInfo->hapPath, ++ abilityInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE, false, abilityInfo->srcEntrance); ++ if (!BindNativeMethods()) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "BindNativeMethods failed"); ++ return; ++ } ++} ++ ++void EtsUIAbility::SetAbilityContext(std::shared_ptr abilityInfo, std::shared_ptr want, ++ const std::string &moduleName, const std::string &srcPath, const std::shared_ptr &application) ++{ ++ TAG_LOGD(AAFwkTag::UIABILITY, "SetAbilityContext called"); ++ UpdateAbilityObj(abilityInfo, moduleName, srcPath); ++ if (etsAbilityObj_ == nullptr || abilityContext_ == nullptr || want == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null etsAbilityObj_ or abilityContext_ or want"); ++ return; ++ } ++} ++ ++void EtsUIAbility::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 (!etsAbilityObj_) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "not found Ability.js"); ++ return; ++ } ++ auto env = etsRuntime_.GetAniEnv(); ++ if (env == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); ++ return; ++ } ++ ani_object wantObj = OHOS::AppExecFwk::WrapWant(env, want); ++ if (wantObj == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); ++ return; ++ } ++ ani_status status = ANI_ERROR; ++ if ((status = env->Object_SetFieldByName_Ref(etsAbilityObj_->aniObj, "launchWant", wantObj)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "launchWant Object_SetFieldByName_Ref status: %{public}d", status); ++ return; ++ } ++ if ((status = env->Object_SetFieldByName_Ref(etsAbilityObj_->aniObj, "lastRequestWant", wantObj)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "lastRequestWant Object_SetFieldByName_Ref status: %{public}d", status); ++ return; ++ } ++ auto launchParam = GetLaunchParam(); ++ if (InsightIntentExecuteParam::IsInsightIntentExecute(want)) { ++ launchParam.launchReason = AAFwk::LaunchReason::LAUNCHREASON_INSIGHT_INTENT; ++ } ++ ani_object launchParamObj = nullptr; ++ if (!WrapLaunchParam(env, launchParam, launchParamObj)) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "WrapLaunchParam failed"); ++ return; ++ } ++ CallObjectMethod(false, "onCreate", nullptr, wantObj, launchParamObj); ++ TAG_LOGD(AAFwkTag::UIABILITY, "OnStart end"); ++} ++ ++void EtsUIAbility::OnStop() ++{ ++ HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); ++ TAG_LOGD(AAFwkTag::UIABILITY, "OnStop called"); ++ if (abilityContext_) { ++ TAG_LOGD(AAFwkTag::UIABILITY, "set terminating true"); ++ abilityContext_->SetTerminating(true); ++ } ++ UIAbility::OnStop(); ++ ++ CallObjectMethod(false, "onDestroy", nullptr); ++ OnStopCallback(); ++ TAG_LOGD(AAFwkTag::UIABILITY, "OnStop end"); ++} ++ ++void EtsUIAbility::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, "OnStop Begin"); ++ if (abilityContext_) { ++ TAG_LOGD(AAFwkTag::UIABILITY, "set terminating true"); ++ abilityContext_->SetTerminating(true); ++ } ++ UIAbility::OnStop(); ++ 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); ++ ++ auto env = etsRuntime_.GetAniEnv(); ++ if (env == nullptr || etsAbilityObj_ == nullptr) { ++ isAsyncCallback = false; ++ OnStop(); ++ return; ++ } ++ ++ ani_long destroyCallbackPoint = reinterpret_cast(callbackInfo); ++ ani_status status = ++ env->Object_SetFieldByName_Long(etsAbilityObj_->aniObj, "destroyCallbackPoint", destroyCallbackPoint); ++ if (status != ANI_OK) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "Object_SetFieldByName_Long status: %{public}d", status); ++ return; ++ } ++ isAsyncCallback = CallObjectMethod(true, "callOnDestroy", ":Z"); ++ TAG_LOGD(AAFwkTag::UIABILITY, "callOnDestroy isAsyncCallback: %{public}d", isAsyncCallback); ++ if (!isAsyncCallback) { ++ OnStopCallback(); ++ return; ++ } ++ TAG_LOGD(AAFwkTag::UIABILITY, "OnStop end"); ++} ++ ++void EtsUIAbility::OnStopCallback() ++{ ++ bool ret = ConnectionManager::GetInstance().DisconnectCaller(AbilityContext::token_); ++ if (ret) { ++ ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid()); ++ TAG_LOGD(AAFwkTag::UIABILITY, "the service connection is not disconnected"); ++ } ++} ++ ++#ifdef SUPPORT_SCREEN ++void EtsUIAbility::OnSceneCreated() ++{ ++ HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); ++ TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); ++ UIAbility::OnSceneCreated(); ++ auto etsAppWindowStage = CreateAppWindowStage(); ++ if (etsAppWindowStage == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null etsAppWindowStage"); ++ return; ++ } ++ UpdateEtsWindowStage(reinterpret_cast(etsAppWindowStage)); ++ auto env = etsRuntime_.GetAniEnv(); ++ if (env == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); ++ return; ++ } ++ etsWindowStageObj_ = std::make_shared(); ++ etsWindowStageObj_->aniObj = etsAppWindowStage; ++ ani_ref entryObjectRef = nullptr; ++ env->GlobalReference_Create(etsAppWindowStage, &entryObjectRef); ++ etsWindowStageObj_->aniRef = entryObjectRef; ++ CallObjectMethod(false, "onWindowStageCreate", nullptr, etsAppWindowStage); ++ TAG_LOGD(AAFwkTag::UIABILITY, "OnSceneCreated end"); ++} ++ ++void EtsUIAbility::onSceneDestroyed() ++{ ++ TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); ++ UIAbility::onSceneDestroyed(); ++ UpdateEtsWindowStage(nullptr); ++ CallObjectMethod(false, "onWindowStageDestroy", nullptr); ++ if (scene_ != nullptr) { ++ auto window = scene_->GetMainWindow(); ++ if (window != nullptr) { ++ TAG_LOGD(AAFwkTag::UIABILITY, "unRegisterDisplaymovelistener"); ++ window->UnregisterDisplayMoveListener(abilityDisplayMoveListener_); ++ } ++ } ++ TAG_LOGD(AAFwkTag::UIABILITY, "onSceneDestroyed end"); ++} ++ ++void EtsUIAbility::OnForeground(const Want &want) ++{ ++ HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); ++ TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); ++ UIAbility::OnForeground(want); ++ if (CheckIsSilentForeground()) { ++ TAG_LOGD(AAFwkTag::UIABILITY, "silent foreground, do not call 'onForeground'"); ++ return; ++ } ++ CallOnForegroundFunc(want); ++} ++ ++void EtsUIAbility::CallOnForegroundFunc(const Want &want) ++{ ++ auto env = etsRuntime_.GetAniEnv(); ++ if (env == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); ++ return; ++ } ++ if (etsAbilityObj_ == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null etsAbilityObj_"); ++ return; ++ } ++ ani_status status = ANI_ERROR; ++ ani_ref wantRef = OHOS::AppExecFwk::WrapWant(env, want); ++ if (wantRef == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); ++ return; ++ } ++ if ((status = env->Object_SetFieldByName_Ref(etsAbilityObj_->aniObj, "lastRequestWant", wantRef)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "lastRequestWant Object_SetFieldByName_Ref status: %{public}d", status); ++ return; ++ } ++ CallObjectMethod(false, "onForeground", nullptr, wantRef); ++ TAG_LOGD(AAFwkTag::UIABILITY, "CallOnForegroundFunc end"); ++} ++ ++void EtsUIAbility::OnBackground() ++{ ++ HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); ++ TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); ++ CallObjectMethod(false, "onBackground", nullptr); ++ UIAbility::OnBackground(); ++ TAG_LOGD(AAFwkTag::UIABILITY, "OnBackground end"); ++} ++ ++ani_object EtsUIAbility::CreateAppWindowStage() ++{ ++ HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); ++ auto env = etsRuntime_.GetAniEnv(); ++ if (env == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); ++ return nullptr; ++ } ++ auto scene = GetScene(); ++ if (scene == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "scene not found"); ++ return nullptr; ++ } ++ ani_object etsWindowStage = nullptr; ++ // ani_object etsWindowStage = CreateAniWindowStage(env, scene); ++ if (etsWindowStage == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null etsWindowStage"); ++ return nullptr; ++ } ++ return etsWindowStage; ++} ++ ++void EtsUIAbility::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 EtsUIAbility::IsRestorePageStack(const Want &want) ++{ ++ return want.GetBoolParam(SUPPORT_CONTINUE_PAGE_STACK_PROPERTY_NAME, true); ++} ++ ++void EtsUIAbility::RestorePageStack(const Want &want) ++{ ++ if (IsRestorePageStack(want)) { ++ std::string pageStack; ++ GetPageStackFromWant(want, pageStack); ++ // to be done: AniSetUIContent ++ } ++} ++ ++void EtsUIAbility::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); ++ NotifyContinuationResult(want, true); ++ } else if (ShouldRecoverState(want)) { ++ std::string pageStack = abilityRecovery_->GetSavedPageStack(AppExecFwk::StateReason::DEVELOPER_REQUEST); ++ ++ auto mainWindow = scene_->GetMainWindow(); ++ if (mainWindow == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null mainWindow"); ++ } ++ } 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 EtsUIAbility::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_); ++ HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, "scene_->GoForeground"); ++ scene_->GoForeground(UIAbility::sceneFlag_); ++ TAG_LOGD(AAFwkTag::UIABILITY, "DoOnForeground end"); ++} ++ ++void EtsUIAbility::DoOnForegroundForSceneIsNull(const Want &want) ++{ ++ scene_ = std::make_shared(); ++ int32_t displayId = AAFwk::DisplayUtil::GetDefaultDisplayId(); ++ if (setting_ != nullptr) { ++ std::string strDisplayId = setting_->GetProperty(OHOS::AppExecFwk::AbilityStartSetting::WINDOW_DISPLAY_ID_KEY); ++ std::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"); ++ 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 EtsUIAbility::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); ++ NotifyContinuationResult(want, true); ++} ++ ++void EtsUIAbility::UpdateEtsWindowStage(ani_ref windowStage) ++{ ++ TAG_LOGD(AAFwkTag::UIABILITY, "UpdateEtsWindowStage called"); ++ if (shellContextRef_ == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null shellContextRef_"); ++ return; ++ } ++ auto env = etsRuntime_.GetAniEnv(); ++ if (env == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); ++ return; ++ } ++ ani_status status = ANI_ERROR; ++ if (windowStage == nullptr) { ++ ani_ref undefinedRef = nullptr; ++ env->GetUndefined(&undefinedRef); ++ if ((status = env->Object_SetFieldByName_Ref(shellContextRef_->aniObj, "windowStage", undefinedRef)) != ++ ANI_OK) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "Object_SetFieldByName_Ref status: %{public}d", status); ++ return; ++ } ++ return; ++ } ++ if ((status = env->Object_SetFieldByName_Ref(shellContextRef_->aniObj, "windowStage", windowStage)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "Object_SetFieldByName_Ref status: %{public}d", status); ++ return; ++ } ++} ++#endif ++ ++void EtsUIAbility::OnNewWant(const Want &want) ++{ ++ TAG_LOGD(AAFwkTag::UIABILITY, "OnNewWant called"); ++ UIAbility::OnNewWant(want); ++ ++#ifdef SUPPORT_SCREEN ++ if (scene_) { ++ scene_->OnNewWant(want); ++ } ++#endif ++ auto env = etsRuntime_.GetAniEnv(); ++ if (env == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); ++ return; ++ } ++ if (etsAbilityObj_ == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null etsAbilityObj_"); ++ return; ++ } ++ ani_object wantObj = OHOS::AppExecFwk::WrapWant(env, want); ++ if (wantObj == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); ++ return; ++ } ++ ani_status status = env->Object_SetFieldByName_Ref(etsAbilityObj_->aniObj, "lastRequestWant", wantObj); ++ if (status != ANI_OK) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "lastRequestWant Object_SetFieldByName_Ref status: %{public}d", status); ++ return; ++ } ++ auto launchParam = GetLaunchParam(); ++ if (InsightIntentExecuteParam::IsInsightIntentExecute(want)) { ++ launchParam.launchReason = AAFwk::LaunchReason::LAUNCHREASON_INSIGHT_INTENT; ++ } ++ ani_object launchParamObj = nullptr; ++ if (!WrapLaunchParam(env, launchParam, launchParamObj)) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "WrapLaunchParam failed"); ++ return; ++ } ++ std::string methodName = "OnNewWant"; ++ CallObjectMethod(false, "onNewWant", nullptr, wantObj, launchParamObj); ++ TAG_LOGD(AAFwkTag::UIABILITY, "OnNewWant end"); ++} ++ ++void EtsUIAbility::OnAbilityResult(int requestCode, int resultCode, const Want &resultData) ++{ ++ TAG_LOGD(AAFwkTag::UIABILITY, "OnAbilityResult 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, "OnAbilityResult end"); ++} ++ ++bool EtsUIAbility::CallObjectMethod(bool withResult, const char *name, const char *signature, ...) ++{ ++ HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name); ++ TAG_LOGI(AAFwkTag::UIABILITY, "EtsUIAbility call ets, name: %{public}s", name); ++ if (etsAbilityObj_ == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null etsAbilityObj"); ++ return false; ++ } ++ auto env = etsRuntime_.GetAniEnv(); ++ if (env == nullptr) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); ++ return false; ++ } ++ auto obj = etsAbilityObj_->aniObj; ++ auto cls = etsAbilityObj_->aniCls; ++ ++ ani_method method {}; ++ ani_status status = env->Class_FindMethod(cls, name, signature, &method); ++ if (status != ANI_OK) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "Class_FindMethod status: %{public}d", status); ++ env->ResetError(); ++ return false; ++ } ++ 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, "Object_CallMethod_Boolean_V status: %{public}d", status); ++ etsRuntime_.HandleUncaughtError(); ++ return false; ++ } ++ va_end(args); ++ return res; ++ } ++ va_list args; ++ va_start(args, signature); ++ if ((status = env->Object_CallMethod_Void_V(obj, method, args)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::UIABILITY, "Object_CallMethod_Void_V status: %{public}d", status); ++ etsRuntime_.HandleUncaughtError(); ++ return false; ++ } ++ va_end(args); ++ TAG_LOGI(AAFwkTag::UIABILITY, "CallObjectMethod end, name: %{public}s", name); ++ return false; ++} ++} // namespace AbilityRuntime ++} // namespace OHOS +diff --git a/frameworks/native/ability/native/extension_ability_thread.cpp b/frameworks/native/ability/native/extension_ability_thread.cpp +index f72fa0f4c2a0baf0747fcde775a4cb4ec02b887a..6a7633b35194a6998d9e00c87f75cf097d648bd9 100644 +--- a/frameworks/native/ability/native/extension_ability_thread.cpp ++++ b/frameworks/native/ability/native/extension_ability_thread.cpp +@@ -242,7 +242,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/ui_ability_thread.cpp b/frameworks/native/ability/native/ui_ability_thread.cpp +index 18d97dee4d6e877cd0b78765fd3c7611c0128c44..e20643c444024976ee2d7b3daff98bc6a6239792 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/appkit/BUILD.gn b/frameworks/native/appkit/BUILD.gn +index cc0227d2feb3217aad08944d7a2786747cca7d8b..11863d7b8bd13c71b1da20dcdbd81cfc737d3765 100644 +--- a/frameworks/native/appkit/BUILD.gn ++++ b/frameworks/native/appkit/BUILD.gn +@@ -54,6 +54,7 @@ config("appkit_config") { + config("appkit_public_config") { + visibility = [ ":*" ] + include_dirs = [ ++ "${ability_runtime_path}/ets_environment/interfaces/inner_api", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_delegator", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", +@@ -75,6 +76,7 @@ config("appkit_public_config") { + ohos_shared_library("appkit_native") { + include_dirs = [ + "native", ++ "${ability_runtime_path}/ets_environment/interfaces/inner_api", + "${ability_runtime_path}/interfaces/inner_api/error_utils/include", + "${ability_runtime_path}/interfaces/kits/native/appkit", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_bundle_manager_helper", +@@ -166,6 +168,7 @@ 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_path}/ets_environment/frameworks/ets_environment:ets_environment", + "${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", +@@ -208,6 +211,7 @@ ohos_shared_library("appkit_native") { + "napi:ace_napi", + "preferences:native_preferences", + "resource_management:global_resmgr", ++ "runtime_core:ani", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + "storage_service:storage_manager_acl", +diff --git a/frameworks/native/appkit/ability_delegator/ability_delegator_registry.cpp b/frameworks/native/appkit/ability_delegator/ability_delegator_registry.cpp +index 7187c88382eac76eabb85137bf793722dba009b7..7cd73453052ed30544d1f69b093cd2954774d90b 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 + +@@ -39,11 +49,11 @@ std::shared_ptr AbilityDelegatorRegistry::GetArguments() + return abilityDelegatorArgs_; + } + +-void AbilityDelegatorRegistry::RegisterInstance( +- const std::shared_ptr& delegator, const std::shared_ptr& args) ++void AbilityDelegatorRegistry::RegisterInstance(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/app/application_data_manager.cpp b/frameworks/native/appkit/app/application_data_manager.cpp +index 6dfd3a4493efb0896184c21819410ade2e088f11..79c2449ccbffee933660e96284a27195137eed92 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::NotifyETSUnhandledException(const std::string &errMsg) ++{ ++ if (errorObserver_) { ++ errorObserver_->OnUnhandledException(errMsg); ++ return true; ++ } ++ return AppRecovery::GetInstance().TryRecoverApp(StateReason::JS_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::NotifyETSExceptionObject(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::JS_ERROR); ++} + } // namespace AppExecFwk + } // namespace OHOS +diff --git a/frameworks/native/appkit/app/dump_runtime_helper.cpp b/frameworks/native/appkit/app/dump_runtime_helper.cpp +index 945867d5b91541371d8a8ae7eef1c18f45e61cac..052ec4ece780ccf21afa532700a9d370de81a831 100644 +--- a/frameworks/native/appkit/app/dump_runtime_helper.cpp ++++ b/frameworks/native/appkit/app/dump_runtime_helper.cpp +@@ -87,7 +87,7 @@ void DumpRuntimeHelper::SetAppFreezeFilterCallback() + TAG_LOGE(AAFwkTag::APPKIT, "null application"); + return; + } +- auto& runtime = application_->GetRuntime(); ++ auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); + if (runtime == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + return; +@@ -205,7 +205,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::CODE_LANGUAGE_ARKTS_1_0); + if (runtime == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + return; +@@ -235,7 +235,7 @@ void DumpRuntimeHelper::DumpCjHeap(const OHOS::AppExecFwk::CjHeapDumpInfo &info) + TAG_LOGE(AAFwkTag::APPKIT, "null application"); + return; + } +- auto& runtime = application_->GetRuntime(); ++ auto &runtime = application_->GetRuntime(AbilityRuntime::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 5d12647990300e3fc3812a3ac2a8d20658d001e1..10f4b21bdaaff9e6ed0f642ec56288b71427b9ea 100644 +--- a/frameworks/native/appkit/app/main_thread.cpp ++++ b/frameworks/native/appkit/app/main_thread.cpp +@@ -75,6 +75,7 @@ + #include "if_system_ability_manager.h" + #include "iservice_registry.h" + #include "js_runtime.h" ++#include "ets_runtime.h" + #ifdef CJ_FRONTEND + #include "cj_runtime.h" + #endif +@@ -183,6 +184,7 @@ const char* PC_LIBRARY_PATH = "/system/lib64/liblayered_parameters_manager.z.so" + const char* PC_FUNC_INFO = "DetermineResourceType"; + const int32_t TYPE_RESERVE = 1; + const int32_t TYPE_OTHERS = 2; ++std::unique_ptr RUNTIME_NULL = nullptr; + + #if defined(NWEB) + constexpr int32_t PRELOAD_DELAY_TIME = 2000; //millisecond +@@ -1395,6 +1397,59 @@ CJUncaughtExceptionInfo MainThread::CreateCjExceptionInfo(const std::string &bun + return uncaughtExceptionInfo; + } + #endif ++ ++EtsEnv::ETSUncaughtExceptionInfo MainThread::CreateEtsExceptionInfo(const std::string &bundleName, uint32_t versionCode, ++ const std::string &hapPath, std::string &appRunningId, int32_t pid, std::string &processName) ++{ ++ EtsEnv::ETSUncaughtExceptionInfo uncaughtExceptionInfo; ++ wptr weak = this; ++ uncaughtExceptionInfo.uncaughtTask = [weak, bundleName, versionCode, appRunningId = std::move(appRunningId), pid, ++ processName](std::string summary, const EtsEnv::ETSErrorObject 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); ++ if (ApplicationDataManager::GetInstance().NotifyETSUnhandledException(summary) && ++ ApplicationDataManager::GetInstance().NotifyETSExceptionObject(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; ++} + /** + * + * @brief Launch the application. +@@ -1582,6 +1637,9 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con + } else { + #endif + AbilityRuntime::JsRuntime::SetAppLibPath(appLibPaths, isSystemApp); ++ if (IsNeedEtsInit(appInfo)) { ++ AbilityRuntime::ETSRuntime::SetAppLibPath(appLibPaths); ++ } + #ifdef CJ_FRONTEND + } + #endif +@@ -1608,7 +1666,14 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con + options.pkgContextInfoJsonStringMap = pkgContextInfoJsonStringMap; + options.allowArkTsLargeHeap = appInfo.allowArkTsLargeHeap; + #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()); +@@ -1642,12 +1707,12 @@ 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; + } +- ++ auto &runtimeVerOne = GetVerOneRuntime(appInfo, runtimes); + if (appInfo.debug && appLaunchData.GetDebugApp()) { + wptr weak = this; + auto cb = [weak]() { +@@ -1658,7 +1723,9 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con + } + return appThread->NotifyDeviceDisConnect(); + }; +- runtime->SetDeviceDisconnectCallback(cb); ++ if (runtimeVerOne != nullptr) { ++ runtimeVerOne->SetDeviceDisconnectCallback(cb); ++ } + } + auto perfCmd = appLaunchData.GetPerfCmd(); + +@@ -1669,11 +1736,13 @@ 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); +- }); ++ if (runtimeVerOne != nullptr) { ++ runtimeVerOne->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.isStartWithDebug = appLaunchData.GetDebugApp(); + debugOption.processName = processName; +@@ -1683,13 +1752,19 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con + debugOption.isDebugFromLocal = appLaunchData.GetDebugFromLocal(); + debugOption.perfCmd = perfCmd; + debugOption.isDeveloperMode = isDeveloperMode_; +- runtime->SetDebugOption(debugOption); ++ if (runtimeVerOne != nullptr) { ++ runtimeVerOne->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); ++ if (runtimeVerOne != nullptr) { ++ runtimeVerOne->StartProfiler(debugOption); ++ } + } else { +- runtime->StartDebugMode(debugOption); ++ if (runtimeVerOne != nullptr) { ++ runtimeVerOne->StartDebugMode(debugOption); ++ } + } + + std::vector hqfInfos = appInfo.appQuickFix.deployedAppqfInfo.hqfInfos; +@@ -1700,7 +1775,9 @@ 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); ++ if (runtimeVerOne != nullptr) { ++ runtimeVerOne->RegisterQuickFixQueryFunc(modulePaths); ++ } + } + + auto bundleName = appInfo.bundleName; +@@ -1708,18 +1785,37 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con + #ifdef CJ_FRONTEND + if (!isCJApp) { + #endif +- JsEnv::UncaughtExceptionInfo uncaughtExceptionInfo; +- uncaughtExceptionInfo.hapPath = hapPath; +- UncatchableTaskInfo uncatchableTaskInfo = {bundleName, versionCode, appRunningId, pid, processName}; +- InitUncatchableTask(uncaughtExceptionInfo.uncaughtTask, uncatchableTaskInfo); +- (static_cast(*runtime)).RegisterUncaughtExceptionHandler(uncaughtExceptionInfo); +- JsEnv::UncatchableTask uncatchableTask; +- InitUncatchableTask(uncatchableTask, uncatchableTaskInfo, true); +- (static_cast(*runtime)).RegisterUncatchableExceptionHandler(uncatchableTask); ++ for (const auto &runtime : runtimes) { ++ if (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0 && ++ runtime->GetLanguage() == AbilityRuntime::Runtime::Language::JS) { ++ JsEnv::UncaughtExceptionInfo uncaughtExceptionInfo; ++ uncaughtExceptionInfo.hapPath = hapPath; ++ UncatchableTaskInfo uncatchableTaskInfo = {bundleName, versionCode, appRunningId, pid, processName}; ++ InitUncatchableTask(uncaughtExceptionInfo.uncaughtTask, uncatchableTaskInfo); ++ (static_cast(*runtime)).RegisterUncaughtExceptionHandler( ++ uncaughtExceptionInfo); ++ JsEnv::UncatchableTask uncatchableTask; ++ InitUncatchableTask(uncatchableTask, uncatchableTaskInfo, true); ++ (static_cast(*runtime)).RegisterUncatchableExceptionHandler( ++ uncatchableTask); ++ } ++ if ((appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2 || ++ appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_HYBRID) && ++ runtime->GetLanguage() == AbilityRuntime::Runtime::Language::ETS) { ++ auto expectionInfo = ++ CreateEtsExceptionInfo(bundleName, versionCode, hapPath, appRunningId, pid, processName); ++ runtime->RegisterUncaughtExceptionHandler((void*)&expectionInfo); ++ } ++ } + #ifdef CJ_FRONTEND + } else { +- auto expectionInfo = CreateCjExceptionInfo(bundleName, versionCode, hapPath); +- (static_cast(*runtime)).RegisterUncaughtExceptionHandler(expectionInfo); ++ for (const auto &runtime : runtimes) { ++ if (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0 && ++ runtime->GetLanguage() == AbilityRuntime::Runtime::Language::CJ) { ++ auto expectionInfo = CreateCjExceptionInfo(bundleName, versionCode, hapPath); ++ runtime->RegisterUncaughtExceptionHandler((void*)&expectionInfo); ++ } ++ } + } + #endif + wptr weak = this; +@@ -1733,14 +1829,21 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con + }; + applicationContext->RegisterProcessSecurityExit(callback); + +- application_->SetRuntime(std::move(runtime)); +- ++ for (auto &runtime : runtimes) { ++ application_->AddRuntime(std::move(runtime)); ++ } + 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::CODE_LANGUAGE_ARKTS_1_2) { ++ return AbilityRuntime::UIAbility::Create(app->GetRuntime( ++ AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2)); ++ } else { ++ return AbilityRuntime::UIAbility::Create(app->GetRuntime( ++ AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0)); ++ } + } + TAG_LOGE(AAFwkTag::APPKIT, "failed"); + return nullptr; +@@ -1748,33 +1851,18 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con + #ifdef CJ_FRONTEND + if (!isCJApp) { + #endif +- auto& jsEngine = (static_cast(*application_->GetRuntime())).GetNativeEngine(); + if (application_ != nullptr) { +- LoadAllExtensions(jsEngine); ++ TAG_LOGD(AAFwkTag::APPKIT, "LoadAllExtensions lan:%{public}s", appInfo.codeLanguage.c_str()); ++ LoadAllExtensions(); + } +- +- 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 (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) { ++ auto &runtime = application_->GetRuntime(appInfo.codeLanguage); + 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); +- +- auto helper = std::make_shared(application_); +- helper->SetAppFreezeFilterCallback(); ++ SetJsIdleCallback(wpApplication, runtime); ++ } + #ifdef CJ_FRONTEND + } else { + LoadAllExtensions(); +@@ -1784,7 +1872,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; + } +@@ -1876,7 +1965,9 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con + } + #endif + if (appLaunchData.IsNeedPreloadModule()) { +- PreloadModule(entryHapModuleInfo, application_->GetRuntime()); ++ for (auto &runtime : application_->GetRuntime()) { ++ PreloadModule(entryHapModuleInfo, runtime); ++ } + } + } + +@@ -1911,7 +2002,8 @@ void MainThread::InitUncatchableTask(JsEnv::UncatchableTask &uncatchableTask, co + EVENT_KEY_PROCESS_RSS_MEMINFO, std::to_string(DumpProcessHelper::GetProcRssMemInfo())); + + ErrorObject appExecErrorObj = { errorObject.name, errorObject.message, errorObject.stack}; +- auto napiEnv = (static_cast(*appThread->application_->GetRuntime())).GetNapiEnv(); ++ auto napiEnv = (static_cast( ++ *appThread->application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0))).GetNapiEnv(); + if (!isUncatchable && NapiErrorManager::GetInstance()->NotifyUncaughtException(napiEnv, summary, + appExecErrorObj.name, appExecErrorObj.message, appExecErrorObj.stack)) { + return; +@@ -2054,7 +2146,7 @@ void MainThread::ProcessMainAbility(const AbilityInfo &info, const std::unique_p + } + + void MainThread::PreloadModule(const AppExecFwk::HapModuleInfo &entryHapModuleInfo, +- const std::unique_ptr& runtime) ++ const std::unique_ptr &runtime) + { + TAG_LOGI(AAFwkTag::APPKIT, "preload module %{public}s", entryHapModuleInfo.moduleName.c_str()); + auto callback = []() {}; +@@ -2204,7 +2296,7 @@ void MainThread::HandleUpdatePluginInfoInstalled(const ApplicationInfo &pluginAp + TAG_LOGE(AAFwkTag::APPKIT, "null application_"); + return; + } +- auto& runtime = application_->GetRuntime(); ++ auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); + if (runtime == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + return; +@@ -2254,7 +2346,7 @@ void MainThread::HandleUpdateApplicationInfoInstalled(const ApplicationInfo& app + } + application_->UpdateApplicationInfoInstalled(appInfo); + +- auto& runtime = application_->GetRuntime(); ++ auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); + if (runtime == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + return; +@@ -2342,10 +2434,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; +@@ -2355,7 +2448,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) { +@@ -2365,12 +2459,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::CODE_LANGUAGE_ARKTS_1_0) { ++ TAG_LOGI(AAFwkTag::DELEGATOR, "create 1.0 testrunner"); ++ auto &runtime = application_->GetRuntime(AbilityRuntime::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, runtime->GetLanguage()); ++ delegator->SetApiTargetVersion(targetVersion); ++ delegator->Prepare(); ++ } ++ ++ if (applicationCodeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2) { ++ TAG_LOGI(AAFwkTag::DELEGATOR, "create 1.2 testrunner"); ++ auto &runtime = application_->GetRuntime(AbilityRuntime::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, runtime->GetLanguage()); ++ delegator->SetApiTargetVersion(targetVersion); ++ delegator->Prepare(); ++ } + } else { // FA model + TAG_LOGD(AAFwkTag::APPKIT, "FA model"); + AbilityRuntime::Runtime::Options options; +@@ -2400,7 +2509,7 @@ 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, AbilityRuntime::Runtime::Language::JS); + delegator->SetApiTargetVersion(targetVersion); + delegator->Prepare(); + } +@@ -2461,7 +2570,7 @@ void MainThread::HandleLaunchAbility(const std::shared_ptr & + TAG_LOGE(AAFwkTag::APPKIT, "null application"); + return; + } +- auto& runtime = application->GetRuntime(); ++ auto &runtime = application->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); + appThread->UpdateRuntimeModuleChecker(runtime); + #ifdef APP_ABILITY_USE_TWO_RUNNER + AbilityThread::AbilityThreadMain(application, abilityRecord, stageContext); +@@ -2488,7 +2597,7 @@ void MainThread::HandleLaunchAbility(const std::shared_ptr & + return; + } + SetProcessExtensionType(abilityRecord); +- auto& runtime = application_->GetRuntime(); ++ auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); + UpdateRuntimeModuleChecker(runtime); + #ifdef APP_ABILITY_USE_TWO_RUNNER + AbilityThread::AbilityThreadMain(application_, abilityRecord, stageContext); +@@ -2851,7 +2960,7 @@ void MainThread::HandleDumpHeapPrepare() + TAG_LOGE(AAFwkTag::APPKIT, "null app"); + return; + } +- auto &runtime = app->GetRuntime(); ++ auto &runtime = app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); + if (runtime == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + return; +@@ -2871,7 +2980,7 @@ void MainThread::HandleDumpHeap(bool isPrivate) + TAG_LOGE(AAFwkTag::APPKIT, "null app"); + return; + } +- auto &runtime = app->GetRuntime(); ++ auto &runtime = app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); + if (runtime == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + return; +@@ -2924,11 +3033,11 @@ void MainThread::DestroyHeapProfiler() + + auto task = [] { + auto app = applicationForDump_.lock(); +- if (app == nullptr || app->GetRuntime() == nullptr) { ++ if (app == nullptr || app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + return; + } +- app->GetRuntime()->DestroyHeapProfiler(); ++ app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0)->DestroyHeapProfiler(); + }; + mainHandler_->PostTask(task, "MainThread:DestroyHeapProfiler"); + } +@@ -2943,11 +3052,11 @@ void MainThread::ForceFullGC() + + auto task = [] { + auto app = applicationForDump_.lock(); +- if (app == nullptr || app->GetRuntime() == nullptr) { ++ if (app == nullptr || app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + return; + } +- app->GetRuntime()->ForceFullGC(); ++ app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0)->ForceFullGC(); + }; + mainHandler_->PostTask(task, "MainThread:ForceFullGC"); + } +@@ -3675,7 +3784,7 @@ int32_t MainThread::ChangeAppGcState(int32_t state, uint64_t tid) + TAG_LOGE(AAFwkTag::APPKIT, "null application_"); + return ERR_INVALID_VALUE; + } +- auto &runtime = application_->GetRuntime(); ++ auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); + if (runtime == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + return ERR_INVALID_VALUE; +@@ -3727,7 +3836,7 @@ int32_t MainThread::OnAttachLocalDebug(bool isDebugFromLocal) + TAG_LOGE(AAFwkTag::APPKIT, "null application_"); + return ERR_INVALID_VALUE; + } +- auto &runtime = application_->GetRuntime(); ++ auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); + if (runtime == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + return ERR_INVALID_VALUE; +@@ -3949,7 +4058,7 @@ void MainThread::HandleCacheProcess() + + // force gc + if (application_ != nullptr) { +- auto &runtime = application_->GetRuntime(); ++ auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); + if (runtime == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); + return; +@@ -3958,6 +4067,38 @@ void MainThread::HandleCacheProcess() + } + } + ++void MainThread::AddRuntimeLang(ApplicationInfo &appInfo, AbilityRuntime::Runtime::Options &options) ++{ ++ if (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2) { ++ options.langs.emplace(AbilityRuntime::Runtime::Language::ETS, true); ++ } else if (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_HYBRID) { ++ options.langs.emplace(AbilityRuntime::Runtime::Language::ETS, true); ++ } else { ++ options.langs.emplace(AbilityRuntime::Runtime::Language::JS, true); ++ } ++} ++ ++bool MainThread::IsNeedEtsInit(const ApplicationInfo &appInfo) ++{ ++ return appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2 || ++ appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_HYBRID; ++} ++ ++const std::unique_ptr &MainThread::GetVerOneRuntime( ++ const ApplicationInfo &appInfo, const std::vector> &runtimes) ++{ ++ if (appInfo.codeLanguage != AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) { ++ return RUNTIME_NULL; ++ } ++ for (auto &runtime : runtimes) { ++ if (runtime->GetLanguage() == AbilityRuntime::Runtime::Language::JS || ++ runtime->GetLanguage() == AbilityRuntime::Runtime::Language::CJ) { ++ return runtime; ++ } ++ } ++ return RUNTIME_NULL; ++} ++ + void MainThread::HandleConfigByPlugin(Configuration &config, BundleInfo &bundleInfo) + { + if (PC_LIBRARY_PATH == nullptr) { +@@ -3980,5 +4121,33 @@ void MainThread::HandleConfigByPlugin(Configuration &config, BundleInfo &bundleI + + entry(config, bundleInfo); + } ++ ++void MainThread::SetJsIdleCallback(const std::weak_ptr &wpApplication, ++ const std::unique_ptr &runtime) ++{ ++ 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::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(); ++ ++ IdleNotifyStatusCallback cb = idleTime_->GetIdleNotifyFunc(); ++ jsEngine.NotifyIdleStatusControl(cb); ++ ++ auto helper = std::make_shared(application_); ++ helper->SetAppFreezeFilterCallback(); ++} + } // namespace AppExecFwk + } // namespace OHOS +diff --git a/frameworks/native/appkit/app/ohos_application.cpp b/frameworks/native/appkit/app/ohos_application.cpp +index 45831ff8001811c05b876e26fa10344ea10802b4..41713dde52b85c112228af397a2d7c92e0cf22f6 100644 +--- a/frameworks/native/appkit/app/ohos_application.cpp ++++ b/frameworks/native/appkit/app/ohos_application.cpp +@@ -37,6 +37,7 @@ + #include "iservice_registry.h" + #include "runtime.h" + #include "js_runtime.h" ++#include "ets_runtime.h" + #include "startup_manager.h" + #include "system_ability_definition.h" + #include "syspara/parameter.h" +@@ -51,6 +52,7 @@ namespace OHOS { + namespace AppExecFwk { + namespace { + constexpr const char* PERSIST_DARKMODE_KEY = "persist.ace.darkmode"; ++ std::unique_ptr RUNTIME_NULL = nullptr; + } + REGISTER_APPLICATION(OHOSApplication, OHOSApplication) + constexpr int32_t APP_ENVIRONMENT_OVERWRITE = 1; +@@ -77,11 +79,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 +102,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 +156,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_.emplace_back(std::move(runtime)); + } + + /** +@@ -369,6 +376,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) +@@ -413,8 +439,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); +@@ -425,7 +453,8 @@ std::shared_ptr OHOSApplication::AddAbilityStage( + stageContext->SetResourceManager(rm); + } + +- abilityStage = AbilityRuntime::AbilityStage::Create(runtime_, *hapModuleInfo); ++ auto &runtimeStage = GetRuntime(hapModuleInfo->codeLanguage); ++ abilityStage = AbilityRuntime::AbilityStage::Create(runtimeStage, *hapModuleInfo); + if (abilityStage == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null abilityStage"); + return nullptr; +@@ -608,8 +637,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; + } + +@@ -633,7 +662,8 @@ bool OHOSApplication::AddAbilityStage( + stageContext->SetResourceManager(rm); + } + +- auto abilityStage = AbilityRuntime::AbilityStage::Create(runtime_, *moduleInfo); ++ auto &runtime = GetRuntime(moduleInfo->codeLanguage); ++ auto abilityStage = AbilityRuntime::AbilityStage::Create(runtime, *moduleInfo); + if (abilityStage == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null abilityStage"); + return false; +@@ -688,9 +718,9 @@ std::shared_ptr OHOSApplication::GetAppContext() const + return abilityRuntimeContext_; + } + +-const std::unique_ptr& OHOSApplication::GetRuntime() const ++const std::vector> &OHOSApplication::GetRuntime() const + { +- return runtime_; ++ return runtimes_; + } + + void OHOSApplication::SetConfiguration(const Configuration &config) +@@ -815,32 +845,60 @@ 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"); ++ 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"); ++ 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) +@@ -1080,5 +1138,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 RUNTIME_NULL; ++} ++ ++void OHOSApplication::SetCJApplication(bool isCJApplication) ++{ ++ isCJApplication_ = isCJApplication; ++} ++ ++AbilityRuntime::Runtime::Language OHOSApplication::ConvertLangToCode(const std::string &language) const ++{ ++ if (language == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) { ++ if (isCJApplication_) { ++ return AbilityRuntime::Runtime::Language::CJ; ++ } else { ++ return AbilityRuntime::Runtime::Language::JS; ++ } ++ } else if (language == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2) { ++ return AbilityRuntime::Runtime::Language::ETS; ++ } else { ++ return AbilityRuntime::Runtime::Language::UNKNOWN; ++ } ++} + } // namespace AppExecFwk + } // namespace OHOS +diff --git a/frameworks/native/runtime/cj_runtime.cpp b/frameworks/native/runtime/cj_runtime.cpp +index ecf1697834d004eebefd5e2e51dbd930083283d0..5ac8d635e22ddc1bb1fa8bc735bfe17371fec614 100644 +--- a/frameworks/native/runtime/cj_runtime.cpp ++++ b/frameworks/native/runtime/cj_runtime.cpp +@@ -118,16 +118,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. +@@ -368,4 +358,14 @@ void CJRuntime::ForceFullGC(uint32_t tid) + return; + } + cjEnv->forceFullGC(); ++} ++ ++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/ets_data_struct_converter.cpp b/frameworks/native/runtime/ets_data_struct_converter.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..a3bf58cd7a6989203e3b92ca8413e4400d52f03a +--- /dev/null ++++ b/frameworks/native/runtime/ets_data_struct_converter.cpp +@@ -0,0 +1,106 @@ ++/* ++ * Copyright (c) 2025 Huawei Device Co., Ltd. ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT 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_data_struct_converter.h" ++ ++#include "ani_enum_convert.h" ++#include "hilog_tag_wrapper.h" ++ ++namespace OHOS { ++namespace AbilityRuntime { ++namespace { ++constexpr const char *CLASSNAME_LAUNCHPARAM = "L@ohos/app/ability/AbilityConstant/LaunchParamImpl"; ++constexpr const char *CLASSNAME_LAUNCHREASON = "L@ohos/app/ability/AbilityConstant/AbilityConstant/LaunchReason;"; ++constexpr const char *CLASSNAME_LAST_EXITREASION = "L@ohos/app/ability/AbilityConstant/AbilityConstant/LastExitReason"; ++ ++ani_string GetAniString(ani_env *env, const std::string &str) ++{ ++ if (env == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env"); ++ return nullptr; ++ } ++ ani_string aniStr = nullptr; ++ ani_status status = env->String_NewUTF8(str.c_str(), str.size(), &aniStr); ++ if (status != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to getAniString, status : %{public}d", status); ++ return nullptr; ++ } ++ return aniStr; ++} ++ ++bool WrapLaunchParamInner(ani_env *env, const AAFwk::LaunchParam &launchParam, ani_object &object) ++{ ++ ani_status status = ANI_ERROR; ++ ani_enum_item launchReasonItem {}; ++ OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts( ++ env, CLASSNAME_LAUNCHREASON, launchParam.launchReason, launchReasonItem); ++ if ((status = env->Object_SetPropertyByName_Ref(object, "launchReason", launchReasonItem)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to set launchReason"); ++ return false; ++ } ++ ++ ani_enum_item lastExitReasonItem {}; ++ OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts( ++ env, CLASSNAME_LAST_EXITREASION, launchParam.lastExitReason, lastExitReasonItem); ++ if ((status = env->Object_SetPropertyByName_Ref(object, "lastExitReason", lastExitReasonItem)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to set lastExitReason"); ++ return false; ++ } ++ return true; ++} ++} // namespace ++ ++bool WrapLaunchParam(ani_env *env, const AAFwk::LaunchParam &launchParam, ani_object &object) ++{ ++ ani_method method = nullptr; ++ ani_status status = ANI_ERROR; ++ ani_class cls = nullptr; ++ if (env == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env"); ++ return false; ++ } ++ if ((status = env->FindClass(CLASSNAME_LAUNCHPARAM, &cls)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to find lanchParam Class, status : %{public}d", status); ++ return false; ++ } ++ if (cls == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null cls"); ++ return false; ++ } ++ if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to find method, status : %{public}d", status); ++ return false; ++ } ++ if (method == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null method"); ++ return false; ++ } ++ if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to create object, status : %{public}d", status); ++ return false; ++ } ++ if (object == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null object"); ++ return false; ++ } ++ if ((status = env->Object_SetPropertyByName_Ref( ++ object, "lastExitMessage", GetAniString(env, launchParam.lastExitMessage))) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to set lastExitMessage"); ++ return false; ++ } ++ return WrapLaunchParamInner(env, launchParam, object); ++} ++} // namespace AbilityRuntime ++} // namespace OHOS +diff --git a/frameworks/native/runtime/ets_runtime.cpp b/frameworks/native/runtime/ets_runtime.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..f851bf77ffbed3214af96818595da9d936a4d1c7 +--- /dev/null ++++ b/frameworks/native/runtime/ets_runtime.cpp +@@ -0,0 +1,481 @@ ++/* ++ * Copyright (c) 2025 Huawei Device Co., Ltd. ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT 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_runtime.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "accesstoken_kit.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 "module_checker_delegate.h" ++#include "parameters.h" ++#include "source_map.h" ++#include "source_map_operator.h" ++#include "ets_environment.h" ++#include "syscap_ts.h" ++#include "system_ability_definition.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 ETS_RT_PATH = SANDBOX_LIB_PATH; ++const std::string ETS_SYSLIB_PATH = ++ "/system/lib64:/system/lib64/platformsdk:/system/lib64/module:/system/lib64/ndk"; ++#else ++const std::string SANDBOX_LIB_PATH = "/system/lib"; ++const std::string ETS_RT_PATH = SANDBOX_LIB_PATH; ++const std::string ETS_SYSLIB_PATH = ++ "/system/lib:/system/lib/platformsdk:/system/lib/module:/system/lib/ndk"; ++#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"; // will deprecated ++constexpr char ENTRY_PATH_MAP_KEY[] = "entryPath"; // will deprecated ++constexpr char DEFAULT_ENTRY_ABILITY_CLASS[] = "entry/src/main/ets/entryability/EntryAbility/EntryAbility"; ++constexpr int32_t DOT_START_LEN = 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::ETSRUNTIME, "no entrypath file"); ++ return false; ++ } ++ nlohmann::json filePathsJson; ++ inFile >> filePathsJson; ++ if (filePathsJson.is_discarded()) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "json discarded error"); ++ inFile.close(); ++ return false; ++ } ++ ++ if (filePathsJson.is_null() || filePathsJson.empty()) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "invalid json"); ++ inFile.close(); ++ return false; ++ } ++ ++ if (!filePathsJson.contains(ENTRY_PATH_MAP_KEY)) { ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "no entrypath key"); ++ return false; ++ } ++ const auto &entryPathMap = filePathsJson[ENTRY_PATH_MAP_KEY]; ++ if (!entryPathMap.is_object()) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "val is not string, key: %{public}s", key.c_str()); ++ continue; ++ } ++ std::string val = entryPath.value(); ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "not found srcEntry: %{public}s", srcEntry.c_str()); ++ return DEFAULT_ENTRY_ABILITY_CLASS; ++ } ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "srcEntry as class: %{public}s", srcEntry.c_str()); ++ return HandleOhmUrlSrcEntry(srcEntry); ++ } ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "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() < DOT_START_LEN) { ++ return false; ++ } ++ std::string prefix = str.substr(0, DOT_START_LEN); ++ 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 ETSRuntime::appLibPaths_; ++ ++std::unique_ptr ETSRuntime::Create(const Options &options, Runtime *jsRuntime) ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "Create called"); ++ if (jsRuntime == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null jsRuntime"); ++ return std::unique_ptr(); ++ } ++ std::unique_ptr instance; ++ if (!options.preload) { ++ auto preloadedInstance = Runtime::GetPreloaded(); ++#ifdef SUPPORT_SCREEN ++ // reload ace if compatible mode changes ++ if (Ace::AceForwardCompatibility::PipelineChanged() && preloadedInstance) { ++ preloadedInstance.reset(); ++ } ++#endif ++ if (preloadedInstance && preloadedInstance->GetLanguage() == Runtime::Language::ETS) { ++ instance.reset(static_cast(preloadedInstance.release())); ++ } else { ++ instance = std::make_unique(); ++ } ++ } else { ++ instance = std::make_unique(); ++ } ++ ++ if (!instance->Initialize(options, jsRuntime)) { ++ return std::unique_ptr(); ++ } ++ EntryPathManager::GetInstance().Init(); ++ ++ return instance; ++} ++ ++void ETSRuntime::SetAppLibPath(const AppLibPathMap &appLibPaths) ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "SetAppLibPath called"); ++ EtsEnv::ETSEnvironment::InitETSSDKNS(ETS_RT_PATH); ++ EtsEnv::ETSEnvironment::InitETSSysNS(ETS_SYSLIB_PATH); ++} ++ ++bool ETSRuntime::Initialize(const Options &options, Runtime *jsRuntime) ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "Initialize called"); ++ if (options.lang != GetLanguage()) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "language mismatch"); ++ return false; ++ } ++ ++ if (!CreateEtsEnv(options, jsRuntime)) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Create etsEnv failed"); ++ return false; ++ } ++ ++ apiTargetVersion_ = options.apiTargetVersion; ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "Initialize: %{public}d", apiTargetVersion_); ++ ++ return true; ++} ++ ++void ETSRuntime::RegisterUncaughtExceptionHandler(void *uncaughtExceptionInfo) ++{ ++ if (etsEnv_ == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null etsEnv_"); ++ return; ++ } ++ ++ if (uncaughtExceptionInfo == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null uncaughtExceptionInfo"); ++ return; ++ } ++ ++ auto handle = static_cast(uncaughtExceptionInfo); ++ if (handle != nullptr) { ++ etsEnv_->RegisterUncaughtExceptionHandler(*handle); ++ } ++} ++ ++ETSRuntime::~ETSRuntime() ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "~ETSRuntime called"); ++ Deinitialize(); ++} ++ ++void ETSRuntime::Deinitialize() ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "Deinitialize called"); ++} ++ ++bool ETSRuntime::CreateEtsEnv(const Options &options, Runtime *jsRuntime) ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "CreateEtsEnv called"); ++ etsEnv_ = std::make_shared(); ++ std::vector aniOptions; ++ 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::ETSRUNTIME, "aotFileString: %{public}s", aotFileString.c_str()); ++ aniOptions.push_back(ani_option { "--ext:--enable-an", nullptr }); ++ } ++ ++ if (!etsEnv_->Initialize(static_cast(jsRuntime)->GetNapiEnv(), aniOptions)) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Init EtsEnv failed"); ++ return false; ++ } ++ ++ return true; ++} ++ ++ani_env *ETSRuntime::GetAniEnv() ++{ ++ if (etsEnv_ == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null etsEnv_"); ++ return nullptr; ++ } ++ return etsEnv_->GetAniEnv(); ++} ++ ++void ETSRuntime::PreloadModule(const std::string &moduleName, const std::string &hapPath, ++ bool isEsMode, bool useCommonTrunk) ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "moduleName: %{public}s", moduleName.c_str()); ++ ani_env *aniEnv = GetAniEnv(); ++ if (aniEnv == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetAniEnv failed"); ++ return; ++ } ++ ++ ani_class cls = nullptr; ++ ani_object object = nullptr; ++ if (!LoadAbcLinker(aniEnv, moduleName, cls, object)) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "LoadAbcLinker failed"); ++ return; ++ } ++ return; ++} ++ ++std::unique_ptr ETSRuntime::LoadModule(const std::string &moduleName, ++ const std::string &modulePath, const std::string &hapPath, bool esmodule, bool useCommonChunk, ++ const std::string &srcEntrance) ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "Load module(%{public}s, %{public}s, %{public}s, %{public}s)", ++ moduleName.c_str(), modulePath.c_str(), hapPath.c_str(), srcEntrance.c_str()); ++ ++ std::string path = moduleName; ++ auto pos = path.find("::"); ++ if (pos != std::string::npos) { ++ path.erase(pos, path.size() - pos); ++ moduleName_ = path; ++ } ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "make module file path: %{public}s failed", modulePath.c_str()); ++ return nullptr; ++ } ++ } ++ std::unique_ptr etsNativeReference = LoadEtsModule(moduleName, fileName, hapPath, srcEntrance); ++ return etsNativeReference; ++} ++ ++bool ETSRuntime::LoadAbcLinker(ani_env *env, const std::string &moduleName, ani_class &abcCls, ani_object &abcObj) ++{ ++ if (env == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env"); ++ return false; ++ } ++ ani_class stringCls = nullptr; ++ if (env->FindClass("Lstd/core/String;", &stringCls) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "FindClass Lstd/core/String Failed"); ++ return false; ++ } ++ std::string modulePath = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_PATH; ++ ani_string aniStr; ++ if (env->String_NewUTF8(modulePath.c_str(), modulePath.size(), &aniStr) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "String_NewUTF8 modulePath Failed"); ++ return false; ++ } ++ ani_ref undefinedRef; ++ if (env->GetUndefined(&undefinedRef) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetUndefined failed"); ++ return false; ++ } ++ ani_array_ref refArray; ++ if (env->Array_New_Ref(stringCls, 1, undefinedRef, &refArray) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Array_New_Ref Failed"); ++ return false; ++ } ++ if (env->Array_Set_Ref(refArray, 0, aniStr) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Array_Set_Ref Failed"); ++ return false; ++ } ++ if (env->FindClass("Lstd/core/AbcRuntimeLinker;", &abcCls) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "FindClass AbcRuntimeLinker failed"); ++ return false; ++ } ++ ani_method method = nullptr; ++ if (env->Class_FindMethod(abcCls, "", "Lstd/core/RuntimeLinker;[Lstd/core/String;:V", &method) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Class_FindMethod ctor failed"); ++ return false; ++ } ++ env->ResetError(); ++ if (env->Object_New(abcCls, method, &abcObj, undefinedRef, refArray) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Object_New AbcRuntimeLinker failed"); ++ HandleUncaughtError(); ++ return false; ++ } ++ return true; ++} ++ ++std::unique_ptr ETSRuntime::LoadEtsModule(const std::string &moduleName, ++ const std::string &fileName, const std::string &hapPath, const std::string &srcEntrance) ++{ ++ auto etsNativeReference = std::make_unique(); ++ ani_env *aniEnv = GetAniEnv(); ++ if (aniEnv == nullptr) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetAniEnv failed"); ++ return std::make_unique(); ++ } ++ ani_class cls = nullptr; ++ ani_object object = nullptr; ++ if (!LoadAbcLinker(aniEnv, moduleName_, cls, object)) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "LoadAbcLinker failed"); ++ return std::make_unique(); ++ } ++ ani_method loadClassMethod = nullptr; ++ if (aniEnv->Class_FindMethod(cls, "loadClass", "Lstd/core/String;Z:Lstd/core/Class;", &loadClassMethod) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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; ++ if (aniEnv->Object_CallMethod_Ref(object, loadClassMethod, &entryClassRef, entryClassStr, false) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "Class_FindMethod ctor failed"); ++ return std::make_unique(); ++ } ++ ani_object entryObject = nullptr; ++ if (aniEnv->Object_New(entryClass, entryMethod, &entryObject) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Object_New AbcRuntimeLinker failed"); ++ return std::make_unique(); ++ } ++ ani_ref entryObjectRef = nullptr; ++ if (aniEnv->GlobalReference_Create(entryObject, &entryObjectRef) != ANI_OK) { ++ TAG_LOGE(AAFwkTag::ETSRUNTIME, "GlobalReference_Create failed"); ++ return std::make_unique(); ++ } ++ etsNativeReference->aniCls = entryClass; ++ etsNativeReference->aniObj = entryObject; ++ etsNativeReference->aniRef = entryObjectRef; ++ return etsNativeReference; ++} ++ ++void ETSRuntime::HandleUncaughtError() ++{ ++ TAG_LOGD(AAFwkTag::ETSRUNTIME, "HandleUncaughtError called"); ++ if (etsEnv_ == nullptr) { ++ return; ++ } ++ etsEnv_->HandleUncaughtError(); ++} ++} // namespace AbilityRuntime ++} // namespace OHOS +\ No newline at end of file +diff --git a/frameworks/native/runtime/js_runtime.cpp b/frameworks/native/runtime/js_runtime.cpp +index 4b04f031c12904c7d98a7d13b749f99b2dd9f16b..cb7c9a217e7b2f69311463c804193995c8ffdecf 100644 +--- a/frameworks/native/runtime/js_runtime.cpp ++++ b/frameworks/native/runtime/js_runtime.cpp +@@ -1765,5 +1765,12 @@ 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/runtime.cpp b/frameworks/native/runtime/runtime.cpp +index 26362dd0dbbe6724c623e7a42581ceee0bdb3892..0beb1b4395345e2673aecb38702be5b990642801 100644 +--- a/frameworks/native/runtime/runtime.cpp ++++ b/frameworks/native/runtime/runtime.cpp +@@ -19,6 +19,7 @@ + #include "cj_runtime.h" + #endif + #include "js_runtime.h" ++#include "ets_runtime.h" + + namespace OHOS { + namespace AbilityRuntime { +@@ -26,8 +27,45 @@ namespace { + std::unique_ptr g_preloadedInstance; + } + +-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.emplace_back(JsRuntime::Create(options)); ++ break; ++#ifdef CJ_FRONTEND ++ case Runtime::Language::CJ: ++ options.lang = Runtime::Language::CJ; ++ runtimes.emplace_back(CJRuntime::Create(options)); ++ break; ++#endif ++ case Runtime::Language::ETS: { ++ options.lang = Runtime::Language::JS; ++ auto &jsRuntime = runtimes.emplace_back(JsRuntime::Create(options)); ++ options.lang = Runtime::Language::ETS; ++ runtimes.emplace_back(ETSRuntime::Create(options, ++ static_cast(jsRuntime.get()))); ++ break; ++ } ++ default: ++ runtimes.emplace_back(std::unique_ptr()); ++ break; ++ } ++ } ++ return runtimes; ++} ++ ++std::unique_ptr Runtime::Create(Runtime::Options &options) ++{ ++ std::unique_ptr jsRuntime; ++ if (options.lang == Runtime::Language::ETS) { ++ options.lang = Runtime::Language::JS; ++ jsRuntime = JsRuntime::Create(options); ++ options.lang = Runtime::Language::ETS; ++ } + switch (options.lang) { + case Runtime::Language::JS: + return JsRuntime::Create(options); +@@ -35,6 +73,8 @@ std::unique_ptr Runtime::Create(const Runtime::Options& options) + case Runtime::Language::CJ: + return CJRuntime::Create(options); + #endif ++ case Runtime::Language::ETS: ++ return ETSRuntime::Create(options, jsRuntime.get()); + default: + return std::unique_ptr(); + } +diff --git a/frameworks/simulator/ability_simulator/src/js_runtime.cpp b/frameworks/simulator/ability_simulator/src/js_runtime.cpp +index 7e173d8a07c02d6a7e8b4b074b6642a97dd33f1b..3bed249733a419884556d1f715175eaeb43bb774 100644 +--- a/frameworks/simulator/ability_simulator/src/js_runtime.cpp ++++ b/frameworks/simulator/ability_simulator/src/js_runtime.cpp +@@ -158,5 +158,8 @@ std::unique_ptr JsRuntime::LoadSystemModuleByEngine( + napi_create_reference(env, instanceValue, 1, &result); + return std::unique_ptr(reinterpret_cast(result)); + } ++ ++void JsRuntime::RegisterUncaughtExceptionHandler(void *uncaughtExceptionInfo) ++{} + } // namespace AbilityRuntime + } // namespace OHOS +diff --git a/interfaces/inner_api/runtime/BUILD.gn b/interfaces/inner_api/runtime/BUILD.gn +index 836d126b83bdd2b6b003f52e584aaee97e588774..9b78f45490fd2368da7553467750c89ae3e6ffb6 100644 +--- a/interfaces/inner_api/runtime/BUILD.gn ++++ b/interfaces/inner_api/runtime/BUILD.gn +@@ -52,6 +52,7 @@ ohos_shared_library("runtime") { + branch_protector_ret = "pac_ret" + + include_dirs = [ ++ "${ability_runtime_path}/ets_environment/interfaces/inner_api", + "${ability_runtime_path}/services/abilitymgr/include", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_bundle_manager_helper", + "${ability_runtime_path}/frameworks/ets/ani/enum_convert", +@@ -60,6 +61,8 @@ ohos_shared_library("runtime") { + + sources = [ + "${ability_runtime_native_path}/appkit/ability_bundle_manager_helper/bundle_mgr_helper.cpp", ++ "${ability_runtime_native_path}/runtime/ets_data_struct_converter.cpp", ++ "${ability_runtime_native_path}/runtime/ets_runtime.cpp", + "${ability_runtime_native_path}/runtime/hdc_register.cpp", + "${ability_runtime_native_path}/runtime/js_app_process_state.cpp", + "${ability_runtime_native_path}/runtime/js_data_struct_converter.cpp", +@@ -90,6 +93,7 @@ ohos_shared_library("runtime") { + "${ability_runtime_innerkits_path}/connect_server_manager:connect_server_manager", + "${ability_runtime_native_path}/ability/native:ability_business_error", + "${ability_runtime_native_path}/appkit:appkit_manager_helper", ++ "${ability_runtime_path}/ets_environment/frameworks/ets_environment:ets_environment", + "${ability_runtime_path}/js_environment/frameworks/js_environment:js_environment", + "${ability_runtime_services_path}/common:app_util", + "${ability_runtime_services_path}/common:record_cost_time_util", +@@ -122,6 +126,7 @@ ohos_shared_library("runtime") { + "jsoncpp:jsoncpp", + "napi:ace_napi", + "resource_management:global_resmgr", ++ "runtime_core:ani", + "samgr:samgr_proxy", + "zlib:shared_libz", + "faultloggerd:libfaultloggerd", +diff --git a/interfaces/inner_api/runtime/include/cj_runtime.h b/interfaces/inner_api/runtime/include/cj_runtime.h +index 0d406dc6f33831c5cb9d87bdf67ff7716a125292..04778b740086e49638f4e4ad07afd4a2051d6168 100644 +--- a/interfaces/inner_api/runtime/include/cj_runtime.h ++++ b/interfaces/inner_api/runtime/include/cj_runtime.h +@@ -55,6 +55,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; } +@@ -72,8 +74,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(); +diff --git a/interfaces/inner_api/runtime/include/ets_data_struct_converter.h b/interfaces/inner_api/runtime/include/ets_data_struct_converter.h +new file mode 100644 +index 0000000000000000000000000000000000000000..1f196768185cd4881b89b7fc3874b6c709a3e3f7 +--- /dev/null ++++ b/interfaces/inner_api/runtime/include/ets_data_struct_converter.h +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (c) 2025 Huawei Device Co., Ltd. ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#ifndef OHOS_ABILITY_RUNTIME_ETS_DATA_STRUCT_CONVERTER_H ++#define OHOS_ABILITY_RUNTIME_ETS_DATA_STRUCT_CONVERTER_H ++ ++#include "ani.h" ++#include "launch_param.h" ++ ++namespace OHOS { ++namespace AbilityRuntime { ++bool WrapLaunchParam(ani_env *env, const AAFwk::LaunchParam &launchParam, ani_object &object); ++} // namespace AbilityRuntime ++} // namespace OHOS ++#endif // OHOS_ABILITY_RUNTIME_ETS_DATA_STRUCT_CONVERTER_H +diff --git a/interfaces/inner_api/runtime/include/ets_runtime.h b/interfaces/inner_api/runtime/include/ets_runtime.h +new file mode 100644 +index 0000000000000000000000000000000000000000..7b1126f1c0e9e032c31eb13a1523b352b6095038 +--- /dev/null ++++ b/interfaces/inner_api/runtime/include/ets_runtime.h +@@ -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. ++ */ ++ ++#ifndef OHOS_ABILITY_RUNTIME_ETS_RUNTIME_H ++#define OHOS_ABILITY_RUNTIME_ETS_RUNTIME_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "runtime.h" ++#include "js_runtime.h" ++#include "ets_exception_callback.h" ++#include "ani.h" ++ ++using AppLibPathMap = std::map>; ++using AppLibPathVec = std::vector; ++ ++namespace OHOS { ++namespace EtsEnv { ++class ETSEnvironment; ++} // namespace EtsEnv ++ ++namespace AbilityRuntime { ++struct ETSNativeReference { ++ ani_class aniCls = nullptr; ++ ani_object aniObj = nullptr; ++ ani_ref aniRef = nullptr; ++}; ++ ++class ETSRuntime : public Runtime { ++public: ++ static std::unique_ptr Create(const Options &options, Runtime *jsRuntime); ++ static void SetAppLibPath(const AppLibPathMap &appLibPaths); ++ ~ETSRuntime() override; ++ Language GetLanguage() const override ++ { ++ return Language::ETS; ++ } ++ ++ 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 {}; ++ 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; ++ 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 LoadEtsModule(const std::string &moduleName, const std::string &fileName, ++ const std::string &hapPath, const std::string &srcEntrance); ++ void HandleUncaughtError(); ++ ++private: ++ bool Initialize(const Options &options, Runtime *jsRuntime); ++ void Deinitialize(); ++ bool CreateEtsEnv(const Options &options, Runtime *jsRuntime); ++ bool LoadAbcLinker(ani_env *env, const std::string &moduleName, ani_class &abcCls, ani_object &abcObj); ++ std::shared_ptr etsEnv_; ++ int32_t apiTargetVersion_ = 0; ++ std::string codePath_; ++ static AppLibPathVec appLibPaths_; ++ std::string moduleName_; ++}; ++} // namespace AbilityRuntime ++} // namespace OHOS ++#endif // OHOS_ABILITY_RUNTIME_ETS_RUNTIME_H +diff --git a/interfaces/inner_api/runtime/include/js_runtime.h b/interfaces/inner_api/runtime/include/js_runtime.h +index d573886e3c6ebcf7164668e9129cedb044bedfed..dcc410a2cf06f39e99a6cb99bf728dbb3a9483a3 100644 +--- a/interfaces/inner_api/runtime/include/js_runtime.h ++++ b/interfaces/inner_api/runtime/include/js_runtime.h +@@ -103,6 +103,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 {} + bool PopPreloadObj(const std::string& key, std::unique_ptr& obj); + void StartDebugMode(const DebugOption debugOption) override; + void SetDebugOption(const DebugOption debugOption) override; +@@ -156,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 5b3312752f12c526bc9eac08395af8e769c84cc4..faf6685bbd2e6e2d5159820a1b539585682e7f1b 100644 +--- a/interfaces/inner_api/runtime/include/runtime.h ++++ b/interfaces/inner_api/runtime/include/runtime.h +@@ -27,14 +27,23 @@ namespace AppExecFwk { + class EventRunner; + } // namespace AppExecFwk + namespace AbilityRuntime { ++namespace { ++const std::string CODE_LANGUAGE_ARKTS_1_0 = "1.1"; ++const std::string CODE_LANGUAGE_ARKTS_1_2 = "1.2"; ++const std::string CODE_LANGUAGE_ARKTS_HYBRID = "hybrid"; ++} // namespace ++ + class Runtime { + public: + enum class Language { + JS = 0, +- CJ ++ CJ, ++ ETS, ++ UNKNOWN, + }; + + struct Options { ++ std::map langs; + Language lang = Language::JS; + std::string bundleName; + std::string moduleName; +@@ -80,7 +89,8 @@ public: + bool isDeveloperMode; + }; + +- static std::unique_ptr Create(const Options& options); ++ static std::vector> CreateRuntimes(Options &options); ++ static std::unique_ptr Create(Options &options); + static void SavePreloaded(std::unique_ptr&& instance); + static std::unique_ptr GetPreloaded(); + +@@ -108,6 +118,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; +@@ -122,6 +134,7 @@ public: + Runtime(Runtime&&) = delete; + Runtime& operator=(const Runtime&) = delete; + Runtime& operator=(Runtime&&) = delete; ++ virtual void RegisterUncaughtExceptionHandler(void *uncaughtExceptionInfo) {} + }; + } // namespace AbilityRuntime + } // namespace OHOS +diff --git a/interfaces/kits/native/ability/native/ability_loader.h b/interfaces/kits/native/ability/native/ability_loader.h +index 23947ec898c2169a47b0bfab43365a590337d66b..18fd34818d50bb9987e01b62b66220331fc1f784 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::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/ets_ui_ability.h b/interfaces/kits/native/ability/native/ability_runtime/ets_ui_ability.h +new file mode 100644 +index 0000000000000000000000000000000000000000..cecb7e7a835c7cfd6d908adde75cc8033c6135ab +--- /dev/null ++++ b/interfaces/kits/native/ability/native/ability_runtime/ets_ui_ability.h +@@ -0,0 +1,168 @@ ++/* ++ * Copyright (c) 2025 Huawei Device Co., Ltd. ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#ifndef OHOS_ABILITY_RUNTIME_ETS_UI_ABILITY_H ++#define OHOS_ABILITY_RUNTIME_ETS_UI_ABILITY_H ++ ++#include "ets_runtime.h" ++#include "ui_ability.h" ++ ++namespace OHOS { ++namespace AbilityRuntime { ++using AbilityHandler = AppExecFwk::AbilityHandler; ++using AbilityInfo = AppExecFwk::AbilityInfo; ++using OHOSApplication = AppExecFwk::OHOSApplication; ++using Want = AppExecFwk::Want; ++ ++class EtsUIAbility : public UIAbility { ++public: ++ /** ++ * @brief Create a EtsUIAbility instance through the singleton pattern ++ * @param runtime The runtime of the ability ++ * @return Returns the EtsUIability Instance point ++ */ ++ static UIAbility *Create(const std::unique_ptr &runtime); ++ ++ explicit EtsUIAbility(ETSRuntime &etsRuntime); ++ ~EtsUIAbility() 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 EtssUIability ++ * @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 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 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; ++ ++#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 onSceneDestroyed() 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" ets function barely. ++ * ++ * @param want Want ++ */ ++ void CallOnForegroundFunc(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; ++ ++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 UpdateEtsWindowStage(ani_ref windowStage); ++ ++ std::shared_ptr etsWindowStageObj_; ++ int32_t windowMode_ = 0; ++#endif ++ ++private: ++ bool CallObjectMethod(bool withResult, const char *name, const char *signature, ...); ++ ani_object CreateAppWindowStage(); ++ void SetAbilityContext(std::shared_ptr abilityInfo, std::shared_ptr want, ++ const std::string &moduleName, const std::string &srcPath, const std::shared_ptr &application); ++ void DoOnForegroundForSceneIsNull(const Want &want); ++ void UpdateAbilityObj(std::shared_ptr abilityInfo, ++ const std::string &moduleName, const std::string &srcPath); ++ bool BindNativeMethods(); ++ ++ ETSRuntime &etsRuntime_; ++ std::shared_ptr shellContextRef_; ++ std::shared_ptr etsAbilityObj_; ++ static std::once_flag singletonFlag_; ++}; ++} // namespace AbilityRuntime ++} // namespace OHOS ++#endif // OHOS_ABILITY_RUNTIME_ETS_UI_ABILITY_H +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/app/application_data_manager.h b/interfaces/kits/native/appkit/app/application_data_manager.h +index 3f8bb01b4e78f8521570be79cb8903df71347d6f..08ddb478a740ecafb472a6d10f3cc96fda3c749b 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 NotifyETSUnhandledException(const std::string &errMsg); + void RemoveErrorObserver(); + bool NotifyExceptionObject(const AppExecFwk::ErrorObject &errorObj); + bool NotifyCJExceptionObject(const AppExecFwk::ErrorObject &errorObj); ++ bool NotifyETSExceptionObject(const AppExecFwk::ErrorObject &errorObj); + + private: + ApplicationDataManager(); +diff --git a/interfaces/kits/native/appkit/app/main_thread.h b/interfaces/kits/native/appkit/app/main_thread.h +index cd5a86a89c5cbfb55f5c95dc2c01fbc909339670..a7e7e7f94156d3490723c2b04222bc51170ae840 100644 +--- a/interfaces/kits/native/appkit/app/main_thread.h ++++ b/interfaces/kits/native/appkit/app/main_thread.h +@@ -40,6 +40,7 @@ + #include "resource_manager.h" + #include "runtime.h" + #include "watchdog.h" ++#include "ets_runtime.h" + + #ifdef CJ_FRONTEND + #include "cj_envsetup.h" +@@ -323,6 +324,8 @@ public: + CJUncaughtExceptionInfo CreateCjExceptionInfo(const std::string &bundleName, uint32_t versionCode, + const std::string &hapPath); + #endif ++ EtsEnv::ETSUncaughtExceptionInfo CreateEtsExceptionInfo(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. + * +@@ -622,7 +625,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 +@@ -797,6 +801,12 @@ private: + void SetAppDebug(uint32_t modeFlag, bool isDebug); + void GetPluginNativeLibPath(std::vector &pluginBundleInfos, + AppLibPathMap &appLibPaths); ++ void AddRuntimeLang(ApplicationInfo &appInfo, AbilityRuntime::Runtime::Options &options); ++ bool IsNeedEtsInit(const ApplicationInfo &appInfo); ++ const std::unique_ptr &GetVerOneRuntime( ++ const ApplicationInfo &appInfo, const std::vector> &runtimes); ++ void SetJsIdleCallback(const std::weak_ptr &wpApplication, ++ const std::unique_ptr &runtime); + + std::vector fileEntries_; + std::vector nativeFileEntries_; +diff --git a/interfaces/kits/native/appkit/app/ohos_application.h b/interfaces/kits/native/appkit/app/ohos_application.h +index 783bd601495d60835ba55080a9bf51a95ec5992d..3bc1c5697a8c5f78a57f34fd5c3b3fb2850cd708 100644 +--- a/interfaces/kits/native/appkit/app/ohos_application.h ++++ b/interfaces/kits/native/appkit/app/ohos_application.h +@@ -27,6 +27,7 @@ + #include "ability_stage_context.h" + #include "application_configuration_manager.h" + #include "app_launch_data.h" ++#include "runtime.h" + + namespace OHOS { + namespace AbilityRuntime { +@@ -49,11 +50,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 +@@ -168,12 +169,19 @@ public: + */ + std::shared_ptr GetAppContext() const; + ++ /** ++ * @brief return the application runtimes ++ * ++ * @param runtime ++ */ ++ const std::vector> &GetRuntime() const; ++ + /** + * @brief return the application runtime + * + * @param runtime + */ +- const std::unique_ptr& GetRuntime() const; ++ const std::unique_ptr &GetRuntime(const std::string &language) const; + + /* + * +@@ -236,6 +244,8 @@ public: + void PreloadAppStartup(const BundleInfo &bundleInfo, const std::string &preloadModuleName, + std::shared_ptr startupTaskData); + ++ void SetCJApplication(bool isCJApplication = false); ++ + private: + void UpdateAppContextResMgr(const Configuration &config); + bool IsUpdateColorNeeded(Configuration &config, AbilityRuntime::SetLevel level); +@@ -251,14 +261,17 @@ 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::shared_ptr configuration_ = nullptr; + std::map extensionTypeMap_; ++ bool isCJApplication_ = false; + }; + } // namespace AppExecFwk + } // namespace OHOS diff --git a/bundle.json b/bundle.json index 4c096e00742..3cce00df14d 100644 --- a/bundle.json +++ b/bundle.json @@ -135,6 +135,7 @@ "//foundation/ability/ability_runtime/frameworks/js/napi:napi_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/ets_environment/frameworks/ets_environment:ets_environment", "//foundation/ability/ability_runtime/js_environment/frameworks/js_environment:js_environment", "//foundation/ability/ability_runtime/services/abilitymgr/etc:appfwk_etc", "//foundation/ability/ability_runtime/services/dialog_ui/ams_system_dialog:dialog_hap", @@ -261,6 +262,15 @@ }, "name": "//foundation/ability/ability_runtime/js_environment/frameworks/js_environment:js_environment" }, + { + "header": { + "header_base": "//foundation/ability/ability_runtime/ets_environment/interfaces/inner_api", + "header_files": [ + "ets_environment.h" + ] + }, + "name": "//foundation/ability/ability_runtime/ets_environment/frameworks/ets_environment:ets_environment" + }, { "header": { "header_base": "//foundation/ability/ability_runtime/cj_environment/interfaces/inner_api", diff --git a/ets_environment/ets_environment.gni b/ets_environment/ets_environment.gni new file mode 100644 index 00000000000..b044edbd9d0 --- /dev/null +++ b/ets_environment/ets_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/ets_environment" diff --git a/ets_environment/frameworks/ets_environment/BUILD.gn b/ets_environment/frameworks/ets_environment/BUILD.gn new file mode 100644 index 00000000000..a3f1835114b --- /dev/null +++ b/ets_environment/frameworks/ets_environment/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") +import("../../ets_environment.gni") + +config("public_ets_environment_config") { + include_dirs = [ + "include", + "${ability_runtime_path}/ets_environment/interfaces/inner_api", + "${ability_runtime_path}/interfaces/inner_api", + "${ability_runtime_services_path}/common/include", + ] +} + +ohos_shared_library("ets_environment") { + branch_protector_ret = "pac_ret" + + public_configs = [ ":public_ets_environment_config" ] + + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + sources = [ + "src/dynamic_loader.cpp", + "src/ets_environment.cpp", + ] + + defines = [] + + external_deps = [ + "c_utils:utils", + "eventhandler:libeventhandler", + "faultloggerd:libunwinder", + "hilog:libhilog", + "json:nlohmann_json_static", + "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/ets_environment/frameworks/ets_environment/src/dynamic_loader.cpp b/ets_environment/frameworks/ets_environment/src/dynamic_loader.cpp new file mode 100644 index 00000000000..6b293493744 --- /dev/null +++ b/ets_environment/frameworks/ets_environment/src/dynamic_loader.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include +#include +#include + +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace EtsEnv { +namespace { +constexpr int32_t ERROR_BUF_SIZE = 255; +static char g_dlError[ERROR_BUF_SIZE]; +static std::unordered_set g_hasInited; +static std::string g_sharedLibsSonames = ""; +constexpr int32_t OUT_OF_MEMORY = 12; +constexpr int32_t FILE_EXISTS = 17; +constexpr int32_t 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.empty()) { + return; + } + g_sharedLibsSonames = + // 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"; +} +} // namespace + +void DynamicInitNamespace(Dl_namespace *ns, void *parent, const char *entries, const char *name) +{ + if (ns == nullptr || entries == nullptr || name == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Invaild args for init namespace."); + return; + } + if (g_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) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "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, "ets_app") != 0) { + dlns_inherit(ns, ¤t, "allow_all_shared_libs"); + } else { + InitSharedLibsSonames(); + dlns_inherit(ns, ¤t, g_sharedLibsSonames.c_str()); + } + g_hasInited.insert(std::string(name)); +} + +void *DynamicLoadLibrary(Dl_namespace *ns, const char *dlPath, uint32_t mode) +{ + if (ns == nullptr) { + dlns_get("ets_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; +} +} // namespace EtsEnv +} // namespace OHOS \ No newline at end of file diff --git a/ets_environment/frameworks/ets_environment/src/ets_environment.cpp b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp new file mode 100644 index 00000000000..ef09b6afd09 --- /dev/null +++ b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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_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 "unwinder.h" + +#ifdef SUPPORT_GRAPHICS +#include "ui_content.h" +#endif // SUPPORT_GRAPHICS + +namespace OHOS { +namespace EtsEnv { +namespace { +const char ETS_CREATE_VM[] = "ANI_CreateVM"; +const char ETS_ANI_GET_CREATEDVMS[] = "ANI_GetCreatedVMs"; +const char ETS_LIB_PATH[] = "libets_interop_js_napi.z.so"; +const char BOOT_PATH[] = "/system/framework/bootpath.json"; +const char BACKTRACE[] = "=====================Backtrace========================"; + +using CreateVMETSRuntimeType = 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 ETS_SDK_NSNAME[] = "ets_sdk"; +const char ETS_SYS_NSNAME[] = "ets_system"; +} // namespace + +ETSRuntimeAPI ETSEnvironment::lazyApis_ {}; + +bool ETSEnvironment::LoadBootPathFile(std::string &bootfiles) +{ + std::ifstream inFile; + inFile.open(BOOT_PATH, std::ios::in); + if (!inFile.is_open()) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "read json error"); + return false; + } + nlohmann::json jsonObject = nlohmann::json::parse(inFile); + if (jsonObject.is_discarded()) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "json discarded error"); + inFile.close(); + return false; + } + + if (jsonObject.is_null() || jsonObject.empty()) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "json value of %{public}s is empty", key.c_str()); + continue; + } + if (!bootfiles.empty()) { + bootfiles += ":"; + } + bootfiles += jsonValue.c_str(); + } + } + inFile.close(); + return true; +} + +bool ETSEnvironment::LoadRuntimeApis() +{ + static bool isRuntimeApiLoaded { false }; + if (isRuntimeApiLoaded) { + return true; + } + + Dl_namespace ns; + dlns_get(ETS_SDK_NSNAME, &ns); + auto dso = DynamicLoadLibrary(&ns, ETS_LIB_PATH, 1); + if (!dso) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "load library failed: %{public}s", ETS_LIB_PATH); + return false; + } + + if (!LoadSymbolCreateVM(dso, lazyApis_) || + !LoadSymbolANIGetCreatedVMs(dso, lazyApis_)) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "load symbol failed"); + return false; + } + + isRuntimeApiLoaded = true; + return true; +} + +std::string ETSEnvironment::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(); + if (elfFile == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null elfFile"); + break; + } + std::string buildId = elfFile->GetBuildId(); + if (i != 0 && !buildId.empty()) { + addBuildId += tempStr + "(" + buildId + ")" + "\n"; + } else { + addBuildId += tempStr + "\n"; + } + } + i++; + } + return addBuildId; +} + +void ETSEnvironment::RegisterUncaughtExceptionHandler(const ETSUncaughtExceptionInfo &handle) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "RegisterUncaughtExceptionHandler called"); + uncaughtExceptionInfo_ = handle; +} + +bool ETSEnvironment::LoadSymbolCreateVM(void *handle, ETSRuntimeAPI &apis) +{ + auto symbol = dlsym(handle, ETS_CREATE_VM); + if (symbol == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "runtime api not found: %{public}s", ETS_CREATE_VM); + return false; + } + apis.ANI_CreateVM = reinterpret_cast(symbol); + + return true; +} + +bool ETSEnvironment::LoadSymbolANIGetCreatedVMs(void *handle, ETSRuntimeAPI &apis) +{ + auto symbol = dlsym(handle, ETS_ANI_GET_CREATEDVMS); + if (symbol == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "runtime api not found: %{public}s", ETS_ANI_GET_CREATEDVMS); + return false; + } + apis.ANI_GetCreatedVMs = reinterpret_cast(symbol); + + return true; +} + +void ETSEnvironment::InitETSSDKNS(const std::string &path) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "InitETSSDKNS: %{public}s", path.c_str()); + Dl_namespace ndk; + Dl_namespace ns; + DynamicInitNamespace(&ns, nullptr, path.c_str(), ETS_SDK_NSNAME); + dlns_get("ndk", &ndk); + dlns_inherit(&ns, &ndk, "allow_all_shared_libs"); +} + +void ETSEnvironment::InitETSSysNS(const std::string &path) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "InitETSSysNS: %{public}s", path.c_str()); + Dl_namespace ets_sdk; + Dl_namespace ndk; + Dl_namespace ns; + dlns_get(ETS_SDK_NSNAME, &ets_sdk); + DynamicInitNamespace(&ns, &ets_sdk, path.c_str(), ETS_SYS_NSNAME); + dlns_get("ndk", &ndk); + dlns_inherit(&ns, &ndk, "allow_all_shared_libs"); +} + +bool ETSEnvironment::Initialize(napi_env napiEnv, std::vector &options) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "StartRuntime called"); + if (!LoadRuntimeApis()) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "LoadRuntimeApis failed"); + return false; + } + std::string bootfiles; + if (!LoadBootPathFile(bootfiles)) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "bootString %{public}s", bootString.c_str()); + options.push_back(ani_option { bootString.c_str(), nullptr }); + std::string schedulingExternal = optionPrefix + "--coroutine-enable-external-scheduling=true"; + ani_option schedulingExternalOption = { schedulingExternal.data(), nullptr }; + options.push_back(schedulingExternalOption); + + 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 enableVerfication = optionPrefix + "--verification-enabled=true"; + ani_option enableVerficationOption = { enableVerfication.data(), nullptr }; + options.push_back(enableVerficationOption); + + std::string verificationMode = optionPrefix + "--verification-mode=on-the-fly"; + ani_option verificationModeOption = { verificationMode.data(), nullptr }; + options.push_back(verificationModeOption); + + std::string interop = optionPrefix + "interop"; + ani_option interopOption = { interop.data(), (void *)napiEnv }; + options.push_back(interopOption); + ani_options optionsPtr = { options.size(), options.data() }; + ani_status status = ANI_ERROR; + if ((status = lazyApis_.ANI_CreateVM(&optionsPtr, ANI_VERSION_1, &vmEntry_.aniVm_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "ANI_CreateVM failed %{public}d", status); + return false; + } + if ((status = vmEntry_.aniVm_->GetEnv(ANI_VERSION_1, &vmEntry_.aniEnv_)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetEnv failed %{public}d", status); + return false; + } + return true; +} + +ani_env *ETSEnvironment::GetAniEnv() +{ + return vmEntry_.aniEnv_; +} + +void ETSEnvironment::HandleUncaughtError() +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "HandleUncaughtError called"); + const EtsEnv::ETSErrorObject errorObj = GetETSErrorObject(); + std::string errorStack = errorObj.stack; + if (errorStack.empty()) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "errorStack is empty"); + return; + } + TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "uncaughtTask called"); + uncaughtExceptionInfo_.uncaughtTask(summary, errorObj); + } +} + +EtsEnv::ETSErrorObject ETSEnvironment::GetETSErrorObject() +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "GetETSErrorObject called"); + ani_boolean errorExists = ANI_FALSE; + ani_status status = ANI_ERROR; + auto aniEnv = GetAniEnv(); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env"); + return EtsEnv::ETSErrorObject(); + } + if ((status = aniEnv->ExistUnhandledError(&errorExists)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "ExistUnhandledError failed, status : %{public}d", status); + return EtsEnv::ETSErrorObject(); + } + if (errorExists == ANI_FALSE) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "not exist error"); + return EtsEnv::ETSErrorObject(); + } + ani_error aniError = nullptr; + if ((status = aniEnv->GetUnhandledError(&aniError)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetUnhandledError failed, status : %{public}d", status); + return EtsEnv::ETSErrorObject(); + } + if ((status = aniEnv->ResetError()) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "ResetError failed, status : %{public}d", status); + return EtsEnv::ETSErrorObject(); + } + std::string errorMsg = GetErrorProperty(aniError, "message"); + std::string errorName = GetErrorProperty(aniError, "name"); + std::string errorStack = GetErrorProperty(aniError, "stack"); + const EtsEnv::ETSErrorObject errorObj = { + .name = errorName, + .message = errorMsg, + .stack = errorStack + }; + return errorObj; +} + +std::string ETSEnvironment::GetErrorProperty(ani_error aniError, const char *property) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "GetErrorProperty called"); + auto aniEnv = GetAniEnv(); + std::string propertyValue; + ani_status status = ANI_ERROR; + ani_type errorType = nullptr; + if ((status = aniEnv->Object_GetType(aniError, &errorType)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "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::ETSRUNTIME, "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::ETSRUNTIME, "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::ETSRUNTIME, "String_GetUTF8SubString failed, status : %{public}d", status); + return propertyValue; + } + propertyValue.resize(sz); + return propertyValue; +} +} // namespace EtsEnv +} // namespace OHOS diff --git a/ets_environment/interfaces/inner_api/dynamic_loader.h b/ets_environment/interfaces/inner_api/dynamic_loader.h new file mode 100644 index 00000000000..6155e797e8e --- /dev/null +++ b/ets_environment/interfaces/inner_api/dynamic_loader.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_DYNAMIC_LOADER_H +#define OHOS_ABILITY_RUNTIME_DYNAMIC_LOADER_H + +#include +#include + +namespace OHOS { +namespace EtsEnv { +void *DynamicLoadLibrary(Dl_namespace *ns, const char *dlPath, uint32_t 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); +} // namespace EtsEnv +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_DYNAMIC_LOADER_H diff --git a/ets_environment/interfaces/inner_api/ets_environment.h b/ets_environment/interfaces/inner_api/ets_environment.h new file mode 100644 index 00000000000..2c37be0747a --- /dev/null +++ b/ets_environment/interfaces/inner_api/ets_environment.h @@ -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. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_ENVIRONMENT_H +#define OHOS_ABILITY_RUNTIME_ETS_ENVIRONMENT_H + +#include +#include +#include +#include + +#include "ani.h" +#include "ets_exception_callback.h" +#include "event_handler.h" +#include "napi/native_api.h" + +namespace OHOS { +namespace EtsEnv { +struct ETSRuntimeAPI { + 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); +}; + +class ETSEnvironment final : public std::enable_shared_from_this { +public: + ETSEnvironment() {}; + + static void InitETSSDKNS(const std::string &path); + static void InitETSSysNS(const std::string &path); + + bool Initialize(napi_env napiEnv, std::vector &options); + void RegisterUncaughtExceptionHandler(const ETSUncaughtExceptionInfo &handle); + ani_env *GetAniEnv(); + void HandleUncaughtError(); + + struct VMEntry { + ani_vm *aniVm_; + ani_env *aniEnv_; + VMEntry() + { + aniVm_ = nullptr; + aniEnv_ = nullptr; + } + }; + +private: + bool LoadRuntimeApis(); + bool LoadSymbolCreateVM(void *handle, ETSRuntimeAPI &apis); + bool LoadSymbolANIGetCreatedVMs(void *handle, ETSRuntimeAPI &apis); + bool LoadBootPathFile(std::string &bootfiles); + std::string GetBuildId(std::string stack); + EtsEnv::ETSErrorObject GetETSErrorObject(); + std::string GetErrorProperty(ani_error aniError, const char *property); + static ETSRuntimeAPI lazyApis_; + VMEntry vmEntry_; + ETSUncaughtExceptionInfo uncaughtExceptionInfo_; +}; +} // namespace EtsEnv +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_ENVIRONMENT_H diff --git a/ets_environment/interfaces/inner_api/ets_exception_callback.h b/ets_environment/interfaces/inner_api/ets_exception_callback.h new file mode 100644 index 00000000000..2d935af7f1f --- /dev/null +++ b/ets_environment/interfaces/inner_api/ets_exception_callback.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_EXCEPTION_CALLBACK_H +#define OHOS_ABILITY_RUNTIME_ETS_EXCEPTION_CALLBACK_H + +#include + +namespace OHOS { +namespace EtsEnv { +struct ETSErrorObject { + std::string name; + std::string message; + std::string stack; +}; + +struct ETSUncaughtExceptionInfo { + std::function uncaughtTask; +}; +} // namespace EtsEnv +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_EXCEPTION_CALLBACK_H diff --git a/frameworks/cj/ffi/BUILD.gn b/frameworks/cj/ffi/BUILD.gn index 03df8fc4f90..b9797aa4792 100644 --- a/frameworks/cj/ffi/BUILD.gn +++ b/frameworks/cj/ffi/BUILD.gn @@ -69,6 +69,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/ani_common/src/ani_common_util.cpp b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp index d909518810b..8d2a9961007 100644 --- a/frameworks/ets/ani/ani_common/src/ani_common_util.cpp +++ b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp @@ -93,7 +93,7 @@ bool GetFieldBoolByName(ani_env *env, ani_object object, const char *name, bool return false; } ani_boolean isUndefined = true; - if ((status = env->Reference_IsUndefined(object, &isUndefined)) != ANI_OK) { + if ((status = env->Reference_IsUndefined(field, &isUndefined)) != ANI_OK) { TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); return false; } @@ -103,7 +103,7 @@ bool GetFieldBoolByName(ani_env *env, ani_object object, const char *name, bool } ani_boolean aniValue = false; if ((status = env->Object_CallMethodByName_Boolean( - reinterpret_cast(object), "booleanValue", nullptr, &aniValue)) != ANI_OK) { + reinterpret_cast(field), "booleanValue", nullptr, &aniValue)) != ANI_OK) { TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); return false; } @@ -143,7 +143,7 @@ bool GetFieldStringByName(ani_env *env, ani_object object, const char *name, std return false; } ani_boolean isUndefined = true; - if ((status = env->Reference_IsUndefined(object, &isUndefined)) != ANI_OK) { + if ((status = env->Reference_IsUndefined(field, &isUndefined)) != ANI_OK) { TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); return false; } diff --git a/frameworks/ets/ani/ani_common/src/ani_common_want.cpp b/frameworks/ets/ani/ani_common/src/ani_common_want.cpp index 0f6f8ad80cb..0fcacfbf24a 100644 --- a/frameworks/ets/ani/ani_common/src/ani_common_want.cpp +++ b/frameworks/ets/ani/ani_common/src/ani_common_want.cpp @@ -61,6 +61,10 @@ bool InnerUnwrapWantParams(ani_env* env, ani_object wantObject, AAFwk::WantParam ani_object WrapWant(ani_env *env, const AAFwk::Want &want) { TAG_LOGD(AAFwkTag::ANI, "WrapWant called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ANI, "null env"); + return nullptr; + } ani_class cls = nullptr; ani_status status = ANI_ERROR; ani_method method = nullptr; diff --git a/frameworks/ets/ani/enum_convert/ani_enum_convert.h b/frameworks/ets/ani/enum_convert/ani_enum_convert.h index 6234c8bc88f..a61bbe0b3d7 100644 --- a/frameworks/ets/ani/enum_convert/ani_enum_convert.h +++ b/frameworks/ets/ani/enum_convert/ani_enum_convert.h @@ -47,7 +47,7 @@ static bool EnumConvert_EtsToNative(ani_env *env, ani_enum_item enumItem, T &res ani_int intValue{}; status = env->EnumItem_GetValue_Int(enumItem, &intValue); if (ANI_OK != status) { - TAG_LOGE(AAFwkTag::EtsRUNTIME, "EnumConvert_EtsToNative failed, status : %{public}d", status); + TAG_LOGE(AAFwkTag::ETSRUNTIME, "EnumConvert_EtsToNative failed, status : %{public}d", status); return false; } result = static_cast(intValue); @@ -56,12 +56,12 @@ static bool EnumConvert_EtsToNative(ani_env *env, ani_enum_item enumItem, T &res ani_string strValue{}; status = env->EnumItem_GetValue_String(enumItem, &strValue); if (ANI_OK != status) { - TAG_LOGE(AAFwkTag::EtsRUNTIME, "EnumItem_GetValue_String failed, status : %{public}d", status); + TAG_LOGE(AAFwkTag::ETSRUNTIME, "EnumItem_GetValue_String failed, status : %{public}d", status); return false; } return GetStdString(env, strValue, result); } else { - TAG_LOGE(AAFwkTag::EtsRUNTIME, "Enum convert failed: type not supported"); + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Enum convert failed: type not supported"); return false; } } @@ -78,7 +78,7 @@ static bool EnumConvert_NativeToEts(ani_env *env, const char *enumName, const T ani_enum aniEnum{}; ani_status status = env->FindEnum(enumName, &aniEnum); if (ANI_OK != status) { - TAG_LOGE(AAFwkTag::EtsRUNTIME, "Enum convert FindEnum failed: %{public}s status: %{public}d", enumName, status); + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Enum convert FindEnum failed: %{public}s status: %{public}d", enumName, status); return false; } constexpr int32_t loopMaxNum = 1000; @@ -86,7 +86,7 @@ static bool EnumConvert_NativeToEts(ani_env *env, const char *enumName, const T ani_enum_item enumItem{}; status = env->Enum_GetEnumItemByIndex(aniEnum, index, &enumItem); if (ANI_OK != status) { - TAG_LOGE(AAFwkTag::EtsRUNTIME, + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Enum convert Enum_GetEnumItemByIndex failed: enumName:%{public}s index:%{public}d status:%{public}d", enumName, index, status); return false; @@ -98,7 +98,7 @@ static bool EnumConvert_NativeToEts(ani_env *env, const char *enumName, const T return true; } } - TAG_LOGE(AAFwkTag::EtsRUNTIME, "EnumConvert_NativeToEts failed enumName: %{public}s", enumName); + TAG_LOGE(AAFwkTag::ETSRUNTIME, "EnumConvert_NativeToEts failed enumName: %{public}s", enumName); return false; } } 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 00000000000..4c72a344a57 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets @@ -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. + */ + +namespace AbilityConstant { + export interface LaunchParam { + launchReason: LaunchReason; + launchReasonMessage?: string; + lastExitReason: LastExitReason; + lastExitMessage: string; + } + + 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 = ''; +} + +export default AbilityConstant; 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 00000000000..c4a6565f60e --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.StartOptions.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 StartOptions { + displayId?: number; +} 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 00000000000..f53af8d5f3a --- /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 Want from '@ohos.app.ability.Want'; +import window from '@ohos.window'; +import { AbilityUtils } from './utils/AbilityUtils'; + +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 isOverride = AbilityUtils.isOverride(derivedClassType, "onDestroyAsync", uiAbilityClassType); + if (isOverride) { + this.onDestroyAsync().then(() => this.nativeOnDestroyCallback()); + return true; + } + this.onDestroy(); + return false; + } + + launchWant: Want = new Want(); + lastRequestWant: Want = new Want(); + + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + } + + onWindowStageDestroy(): 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.Want.ets b/frameworks/ets/ets/@ohos.app.ability.Want.ets new file mode 100644 index 00000000000..c1a0ec876e0 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.Want.ets @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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' + +type valueType = NullishType; +const DOMAIN_ID = 0xD001300; +const TAG = 'WantSerializeTool'; + +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)) { + // 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, 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 RecordSerializeTool.stringify(obj as Object as Record); + } catch (err) { + hilog.error(DOMAIN_ID, TAG, `RecordSerializeTool.stringify error: ${err}`); + return ''; + } + } + + public static parseNoThrow(text: string): Record { + try { + return RecordSerializeTool.parse(text) as Object as Record; + } catch (err) { + hilog.error(DOMAIN_ID, TAG, `RecordSerializeTool.parse error: ${err}`); + 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; +} 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 00000000000..721b9d7eed1 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.ability.wantConstant.ets @@ -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. + */ + +namespace wantConstant { + export enum Action { + ACTION_HOME = 'ohos.want.action.home', + ACTION_DIAL = 'ohos.want.action.dial', + ACTION_SEARCH = 'ohos.want.action.search', + ACTION_WIRELESS_SETTINGS = 'ohos.settings.wireless', + ACTION_MANAGE_APPLICATIONS_SETTINGS = 'ohos.settings.manage.applications', + ACTION_APPLICATION_DETAILS_SETTINGS = 'ohos.settings.application.details', + ACTION_SET_ALARM = 'ohos.want.action.setAlarm', + ACTION_SHOW_ALARMS = 'ohos.want.action.showAlarms', + ACTION_SNOOZE_ALARM = 'ohos.want.action.snoozeAlarm', + ACTION_DISMISS_ALARM = 'ohos.want.action.dismissAlarm', + ACTION_DISMISS_TIMER = 'ohos.want.action.dismissTimer', + ACTION_SEND_SMS = 'ohos.want.action.sendSms', + ACTION_CHOOSE = 'ohos.want.action.choose', + ACTION_IMAGE_CAPTURE = 'ohos.want.action.imageCapture', + ACTION_VIDEO_CAPTURE = 'ohos.want.action.videoCapture', + ACTION_SELECT = 'ohos.want.action.select', + ACTION_SEND_DATA = 'ohos.want.action.sendData', + ACTION_SEND_MULTIPLE_DATA = 'ohos.want.action.sendMultipleData', + ACTION_SCAN_MEDIA_FILE = 'ohos.want.action.scanMediaFile', + ACTION_VIEW_DATA = 'ohos.want.action.viewData', + ACTION_EDIT_DATA = 'ohos.want.action.editData', + INTENT_PARAMS_INTENT = 'ability.want.params.INTENT', + INTENT_PARAMS_TITLE = 'ability.want.params.TITLE', + ACTION_FILE_SELECT = 'ohos.action.fileSelect', + PARAMS_STREAM = 'ability.params.stream', + ACTION_APP_ACCOUNT_OAUTH = 'ohos.account.appAccount.action.oauth' + } + + export enum Flags { + FLAG_AUTH_READ_URI_PERMISSION = 0x00000001, + FLAG_AUTH_WRITE_URI_PERMISSION = 0x00000002, + FLAG_ABILITY_FORWARD_RESULT = 0x00000004, + FLAG_ABILITY_CONTINUATION = 0x00000008, + FLAG_NOT_OHOS_COMPONENT = 0x00000010, + FLAG_ABILITY_FORM_ENABLED = 0x00000020, + FLAG_AUTH_PERSISTABLE_URI_PERMISSION = 0x00000040, + FLAG_AUTH_PREFIX_URI_PERMISSION = 0x00000080, + FLAG_ABILITYSLICE_MULTI_DEVICE = 0x00000100, + FLAG_START_FOREGROUND_ABILITY = 0x00000200, + FLAG_ABILITY_CONTINUATION_REVERSIBLE = 0x00000400, + FLAG_INSTALL_ON_DEMAND = 0x00000800, + FLAG_INSTALL_WITH_BACKGROUND_MODE = 0x80000000, + FLAG_ABILITY_CLEAR_MISSION = 0x00008000, + FLAG_ABILITY_NEW_MISSION = 0x10000000, + FLAG_ABILITY_MISSION_TOP = 0x20000000 + } +} + +export default wantConstant; diff --git a/frameworks/ets/ets/BUILD.gn b/frameworks/ets/ets/BUILD.gn index 4c90291f2d2..26efc114b17 100644 --- a/frameworks/ets/ets/BUILD.gn +++ b/frameworks/ets/ets/BUILD.gn @@ -31,8 +31,110 @@ ohos_prebuilt_etc("ability_runtime_base_context_abc_etc") { deps = [ ":ability_runtime_base_context_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_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_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_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_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" ] +} + group("ets_packages") { deps = [ ":ability_runtime_base_context_abc_etc", + # ":ability_runtime_ui_ability_abc_etc", + ":ability_runtime_ability_constant_abc_etc", + ":ability_runtime_ability_utils_abc_etc", + ":ability_runtime_start_options_abc_etc", + ":ability_runtime_want_abc_etc", + ":ability_runtime_want_constant_abc_etc", ] } diff --git a/frameworks/ets/ets/utils/AbilityUtils.ets b/frameworks/ets/ets/utils/AbilityUtils.ets new file mode 100644 index 00000000000..573c5d3a207 --- /dev/null +++ b/frameworks/ets/ets/utils/AbilityUtils.ets @@ -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 hilog from '@ohos.hilog' + +const DOMAIN_ID = 0xD001300; +const TAG = 'AbilityUtils'; +const LEVEL = 100; + +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 isOverride(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 true; + } + } + } + let baseType = currType.getBaseType(); + if (baseType.equals(currType)) { + hilog.error(DOMAIN_ID, TAG, `isOverride: baseType equals currType (${currType.getName()})`); + return undefined; + } + level++; + if (level >= LEVEL) { + hilog.error(DOMAIN_ID, TAG, `isOverride: inheritance level >= ${LEVEL}, abort`); + return undefined; + } + currType = baseType; + } catch (err) { + hilog.error(DOMAIN_ID, TAG, `isOverride error: ${err}`); + return undefined; + } + } + return false; + } +} diff --git a/frameworks/js/napi/app/ability_delegator/ability_monitor.cpp b/frameworks/js/napi/app/ability_delegator/ability_monitor.cpp index 5eab898a5a9..950c81b07a0 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 433a48b4828..37bb4b5b2fb 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 b150907480c..68f4863719a 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"); @@ -526,14 +527,15 @@ napi_value JSAbilityDelegator::OnWaitAbilityMonitor(napi_env env, NapiCallbackIn 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) { @@ -795,15 +797,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/native/BUILD.gn b/frameworks/native/ability/native/BUILD.gn index 52d727221b7..d21d8b1129d 100644 --- a/frameworks/native/ability/native/BUILD.gn +++ b/frameworks/native/ability/native/BUILD.gn @@ -155,6 +155,7 @@ ohos_shared_library("abilitykit_utils") { "${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", + "${ability_runtime_innerkits_path}/runtime/include", "${ability_runtime_innerkits_path}/wantagent/include", "${ability_runtime_services_path}/abilitymgr/include/utils", "${ability_runtime_services_path}/abilitymgr/include", @@ -764,6 +765,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", @@ -771,6 +773,7 @@ ohos_shared_library("uiabilitykit_native") { ] sources = [ + "${ability_runtime_native_path}/ability/native/ability_runtime/ets_ui_ability.cpp", "${ability_runtime_native_path}/ability/native/ability_runtime/js_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", @@ -802,6 +805,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", ] @@ -822,6 +826,7 @@ ohos_shared_library("uiabilitykit_native") { "ipc:ipc_napi", "json:nlohmann_json_static", "resource_management:global_resmgr", + "runtime_core:ani", "samgr:samgr_proxy", ] public_external_deps = [ diff --git a/frameworks/native/ability/native/ability_loader.cpp b/frameworks/native/ability/native/ability_loader.cpp index 1c26bd9c57a..1a8f740a1c2 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()); 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/ets_ui_ability.cpp b/frameworks/native/ability/native/ability_runtime/ets_ui_ability.cpp new file mode 100644 index 00000000000..dac5f017eb8 --- /dev/null +++ b/frameworks/native/ability/native/ability_runtime/ets_ui_ability.cpp @@ -0,0 +1,694 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ets_ui_ability.h" + +#include + +#include "ani_common_want.h" +#include "app_recovery.h" +#include "connection_manager.h" +#include "display_util.h" +#include "ets_data_struct_converter.h" +#include "hilog_tag_wrapper.h" +#include "hitrace_meter.h" +#include "string_wrapper.h" +#ifdef SUPPORT_SCREEN +// #include "ani_window_stage.h" +#endif + +namespace OHOS { +namespace AbilityRuntime { +std::once_flag EtsUIAbility::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 +#ifdef SUPPORT_SCREEN +constexpr int32_t BASE_DISPLAY_ID_NUM(10); +#endif +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 called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + ani_long destroyCallbackPtr = 0; + ani_status status = ANI_ERROR; + if ((status = env->Object_GetFieldByName_Long(aniObj, "destroyCallbackPoint", &destroyCallbackPtr)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "Object_GetFieldByName_Long status: %{public}d", status); + return; + } + if (destroyCallbackPtr == 0) { + TAG_LOGE(AAFwkTag::UIABILITY, "null destroyCallbackPtr"); + return; + } + auto *callbackInfo = reinterpret_cast *>(destroyCallbackPtr); + if (callbackInfo == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null callbackInfo"); + return; + } + callbackInfo->Call(); + AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo); +} +} // namespace + +UIAbility *EtsUIAbility::Create(const std::unique_ptr &runtime) +{ + return new (std::nothrow) EtsUIAbility(static_cast(*runtime)); +} + +EtsUIAbility::EtsUIAbility(ETSRuntime &etsRuntime) : etsRuntime_(etsRuntime) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "EtsUIAbility called"); +} + +EtsUIAbility::~EtsUIAbility() +{ + TAG_LOGI(AAFwkTag::UIABILITY, "~EtsUIAbility called"); + if (shellContextRef_ && shellContextRef_->aniRef) { + auto env = etsRuntime_.GetAniEnv(); + if (env != nullptr) { + env->GlobalReference_Delete(shellContextRef_->aniRef); + } + } + if (etsWindowStageObj_ && etsWindowStageObj_->aniRef) { + auto env = etsRuntime_.GetAniEnv(); + if (env != nullptr) { + env->GlobalReference_Delete(etsWindowStageObj_->aniRef); + } + } +} + +void EtsUIAbility::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); + std::string srcPath(abilityInfo->package); + if (!abilityInfo->isModuleJson) { + 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, "etsAbility srcPath: %{public}s", srcPath.c_str()); + } + + std::string moduleName(abilityInfo->moduleName); + moduleName.append("::").append(abilityInfo->name); + SetAbilityContext(abilityInfo, record->GetWant(), moduleName, srcPath, application); +} + +bool EtsUIAbility::BindNativeMethods() +{ + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + 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 EtsUIAbility::UpdateAbilityObj( + std::shared_ptr abilityInfo, const std::string &moduleName, const std::string &srcPath) +{ + std::string key = moduleName + "::" + srcPath; + std::unique_ptr moduleObj = nullptr; + etsAbilityObj_ = etsRuntime_.LoadModule(moduleName, srcPath, abilityInfo->hapPath, + abilityInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE, false, abilityInfo->srcEntrance); + if (!BindNativeMethods()) { + TAG_LOGE(AAFwkTag::UIABILITY, "BindNativeMethods failed"); + return; + } +} + +void EtsUIAbility::SetAbilityContext(std::shared_ptr abilityInfo, std::shared_ptr want, + const std::string &moduleName, const std::string &srcPath, const std::shared_ptr &application) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "SetAbilityContext called"); + UpdateAbilityObj(abilityInfo, moduleName, srcPath); + if (etsAbilityObj_ == nullptr || abilityContext_ == nullptr || want == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null etsAbilityObj_ or abilityContext_ or want"); + return; + } +} + +void EtsUIAbility::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 (!etsAbilityObj_) { + TAG_LOGE(AAFwkTag::UIABILITY, "not found Ability.js"); + return; + } + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + ani_object wantObj = OHOS::AppExecFwk::WrapWant(env, want); + if (wantObj == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); + return; + } + ani_status status = ANI_ERROR; + if ((status = env->Object_SetFieldByName_Ref(etsAbilityObj_->aniObj, "launchWant", wantObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "launchWant Object_SetFieldByName_Ref status: %{public}d", status); + return; + } + if ((status = env->Object_SetFieldByName_Ref(etsAbilityObj_->aniObj, "lastRequestWant", wantObj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "lastRequestWant Object_SetFieldByName_Ref status: %{public}d", status); + return; + } + auto launchParam = GetLaunchParam(); + if (InsightIntentExecuteParam::IsInsightIntentExecute(want)) { + launchParam.launchReason = AAFwk::LaunchReason::LAUNCHREASON_INSIGHT_INTENT; + } + ani_object launchParamObj = nullptr; + if (!WrapLaunchParam(env, launchParam, launchParamObj)) { + TAG_LOGE(AAFwkTag::UIABILITY, "WrapLaunchParam failed"); + return; + } + CallObjectMethod(false, "onCreate", nullptr, wantObj, launchParamObj); + TAG_LOGD(AAFwkTag::UIABILITY, "OnStart end"); +} + +void EtsUIAbility::OnStop() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "OnStop called"); + if (abilityContext_) { + TAG_LOGD(AAFwkTag::UIABILITY, "set terminating true"); + abilityContext_->SetTerminating(true); + } + UIAbility::OnStop(); + + CallObjectMethod(false, "onDestroy", nullptr); + OnStopCallback(); + TAG_LOGD(AAFwkTag::UIABILITY, "OnStop end"); +} + +void EtsUIAbility::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, "OnStop Begin"); + if (abilityContext_) { + TAG_LOGD(AAFwkTag::UIABILITY, "set terminating true"); + abilityContext_->SetTerminating(true); + } + UIAbility::OnStop(); + 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); + + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr || etsAbilityObj_ == nullptr) { + isAsyncCallback = false; + OnStop(); + return; + } + + ani_long destroyCallbackPoint = reinterpret_cast(callbackInfo); + ani_status status = + env->Object_SetFieldByName_Long(etsAbilityObj_->aniObj, "destroyCallbackPoint", destroyCallbackPoint); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "Object_SetFieldByName_Long status: %{public}d", status); + return; + } + isAsyncCallback = CallObjectMethod(true, "callOnDestroy", ":Z"); + TAG_LOGD(AAFwkTag::UIABILITY, "callOnDestroy isAsyncCallback: %{public}d", isAsyncCallback); + if (!isAsyncCallback) { + OnStopCallback(); + return; + } + TAG_LOGD(AAFwkTag::UIABILITY, "OnStop end"); +} + +void EtsUIAbility::OnStopCallback() +{ + bool ret = ConnectionManager::GetInstance().DisconnectCaller(AbilityContext::token_); + if (ret) { + ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid()); + TAG_LOGD(AAFwkTag::UIABILITY, "the service connection is not disconnected"); + } +} + +#ifdef SUPPORT_SCREEN +void EtsUIAbility::OnSceneCreated() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); + UIAbility::OnSceneCreated(); + auto etsAppWindowStage = CreateAppWindowStage(); + if (etsAppWindowStage == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null etsAppWindowStage"); + return; + } + UpdateEtsWindowStage(reinterpret_cast(etsAppWindowStage)); + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + etsWindowStageObj_ = std::make_shared(); + etsWindowStageObj_->aniObj = etsAppWindowStage; + ani_ref entryObjectRef = nullptr; + env->GlobalReference_Create(etsAppWindowStage, &entryObjectRef); + etsWindowStageObj_->aniRef = entryObjectRef; + CallObjectMethod(false, "onWindowStageCreate", nullptr, etsAppWindowStage); + TAG_LOGD(AAFwkTag::UIABILITY, "OnSceneCreated end"); +} + +void EtsUIAbility::onSceneDestroyed() +{ + TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); + UIAbility::onSceneDestroyed(); + UpdateEtsWindowStage(nullptr); + CallObjectMethod(false, "onWindowStageDestroy", nullptr); + if (scene_ != nullptr) { + auto window = scene_->GetMainWindow(); + if (window != nullptr) { + TAG_LOGD(AAFwkTag::UIABILITY, "unRegisterDisplaymovelistener"); + window->UnregisterDisplayMoveListener(abilityDisplayMoveListener_); + } + } + TAG_LOGD(AAFwkTag::UIABILITY, "onSceneDestroyed end"); +} + +void EtsUIAbility::OnForeground(const Want &want) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); + UIAbility::OnForeground(want); + if (CheckIsSilentForeground()) { + TAG_LOGD(AAFwkTag::UIABILITY, "silent foreground, do not call 'onForeground'"); + return; + } + CallOnForegroundFunc(want); +} + +void EtsUIAbility::CallOnForegroundFunc(const Want &want) +{ + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + if (etsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null etsAbilityObj_"); + return; + } + ani_status status = ANI_ERROR; + ani_ref wantRef = OHOS::AppExecFwk::WrapWant(env, want); + if (wantRef == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); + return; + } + if ((status = env->Object_SetFieldByName_Ref(etsAbilityObj_->aniObj, "lastRequestWant", wantRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "lastRequestWant Object_SetFieldByName_Ref status: %{public}d", status); + return; + } + CallObjectMethod(false, "onForeground", nullptr, wantRef); + TAG_LOGD(AAFwkTag::UIABILITY, "CallOnForegroundFunc end"); +} + +void EtsUIAbility::OnBackground() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); + CallObjectMethod(false, "onBackground", nullptr); + UIAbility::OnBackground(); + TAG_LOGD(AAFwkTag::UIABILITY, "OnBackground end"); +} + +ani_object EtsUIAbility::CreateAppWindowStage() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return nullptr; + } + auto scene = GetScene(); + if (scene == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "scene not found"); + return nullptr; + } + ani_object etsWindowStage = nullptr; + // ani_object etsWindowStage = CreateAniWindowStage(env, scene); + if (etsWindowStage == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null etsWindowStage"); + return nullptr; + } + return etsWindowStage; +} + +void EtsUIAbility::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 EtsUIAbility::IsRestorePageStack(const Want &want) +{ + return want.GetBoolParam(SUPPORT_CONTINUE_PAGE_STACK_PROPERTY_NAME, true); +} + +void EtsUIAbility::RestorePageStack(const Want &want) +{ + if (IsRestorePageStack(want)) { + std::string pageStack; + GetPageStackFromWant(want, pageStack); + // to be done: AniSetUIContent + } +} + +void EtsUIAbility::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); + NotifyContinuationResult(want, true); + } else if (ShouldRecoverState(want)) { + std::string pageStack = abilityRecovery_->GetSavedPageStack(AppExecFwk::StateReason::DEVELOPER_REQUEST); + + auto mainWindow = scene_->GetMainWindow(); + if (mainWindow == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null mainWindow"); + } + } 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 EtsUIAbility::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_); + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, "scene_->GoForeground"); + scene_->GoForeground(UIAbility::sceneFlag_); + TAG_LOGD(AAFwkTag::UIABILITY, "DoOnForeground end"); +} + +void EtsUIAbility::DoOnForegroundForSceneIsNull(const Want &want) +{ + scene_ = std::make_shared(); + int32_t displayId = AAFwk::DisplayUtil::GetDefaultDisplayId(); + if (setting_ != nullptr) { + std::string strDisplayId = setting_->GetProperty(OHOS::AppExecFwk::AbilityStartSetting::WINDOW_DISPLAY_ID_KEY); + std::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"); + 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 EtsUIAbility::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); + NotifyContinuationResult(want, true); +} + +void EtsUIAbility::UpdateEtsWindowStage(ani_ref windowStage) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "UpdateEtsWindowStage called"); + if (shellContextRef_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null shellContextRef_"); + return; + } + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + ani_status status = ANI_ERROR; + if (windowStage == nullptr) { + ani_ref undefinedRef = nullptr; + env->GetUndefined(&undefinedRef); + if ((status = env->Object_SetFieldByName_Ref(shellContextRef_->aniObj, "windowStage", undefinedRef)) != + ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "Object_SetFieldByName_Ref status: %{public}d", status); + return; + } + return; + } + if ((status = env->Object_SetFieldByName_Ref(shellContextRef_->aniObj, "windowStage", windowStage)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "Object_SetFieldByName_Ref status: %{public}d", status); + return; + } +} +#endif + +void EtsUIAbility::OnNewWant(const Want &want) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "OnNewWant called"); + UIAbility::OnNewWant(want); + +#ifdef SUPPORT_SCREEN + if (scene_) { + scene_->OnNewWant(want); + } +#endif + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return; + } + if (etsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null etsAbilityObj_"); + return; + } + ani_object wantObj = OHOS::AppExecFwk::WrapWant(env, want); + if (wantObj == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); + return; + } + ani_status status = env->Object_SetFieldByName_Ref(etsAbilityObj_->aniObj, "lastRequestWant", wantObj); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "lastRequestWant Object_SetFieldByName_Ref status: %{public}d", status); + return; + } + auto launchParam = GetLaunchParam(); + if (InsightIntentExecuteParam::IsInsightIntentExecute(want)) { + launchParam.launchReason = AAFwk::LaunchReason::LAUNCHREASON_INSIGHT_INTENT; + } + ani_object launchParamObj = nullptr; + if (!WrapLaunchParam(env, launchParam, launchParamObj)) { + TAG_LOGE(AAFwkTag::UIABILITY, "WrapLaunchParam failed"); + return; + } + std::string methodName = "OnNewWant"; + CallObjectMethod(false, "onNewWant", nullptr, wantObj, launchParamObj); + TAG_LOGD(AAFwkTag::UIABILITY, "OnNewWant end"); +} + +void EtsUIAbility::OnAbilityResult(int requestCode, int resultCode, const Want &resultData) +{ + TAG_LOGD(AAFwkTag::UIABILITY, "OnAbilityResult 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, "OnAbilityResult end"); +} + +bool EtsUIAbility::CallObjectMethod(bool withResult, const char *name, const char *signature, ...) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name); + TAG_LOGI(AAFwkTag::UIABILITY, "EtsUIAbility call ets, name: %{public}s", name); + if (etsAbilityObj_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null etsAbilityObj"); + return false; + } + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "null env"); + return false; + } + auto obj = etsAbilityObj_->aniObj; + auto cls = etsAbilityObj_->aniCls; + + ani_method method {}; + ani_status status = env->Class_FindMethod(cls, name, signature, &method); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "Class_FindMethod status: %{public}d", status); + env->ResetError(); + return false; + } + 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, "Object_CallMethod_Boolean_V status: %{public}d", status); + etsRuntime_.HandleUncaughtError(); + return false; + } + va_end(args); + return res; + } + va_list args; + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(obj, method, args)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "Object_CallMethod_Void_V status: %{public}d", status); + etsRuntime_.HandleUncaughtError(); + return false; + } + va_end(args); + TAG_LOGI(AAFwkTag::UIABILITY, "CallObjectMethod end, name: %{public}s", name); + return false; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/ability/native/extension_ability_thread.cpp b/frameworks/native/ability/native/extension_ability_thread.cpp index f72fa0f4c2a..6a7633b3519 100644 --- a/frameworks/native/ability/native/extension_ability_thread.cpp +++ b/frameworks/native/ability/native/extension_ability_thread.cpp @@ -242,7 +242,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/ui_ability_thread.cpp b/frameworks/native/ability/native/ui_ability_thread.cpp index 18d97dee4d6..e20643c4440 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/appkit/BUILD.gn b/frameworks/native/appkit/BUILD.gn index cc0227d2feb..11863d7b8bd 100644 --- a/frameworks/native/appkit/BUILD.gn +++ b/frameworks/native/appkit/BUILD.gn @@ -54,6 +54,7 @@ config("appkit_config") { config("appkit_public_config") { visibility = [ ":*" ] include_dirs = [ + "${ability_runtime_path}/ets_environment/interfaces/inner_api", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_delegator", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", @@ -75,6 +76,7 @@ config("appkit_public_config") { ohos_shared_library("appkit_native") { include_dirs = [ "native", + "${ability_runtime_path}/ets_environment/interfaces/inner_api", "${ability_runtime_path}/interfaces/inner_api/error_utils/include", "${ability_runtime_path}/interfaces/kits/native/appkit", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_bundle_manager_helper", @@ -166,6 +168,7 @@ 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_path}/ets_environment/frameworks/ets_environment:ets_environment", "${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", @@ -208,6 +211,7 @@ ohos_shared_library("appkit_native") { "napi:ace_napi", "preferences:native_preferences", "resource_management:global_resmgr", + "runtime_core:ani", "safwk:system_ability_fwk", "samgr:samgr_proxy", "storage_service:storage_manager_acl", diff --git a/frameworks/native/appkit/ability_delegator/ability_delegator.cpp b/frameworks/native/appkit/ability_delegator/ability_delegator.cpp index 1449f61557f..0c9ef8125c7 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) { @@ -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) { @@ -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,9 +388,8 @@ void AbilityDelegator::PostPerformStart(const std::shared_ptrMatch(ability, true)) { - monitor->OnAbilityStart(ability->object_); + monitor->OnAbilityStart(ability); } } } @@ -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 7187c88382e..7cd73453052 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 @@ -39,11 +49,11 @@ std::shared_ptr AbilityDelegatorRegistry::GetArguments() return abilityDelegatorArgs_; } -void AbilityDelegatorRegistry::RegisterInstance( - const std::shared_ptr& delegator, const std::shared_ptr& args) +void AbilityDelegatorRegistry::RegisterInstance(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_monitor.cpp b/frameworks/native/appkit/ability_delegator/iability_monitor.cpp index 17bf4c740bd..4a6238cb047 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,25 @@ 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/app/application_data_manager.cpp b/frameworks/native/appkit/app/application_data_manager.cpp index 6dfd3a4493e..79c2449ccbf 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::NotifyETSUnhandledException(const std::string &errMsg) +{ + if (errorObserver_) { + errorObserver_->OnUnhandledException(errMsg); + return true; + } + return AppRecovery::GetInstance().TryRecoverApp(StateReason::JS_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::NotifyETSExceptionObject(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::JS_ERROR); +} } // namespace AppExecFwk } // namespace OHOS diff --git a/frameworks/native/appkit/app/dump_runtime_helper.cpp b/frameworks/native/appkit/app/dump_runtime_helper.cpp index 945867d5b91..052ec4ece78 100644 --- a/frameworks/native/appkit/app/dump_runtime_helper.cpp +++ b/frameworks/native/appkit/app/dump_runtime_helper.cpp @@ -87,7 +87,7 @@ void DumpRuntimeHelper::SetAppFreezeFilterCallback() TAG_LOGE(AAFwkTag::APPKIT, "null application"); return; } - auto& runtime = application_->GetRuntime(); + auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); if (runtime == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); return; @@ -205,7 +205,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::CODE_LANGUAGE_ARKTS_1_0); if (runtime == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); return; @@ -235,7 +235,7 @@ void DumpRuntimeHelper::DumpCjHeap(const OHOS::AppExecFwk::CjHeapDumpInfo &info) TAG_LOGE(AAFwkTag::APPKIT, "null application"); return; } - auto& runtime = application_->GetRuntime(); + auto &runtime = application_->GetRuntime(AbilityRuntime::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 5d126479903..10f4b21bdaa 100644 --- a/frameworks/native/appkit/app/main_thread.cpp +++ b/frameworks/native/appkit/app/main_thread.cpp @@ -75,6 +75,7 @@ #include "if_system_ability_manager.h" #include "iservice_registry.h" #include "js_runtime.h" +#include "ets_runtime.h" #ifdef CJ_FRONTEND #include "cj_runtime.h" #endif @@ -183,6 +184,7 @@ const char* PC_LIBRARY_PATH = "/system/lib64/liblayered_parameters_manager.z.so" const char* PC_FUNC_INFO = "DetermineResourceType"; const int32_t TYPE_RESERVE = 1; const int32_t TYPE_OTHERS = 2; +std::unique_ptr RUNTIME_NULL = nullptr; #if defined(NWEB) constexpr int32_t PRELOAD_DELAY_TIME = 2000; //millisecond @@ -1395,6 +1397,59 @@ CJUncaughtExceptionInfo MainThread::CreateCjExceptionInfo(const std::string &bun return uncaughtExceptionInfo; } #endif + +EtsEnv::ETSUncaughtExceptionInfo MainThread::CreateEtsExceptionInfo(const std::string &bundleName, uint32_t versionCode, + const std::string &hapPath, std::string &appRunningId, int32_t pid, std::string &processName) +{ + EtsEnv::ETSUncaughtExceptionInfo uncaughtExceptionInfo; + wptr weak = this; + uncaughtExceptionInfo.uncaughtTask = [weak, bundleName, versionCode, appRunningId = std::move(appRunningId), pid, + processName](std::string summary, const EtsEnv::ETSErrorObject 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); + if (ApplicationDataManager::GetInstance().NotifyETSUnhandledException(summary) && + ApplicationDataManager::GetInstance().NotifyETSExceptionObject(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; +} /** * * @brief Launch the application. @@ -1582,6 +1637,9 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con } else { #endif AbilityRuntime::JsRuntime::SetAppLibPath(appLibPaths, isSystemApp); + if (IsNeedEtsInit(appInfo)) { + AbilityRuntime::ETSRuntime::SetAppLibPath(appLibPaths); + } #ifdef CJ_FRONTEND } #endif @@ -1608,7 +1666,14 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con options.pkgContextInfoJsonStringMap = pkgContextInfoJsonStringMap; options.allowArkTsLargeHeap = appInfo.allowArkTsLargeHeap; #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()); @@ -1642,12 +1707,12 @@ 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; } - + auto &runtimeVerOne = GetVerOneRuntime(appInfo, runtimes); if (appInfo.debug && appLaunchData.GetDebugApp()) { wptr weak = this; auto cb = [weak]() { @@ -1658,7 +1723,9 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con } return appThread->NotifyDeviceDisConnect(); }; - runtime->SetDeviceDisconnectCallback(cb); + if (runtimeVerOne != nullptr) { + runtimeVerOne->SetDeviceDisconnectCallback(cb); + } } auto perfCmd = appLaunchData.GetPerfCmd(); @@ -1669,11 +1736,13 @@ 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); - }); + if (runtimeVerOne != nullptr) { + runtimeVerOne->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.isStartWithDebug = appLaunchData.GetDebugApp(); debugOption.processName = processName; @@ -1683,13 +1752,19 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con debugOption.isDebugFromLocal = appLaunchData.GetDebugFromLocal(); debugOption.perfCmd = perfCmd; debugOption.isDeveloperMode = isDeveloperMode_; - runtime->SetDebugOption(debugOption); + if (runtimeVerOne != nullptr) { + runtimeVerOne->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); + if (runtimeVerOne != nullptr) { + runtimeVerOne->StartProfiler(debugOption); + } } else { - runtime->StartDebugMode(debugOption); + if (runtimeVerOne != nullptr) { + runtimeVerOne->StartDebugMode(debugOption); + } } std::vector hqfInfos = appInfo.appQuickFix.deployedAppqfInfo.hqfInfos; @@ -1700,7 +1775,9 @@ 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); + if (runtimeVerOne != nullptr) { + runtimeVerOne->RegisterQuickFixQueryFunc(modulePaths); + } } auto bundleName = appInfo.bundleName; @@ -1708,18 +1785,37 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con #ifdef CJ_FRONTEND if (!isCJApp) { #endif - JsEnv::UncaughtExceptionInfo uncaughtExceptionInfo; - uncaughtExceptionInfo.hapPath = hapPath; - UncatchableTaskInfo uncatchableTaskInfo = {bundleName, versionCode, appRunningId, pid, processName}; - InitUncatchableTask(uncaughtExceptionInfo.uncaughtTask, uncatchableTaskInfo); - (static_cast(*runtime)).RegisterUncaughtExceptionHandler(uncaughtExceptionInfo); - JsEnv::UncatchableTask uncatchableTask; - InitUncatchableTask(uncatchableTask, uncatchableTaskInfo, true); - (static_cast(*runtime)).RegisterUncatchableExceptionHandler(uncatchableTask); + for (const auto &runtime : runtimes) { + if (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0 && + runtime->GetLanguage() == AbilityRuntime::Runtime::Language::JS) { + JsEnv::UncaughtExceptionInfo uncaughtExceptionInfo; + uncaughtExceptionInfo.hapPath = hapPath; + UncatchableTaskInfo uncatchableTaskInfo = {bundleName, versionCode, appRunningId, pid, processName}; + InitUncatchableTask(uncaughtExceptionInfo.uncaughtTask, uncatchableTaskInfo); + (static_cast(*runtime)).RegisterUncaughtExceptionHandler( + uncaughtExceptionInfo); + JsEnv::UncatchableTask uncatchableTask; + InitUncatchableTask(uncatchableTask, uncatchableTaskInfo, true); + (static_cast(*runtime)).RegisterUncatchableExceptionHandler( + uncatchableTask); + } + if ((appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2 || + appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_HYBRID) && + runtime->GetLanguage() == AbilityRuntime::Runtime::Language::ETS) { + auto expectionInfo = + CreateEtsExceptionInfo(bundleName, versionCode, hapPath, appRunningId, pid, processName); + runtime->RegisterUncaughtExceptionHandler((void*)&expectionInfo); + } + } #ifdef CJ_FRONTEND } else { - auto expectionInfo = CreateCjExceptionInfo(bundleName, versionCode, hapPath); - (static_cast(*runtime)).RegisterUncaughtExceptionHandler(expectionInfo); + for (const auto &runtime : runtimes) { + if (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0 && + runtime->GetLanguage() == AbilityRuntime::Runtime::Language::CJ) { + auto expectionInfo = CreateCjExceptionInfo(bundleName, versionCode, hapPath); + runtime->RegisterUncaughtExceptionHandler((void*)&expectionInfo); + } + } } #endif wptr weak = this; @@ -1733,14 +1829,21 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con }; applicationContext->RegisterProcessSecurityExit(callback); - application_->SetRuntime(std::move(runtime)); - + for (auto &runtime : runtimes) { + application_->AddRuntime(std::move(runtime)); + } 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::CODE_LANGUAGE_ARKTS_1_2) { + return AbilityRuntime::UIAbility::Create(app->GetRuntime( + AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2)); + } else { + return AbilityRuntime::UIAbility::Create(app->GetRuntime( + AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0)); + } } TAG_LOGE(AAFwkTag::APPKIT, "failed"); return nullptr; @@ -1748,33 +1851,18 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con #ifdef CJ_FRONTEND if (!isCJApp) { #endif - auto& jsEngine = (static_cast(*application_->GetRuntime())).GetNativeEngine(); if (application_ != nullptr) { - LoadAllExtensions(jsEngine); + TAG_LOGD(AAFwkTag::APPKIT, "LoadAllExtensions lan:%{public}s", appInfo.codeLanguage.c_str()); + LoadAllExtensions(); } - - 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 (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) { + auto &runtime = application_->GetRuntime(appInfo.codeLanguage); 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); - - auto helper = std::make_shared(application_); - helper->SetAppFreezeFilterCallback(); + SetJsIdleCallback(wpApplication, runtime); + } #ifdef CJ_FRONTEND } else { LoadAllExtensions(); @@ -1784,7 +1872,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; } @@ -1876,7 +1965,9 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con } #endif if (appLaunchData.IsNeedPreloadModule()) { - PreloadModule(entryHapModuleInfo, application_->GetRuntime()); + for (auto &runtime : application_->GetRuntime()) { + PreloadModule(entryHapModuleInfo, runtime); + } } } @@ -1911,7 +2002,8 @@ void MainThread::InitUncatchableTask(JsEnv::UncatchableTask &uncatchableTask, co EVENT_KEY_PROCESS_RSS_MEMINFO, std::to_string(DumpProcessHelper::GetProcRssMemInfo())); ErrorObject appExecErrorObj = { errorObject.name, errorObject.message, errorObject.stack}; - auto napiEnv = (static_cast(*appThread->application_->GetRuntime())).GetNapiEnv(); + auto napiEnv = (static_cast( + *appThread->application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0))).GetNapiEnv(); if (!isUncatchable && NapiErrorManager::GetInstance()->NotifyUncaughtException(napiEnv, summary, appExecErrorObj.name, appExecErrorObj.message, appExecErrorObj.stack)) { return; @@ -2054,7 +2146,7 @@ void MainThread::ProcessMainAbility(const AbilityInfo &info, const std::unique_p } void MainThread::PreloadModule(const AppExecFwk::HapModuleInfo &entryHapModuleInfo, - const std::unique_ptr& runtime) + const std::unique_ptr &runtime) { TAG_LOGI(AAFwkTag::APPKIT, "preload module %{public}s", entryHapModuleInfo.moduleName.c_str()); auto callback = []() {}; @@ -2204,7 +2296,7 @@ void MainThread::HandleUpdatePluginInfoInstalled(const ApplicationInfo &pluginAp TAG_LOGE(AAFwkTag::APPKIT, "null application_"); return; } - auto& runtime = application_->GetRuntime(); + auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); if (runtime == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); return; @@ -2254,7 +2346,7 @@ void MainThread::HandleUpdateApplicationInfoInstalled(const ApplicationInfo& app } application_->UpdateApplicationInfoInstalled(appInfo); - auto& runtime = application_->GetRuntime(); + auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); if (runtime == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); return; @@ -2342,10 +2434,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; @@ -2355,7 +2448,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) { @@ -2365,12 +2459,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::CODE_LANGUAGE_ARKTS_1_0) { + TAG_LOGI(AAFwkTag::DELEGATOR, "create 1.0 testrunner"); + auto &runtime = application_->GetRuntime(AbilityRuntime::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, runtime->GetLanguage()); + delegator->SetApiTargetVersion(targetVersion); + delegator->Prepare(); + } + + if (applicationCodeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2) { + TAG_LOGI(AAFwkTag::DELEGATOR, "create 1.2 testrunner"); + auto &runtime = application_->GetRuntime(AbilityRuntime::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, runtime->GetLanguage()); + delegator->SetApiTargetVersion(targetVersion); + delegator->Prepare(); + } } else { // FA model TAG_LOGD(AAFwkTag::APPKIT, "FA model"); AbilityRuntime::Runtime::Options options; @@ -2400,7 +2509,7 @@ 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, AbilityRuntime::Runtime::Language::JS); delegator->SetApiTargetVersion(targetVersion); delegator->Prepare(); } @@ -2461,7 +2570,7 @@ void MainThread::HandleLaunchAbility(const std::shared_ptr & TAG_LOGE(AAFwkTag::APPKIT, "null application"); return; } - auto& runtime = application->GetRuntime(); + auto &runtime = application->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); appThread->UpdateRuntimeModuleChecker(runtime); #ifdef APP_ABILITY_USE_TWO_RUNNER AbilityThread::AbilityThreadMain(application, abilityRecord, stageContext); @@ -2488,7 +2597,7 @@ void MainThread::HandleLaunchAbility(const std::shared_ptr & return; } SetProcessExtensionType(abilityRecord); - auto& runtime = application_->GetRuntime(); + auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); UpdateRuntimeModuleChecker(runtime); #ifdef APP_ABILITY_USE_TWO_RUNNER AbilityThread::AbilityThreadMain(application_, abilityRecord, stageContext); @@ -2851,7 +2960,7 @@ void MainThread::HandleDumpHeapPrepare() TAG_LOGE(AAFwkTag::APPKIT, "null app"); return; } - auto &runtime = app->GetRuntime(); + auto &runtime = app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); if (runtime == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); return; @@ -2871,7 +2980,7 @@ void MainThread::HandleDumpHeap(bool isPrivate) TAG_LOGE(AAFwkTag::APPKIT, "null app"); return; } - auto &runtime = app->GetRuntime(); + auto &runtime = app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); if (runtime == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); return; @@ -2924,11 +3033,11 @@ void MainThread::DestroyHeapProfiler() auto task = [] { auto app = applicationForDump_.lock(); - if (app == nullptr || app->GetRuntime() == nullptr) { + if (app == nullptr || app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); return; } - app->GetRuntime()->DestroyHeapProfiler(); + app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0)->DestroyHeapProfiler(); }; mainHandler_->PostTask(task, "MainThread:DestroyHeapProfiler"); } @@ -2943,11 +3052,11 @@ void MainThread::ForceFullGC() auto task = [] { auto app = applicationForDump_.lock(); - if (app == nullptr || app->GetRuntime() == nullptr) { + if (app == nullptr || app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); return; } - app->GetRuntime()->ForceFullGC(); + app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0)->ForceFullGC(); }; mainHandler_->PostTask(task, "MainThread:ForceFullGC"); } @@ -3675,7 +3784,7 @@ int32_t MainThread::ChangeAppGcState(int32_t state, uint64_t tid) TAG_LOGE(AAFwkTag::APPKIT, "null application_"); return ERR_INVALID_VALUE; } - auto &runtime = application_->GetRuntime(); + auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); if (runtime == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); return ERR_INVALID_VALUE; @@ -3727,7 +3836,7 @@ int32_t MainThread::OnAttachLocalDebug(bool isDebugFromLocal) TAG_LOGE(AAFwkTag::APPKIT, "null application_"); return ERR_INVALID_VALUE; } - auto &runtime = application_->GetRuntime(); + auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); if (runtime == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); return ERR_INVALID_VALUE; @@ -3949,7 +4058,7 @@ void MainThread::HandleCacheProcess() // force gc if (application_ != nullptr) { - auto &runtime = application_->GetRuntime(); + auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); if (runtime == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); return; @@ -3958,6 +4067,38 @@ void MainThread::HandleCacheProcess() } } +void MainThread::AddRuntimeLang(ApplicationInfo &appInfo, AbilityRuntime::Runtime::Options &options) +{ + if (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2) { + options.langs.emplace(AbilityRuntime::Runtime::Language::ETS, true); + } else if (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_HYBRID) { + options.langs.emplace(AbilityRuntime::Runtime::Language::ETS, true); + } else { + options.langs.emplace(AbilityRuntime::Runtime::Language::JS, true); + } +} + +bool MainThread::IsNeedEtsInit(const ApplicationInfo &appInfo) +{ + return appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2 || + appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_HYBRID; +} + +const std::unique_ptr &MainThread::GetVerOneRuntime( + const ApplicationInfo &appInfo, const std::vector> &runtimes) +{ + if (appInfo.codeLanguage != AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) { + return RUNTIME_NULL; + } + for (auto &runtime : runtimes) { + if (runtime->GetLanguage() == AbilityRuntime::Runtime::Language::JS || + runtime->GetLanguage() == AbilityRuntime::Runtime::Language::CJ) { + return runtime; + } + } + return RUNTIME_NULL; +} + void MainThread::HandleConfigByPlugin(Configuration &config, BundleInfo &bundleInfo) { if (PC_LIBRARY_PATH == nullptr) { @@ -3980,5 +4121,33 @@ void MainThread::HandleConfigByPlugin(Configuration &config, BundleInfo &bundleI entry(config, bundleInfo); } + +void MainThread::SetJsIdleCallback(const std::weak_ptr &wpApplication, + const std::unique_ptr &runtime) +{ + 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::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(); + + IdleNotifyStatusCallback cb = idleTime_->GetIdleNotifyFunc(); + jsEngine.NotifyIdleStatusControl(cb); + + auto helper = std::make_shared(application_); + helper->SetAppFreezeFilterCallback(); +} } // namespace AppExecFwk } // namespace OHOS diff --git a/frameworks/native/appkit/app/ohos_application.cpp b/frameworks/native/appkit/app/ohos_application.cpp index 45831ff8001..41713dde52b 100644 --- a/frameworks/native/appkit/app/ohos_application.cpp +++ b/frameworks/native/appkit/app/ohos_application.cpp @@ -37,6 +37,7 @@ #include "iservice_registry.h" #include "runtime.h" #include "js_runtime.h" +#include "ets_runtime.h" #include "startup_manager.h" #include "system_ability_definition.h" #include "syspara/parameter.h" @@ -51,6 +52,7 @@ namespace OHOS { namespace AppExecFwk { namespace { constexpr const char* PERSIST_DARKMODE_KEY = "persist.ace.darkmode"; + std::unique_ptr RUNTIME_NULL = nullptr; } REGISTER_APPLICATION(OHOSApplication, OHOSApplication) constexpr int32_t APP_ENVIRONMENT_OVERWRITE = 1; @@ -77,11 +79,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 +102,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 +156,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_.emplace_back(std::move(runtime)); } /** @@ -369,6 +376,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) @@ -413,8 +439,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); @@ -425,7 +453,8 @@ std::shared_ptr OHOSApplication::AddAbilityStage( stageContext->SetResourceManager(rm); } - abilityStage = AbilityRuntime::AbilityStage::Create(runtime_, *hapModuleInfo); + auto &runtimeStage = GetRuntime(hapModuleInfo->codeLanguage); + abilityStage = AbilityRuntime::AbilityStage::Create(runtimeStage, *hapModuleInfo); if (abilityStage == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null abilityStage"); return nullptr; @@ -608,8 +637,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; } @@ -633,7 +662,8 @@ bool OHOSApplication::AddAbilityStage( stageContext->SetResourceManager(rm); } - auto abilityStage = AbilityRuntime::AbilityStage::Create(runtime_, *moduleInfo); + auto &runtime = GetRuntime(moduleInfo->codeLanguage); + auto abilityStage = AbilityRuntime::AbilityStage::Create(runtime, *moduleInfo); if (abilityStage == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null abilityStage"); return false; @@ -688,9 +718,9 @@ std::shared_ptr OHOSApplication::GetAppContext() const return abilityRuntimeContext_; } -const std::unique_ptr& OHOSApplication::GetRuntime() const +const std::vector> &OHOSApplication::GetRuntime() const { - return runtime_; + return runtimes_; } void OHOSApplication::SetConfiguration(const Configuration &config) @@ -815,32 +845,60 @@ 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"); + 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"); + 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) @@ -1080,5 +1138,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 RUNTIME_NULL; +} + +void OHOSApplication::SetCJApplication(bool isCJApplication) +{ + isCJApplication_ = isCJApplication; +} + +AbilityRuntime::Runtime::Language OHOSApplication::ConvertLangToCode(const std::string &language) const +{ + if (language == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) { + if (isCJApplication_) { + return AbilityRuntime::Runtime::Language::CJ; + } else { + return AbilityRuntime::Runtime::Language::JS; + } + } else if (language == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2) { + return AbilityRuntime::Runtime::Language::ETS; + } else { + return AbilityRuntime::Runtime::Language::UNKNOWN; + } +} } // namespace AppExecFwk } // namespace OHOS diff --git a/frameworks/native/runtime/cj_runtime.cpp b/frameworks/native/runtime/cj_runtime.cpp index ecf1697834d..5ac8d635e22 100644 --- a/frameworks/native/runtime/cj_runtime.cpp +++ b/frameworks/native/runtime/cj_runtime.cpp @@ -118,16 +118,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. @@ -368,4 +358,14 @@ void CJRuntime::ForceFullGC(uint32_t tid) return; } cjEnv->forceFullGC(); +} + +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/ets_data_struct_converter.cpp b/frameworks/native/runtime/ets_data_struct_converter.cpp new file mode 100644 index 00000000000..a3bf58cd7a6 --- /dev/null +++ b/frameworks/native/runtime/ets_data_struct_converter.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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_data_struct_converter.h" + +#include "ani_enum_convert.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char *CLASSNAME_LAUNCHPARAM = "L@ohos/app/ability/AbilityConstant/LaunchParamImpl"; +constexpr const char *CLASSNAME_LAUNCHREASON = "L@ohos/app/ability/AbilityConstant/AbilityConstant/LaunchReason;"; +constexpr const char *CLASSNAME_LAST_EXITREASION = "L@ohos/app/ability/AbilityConstant/AbilityConstant/LastExitReason"; + +ani_string GetAniString(ani_env *env, const std::string &str) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env"); + return nullptr; + } + ani_string aniStr = nullptr; + ani_status status = env->String_NewUTF8(str.c_str(), str.size(), &aniStr); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to getAniString, status : %{public}d", status); + return nullptr; + } + return aniStr; +} + +bool WrapLaunchParamInner(ani_env *env, const AAFwk::LaunchParam &launchParam, ani_object &object) +{ + ani_status status = ANI_ERROR; + ani_enum_item launchReasonItem {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts( + env, CLASSNAME_LAUNCHREASON, launchParam.launchReason, launchReasonItem); + if ((status = env->Object_SetPropertyByName_Ref(object, "launchReason", launchReasonItem)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to set launchReason"); + return false; + } + + ani_enum_item lastExitReasonItem {}; + OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts( + env, CLASSNAME_LAST_EXITREASION, launchParam.lastExitReason, lastExitReasonItem); + if ((status = env->Object_SetPropertyByName_Ref(object, "lastExitReason", lastExitReasonItem)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to set lastExitReason"); + return false; + } + return true; +} +} // namespace + +bool WrapLaunchParam(ani_env *env, const AAFwk::LaunchParam &launchParam, ani_object &object) +{ + ani_method method = nullptr; + ani_status status = ANI_ERROR; + ani_class cls = nullptr; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env"); + return false; + } + if ((status = env->FindClass(CLASSNAME_LAUNCHPARAM, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to find lanchParam Class, status : %{public}d", status); + return false; + } + if (cls == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null cls"); + return false; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to find method, status : %{public}d", status); + return false; + } + if (method == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null method"); + return false; + } + if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to create object, status : %{public}d", status); + return false; + } + if (object == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null object"); + return false; + } + if ((status = env->Object_SetPropertyByName_Ref( + object, "lastExitMessage", GetAniString(env, launchParam.lastExitMessage))) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to set lastExitMessage"); + return false; + } + return WrapLaunchParamInner(env, launchParam, object); +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/runtime/ets_runtime.cpp b/frameworks/native/runtime/ets_runtime.cpp new file mode 100644 index 00000000000..f851bf77ffb --- /dev/null +++ b/frameworks/native/runtime/ets_runtime.cpp @@ -0,0 +1,481 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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_runtime.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "accesstoken_kit.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 "module_checker_delegate.h" +#include "parameters.h" +#include "source_map.h" +#include "source_map_operator.h" +#include "ets_environment.h" +#include "syscap_ts.h" +#include "system_ability_definition.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 ETS_RT_PATH = SANDBOX_LIB_PATH; +const std::string ETS_SYSLIB_PATH = + "/system/lib64:/system/lib64/platformsdk:/system/lib64/module:/system/lib64/ndk"; +#else +const std::string SANDBOX_LIB_PATH = "/system/lib"; +const std::string ETS_RT_PATH = SANDBOX_LIB_PATH; +const std::string ETS_SYSLIB_PATH = + "/system/lib:/system/lib/platformsdk:/system/lib/module:/system/lib/ndk"; +#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"; // will deprecated +constexpr char ENTRY_PATH_MAP_KEY[] = "entryPath"; // will deprecated +constexpr char DEFAULT_ENTRY_ABILITY_CLASS[] = "entry/src/main/ets/entryability/EntryAbility/EntryAbility"; +constexpr int32_t DOT_START_LEN = 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::ETSRUNTIME, "no entrypath file"); + return false; + } + nlohmann::json filePathsJson; + inFile >> filePathsJson; + if (filePathsJson.is_discarded()) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "json discarded error"); + inFile.close(); + return false; + } + + if (filePathsJson.is_null() || filePathsJson.empty()) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "invalid json"); + inFile.close(); + return false; + } + + if (!filePathsJson.contains(ENTRY_PATH_MAP_KEY)) { + TAG_LOGD(AAFwkTag::ETSRUNTIME, "no entrypath key"); + return false; + } + const auto &entryPathMap = filePathsJson[ENTRY_PATH_MAP_KEY]; + if (!entryPathMap.is_object()) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "val is not string, key: %{public}s", key.c_str()); + continue; + } + std::string val = entryPath.value(); + TAG_LOGD(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "not found srcEntry: %{public}s", srcEntry.c_str()); + return DEFAULT_ENTRY_ABILITY_CLASS; + } + TAG_LOGD(AAFwkTag::ETSRUNTIME, "srcEntry as class: %{public}s", srcEntry.c_str()); + return HandleOhmUrlSrcEntry(srcEntry); + } + TAG_LOGD(AAFwkTag::ETSRUNTIME, "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() < DOT_START_LEN) { + return false; + } + std::string prefix = str.substr(0, DOT_START_LEN); + 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 ETSRuntime::appLibPaths_; + +std::unique_ptr ETSRuntime::Create(const Options &options, Runtime *jsRuntime) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "Create called"); + if (jsRuntime == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null jsRuntime"); + return std::unique_ptr(); + } + std::unique_ptr instance; + if (!options.preload) { + auto preloadedInstance = Runtime::GetPreloaded(); +#ifdef SUPPORT_SCREEN + // reload ace if compatible mode changes + if (Ace::AceForwardCompatibility::PipelineChanged() && preloadedInstance) { + preloadedInstance.reset(); + } +#endif + if (preloadedInstance && preloadedInstance->GetLanguage() == Runtime::Language::ETS) { + instance.reset(static_cast(preloadedInstance.release())); + } else { + instance = std::make_unique(); + } + } else { + instance = std::make_unique(); + } + + if (!instance->Initialize(options, jsRuntime)) { + return std::unique_ptr(); + } + EntryPathManager::GetInstance().Init(); + + return instance; +} + +void ETSRuntime::SetAppLibPath(const AppLibPathMap &appLibPaths) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "SetAppLibPath called"); + EtsEnv::ETSEnvironment::InitETSSDKNS(ETS_RT_PATH); + EtsEnv::ETSEnvironment::InitETSSysNS(ETS_SYSLIB_PATH); +} + +bool ETSRuntime::Initialize(const Options &options, Runtime *jsRuntime) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "Initialize called"); + if (options.lang != GetLanguage()) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "language mismatch"); + return false; + } + + if (!CreateEtsEnv(options, jsRuntime)) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Create etsEnv failed"); + return false; + } + + apiTargetVersion_ = options.apiTargetVersion; + TAG_LOGD(AAFwkTag::ETSRUNTIME, "Initialize: %{public}d", apiTargetVersion_); + + return true; +} + +void ETSRuntime::RegisterUncaughtExceptionHandler(void *uncaughtExceptionInfo) +{ + if (etsEnv_ == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null etsEnv_"); + return; + } + + if (uncaughtExceptionInfo == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null uncaughtExceptionInfo"); + return; + } + + auto handle = static_cast(uncaughtExceptionInfo); + if (handle != nullptr) { + etsEnv_->RegisterUncaughtExceptionHandler(*handle); + } +} + +ETSRuntime::~ETSRuntime() +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "~ETSRuntime called"); + Deinitialize(); +} + +void ETSRuntime::Deinitialize() +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "Deinitialize called"); +} + +bool ETSRuntime::CreateEtsEnv(const Options &options, Runtime *jsRuntime) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "CreateEtsEnv called"); + etsEnv_ = std::make_shared(); + std::vector aniOptions; + 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::ETSRUNTIME, "aotFileString: %{public}s", aotFileString.c_str()); + aniOptions.push_back(ani_option { "--ext:--enable-an", nullptr }); + } + + if (!etsEnv_->Initialize(static_cast(jsRuntime)->GetNapiEnv(), aniOptions)) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Init EtsEnv failed"); + return false; + } + + return true; +} + +ani_env *ETSRuntime::GetAniEnv() +{ + if (etsEnv_ == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null etsEnv_"); + return nullptr; + } + return etsEnv_->GetAniEnv(); +} + +void ETSRuntime::PreloadModule(const std::string &moduleName, const std::string &hapPath, + bool isEsMode, bool useCommonTrunk) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "moduleName: %{public}s", moduleName.c_str()); + ani_env *aniEnv = GetAniEnv(); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetAniEnv failed"); + return; + } + + ani_class cls = nullptr; + ani_object object = nullptr; + if (!LoadAbcLinker(aniEnv, moduleName, cls, object)) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "LoadAbcLinker failed"); + return; + } + return; +} + +std::unique_ptr ETSRuntime::LoadModule(const std::string &moduleName, + const std::string &modulePath, const std::string &hapPath, bool esmodule, bool useCommonChunk, + const std::string &srcEntrance) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "Load module(%{public}s, %{public}s, %{public}s, %{public}s)", + moduleName.c_str(), modulePath.c_str(), hapPath.c_str(), srcEntrance.c_str()); + + std::string path = moduleName; + auto pos = path.find("::"); + if (pos != std::string::npos) { + path.erase(pos, path.size() - pos); + moduleName_ = path; + } + TAG_LOGD(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "make module file path: %{public}s failed", modulePath.c_str()); + return nullptr; + } + } + std::unique_ptr etsNativeReference = LoadEtsModule(moduleName, fileName, hapPath, srcEntrance); + return etsNativeReference; +} + +bool ETSRuntime::LoadAbcLinker(ani_env *env, const std::string &moduleName, ani_class &abcCls, ani_object &abcObj) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env"); + return false; + } + ani_class stringCls = nullptr; + if (env->FindClass("Lstd/core/String;", &stringCls) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "FindClass Lstd/core/String Failed"); + return false; + } + std::string modulePath = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_PATH; + ani_string aniStr; + if (env->String_NewUTF8(modulePath.c_str(), modulePath.size(), &aniStr) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "String_NewUTF8 modulePath Failed"); + return false; + } + ani_ref undefinedRef; + if (env->GetUndefined(&undefinedRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetUndefined failed"); + return false; + } + ani_array_ref refArray; + if (env->Array_New_Ref(stringCls, 1, undefinedRef, &refArray) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Array_New_Ref Failed"); + return false; + } + if (env->Array_Set_Ref(refArray, 0, aniStr) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Array_Set_Ref Failed"); + return false; + } + if (env->FindClass("Lstd/core/AbcRuntimeLinker;", &abcCls) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "FindClass AbcRuntimeLinker failed"); + return false; + } + ani_method method = nullptr; + if (env->Class_FindMethod(abcCls, "", "Lstd/core/RuntimeLinker;[Lstd/core/String;:V", &method) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Class_FindMethod ctor failed"); + return false; + } + env->ResetError(); + if (env->Object_New(abcCls, method, &abcObj, undefinedRef, refArray) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Object_New AbcRuntimeLinker failed"); + HandleUncaughtError(); + return false; + } + return true; +} + +std::unique_ptr ETSRuntime::LoadEtsModule(const std::string &moduleName, + const std::string &fileName, const std::string &hapPath, const std::string &srcEntrance) +{ + auto etsNativeReference = std::make_unique(); + ani_env *aniEnv = GetAniEnv(); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetAniEnv failed"); + return std::make_unique(); + } + ani_class cls = nullptr; + ani_object object = nullptr; + if (!LoadAbcLinker(aniEnv, moduleName_, cls, object)) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "LoadAbcLinker failed"); + return std::make_unique(); + } + ani_method loadClassMethod = nullptr; + if (aniEnv->Class_FindMethod(cls, "loadClass", "Lstd/core/String;Z:Lstd/core/Class;", &loadClassMethod) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "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; + if (aniEnv->Object_CallMethod_Ref(object, loadClassMethod, &entryClassRef, entryClassStr, false) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "Class_FindMethod ctor failed"); + return std::make_unique(); + } + ani_object entryObject = nullptr; + if (aniEnv->Object_New(entryClass, entryMethod, &entryObject) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Object_New AbcRuntimeLinker failed"); + return std::make_unique(); + } + ani_ref entryObjectRef = nullptr; + if (aniEnv->GlobalReference_Create(entryObject, &entryObjectRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "GlobalReference_Create failed"); + return std::make_unique(); + } + etsNativeReference->aniCls = entryClass; + etsNativeReference->aniObj = entryObject; + etsNativeReference->aniRef = entryObjectRef; + return etsNativeReference; +} + +void ETSRuntime::HandleUncaughtError() +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "HandleUncaughtError called"); + if (etsEnv_ == nullptr) { + return; + } + etsEnv_->HandleUncaughtError(); +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/runtime/js_runtime.cpp b/frameworks/native/runtime/js_runtime.cpp index 4b04f031c12..cb7c9a217e7 100644 --- a/frameworks/native/runtime/js_runtime.cpp +++ b/frameworks/native/runtime/js_runtime.cpp @@ -1765,5 +1765,12 @@ 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/runtime.cpp b/frameworks/native/runtime/runtime.cpp index 26362dd0dbb..0beb1b43953 100644 --- a/frameworks/native/runtime/runtime.cpp +++ b/frameworks/native/runtime/runtime.cpp @@ -19,6 +19,7 @@ #include "cj_runtime.h" #endif #include "js_runtime.h" +#include "ets_runtime.h" namespace OHOS { namespace AbilityRuntime { @@ -26,8 +27,45 @@ namespace { std::unique_ptr g_preloadedInstance; } -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.emplace_back(JsRuntime::Create(options)); + break; +#ifdef CJ_FRONTEND + case Runtime::Language::CJ: + options.lang = Runtime::Language::CJ; + runtimes.emplace_back(CJRuntime::Create(options)); + break; +#endif + case Runtime::Language::ETS: { + options.lang = Runtime::Language::JS; + auto &jsRuntime = runtimes.emplace_back(JsRuntime::Create(options)); + options.lang = Runtime::Language::ETS; + runtimes.emplace_back(ETSRuntime::Create(options, + static_cast(jsRuntime.get()))); + break; + } + default: + runtimes.emplace_back(std::unique_ptr()); + break; + } + } + return runtimes; +} + +std::unique_ptr Runtime::Create(Runtime::Options &options) +{ + std::unique_ptr jsRuntime; + if (options.lang == Runtime::Language::ETS) { + options.lang = Runtime::Language::JS; + jsRuntime = JsRuntime::Create(options); + options.lang = Runtime::Language::ETS; + } switch (options.lang) { case Runtime::Language::JS: return JsRuntime::Create(options); @@ -35,6 +73,8 @@ std::unique_ptr Runtime::Create(const Runtime::Options& options) case Runtime::Language::CJ: return CJRuntime::Create(options); #endif + case Runtime::Language::ETS: + return ETSRuntime::Create(options, jsRuntime.get()); default: return std::unique_ptr(); } diff --git a/frameworks/simulator/ability_simulator/src/js_runtime.cpp b/frameworks/simulator/ability_simulator/src/js_runtime.cpp index 7e173d8a07c..3bed249733a 100644 --- a/frameworks/simulator/ability_simulator/src/js_runtime.cpp +++ b/frameworks/simulator/ability_simulator/src/js_runtime.cpp @@ -158,5 +158,8 @@ std::unique_ptr JsRuntime::LoadSystemModuleByEngine( napi_create_reference(env, instanceValue, 1, &result); return std::unique_ptr(reinterpret_cast(result)); } + +void JsRuntime::RegisterUncaughtExceptionHandler(void *uncaughtExceptionInfo) +{} } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/inner_api/runtime/BUILD.gn b/interfaces/inner_api/runtime/BUILD.gn index 836d126b83b..9b78f45490f 100644 --- a/interfaces/inner_api/runtime/BUILD.gn +++ b/interfaces/inner_api/runtime/BUILD.gn @@ -52,6 +52,7 @@ ohos_shared_library("runtime") { branch_protector_ret = "pac_ret" include_dirs = [ + "${ability_runtime_path}/ets_environment/interfaces/inner_api", "${ability_runtime_path}/services/abilitymgr/include", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_bundle_manager_helper", "${ability_runtime_path}/frameworks/ets/ani/enum_convert", @@ -60,6 +61,8 @@ ohos_shared_library("runtime") { sources = [ "${ability_runtime_native_path}/appkit/ability_bundle_manager_helper/bundle_mgr_helper.cpp", + "${ability_runtime_native_path}/runtime/ets_data_struct_converter.cpp", + "${ability_runtime_native_path}/runtime/ets_runtime.cpp", "${ability_runtime_native_path}/runtime/hdc_register.cpp", "${ability_runtime_native_path}/runtime/js_app_process_state.cpp", "${ability_runtime_native_path}/runtime/js_data_struct_converter.cpp", @@ -90,6 +93,7 @@ ohos_shared_library("runtime") { "${ability_runtime_innerkits_path}/connect_server_manager:connect_server_manager", "${ability_runtime_native_path}/ability/native:ability_business_error", "${ability_runtime_native_path}/appkit:appkit_manager_helper", + "${ability_runtime_path}/ets_environment/frameworks/ets_environment:ets_environment", "${ability_runtime_path}/js_environment/frameworks/js_environment:js_environment", "${ability_runtime_services_path}/common:app_util", "${ability_runtime_services_path}/common:record_cost_time_util", @@ -122,6 +126,7 @@ ohos_shared_library("runtime") { "jsoncpp:jsoncpp", "napi:ace_napi", "resource_management:global_resmgr", + "runtime_core:ani", "samgr:samgr_proxy", "zlib:shared_libz", "faultloggerd:libfaultloggerd", diff --git a/interfaces/inner_api/runtime/include/cj_runtime.h b/interfaces/inner_api/runtime/include/cj_runtime.h index 0d406dc6f33..04778b74008 100644 --- a/interfaces/inner_api/runtime/include/cj_runtime.h +++ b/interfaces/inner_api/runtime/include/cj_runtime.h @@ -55,6 +55,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; } @@ -72,8 +74,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(); diff --git a/interfaces/inner_api/runtime/include/ets_data_struct_converter.h b/interfaces/inner_api/runtime/include/ets_data_struct_converter.h new file mode 100644 index 00000000000..1f196768185 --- /dev/null +++ b/interfaces/inner_api/runtime/include/ets_data_struct_converter.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_DATA_STRUCT_CONVERTER_H +#define OHOS_ABILITY_RUNTIME_ETS_DATA_STRUCT_CONVERTER_H + +#include "ani.h" +#include "launch_param.h" + +namespace OHOS { +namespace AbilityRuntime { +bool WrapLaunchParam(ani_env *env, const AAFwk::LaunchParam &launchParam, ani_object &object); +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_DATA_STRUCT_CONVERTER_H diff --git a/interfaces/inner_api/runtime/include/ets_runtime.h b/interfaces/inner_api/runtime/include/ets_runtime.h new file mode 100644 index 00000000000..7b1126f1c0e --- /dev/null +++ b/interfaces/inner_api/runtime/include/ets_runtime.h @@ -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. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_RUNTIME_H +#define OHOS_ABILITY_RUNTIME_ETS_RUNTIME_H + +#include +#include +#include +#include +#include +#include +#include + +#include "runtime.h" +#include "js_runtime.h" +#include "ets_exception_callback.h" +#include "ani.h" + +using AppLibPathMap = std::map>; +using AppLibPathVec = std::vector; + +namespace OHOS { +namespace EtsEnv { +class ETSEnvironment; +} // namespace EtsEnv + +namespace AbilityRuntime { +struct ETSNativeReference { + ani_class aniCls = nullptr; + ani_object aniObj = nullptr; + ani_ref aniRef = nullptr; +}; + +class ETSRuntime : public Runtime { +public: + static std::unique_ptr Create(const Options &options, Runtime *jsRuntime); + static void SetAppLibPath(const AppLibPathMap &appLibPaths); + ~ETSRuntime() override; + Language GetLanguage() const override + { + return Language::ETS; + } + + 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 {}; + 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; + 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 LoadEtsModule(const std::string &moduleName, const std::string &fileName, + const std::string &hapPath, const std::string &srcEntrance); + void HandleUncaughtError(); + +private: + bool Initialize(const Options &options, Runtime *jsRuntime); + void Deinitialize(); + bool CreateEtsEnv(const Options &options, Runtime *jsRuntime); + bool LoadAbcLinker(ani_env *env, const std::string &moduleName, ani_class &abcCls, ani_object &abcObj); + std::shared_ptr etsEnv_; + int32_t apiTargetVersion_ = 0; + std::string codePath_; + static AppLibPathVec appLibPaths_; + std::string moduleName_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_RUNTIME_H diff --git a/interfaces/inner_api/runtime/include/js_runtime.h b/interfaces/inner_api/runtime/include/js_runtime.h index d573886e3c6..dcc410a2cf0 100644 --- a/interfaces/inner_api/runtime/include/js_runtime.h +++ b/interfaces/inner_api/runtime/include/js_runtime.h @@ -103,6 +103,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 {} bool PopPreloadObj(const std::string& key, std::unique_ptr& obj); void StartDebugMode(const DebugOption debugOption) override; void SetDebugOption(const DebugOption debugOption) override; @@ -156,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 5b3312752f1..faf6685bbd2 100644 --- a/interfaces/inner_api/runtime/include/runtime.h +++ b/interfaces/inner_api/runtime/include/runtime.h @@ -27,14 +27,23 @@ namespace AppExecFwk { class EventRunner; } // namespace AppExecFwk namespace AbilityRuntime { +namespace { +const std::string CODE_LANGUAGE_ARKTS_1_0 = "1.1"; +const std::string CODE_LANGUAGE_ARKTS_1_2 = "1.2"; +const std::string CODE_LANGUAGE_ARKTS_HYBRID = "hybrid"; +} // namespace + class Runtime { public: enum class Language { JS = 0, - CJ + CJ, + ETS, + UNKNOWN, }; struct Options { + std::map langs; Language lang = Language::JS; std::string bundleName; std::string moduleName; @@ -80,7 +89,8 @@ public: bool isDeveloperMode; }; - static std::unique_ptr Create(const Options& options); + static std::vector> CreateRuntimes(Options &options); + static std::unique_ptr Create(Options &options); static void SavePreloaded(std::unique_ptr&& instance); static std::unique_ptr GetPreloaded(); @@ -108,6 +118,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; @@ -122,6 +134,7 @@ public: Runtime(Runtime&&) = delete; Runtime& operator=(const Runtime&) = delete; Runtime& operator=(Runtime&&) = delete; + virtual void RegisterUncaughtExceptionHandler(void *uncaughtExceptionInfo) {} }; } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/kits/native/ability/native/ability_loader.h b/interfaces/kits/native/ability/native/ability_loader.h index 23947ec898c..18fd34818d5 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::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/ets_ui_ability.h b/interfaces/kits/native/ability/native/ability_runtime/ets_ui_ability.h new file mode 100644 index 00000000000..cecb7e7a835 --- /dev/null +++ b/interfaces/kits/native/ability/native/ability_runtime/ets_ui_ability.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_ETS_UI_ABILITY_H +#define OHOS_ABILITY_RUNTIME_ETS_UI_ABILITY_H + +#include "ets_runtime.h" +#include "ui_ability.h" + +namespace OHOS { +namespace AbilityRuntime { +using AbilityHandler = AppExecFwk::AbilityHandler; +using AbilityInfo = AppExecFwk::AbilityInfo; +using OHOSApplication = AppExecFwk::OHOSApplication; +using Want = AppExecFwk::Want; + +class EtsUIAbility : public UIAbility { +public: + /** + * @brief Create a EtsUIAbility instance through the singleton pattern + * @param runtime The runtime of the ability + * @return Returns the EtsUIability Instance point + */ + static UIAbility *Create(const std::unique_ptr &runtime); + + explicit EtsUIAbility(ETSRuntime &etsRuntime); + ~EtsUIAbility() 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 EtssUIability + * @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 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 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; + +#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 onSceneDestroyed() 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" ets function barely. + * + * @param want Want + */ + void CallOnForegroundFunc(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; + +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 UpdateEtsWindowStage(ani_ref windowStage); + + std::shared_ptr etsWindowStageObj_; + int32_t windowMode_ = 0; +#endif + +private: + bool CallObjectMethod(bool withResult, const char *name, const char *signature, ...); + ani_object CreateAppWindowStage(); + void SetAbilityContext(std::shared_ptr abilityInfo, std::shared_ptr want, + const std::string &moduleName, const std::string &srcPath, const std::shared_ptr &application); + void DoOnForegroundForSceneIsNull(const Want &want); + void UpdateAbilityObj(std::shared_ptr abilityInfo, + const std::string &moduleName, const std::string &srcPath); + bool BindNativeMethods(); + + ETSRuntime &etsRuntime_; + std::shared_ptr shellContextRef_; + std::shared_ptr etsAbilityObj_; + static std::once_flag singletonFlag_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_UI_ABILITY_H diff --git a/interfaces/kits/native/appkit/ability_delegator/ability_delegator.h b/interfaces/kits/native/appkit/ability_delegator/ability_delegator.h index 19f5e0cc52d..217952afe26 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. @@ -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); /** @@ -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,7 +259,7 @@ 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. @@ -273,42 +273,42 @@ public: * * @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 3f649fb32ca..f2700318243 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 "ets_runtime.h" class NativeReference; namespace OHOS { namespace AppExecFwk { -struct ADelegatorAbilityProperty { + +struct BaseDelegatorAbilityProperty { // token of ability sptr token_; // name of ability @@ -35,10 +37,15 @@ 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 ETSDelegatorAbilityProperty : public BaseDelegatorAbilityProperty { + std::weak_ptr object_; +}; + struct DelegatorAbilityStageProperty { std::string moduleName_; std::string srcEntrance_; 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 1fd257b8231..57f9c383be7 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 6a91fec7732..f899604dd30 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/app/application_data_manager.h b/interfaces/kits/native/appkit/app/application_data_manager.h index 3f8bb01b4e7..08ddb478a74 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 NotifyETSUnhandledException(const std::string &errMsg); void RemoveErrorObserver(); bool NotifyExceptionObject(const AppExecFwk::ErrorObject &errorObj); bool NotifyCJExceptionObject(const AppExecFwk::ErrorObject &errorObj); + bool NotifyETSExceptionObject(const AppExecFwk::ErrorObject &errorObj); private: ApplicationDataManager(); diff --git a/interfaces/kits/native/appkit/app/main_thread.h b/interfaces/kits/native/appkit/app/main_thread.h index cd5a86a89c5..a7e7e7f9415 100644 --- a/interfaces/kits/native/appkit/app/main_thread.h +++ b/interfaces/kits/native/appkit/app/main_thread.h @@ -40,6 +40,7 @@ #include "resource_manager.h" #include "runtime.h" #include "watchdog.h" +#include "ets_runtime.h" #ifdef CJ_FRONTEND #include "cj_envsetup.h" @@ -323,6 +324,8 @@ public: CJUncaughtExceptionInfo CreateCjExceptionInfo(const std::string &bundleName, uint32_t versionCode, const std::string &hapPath); #endif + EtsEnv::ETSUncaughtExceptionInfo CreateEtsExceptionInfo(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. * @@ -622,7 +625,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 @@ -797,6 +801,12 @@ private: void SetAppDebug(uint32_t modeFlag, bool isDebug); void GetPluginNativeLibPath(std::vector &pluginBundleInfos, AppLibPathMap &appLibPaths); + void AddRuntimeLang(ApplicationInfo &appInfo, AbilityRuntime::Runtime::Options &options); + bool IsNeedEtsInit(const ApplicationInfo &appInfo); + const std::unique_ptr &GetVerOneRuntime( + const ApplicationInfo &appInfo, const std::vector> &runtimes); + void SetJsIdleCallback(const std::weak_ptr &wpApplication, + const std::unique_ptr &runtime); std::vector fileEntries_; std::vector nativeFileEntries_; diff --git a/interfaces/kits/native/appkit/app/ohos_application.h b/interfaces/kits/native/appkit/app/ohos_application.h index 783bd601495..3bc1c5697a8 100644 --- a/interfaces/kits/native/appkit/app/ohos_application.h +++ b/interfaces/kits/native/appkit/app/ohos_application.h @@ -27,6 +27,7 @@ #include "ability_stage_context.h" #include "application_configuration_manager.h" #include "app_launch_data.h" +#include "runtime.h" namespace OHOS { namespace AbilityRuntime { @@ -49,11 +50,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 @@ -168,12 +169,19 @@ public: */ std::shared_ptr GetAppContext() const; + /** + * @brief return the application runtimes + * + * @param runtime + */ + const std::vector> &GetRuntime() const; + /** * @brief return the application runtime * * @param runtime */ - const std::unique_ptr& GetRuntime() const; + const std::unique_ptr &GetRuntime(const std::string &language) const; /* * @@ -236,6 +244,8 @@ public: void PreloadAppStartup(const BundleInfo &bundleInfo, const std::string &preloadModuleName, std::shared_ptr startupTaskData); + void SetCJApplication(bool isCJApplication = false); + private: void UpdateAppContextResMgr(const Configuration &config); bool IsUpdateColorNeeded(Configuration &config, AbilityRuntime::SetLevel level); @@ -251,14 +261,17 @@ 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::shared_ptr configuration_ = nullptr; std::map extensionTypeMap_; + bool isCJApplication_ = false; }; } // namespace AppExecFwk } // namespace OHOS -- Gitee From 764b0ea433f686cad56ea88ffb42c02032d919a3 Mon Sep 17 00:00:00 2001 From: zhangzezhong Date: Mon, 9 Jun 2025 13:42:00 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20all.?= =?UTF-8?q?diff?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- all.diff | 4890 ------------------------------------------------------ 1 file changed, 4890 deletions(-) delete mode 100644 all.diff diff --git a/all.diff b/all.diff deleted file mode 100644 index 69cef01d987..00000000000 --- a/all.diff +++ /dev/null @@ -1,4890 +0,0 @@ -diff --git a/bundle.json b/bundle.json -index 4c096e00742f53b3a363ec9cf51c5c0f44f802eb..3cce00df14d16eedee08485ca7446239fa74cc87 100644 ---- a/bundle.json -+++ b/bundle.json -@@ -135,6 +135,7 @@ - "//foundation/ability/ability_runtime/frameworks/js/napi:napi_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/ets_environment/frameworks/ets_environment:ets_environment", - "//foundation/ability/ability_runtime/js_environment/frameworks/js_environment:js_environment", - "//foundation/ability/ability_runtime/services/abilitymgr/etc:appfwk_etc", - "//foundation/ability/ability_runtime/services/dialog_ui/ams_system_dialog:dialog_hap", -@@ -261,6 +262,15 @@ - }, - "name": "//foundation/ability/ability_runtime/js_environment/frameworks/js_environment:js_environment" - }, -+ { -+ "header": { -+ "header_base": "//foundation/ability/ability_runtime/ets_environment/interfaces/inner_api", -+ "header_files": [ -+ "ets_environment.h" -+ ] -+ }, -+ "name": "//foundation/ability/ability_runtime/ets_environment/frameworks/ets_environment:ets_environment" -+ }, - { - "header": { - "header_base": "//foundation/ability/ability_runtime/cj_environment/interfaces/inner_api", -diff --git a/ets_environment/ets_environment.gni b/ets_environment/ets_environment.gni -new file mode 100644 -index 0000000000000000000000000000000000000000..b044edbd9d057f4000e0f620cea72d1567c63af0 ---- /dev/null -+++ b/ets_environment/ets_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/ets_environment" -diff --git a/ets_environment/frameworks/ets_environment/BUILD.gn b/ets_environment/frameworks/ets_environment/BUILD.gn -new file mode 100644 -index 0000000000000000000000000000000000000000..a3f1835114b196ff9b7335949951658505490076 ---- /dev/null -+++ b/ets_environment/frameworks/ets_environment/BUILD.gn -@@ -0,0 +1,63 @@ -+# Copyright (c) 2025 Huawei Device Co., Ltd. -+# Licensed under the Apache License, Version 2.0 (the "License"); -+# you may not use this file except in compliance with the License. -+# You may obtain a copy of the License at -+# -+# http://www.apache.org/licenses/LICENSE-2.0 -+# -+# Unless required by applicable law or agreed to in writing, software -+# distributed under the License is distributed on an "AS IS" BASIS, -+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+# See the License for the specific language governing permissions and -+# limitations under the License. -+ -+import("//build/ohos.gni") -+import("//foundation/ability/ability_runtime/ability_runtime.gni") -+import("../../ets_environment.gni") -+ -+config("public_ets_environment_config") { -+ include_dirs = [ -+ "include", -+ "${ability_runtime_path}/ets_environment/interfaces/inner_api", -+ "${ability_runtime_path}/interfaces/inner_api", -+ "${ability_runtime_services_path}/common/include", -+ ] -+} -+ -+ohos_shared_library("ets_environment") { -+ branch_protector_ret = "pac_ret" -+ -+ public_configs = [ ":public_ets_environment_config" ] -+ -+ sanitize = { -+ cfi = true -+ cfi_cross_dso = true -+ debug = false -+ } -+ -+ sources = [ -+ "src/dynamic_loader.cpp", -+ "src/ets_environment.cpp", -+ ] -+ -+ defines = [] -+ -+ external_deps = [ -+ "c_utils:utils", -+ "eventhandler:libeventhandler", -+ "faultloggerd:libunwinder", -+ "hilog:libhilog", -+ "json:nlohmann_json_static", -+ "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/ets_environment/frameworks/ets_environment/src/dynamic_loader.cpp b/ets_environment/frameworks/ets_environment/src/dynamic_loader.cpp -new file mode 100644 -index 0000000000000000000000000000000000000000..6b2934937440590733373c543d94982429321f8b ---- /dev/null -+++ b/ets_environment/frameworks/ets_environment/src/dynamic_loader.cpp -@@ -0,0 +1,194 @@ -+/* -+ * Copyright (c) 2025 Huawei Device Co., Ltd. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT 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 -+#include -+#include -+#include -+#include -+ -+#include "hilog_tag_wrapper.h" -+ -+namespace OHOS { -+namespace EtsEnv { -+namespace { -+constexpr int32_t ERROR_BUF_SIZE = 255; -+static char g_dlError[ERROR_BUF_SIZE]; -+static std::unordered_set g_hasInited; -+static std::string g_sharedLibsSonames = ""; -+constexpr int32_t OUT_OF_MEMORY = 12; -+constexpr int32_t FILE_EXISTS = 17; -+constexpr int32_t 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.empty()) { -+ return; -+ } -+ g_sharedLibsSonames = -+ // 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"; -+} -+} // namespace -+ -+void DynamicInitNamespace(Dl_namespace *ns, void *parent, const char *entries, const char *name) -+{ -+ if (ns == nullptr || entries == nullptr || name == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Invaild args for init namespace."); -+ return; -+ } -+ if (g_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) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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, "ets_app") != 0) { -+ dlns_inherit(ns, ¤t, "allow_all_shared_libs"); -+ } else { -+ InitSharedLibsSonames(); -+ dlns_inherit(ns, ¤t, g_sharedLibsSonames.c_str()); -+ } -+ g_hasInited.insert(std::string(name)); -+} -+ -+void *DynamicLoadLibrary(Dl_namespace *ns, const char *dlPath, uint32_t mode) -+{ -+ if (ns == nullptr) { -+ dlns_get("ets_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; -+} -+} // namespace EtsEnv -+} // namespace OHOS -\ No newline at end of file -diff --git a/ets_environment/frameworks/ets_environment/src/ets_environment.cpp b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp -new file mode 100644 -index 0000000000000000000000000000000000000000..ef09b6afd092495df3721d791a47ba284632af36 ---- /dev/null -+++ b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp -@@ -0,0 +1,356 @@ -+/* -+ * Copyright (c) 2025 Huawei Device Co., Ltd. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT 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_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 "unwinder.h" -+ -+#ifdef SUPPORT_GRAPHICS -+#include "ui_content.h" -+#endif // SUPPORT_GRAPHICS -+ -+namespace OHOS { -+namespace EtsEnv { -+namespace { -+const char ETS_CREATE_VM[] = "ANI_CreateVM"; -+const char ETS_ANI_GET_CREATEDVMS[] = "ANI_GetCreatedVMs"; -+const char ETS_LIB_PATH[] = "libets_interop_js_napi.z.so"; -+const char BOOT_PATH[] = "/system/framework/bootpath.json"; -+const char BACKTRACE[] = "=====================Backtrace========================"; -+ -+using CreateVMETSRuntimeType = 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 ETS_SDK_NSNAME[] = "ets_sdk"; -+const char ETS_SYS_NSNAME[] = "ets_system"; -+} // namespace -+ -+ETSRuntimeAPI ETSEnvironment::lazyApis_ {}; -+ -+bool ETSEnvironment::LoadBootPathFile(std::string &bootfiles) -+{ -+ std::ifstream inFile; -+ inFile.open(BOOT_PATH, std::ios::in); -+ if (!inFile.is_open()) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "read json error"); -+ return false; -+ } -+ nlohmann::json jsonObject = nlohmann::json::parse(inFile); -+ if (jsonObject.is_discarded()) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "json discarded error"); -+ inFile.close(); -+ return false; -+ } -+ -+ if (jsonObject.is_null() || jsonObject.empty()) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "json value of %{public}s is empty", key.c_str()); -+ continue; -+ } -+ if (!bootfiles.empty()) { -+ bootfiles += ":"; -+ } -+ bootfiles += jsonValue.c_str(); -+ } -+ } -+ inFile.close(); -+ return true; -+} -+ -+bool ETSEnvironment::LoadRuntimeApis() -+{ -+ static bool isRuntimeApiLoaded { false }; -+ if (isRuntimeApiLoaded) { -+ return true; -+ } -+ -+ Dl_namespace ns; -+ dlns_get(ETS_SDK_NSNAME, &ns); -+ auto dso = DynamicLoadLibrary(&ns, ETS_LIB_PATH, 1); -+ if (!dso) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "load library failed: %{public}s", ETS_LIB_PATH); -+ return false; -+ } -+ -+ if (!LoadSymbolCreateVM(dso, lazyApis_) || -+ !LoadSymbolANIGetCreatedVMs(dso, lazyApis_)) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "load symbol failed"); -+ return false; -+ } -+ -+ isRuntimeApiLoaded = true; -+ return true; -+} -+ -+std::string ETSEnvironment::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(); -+ if (elfFile == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null elfFile"); -+ break; -+ } -+ std::string buildId = elfFile->GetBuildId(); -+ if (i != 0 && !buildId.empty()) { -+ addBuildId += tempStr + "(" + buildId + ")" + "\n"; -+ } else { -+ addBuildId += tempStr + "\n"; -+ } -+ } -+ i++; -+ } -+ return addBuildId; -+} -+ -+void ETSEnvironment::RegisterUncaughtExceptionHandler(const ETSUncaughtExceptionInfo &handle) -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "RegisterUncaughtExceptionHandler called"); -+ uncaughtExceptionInfo_ = handle; -+} -+ -+bool ETSEnvironment::LoadSymbolCreateVM(void *handle, ETSRuntimeAPI &apis) -+{ -+ auto symbol = dlsym(handle, ETS_CREATE_VM); -+ if (symbol == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "runtime api not found: %{public}s", ETS_CREATE_VM); -+ return false; -+ } -+ apis.ANI_CreateVM = reinterpret_cast(symbol); -+ -+ return true; -+} -+ -+bool ETSEnvironment::LoadSymbolANIGetCreatedVMs(void *handle, ETSRuntimeAPI &apis) -+{ -+ auto symbol = dlsym(handle, ETS_ANI_GET_CREATEDVMS); -+ if (symbol == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "runtime api not found: %{public}s", ETS_ANI_GET_CREATEDVMS); -+ return false; -+ } -+ apis.ANI_GetCreatedVMs = reinterpret_cast(symbol); -+ -+ return true; -+} -+ -+void ETSEnvironment::InitETSSDKNS(const std::string &path) -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "InitETSSDKNS: %{public}s", path.c_str()); -+ Dl_namespace ndk; -+ Dl_namespace ns; -+ DynamicInitNamespace(&ns, nullptr, path.c_str(), ETS_SDK_NSNAME); -+ dlns_get("ndk", &ndk); -+ dlns_inherit(&ns, &ndk, "allow_all_shared_libs"); -+} -+ -+void ETSEnvironment::InitETSSysNS(const std::string &path) -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "InitETSSysNS: %{public}s", path.c_str()); -+ Dl_namespace ets_sdk; -+ Dl_namespace ndk; -+ Dl_namespace ns; -+ dlns_get(ETS_SDK_NSNAME, &ets_sdk); -+ DynamicInitNamespace(&ns, &ets_sdk, path.c_str(), ETS_SYS_NSNAME); -+ dlns_get("ndk", &ndk); -+ dlns_inherit(&ns, &ndk, "allow_all_shared_libs"); -+} -+ -+bool ETSEnvironment::Initialize(napi_env napiEnv, std::vector &options) -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "StartRuntime called"); -+ if (!LoadRuntimeApis()) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "LoadRuntimeApis failed"); -+ return false; -+ } -+ std::string bootfiles; -+ if (!LoadBootPathFile(bootfiles)) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "bootString %{public}s", bootString.c_str()); -+ options.push_back(ani_option { bootString.c_str(), nullptr }); -+ std::string schedulingExternal = optionPrefix + "--coroutine-enable-external-scheduling=true"; -+ ani_option schedulingExternalOption = { schedulingExternal.data(), nullptr }; -+ options.push_back(schedulingExternalOption); -+ -+ 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 enableVerfication = optionPrefix + "--verification-enabled=true"; -+ ani_option enableVerficationOption = { enableVerfication.data(), nullptr }; -+ options.push_back(enableVerficationOption); -+ -+ std::string verificationMode = optionPrefix + "--verification-mode=on-the-fly"; -+ ani_option verificationModeOption = { verificationMode.data(), nullptr }; -+ options.push_back(verificationModeOption); -+ -+ std::string interop = optionPrefix + "interop"; -+ ani_option interopOption = { interop.data(), (void *)napiEnv }; -+ options.push_back(interopOption); -+ ani_options optionsPtr = { options.size(), options.data() }; -+ ani_status status = ANI_ERROR; -+ if ((status = lazyApis_.ANI_CreateVM(&optionsPtr, ANI_VERSION_1, &vmEntry_.aniVm_)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "ANI_CreateVM failed %{public}d", status); -+ return false; -+ } -+ if ((status = vmEntry_.aniVm_->GetEnv(ANI_VERSION_1, &vmEntry_.aniEnv_)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetEnv failed %{public}d", status); -+ return false; -+ } -+ return true; -+} -+ -+ani_env *ETSEnvironment::GetAniEnv() -+{ -+ return vmEntry_.aniEnv_; -+} -+ -+void ETSEnvironment::HandleUncaughtError() -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "HandleUncaughtError called"); -+ const EtsEnv::ETSErrorObject errorObj = GetETSErrorObject(); -+ std::string errorStack = errorObj.stack; -+ if (errorStack.empty()) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "errorStack is empty"); -+ return; -+ } -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "uncaughtTask called"); -+ uncaughtExceptionInfo_.uncaughtTask(summary, errorObj); -+ } -+} -+ -+EtsEnv::ETSErrorObject ETSEnvironment::GetETSErrorObject() -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "GetETSErrorObject called"); -+ ani_boolean errorExists = ANI_FALSE; -+ ani_status status = ANI_ERROR; -+ auto aniEnv = GetAniEnv(); -+ if (aniEnv == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env"); -+ return EtsEnv::ETSErrorObject(); -+ } -+ if ((status = aniEnv->ExistUnhandledError(&errorExists)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "ExistUnhandledError failed, status : %{public}d", status); -+ return EtsEnv::ETSErrorObject(); -+ } -+ if (errorExists == ANI_FALSE) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "not exist error"); -+ return EtsEnv::ETSErrorObject(); -+ } -+ ani_error aniError = nullptr; -+ if ((status = aniEnv->GetUnhandledError(&aniError)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetUnhandledError failed, status : %{public}d", status); -+ return EtsEnv::ETSErrorObject(); -+ } -+ if ((status = aniEnv->ResetError()) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "ResetError failed, status : %{public}d", status); -+ return EtsEnv::ETSErrorObject(); -+ } -+ std::string errorMsg = GetErrorProperty(aniError, "message"); -+ std::string errorName = GetErrorProperty(aniError, "name"); -+ std::string errorStack = GetErrorProperty(aniError, "stack"); -+ const EtsEnv::ETSErrorObject errorObj = { -+ .name = errorName, -+ .message = errorMsg, -+ .stack = errorStack -+ }; -+ return errorObj; -+} -+ -+std::string ETSEnvironment::GetErrorProperty(ani_error aniError, const char *property) -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "GetErrorProperty called"); -+ auto aniEnv = GetAniEnv(); -+ std::string propertyValue; -+ ani_status status = ANI_ERROR; -+ ani_type errorType = nullptr; -+ if ((status = aniEnv->Object_GetType(aniError, &errorType)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "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::ETSRUNTIME, "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::ETSRUNTIME, "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::ETSRUNTIME, "String_GetUTF8SubString failed, status : %{public}d", status); -+ return propertyValue; -+ } -+ propertyValue.resize(sz); -+ return propertyValue; -+} -+} // namespace EtsEnv -+} // namespace OHOS -diff --git a/ets_environment/interfaces/inner_api/dynamic_loader.h b/ets_environment/interfaces/inner_api/dynamic_loader.h -new file mode 100644 -index 0000000000000000000000000000000000000000..6155e797e8e59b1b312376065d856cd554f78d0e ---- /dev/null -+++ b/ets_environment/interfaces/inner_api/dynamic_loader.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_DYNAMIC_LOADER_H -+#define OHOS_ABILITY_RUNTIME_DYNAMIC_LOADER_H -+ -+#include -+#include -+ -+namespace OHOS { -+namespace EtsEnv { -+void *DynamicLoadLibrary(Dl_namespace *ns, const char *dlPath, uint32_t 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); -+} // namespace EtsEnv -+} // namespace OHOS -+#endif // OHOS_ABILITY_RUNTIME_DYNAMIC_LOADER_H -diff --git a/ets_environment/interfaces/inner_api/ets_environment.h b/ets_environment/interfaces/inner_api/ets_environment.h -new file mode 100644 -index 0000000000000000000000000000000000000000..2c37be0747a6ab938aaace948f8600d0f22bdb82 ---- /dev/null -+++ b/ets_environment/interfaces/inner_api/ets_environment.h -@@ -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. -+ */ -+ -+#ifndef OHOS_ABILITY_RUNTIME_ETS_ENVIRONMENT_H -+#define OHOS_ABILITY_RUNTIME_ETS_ENVIRONMENT_H -+ -+#include -+#include -+#include -+#include -+ -+#include "ani.h" -+#include "ets_exception_callback.h" -+#include "event_handler.h" -+#include "napi/native_api.h" -+ -+namespace OHOS { -+namespace EtsEnv { -+struct ETSRuntimeAPI { -+ 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); -+}; -+ -+class ETSEnvironment final : public std::enable_shared_from_this { -+public: -+ ETSEnvironment() {}; -+ -+ static void InitETSSDKNS(const std::string &path); -+ static void InitETSSysNS(const std::string &path); -+ -+ bool Initialize(napi_env napiEnv, std::vector &options); -+ void RegisterUncaughtExceptionHandler(const ETSUncaughtExceptionInfo &handle); -+ ani_env *GetAniEnv(); -+ void HandleUncaughtError(); -+ -+ struct VMEntry { -+ ani_vm *aniVm_; -+ ani_env *aniEnv_; -+ VMEntry() -+ { -+ aniVm_ = nullptr; -+ aniEnv_ = nullptr; -+ } -+ }; -+ -+private: -+ bool LoadRuntimeApis(); -+ bool LoadSymbolCreateVM(void *handle, ETSRuntimeAPI &apis); -+ bool LoadSymbolANIGetCreatedVMs(void *handle, ETSRuntimeAPI &apis); -+ bool LoadBootPathFile(std::string &bootfiles); -+ std::string GetBuildId(std::string stack); -+ EtsEnv::ETSErrorObject GetETSErrorObject(); -+ std::string GetErrorProperty(ani_error aniError, const char *property); -+ static ETSRuntimeAPI lazyApis_; -+ VMEntry vmEntry_; -+ ETSUncaughtExceptionInfo uncaughtExceptionInfo_; -+}; -+} // namespace EtsEnv -+} // namespace OHOS -+#endif // OHOS_ABILITY_RUNTIME_ETS_ENVIRONMENT_H -diff --git a/ets_environment/interfaces/inner_api/ets_exception_callback.h b/ets_environment/interfaces/inner_api/ets_exception_callback.h -new file mode 100644 -index 0000000000000000000000000000000000000000..2d935af7f1fd3cd58a70487b8d17801b3a91e8fc ---- /dev/null -+++ b/ets_environment/interfaces/inner_api/ets_exception_callback.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_EXCEPTION_CALLBACK_H -+#define OHOS_ABILITY_RUNTIME_ETS_EXCEPTION_CALLBACK_H -+ -+#include -+ -+namespace OHOS { -+namespace EtsEnv { -+struct ETSErrorObject { -+ std::string name; -+ std::string message; -+ std::string stack; -+}; -+ -+struct ETSUncaughtExceptionInfo { -+ std::function uncaughtTask; -+}; -+} // namespace EtsEnv -+} // namespace OHOS -+#endif // OHOS_ABILITY_RUNTIME_ETS_EXCEPTION_CALLBACK_H -diff --git a/frameworks/cj/ffi/BUILD.gn b/frameworks/cj/ffi/BUILD.gn -index 03df8fc4f901e9ed2625b89d0ed895e1b7ca304b..b9797aa47928e3073e7626a0c69d8642909fee08 100644 ---- a/frameworks/cj/ffi/BUILD.gn -+++ b/frameworks/cj/ffi/BUILD.gn -@@ -69,6 +69,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/ani_common/src/ani_common_util.cpp b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp -index d909518810b8d955c92bda96a4ac85f8fa1893ed..8d2a9961007957785d74ef7f94cca3fb0912d8a4 100644 ---- a/frameworks/ets/ani/ani_common/src/ani_common_util.cpp -+++ b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp -@@ -93,7 +93,7 @@ bool GetFieldBoolByName(ani_env *env, ani_object object, const char *name, bool - return false; - } - ani_boolean isUndefined = true; -- if ((status = env->Reference_IsUndefined(object, &isUndefined)) != ANI_OK) { -+ if ((status = env->Reference_IsUndefined(field, &isUndefined)) != ANI_OK) { - TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); - return false; - } -@@ -103,7 +103,7 @@ bool GetFieldBoolByName(ani_env *env, ani_object object, const char *name, bool - } - ani_boolean aniValue = false; - if ((status = env->Object_CallMethodByName_Boolean( -- reinterpret_cast(object), "booleanValue", nullptr, &aniValue)) != ANI_OK) { -+ reinterpret_cast(field), "booleanValue", nullptr, &aniValue)) != ANI_OK) { - TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); - return false; - } -@@ -143,7 +143,7 @@ bool GetFieldStringByName(ani_env *env, ani_object object, const char *name, std - return false; - } - ani_boolean isUndefined = true; -- if ((status = env->Reference_IsUndefined(object, &isUndefined)) != ANI_OK) { -+ if ((status = env->Reference_IsUndefined(field, &isUndefined)) != ANI_OK) { - TAG_LOGE(AAFwkTag::ANI, "status: %{public}d", status); - return false; - } -diff --git a/frameworks/ets/ani/ani_common/src/ani_common_want.cpp b/frameworks/ets/ani/ani_common/src/ani_common_want.cpp -index 0f6f8ad80cbbba99916ca1bb186f24dcb14ef313..0fcacfbf24a0f9ecd0c6d9a4d0fe3bb239a6d063 100644 ---- a/frameworks/ets/ani/ani_common/src/ani_common_want.cpp -+++ b/frameworks/ets/ani/ani_common/src/ani_common_want.cpp -@@ -61,6 +61,10 @@ bool InnerUnwrapWantParams(ani_env* env, ani_object wantObject, AAFwk::WantParam - ani_object WrapWant(ani_env *env, const AAFwk::Want &want) - { - TAG_LOGD(AAFwkTag::ANI, "WrapWant called"); -+ if (env == nullptr) { -+ TAG_LOGE(AAFwkTag::ANI, "null env"); -+ return nullptr; -+ } - ani_class cls = nullptr; - ani_status status = ANI_ERROR; - ani_method method = nullptr; -diff --git a/frameworks/ets/ani/enum_convert/ani_enum_convert.h b/frameworks/ets/ani/enum_convert/ani_enum_convert.h -index 6234c8bc88fa2631cee71c7abafbbfe85279ba1f..a61bbe0b3d7e02b3b5590b832bb0c42cf6acf98c 100644 ---- a/frameworks/ets/ani/enum_convert/ani_enum_convert.h -+++ b/frameworks/ets/ani/enum_convert/ani_enum_convert.h -@@ -47,7 +47,7 @@ static bool EnumConvert_EtsToNative(ani_env *env, ani_enum_item enumItem, T &res - ani_int intValue{}; - status = env->EnumItem_GetValue_Int(enumItem, &intValue); - if (ANI_OK != status) { -- TAG_LOGE(AAFwkTag::EtsRUNTIME, "EnumConvert_EtsToNative failed, status : %{public}d", status); -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "EnumConvert_EtsToNative failed, status : %{public}d", status); - return false; - } - result = static_cast(intValue); -@@ -56,12 +56,12 @@ static bool EnumConvert_EtsToNative(ani_env *env, ani_enum_item enumItem, T &res - ani_string strValue{}; - status = env->EnumItem_GetValue_String(enumItem, &strValue); - if (ANI_OK != status) { -- TAG_LOGE(AAFwkTag::EtsRUNTIME, "EnumItem_GetValue_String failed, status : %{public}d", status); -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "EnumItem_GetValue_String failed, status : %{public}d", status); - return false; - } - return GetStdString(env, strValue, result); - } else { -- TAG_LOGE(AAFwkTag::EtsRUNTIME, "Enum convert failed: type not supported"); -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Enum convert failed: type not supported"); - return false; - } - } -@@ -78,7 +78,7 @@ static bool EnumConvert_NativeToEts(ani_env *env, const char *enumName, const T - ani_enum aniEnum{}; - ani_status status = env->FindEnum(enumName, &aniEnum); - if (ANI_OK != status) { -- TAG_LOGE(AAFwkTag::EtsRUNTIME, "Enum convert FindEnum failed: %{public}s status: %{public}d", enumName, status); -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Enum convert FindEnum failed: %{public}s status: %{public}d", enumName, status); - return false; - } - constexpr int32_t loopMaxNum = 1000; -@@ -86,7 +86,7 @@ static bool EnumConvert_NativeToEts(ani_env *env, const char *enumName, const T - ani_enum_item enumItem{}; - status = env->Enum_GetEnumItemByIndex(aniEnum, index, &enumItem); - if (ANI_OK != status) { -- TAG_LOGE(AAFwkTag::EtsRUNTIME, -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, - "Enum convert Enum_GetEnumItemByIndex failed: enumName:%{public}s index:%{public}d status:%{public}d", - enumName, index, status); - return false; -@@ -98,7 +98,7 @@ static bool EnumConvert_NativeToEts(ani_env *env, const char *enumName, const T - return true; - } - } -- TAG_LOGE(AAFwkTag::EtsRUNTIME, "EnumConvert_NativeToEts failed enumName: %{public}s", enumName); -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "EnumConvert_NativeToEts failed enumName: %{public}s", enumName); - return false; - } - } -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..4c72a344a577c6744bbaabbb1d0bcf6438229369 ---- /dev/null -+++ b/frameworks/ets/ets/@ohos.app.ability.AbilityConstant.ets -@@ -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. -+ */ -+ -+namespace AbilityConstant { -+ export interface LaunchParam { -+ launchReason: LaunchReason; -+ launchReasonMessage?: string; -+ lastExitReason: LastExitReason; -+ lastExitMessage: string; -+ } -+ -+ 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 = ''; -+} -+ -+export default AbilityConstant; -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..c4a6565f60e989af6d6f36af74fd1bf0953087b9 ---- /dev/null -+++ b/frameworks/ets/ets/@ohos.app.ability.StartOptions.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 StartOptions { -+ displayId?: number; -+} -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..f53af8d5f3a52ec32b5a2d7f95d02ff0d5803e17 ---- /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 Want from '@ohos.app.ability.Want'; -+import window from '@ohos.window'; -+import { AbilityUtils } from './utils/AbilityUtils'; -+ -+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 isOverride = AbilityUtils.isOverride(derivedClassType, "onDestroyAsync", uiAbilityClassType); -+ if (isOverride) { -+ this.onDestroyAsync().then(() => this.nativeOnDestroyCallback()); -+ return true; -+ } -+ this.onDestroy(); -+ return false; -+ } -+ -+ launchWant: Want = new Want(); -+ lastRequestWant: Want = new Want(); -+ -+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { -+ } -+ -+ onWindowStageCreate(windowStage: window.WindowStage): void { -+ } -+ -+ onWindowStageDestroy(): 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.Want.ets b/frameworks/ets/ets/@ohos.app.ability.Want.ets -new file mode 100644 -index 0000000000000000000000000000000000000000..c1a0ec876e06dda04f1f9587c7f8e5a831f6fdc1 ---- /dev/null -+++ b/frameworks/ets/ets/@ohos.app.ability.Want.ets -@@ -0,0 +1,232 @@ -+/* -+ * Copyright (c) 2025 Huawei Device Co., Ltd. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT 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' -+ -+type valueType = NullishType; -+const DOMAIN_ID = 0xD001300; -+const TAG = 'WantSerializeTool'; -+ -+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)) { -+ // 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, 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 RecordSerializeTool.stringify(obj as Object as Record); -+ } catch (err) { -+ hilog.error(DOMAIN_ID, TAG, `RecordSerializeTool.stringify error: ${err}`); -+ return ''; -+ } -+ } -+ -+ public static parseNoThrow(text: string): Record { -+ try { -+ return RecordSerializeTool.parse(text) as Object as Record; -+ } catch (err) { -+ hilog.error(DOMAIN_ID, TAG, `RecordSerializeTool.parse error: ${err}`); -+ 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; -+} -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..721b9d7eed16e8db803946e9c4644a02f9667979 ---- /dev/null -+++ b/frameworks/ets/ets/@ohos.app.ability.wantConstant.ets -@@ -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. -+ */ -+ -+namespace wantConstant { -+ export enum Action { -+ ACTION_HOME = 'ohos.want.action.home', -+ ACTION_DIAL = 'ohos.want.action.dial', -+ ACTION_SEARCH = 'ohos.want.action.search', -+ ACTION_WIRELESS_SETTINGS = 'ohos.settings.wireless', -+ ACTION_MANAGE_APPLICATIONS_SETTINGS = 'ohos.settings.manage.applications', -+ ACTION_APPLICATION_DETAILS_SETTINGS = 'ohos.settings.application.details', -+ ACTION_SET_ALARM = 'ohos.want.action.setAlarm', -+ ACTION_SHOW_ALARMS = 'ohos.want.action.showAlarms', -+ ACTION_SNOOZE_ALARM = 'ohos.want.action.snoozeAlarm', -+ ACTION_DISMISS_ALARM = 'ohos.want.action.dismissAlarm', -+ ACTION_DISMISS_TIMER = 'ohos.want.action.dismissTimer', -+ ACTION_SEND_SMS = 'ohos.want.action.sendSms', -+ ACTION_CHOOSE = 'ohos.want.action.choose', -+ ACTION_IMAGE_CAPTURE = 'ohos.want.action.imageCapture', -+ ACTION_VIDEO_CAPTURE = 'ohos.want.action.videoCapture', -+ ACTION_SELECT = 'ohos.want.action.select', -+ ACTION_SEND_DATA = 'ohos.want.action.sendData', -+ ACTION_SEND_MULTIPLE_DATA = 'ohos.want.action.sendMultipleData', -+ ACTION_SCAN_MEDIA_FILE = 'ohos.want.action.scanMediaFile', -+ ACTION_VIEW_DATA = 'ohos.want.action.viewData', -+ ACTION_EDIT_DATA = 'ohos.want.action.editData', -+ INTENT_PARAMS_INTENT = 'ability.want.params.INTENT', -+ INTENT_PARAMS_TITLE = 'ability.want.params.TITLE', -+ ACTION_FILE_SELECT = 'ohos.action.fileSelect', -+ PARAMS_STREAM = 'ability.params.stream', -+ ACTION_APP_ACCOUNT_OAUTH = 'ohos.account.appAccount.action.oauth' -+ } -+ -+ export enum Flags { -+ FLAG_AUTH_READ_URI_PERMISSION = 0x00000001, -+ FLAG_AUTH_WRITE_URI_PERMISSION = 0x00000002, -+ FLAG_ABILITY_FORWARD_RESULT = 0x00000004, -+ FLAG_ABILITY_CONTINUATION = 0x00000008, -+ FLAG_NOT_OHOS_COMPONENT = 0x00000010, -+ FLAG_ABILITY_FORM_ENABLED = 0x00000020, -+ FLAG_AUTH_PERSISTABLE_URI_PERMISSION = 0x00000040, -+ FLAG_AUTH_PREFIX_URI_PERMISSION = 0x00000080, -+ FLAG_ABILITYSLICE_MULTI_DEVICE = 0x00000100, -+ FLAG_START_FOREGROUND_ABILITY = 0x00000200, -+ FLAG_ABILITY_CONTINUATION_REVERSIBLE = 0x00000400, -+ FLAG_INSTALL_ON_DEMAND = 0x00000800, -+ FLAG_INSTALL_WITH_BACKGROUND_MODE = 0x80000000, -+ FLAG_ABILITY_CLEAR_MISSION = 0x00008000, -+ FLAG_ABILITY_NEW_MISSION = 0x10000000, -+ FLAG_ABILITY_MISSION_TOP = 0x20000000 -+ } -+} -+ -+export default wantConstant; -diff --git a/frameworks/ets/ets/BUILD.gn b/frameworks/ets/ets/BUILD.gn -index 4c90291f2d28ac92432c2eef65f3b3e6cc5dee4d..26efc114b17d9134c8341923f9b935867e0a6ae8 100644 ---- a/frameworks/ets/ets/BUILD.gn -+++ b/frameworks/ets/ets/BUILD.gn -@@ -31,8 +31,110 @@ ohos_prebuilt_etc("ability_runtime_base_context_abc_etc") { - deps = [ ":ability_runtime_base_context_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_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_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_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_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" ] -+} -+ - group("ets_packages") { - deps = [ - ":ability_runtime_base_context_abc_etc", -+ # ":ability_runtime_ui_ability_abc_etc", -+ ":ability_runtime_ability_constant_abc_etc", -+ ":ability_runtime_ability_utils_abc_etc", -+ ":ability_runtime_start_options_abc_etc", -+ ":ability_runtime_want_abc_etc", -+ ":ability_runtime_want_constant_abc_etc", - ] - } -diff --git a/frameworks/ets/ets/utils/AbilityUtils.ets b/frameworks/ets/ets/utils/AbilityUtils.ets -new file mode 100644 -index 0000000000000000000000000000000000000000..573c5d3a20767a270ff0fff7f770c905f7817cd7 ---- /dev/null -+++ b/frameworks/ets/ets/utils/AbilityUtils.ets -@@ -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 hilog from '@ohos.hilog' -+ -+const DOMAIN_ID = 0xD001300; -+const TAG = 'AbilityUtils'; -+const LEVEL = 100; -+ -+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 isOverride(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 true; -+ } -+ } -+ } -+ let baseType = currType.getBaseType(); -+ if (baseType.equals(currType)) { -+ hilog.error(DOMAIN_ID, TAG, `isOverride: baseType equals currType (${currType.getName()})`); -+ return undefined; -+ } -+ level++; -+ if (level >= LEVEL) { -+ hilog.error(DOMAIN_ID, TAG, `isOverride: inheritance level >= ${LEVEL}, abort`); -+ return undefined; -+ } -+ currType = baseType; -+ } catch (err) { -+ hilog.error(DOMAIN_ID, TAG, `isOverride error: ${err}`); -+ return undefined; -+ } -+ } -+ return false; -+ } -+} -diff --git a/frameworks/native/ability/native/BUILD.gn b/frameworks/native/ability/native/BUILD.gn -index 52d727221b7f227bb5bed8c59e3ca21fceff1a4d..d21d8b1129d240a23ee1550d664ecd511bba9e73 100644 ---- a/frameworks/native/ability/native/BUILD.gn -+++ b/frameworks/native/ability/native/BUILD.gn -@@ -155,6 +155,7 @@ ohos_shared_library("abilitykit_utils") { - "${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", -+ "${ability_runtime_innerkits_path}/runtime/include", - "${ability_runtime_innerkits_path}/wantagent/include", - "${ability_runtime_services_path}/abilitymgr/include/utils", - "${ability_runtime_services_path}/abilitymgr/include", -@@ -764,6 +765,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", -@@ -771,6 +773,7 @@ ohos_shared_library("uiabilitykit_native") { - ] - - sources = [ -+ "${ability_runtime_native_path}/ability/native/ability_runtime/ets_ui_ability.cpp", - "${ability_runtime_native_path}/ability/native/ability_runtime/js_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", -@@ -802,6 +805,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", - ] -@@ -822,6 +826,7 @@ ohos_shared_library("uiabilitykit_native") { - "ipc:ipc_napi", - "json:nlohmann_json_static", - "resource_management:global_resmgr", -+ "runtime_core:ani", - "samgr:samgr_proxy", - ] - public_external_deps = [ -diff --git a/frameworks/native/ability/native/ability_loader.cpp b/frameworks/native/ability/native/ability_loader.cpp -index 1c26bd9c57a4b15d9a00a68a3e7fae84e03eb1b1..1a8f740a1c2e2bef0216900f7cb276eea9397081 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()); - 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/ets_ui_ability.cpp b/frameworks/native/ability/native/ability_runtime/ets_ui_ability.cpp -new file mode 100644 -index 0000000000000000000000000000000000000000..dac5f017eb87aa6839e24f030f7ed97935305a34 ---- /dev/null -+++ b/frameworks/native/ability/native/ability_runtime/ets_ui_ability.cpp -@@ -0,0 +1,694 @@ -+/* -+ * Copyright (c) 2025 Huawei Device Co., Ltd. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#include "ets_ui_ability.h" -+ -+#include -+ -+#include "ani_common_want.h" -+#include "app_recovery.h" -+#include "connection_manager.h" -+#include "display_util.h" -+#include "ets_data_struct_converter.h" -+#include "hilog_tag_wrapper.h" -+#include "hitrace_meter.h" -+#include "string_wrapper.h" -+#ifdef SUPPORT_SCREEN -+// #include "ani_window_stage.h" -+#endif -+ -+namespace OHOS { -+namespace AbilityRuntime { -+std::once_flag EtsUIAbility::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 -+#ifdef SUPPORT_SCREEN -+constexpr int32_t BASE_DISPLAY_ID_NUM(10); -+#endif -+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 called"); -+ if (env == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); -+ return; -+ } -+ ani_long destroyCallbackPtr = 0; -+ ani_status status = ANI_ERROR; -+ if ((status = env->Object_GetFieldByName_Long(aniObj, "destroyCallbackPoint", &destroyCallbackPtr)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "Object_GetFieldByName_Long status: %{public}d", status); -+ return; -+ } -+ if (destroyCallbackPtr == 0) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null destroyCallbackPtr"); -+ return; -+ } -+ auto *callbackInfo = reinterpret_cast *>(destroyCallbackPtr); -+ if (callbackInfo == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null callbackInfo"); -+ return; -+ } -+ callbackInfo->Call(); -+ AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo); -+} -+} // namespace -+ -+UIAbility *EtsUIAbility::Create(const std::unique_ptr &runtime) -+{ -+ return new (std::nothrow) EtsUIAbility(static_cast(*runtime)); -+} -+ -+EtsUIAbility::EtsUIAbility(ETSRuntime &etsRuntime) : etsRuntime_(etsRuntime) -+{ -+ TAG_LOGD(AAFwkTag::UIABILITY, "EtsUIAbility called"); -+} -+ -+EtsUIAbility::~EtsUIAbility() -+{ -+ TAG_LOGI(AAFwkTag::UIABILITY, "~EtsUIAbility called"); -+ if (shellContextRef_ && shellContextRef_->aniRef) { -+ auto env = etsRuntime_.GetAniEnv(); -+ if (env != nullptr) { -+ env->GlobalReference_Delete(shellContextRef_->aniRef); -+ } -+ } -+ if (etsWindowStageObj_ && etsWindowStageObj_->aniRef) { -+ auto env = etsRuntime_.GetAniEnv(); -+ if (env != nullptr) { -+ env->GlobalReference_Delete(etsWindowStageObj_->aniRef); -+ } -+ } -+} -+ -+void EtsUIAbility::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); -+ std::string srcPath(abilityInfo->package); -+ if (!abilityInfo->isModuleJson) { -+ 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, "etsAbility srcPath: %{public}s", srcPath.c_str()); -+ } -+ -+ std::string moduleName(abilityInfo->moduleName); -+ moduleName.append("::").append(abilityInfo->name); -+ SetAbilityContext(abilityInfo, record->GetWant(), moduleName, srcPath, application); -+} -+ -+bool EtsUIAbility::BindNativeMethods() -+{ -+ auto env = etsRuntime_.GetAniEnv(); -+ if (env == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); -+ 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 EtsUIAbility::UpdateAbilityObj( -+ std::shared_ptr abilityInfo, const std::string &moduleName, const std::string &srcPath) -+{ -+ std::string key = moduleName + "::" + srcPath; -+ std::unique_ptr moduleObj = nullptr; -+ etsAbilityObj_ = etsRuntime_.LoadModule(moduleName, srcPath, abilityInfo->hapPath, -+ abilityInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE, false, abilityInfo->srcEntrance); -+ if (!BindNativeMethods()) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "BindNativeMethods failed"); -+ return; -+ } -+} -+ -+void EtsUIAbility::SetAbilityContext(std::shared_ptr abilityInfo, std::shared_ptr want, -+ const std::string &moduleName, const std::string &srcPath, const std::shared_ptr &application) -+{ -+ TAG_LOGD(AAFwkTag::UIABILITY, "SetAbilityContext called"); -+ UpdateAbilityObj(abilityInfo, moduleName, srcPath); -+ if (etsAbilityObj_ == nullptr || abilityContext_ == nullptr || want == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null etsAbilityObj_ or abilityContext_ or want"); -+ return; -+ } -+} -+ -+void EtsUIAbility::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 (!etsAbilityObj_) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "not found Ability.js"); -+ return; -+ } -+ auto env = etsRuntime_.GetAniEnv(); -+ if (env == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); -+ return; -+ } -+ ani_object wantObj = OHOS::AppExecFwk::WrapWant(env, want); -+ if (wantObj == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); -+ return; -+ } -+ ani_status status = ANI_ERROR; -+ if ((status = env->Object_SetFieldByName_Ref(etsAbilityObj_->aniObj, "launchWant", wantObj)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "launchWant Object_SetFieldByName_Ref status: %{public}d", status); -+ return; -+ } -+ if ((status = env->Object_SetFieldByName_Ref(etsAbilityObj_->aniObj, "lastRequestWant", wantObj)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "lastRequestWant Object_SetFieldByName_Ref status: %{public}d", status); -+ return; -+ } -+ auto launchParam = GetLaunchParam(); -+ if (InsightIntentExecuteParam::IsInsightIntentExecute(want)) { -+ launchParam.launchReason = AAFwk::LaunchReason::LAUNCHREASON_INSIGHT_INTENT; -+ } -+ ani_object launchParamObj = nullptr; -+ if (!WrapLaunchParam(env, launchParam, launchParamObj)) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "WrapLaunchParam failed"); -+ return; -+ } -+ CallObjectMethod(false, "onCreate", nullptr, wantObj, launchParamObj); -+ TAG_LOGD(AAFwkTag::UIABILITY, "OnStart end"); -+} -+ -+void EtsUIAbility::OnStop() -+{ -+ HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); -+ TAG_LOGD(AAFwkTag::UIABILITY, "OnStop called"); -+ if (abilityContext_) { -+ TAG_LOGD(AAFwkTag::UIABILITY, "set terminating true"); -+ abilityContext_->SetTerminating(true); -+ } -+ UIAbility::OnStop(); -+ -+ CallObjectMethod(false, "onDestroy", nullptr); -+ OnStopCallback(); -+ TAG_LOGD(AAFwkTag::UIABILITY, "OnStop end"); -+} -+ -+void EtsUIAbility::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, "OnStop Begin"); -+ if (abilityContext_) { -+ TAG_LOGD(AAFwkTag::UIABILITY, "set terminating true"); -+ abilityContext_->SetTerminating(true); -+ } -+ UIAbility::OnStop(); -+ 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); -+ -+ auto env = etsRuntime_.GetAniEnv(); -+ if (env == nullptr || etsAbilityObj_ == nullptr) { -+ isAsyncCallback = false; -+ OnStop(); -+ return; -+ } -+ -+ ani_long destroyCallbackPoint = reinterpret_cast(callbackInfo); -+ ani_status status = -+ env->Object_SetFieldByName_Long(etsAbilityObj_->aniObj, "destroyCallbackPoint", destroyCallbackPoint); -+ if (status != ANI_OK) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "Object_SetFieldByName_Long status: %{public}d", status); -+ return; -+ } -+ isAsyncCallback = CallObjectMethod(true, "callOnDestroy", ":Z"); -+ TAG_LOGD(AAFwkTag::UIABILITY, "callOnDestroy isAsyncCallback: %{public}d", isAsyncCallback); -+ if (!isAsyncCallback) { -+ OnStopCallback(); -+ return; -+ } -+ TAG_LOGD(AAFwkTag::UIABILITY, "OnStop end"); -+} -+ -+void EtsUIAbility::OnStopCallback() -+{ -+ bool ret = ConnectionManager::GetInstance().DisconnectCaller(AbilityContext::token_); -+ if (ret) { -+ ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid()); -+ TAG_LOGD(AAFwkTag::UIABILITY, "the service connection is not disconnected"); -+ } -+} -+ -+#ifdef SUPPORT_SCREEN -+void EtsUIAbility::OnSceneCreated() -+{ -+ HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); -+ TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); -+ UIAbility::OnSceneCreated(); -+ auto etsAppWindowStage = CreateAppWindowStage(); -+ if (etsAppWindowStage == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null etsAppWindowStage"); -+ return; -+ } -+ UpdateEtsWindowStage(reinterpret_cast(etsAppWindowStage)); -+ auto env = etsRuntime_.GetAniEnv(); -+ if (env == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); -+ return; -+ } -+ etsWindowStageObj_ = std::make_shared(); -+ etsWindowStageObj_->aniObj = etsAppWindowStage; -+ ani_ref entryObjectRef = nullptr; -+ env->GlobalReference_Create(etsAppWindowStage, &entryObjectRef); -+ etsWindowStageObj_->aniRef = entryObjectRef; -+ CallObjectMethod(false, "onWindowStageCreate", nullptr, etsAppWindowStage); -+ TAG_LOGD(AAFwkTag::UIABILITY, "OnSceneCreated end"); -+} -+ -+void EtsUIAbility::onSceneDestroyed() -+{ -+ TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); -+ UIAbility::onSceneDestroyed(); -+ UpdateEtsWindowStage(nullptr); -+ CallObjectMethod(false, "onWindowStageDestroy", nullptr); -+ if (scene_ != nullptr) { -+ auto window = scene_->GetMainWindow(); -+ if (window != nullptr) { -+ TAG_LOGD(AAFwkTag::UIABILITY, "unRegisterDisplaymovelistener"); -+ window->UnregisterDisplayMoveListener(abilityDisplayMoveListener_); -+ } -+ } -+ TAG_LOGD(AAFwkTag::UIABILITY, "onSceneDestroyed end"); -+} -+ -+void EtsUIAbility::OnForeground(const Want &want) -+{ -+ HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); -+ TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); -+ UIAbility::OnForeground(want); -+ if (CheckIsSilentForeground()) { -+ TAG_LOGD(AAFwkTag::UIABILITY, "silent foreground, do not call 'onForeground'"); -+ return; -+ } -+ CallOnForegroundFunc(want); -+} -+ -+void EtsUIAbility::CallOnForegroundFunc(const Want &want) -+{ -+ auto env = etsRuntime_.GetAniEnv(); -+ if (env == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); -+ return; -+ } -+ if (etsAbilityObj_ == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null etsAbilityObj_"); -+ return; -+ } -+ ani_status status = ANI_ERROR; -+ ani_ref wantRef = OHOS::AppExecFwk::WrapWant(env, want); -+ if (wantRef == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); -+ return; -+ } -+ if ((status = env->Object_SetFieldByName_Ref(etsAbilityObj_->aniObj, "lastRequestWant", wantRef)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "lastRequestWant Object_SetFieldByName_Ref status: %{public}d", status); -+ return; -+ } -+ CallObjectMethod(false, "onForeground", nullptr, wantRef); -+ TAG_LOGD(AAFwkTag::UIABILITY, "CallOnForegroundFunc end"); -+} -+ -+void EtsUIAbility::OnBackground() -+{ -+ HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); -+ TAG_LOGD(AAFwkTag::UIABILITY, "ability: %{public}s", GetAbilityName().c_str()); -+ CallObjectMethod(false, "onBackground", nullptr); -+ UIAbility::OnBackground(); -+ TAG_LOGD(AAFwkTag::UIABILITY, "OnBackground end"); -+} -+ -+ani_object EtsUIAbility::CreateAppWindowStage() -+{ -+ HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); -+ auto env = etsRuntime_.GetAniEnv(); -+ if (env == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); -+ return nullptr; -+ } -+ auto scene = GetScene(); -+ if (scene == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "scene not found"); -+ return nullptr; -+ } -+ ani_object etsWindowStage = nullptr; -+ // ani_object etsWindowStage = CreateAniWindowStage(env, scene); -+ if (etsWindowStage == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null etsWindowStage"); -+ return nullptr; -+ } -+ return etsWindowStage; -+} -+ -+void EtsUIAbility::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 EtsUIAbility::IsRestorePageStack(const Want &want) -+{ -+ return want.GetBoolParam(SUPPORT_CONTINUE_PAGE_STACK_PROPERTY_NAME, true); -+} -+ -+void EtsUIAbility::RestorePageStack(const Want &want) -+{ -+ if (IsRestorePageStack(want)) { -+ std::string pageStack; -+ GetPageStackFromWant(want, pageStack); -+ // to be done: AniSetUIContent -+ } -+} -+ -+void EtsUIAbility::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); -+ NotifyContinuationResult(want, true); -+ } else if (ShouldRecoverState(want)) { -+ std::string pageStack = abilityRecovery_->GetSavedPageStack(AppExecFwk::StateReason::DEVELOPER_REQUEST); -+ -+ auto mainWindow = scene_->GetMainWindow(); -+ if (mainWindow == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null mainWindow"); -+ } -+ } 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 EtsUIAbility::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_); -+ HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, "scene_->GoForeground"); -+ scene_->GoForeground(UIAbility::sceneFlag_); -+ TAG_LOGD(AAFwkTag::UIABILITY, "DoOnForeground end"); -+} -+ -+void EtsUIAbility::DoOnForegroundForSceneIsNull(const Want &want) -+{ -+ scene_ = std::make_shared(); -+ int32_t displayId = AAFwk::DisplayUtil::GetDefaultDisplayId(); -+ if (setting_ != nullptr) { -+ std::string strDisplayId = setting_->GetProperty(OHOS::AppExecFwk::AbilityStartSetting::WINDOW_DISPLAY_ID_KEY); -+ std::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"); -+ 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 EtsUIAbility::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); -+ NotifyContinuationResult(want, true); -+} -+ -+void EtsUIAbility::UpdateEtsWindowStage(ani_ref windowStage) -+{ -+ TAG_LOGD(AAFwkTag::UIABILITY, "UpdateEtsWindowStage called"); -+ if (shellContextRef_ == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null shellContextRef_"); -+ return; -+ } -+ auto env = etsRuntime_.GetAniEnv(); -+ if (env == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); -+ return; -+ } -+ ani_status status = ANI_ERROR; -+ if (windowStage == nullptr) { -+ ani_ref undefinedRef = nullptr; -+ env->GetUndefined(&undefinedRef); -+ if ((status = env->Object_SetFieldByName_Ref(shellContextRef_->aniObj, "windowStage", undefinedRef)) != -+ ANI_OK) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "Object_SetFieldByName_Ref status: %{public}d", status); -+ return; -+ } -+ return; -+ } -+ if ((status = env->Object_SetFieldByName_Ref(shellContextRef_->aniObj, "windowStage", windowStage)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "Object_SetFieldByName_Ref status: %{public}d", status); -+ return; -+ } -+} -+#endif -+ -+void EtsUIAbility::OnNewWant(const Want &want) -+{ -+ TAG_LOGD(AAFwkTag::UIABILITY, "OnNewWant called"); -+ UIAbility::OnNewWant(want); -+ -+#ifdef SUPPORT_SCREEN -+ if (scene_) { -+ scene_->OnNewWant(want); -+ } -+#endif -+ auto env = etsRuntime_.GetAniEnv(); -+ if (env == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); -+ return; -+ } -+ if (etsAbilityObj_ == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null etsAbilityObj_"); -+ return; -+ } -+ ani_object wantObj = OHOS::AppExecFwk::WrapWant(env, want); -+ if (wantObj == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null wantObj"); -+ return; -+ } -+ ani_status status = env->Object_SetFieldByName_Ref(etsAbilityObj_->aniObj, "lastRequestWant", wantObj); -+ if (status != ANI_OK) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "lastRequestWant Object_SetFieldByName_Ref status: %{public}d", status); -+ return; -+ } -+ auto launchParam = GetLaunchParam(); -+ if (InsightIntentExecuteParam::IsInsightIntentExecute(want)) { -+ launchParam.launchReason = AAFwk::LaunchReason::LAUNCHREASON_INSIGHT_INTENT; -+ } -+ ani_object launchParamObj = nullptr; -+ if (!WrapLaunchParam(env, launchParam, launchParamObj)) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "WrapLaunchParam failed"); -+ return; -+ } -+ std::string methodName = "OnNewWant"; -+ CallObjectMethod(false, "onNewWant", nullptr, wantObj, launchParamObj); -+ TAG_LOGD(AAFwkTag::UIABILITY, "OnNewWant end"); -+} -+ -+void EtsUIAbility::OnAbilityResult(int requestCode, int resultCode, const Want &resultData) -+{ -+ TAG_LOGD(AAFwkTag::UIABILITY, "OnAbilityResult 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, "OnAbilityResult end"); -+} -+ -+bool EtsUIAbility::CallObjectMethod(bool withResult, const char *name, const char *signature, ...) -+{ -+ HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name); -+ TAG_LOGI(AAFwkTag::UIABILITY, "EtsUIAbility call ets, name: %{public}s", name); -+ if (etsAbilityObj_ == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null etsAbilityObj"); -+ return false; -+ } -+ auto env = etsRuntime_.GetAniEnv(); -+ if (env == nullptr) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "null env"); -+ return false; -+ } -+ auto obj = etsAbilityObj_->aniObj; -+ auto cls = etsAbilityObj_->aniCls; -+ -+ ani_method method {}; -+ ani_status status = env->Class_FindMethod(cls, name, signature, &method); -+ if (status != ANI_OK) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "Class_FindMethod status: %{public}d", status); -+ env->ResetError(); -+ return false; -+ } -+ 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, "Object_CallMethod_Boolean_V status: %{public}d", status); -+ etsRuntime_.HandleUncaughtError(); -+ return false; -+ } -+ va_end(args); -+ return res; -+ } -+ va_list args; -+ va_start(args, signature); -+ if ((status = env->Object_CallMethod_Void_V(obj, method, args)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::UIABILITY, "Object_CallMethod_Void_V status: %{public}d", status); -+ etsRuntime_.HandleUncaughtError(); -+ return false; -+ } -+ va_end(args); -+ TAG_LOGI(AAFwkTag::UIABILITY, "CallObjectMethod end, name: %{public}s", name); -+ return false; -+} -+} // namespace AbilityRuntime -+} // namespace OHOS -diff --git a/frameworks/native/ability/native/extension_ability_thread.cpp b/frameworks/native/ability/native/extension_ability_thread.cpp -index f72fa0f4c2a0baf0747fcde775a4cb4ec02b887a..6a7633b35194a6998d9e00c87f75cf097d648bd9 100644 ---- a/frameworks/native/ability/native/extension_ability_thread.cpp -+++ b/frameworks/native/ability/native/extension_ability_thread.cpp -@@ -242,7 +242,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/ui_ability_thread.cpp b/frameworks/native/ability/native/ui_ability_thread.cpp -index 18d97dee4d6e877cd0b78765fd3c7611c0128c44..e20643c444024976ee2d7b3daff98bc6a6239792 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/appkit/BUILD.gn b/frameworks/native/appkit/BUILD.gn -index cc0227d2feb3217aad08944d7a2786747cca7d8b..11863d7b8bd13c71b1da20dcdbd81cfc737d3765 100644 ---- a/frameworks/native/appkit/BUILD.gn -+++ b/frameworks/native/appkit/BUILD.gn -@@ -54,6 +54,7 @@ config("appkit_config") { - config("appkit_public_config") { - visibility = [ ":*" ] - include_dirs = [ -+ "${ability_runtime_path}/ets_environment/interfaces/inner_api", - "${ability_runtime_path}/interfaces/kits/native/appkit/ability_delegator", - "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", - "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", -@@ -75,6 +76,7 @@ config("appkit_public_config") { - ohos_shared_library("appkit_native") { - include_dirs = [ - "native", -+ "${ability_runtime_path}/ets_environment/interfaces/inner_api", - "${ability_runtime_path}/interfaces/inner_api/error_utils/include", - "${ability_runtime_path}/interfaces/kits/native/appkit", - "${ability_runtime_path}/interfaces/kits/native/appkit/ability_bundle_manager_helper", -@@ -166,6 +168,7 @@ 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_path}/ets_environment/frameworks/ets_environment:ets_environment", - "${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", -@@ -208,6 +211,7 @@ ohos_shared_library("appkit_native") { - "napi:ace_napi", - "preferences:native_preferences", - "resource_management:global_resmgr", -+ "runtime_core:ani", - "safwk:system_ability_fwk", - "samgr:samgr_proxy", - "storage_service:storage_manager_acl", -diff --git a/frameworks/native/appkit/ability_delegator/ability_delegator_registry.cpp b/frameworks/native/appkit/ability_delegator/ability_delegator_registry.cpp -index 7187c88382eac76eabb85137bf793722dba009b7..7cd73453052ed30544d1f69b093cd2954774d90b 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 - -@@ -39,11 +49,11 @@ std::shared_ptr AbilityDelegatorRegistry::GetArguments() - return abilityDelegatorArgs_; - } - --void AbilityDelegatorRegistry::RegisterInstance( -- const std::shared_ptr& delegator, const std::shared_ptr& args) -+void AbilityDelegatorRegistry::RegisterInstance(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/app/application_data_manager.cpp b/frameworks/native/appkit/app/application_data_manager.cpp -index 6dfd3a4493efb0896184c21819410ade2e088f11..79c2449ccbffee933660e96284a27195137eed92 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::NotifyETSUnhandledException(const std::string &errMsg) -+{ -+ if (errorObserver_) { -+ errorObserver_->OnUnhandledException(errMsg); -+ return true; -+ } -+ return AppRecovery::GetInstance().TryRecoverApp(StateReason::JS_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::NotifyETSExceptionObject(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::JS_ERROR); -+} - } // namespace AppExecFwk - } // namespace OHOS -diff --git a/frameworks/native/appkit/app/dump_runtime_helper.cpp b/frameworks/native/appkit/app/dump_runtime_helper.cpp -index 945867d5b91541371d8a8ae7eef1c18f45e61cac..052ec4ece780ccf21afa532700a9d370de81a831 100644 ---- a/frameworks/native/appkit/app/dump_runtime_helper.cpp -+++ b/frameworks/native/appkit/app/dump_runtime_helper.cpp -@@ -87,7 +87,7 @@ void DumpRuntimeHelper::SetAppFreezeFilterCallback() - TAG_LOGE(AAFwkTag::APPKIT, "null application"); - return; - } -- auto& runtime = application_->GetRuntime(); -+ auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); - return; -@@ -205,7 +205,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::CODE_LANGUAGE_ARKTS_1_0); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); - return; -@@ -235,7 +235,7 @@ void DumpRuntimeHelper::DumpCjHeap(const OHOS::AppExecFwk::CjHeapDumpInfo &info) - TAG_LOGE(AAFwkTag::APPKIT, "null application"); - return; - } -- auto& runtime = application_->GetRuntime(); -+ auto &runtime = application_->GetRuntime(AbilityRuntime::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 5d12647990300e3fc3812a3ac2a8d20658d001e1..10f4b21bdaaff9e6ed0f642ec56288b71427b9ea 100644 ---- a/frameworks/native/appkit/app/main_thread.cpp -+++ b/frameworks/native/appkit/app/main_thread.cpp -@@ -75,6 +75,7 @@ - #include "if_system_ability_manager.h" - #include "iservice_registry.h" - #include "js_runtime.h" -+#include "ets_runtime.h" - #ifdef CJ_FRONTEND - #include "cj_runtime.h" - #endif -@@ -183,6 +184,7 @@ const char* PC_LIBRARY_PATH = "/system/lib64/liblayered_parameters_manager.z.so" - const char* PC_FUNC_INFO = "DetermineResourceType"; - const int32_t TYPE_RESERVE = 1; - const int32_t TYPE_OTHERS = 2; -+std::unique_ptr RUNTIME_NULL = nullptr; - - #if defined(NWEB) - constexpr int32_t PRELOAD_DELAY_TIME = 2000; //millisecond -@@ -1395,6 +1397,59 @@ CJUncaughtExceptionInfo MainThread::CreateCjExceptionInfo(const std::string &bun - return uncaughtExceptionInfo; - } - #endif -+ -+EtsEnv::ETSUncaughtExceptionInfo MainThread::CreateEtsExceptionInfo(const std::string &bundleName, uint32_t versionCode, -+ const std::string &hapPath, std::string &appRunningId, int32_t pid, std::string &processName) -+{ -+ EtsEnv::ETSUncaughtExceptionInfo uncaughtExceptionInfo; -+ wptr weak = this; -+ uncaughtExceptionInfo.uncaughtTask = [weak, bundleName, versionCode, appRunningId = std::move(appRunningId), pid, -+ processName](std::string summary, const EtsEnv::ETSErrorObject 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); -+ if (ApplicationDataManager::GetInstance().NotifyETSUnhandledException(summary) && -+ ApplicationDataManager::GetInstance().NotifyETSExceptionObject(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; -+} - /** - * - * @brief Launch the application. -@@ -1582,6 +1637,9 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con - } else { - #endif - AbilityRuntime::JsRuntime::SetAppLibPath(appLibPaths, isSystemApp); -+ if (IsNeedEtsInit(appInfo)) { -+ AbilityRuntime::ETSRuntime::SetAppLibPath(appLibPaths); -+ } - #ifdef CJ_FRONTEND - } - #endif -@@ -1608,7 +1666,14 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con - options.pkgContextInfoJsonStringMap = pkgContextInfoJsonStringMap; - options.allowArkTsLargeHeap = appInfo.allowArkTsLargeHeap; - #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()); -@@ -1642,12 +1707,12 @@ 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; - } -- -+ auto &runtimeVerOne = GetVerOneRuntime(appInfo, runtimes); - if (appInfo.debug && appLaunchData.GetDebugApp()) { - wptr weak = this; - auto cb = [weak]() { -@@ -1658,7 +1723,9 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con - } - return appThread->NotifyDeviceDisConnect(); - }; -- runtime->SetDeviceDisconnectCallback(cb); -+ if (runtimeVerOne != nullptr) { -+ runtimeVerOne->SetDeviceDisconnectCallback(cb); -+ } - } - auto perfCmd = appLaunchData.GetPerfCmd(); - -@@ -1669,11 +1736,13 @@ 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); -- }); -+ if (runtimeVerOne != nullptr) { -+ runtimeVerOne->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.isStartWithDebug = appLaunchData.GetDebugApp(); - debugOption.processName = processName; -@@ -1683,13 +1752,19 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con - debugOption.isDebugFromLocal = appLaunchData.GetDebugFromLocal(); - debugOption.perfCmd = perfCmd; - debugOption.isDeveloperMode = isDeveloperMode_; -- runtime->SetDebugOption(debugOption); -+ if (runtimeVerOne != nullptr) { -+ runtimeVerOne->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); -+ if (runtimeVerOne != nullptr) { -+ runtimeVerOne->StartProfiler(debugOption); -+ } - } else { -- runtime->StartDebugMode(debugOption); -+ if (runtimeVerOne != nullptr) { -+ runtimeVerOne->StartDebugMode(debugOption); -+ } - } - - std::vector hqfInfos = appInfo.appQuickFix.deployedAppqfInfo.hqfInfos; -@@ -1700,7 +1775,9 @@ 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); -+ if (runtimeVerOne != nullptr) { -+ runtimeVerOne->RegisterQuickFixQueryFunc(modulePaths); -+ } - } - - auto bundleName = appInfo.bundleName; -@@ -1708,18 +1785,37 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con - #ifdef CJ_FRONTEND - if (!isCJApp) { - #endif -- JsEnv::UncaughtExceptionInfo uncaughtExceptionInfo; -- uncaughtExceptionInfo.hapPath = hapPath; -- UncatchableTaskInfo uncatchableTaskInfo = {bundleName, versionCode, appRunningId, pid, processName}; -- InitUncatchableTask(uncaughtExceptionInfo.uncaughtTask, uncatchableTaskInfo); -- (static_cast(*runtime)).RegisterUncaughtExceptionHandler(uncaughtExceptionInfo); -- JsEnv::UncatchableTask uncatchableTask; -- InitUncatchableTask(uncatchableTask, uncatchableTaskInfo, true); -- (static_cast(*runtime)).RegisterUncatchableExceptionHandler(uncatchableTask); -+ for (const auto &runtime : runtimes) { -+ if (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0 && -+ runtime->GetLanguage() == AbilityRuntime::Runtime::Language::JS) { -+ JsEnv::UncaughtExceptionInfo uncaughtExceptionInfo; -+ uncaughtExceptionInfo.hapPath = hapPath; -+ UncatchableTaskInfo uncatchableTaskInfo = {bundleName, versionCode, appRunningId, pid, processName}; -+ InitUncatchableTask(uncaughtExceptionInfo.uncaughtTask, uncatchableTaskInfo); -+ (static_cast(*runtime)).RegisterUncaughtExceptionHandler( -+ uncaughtExceptionInfo); -+ JsEnv::UncatchableTask uncatchableTask; -+ InitUncatchableTask(uncatchableTask, uncatchableTaskInfo, true); -+ (static_cast(*runtime)).RegisterUncatchableExceptionHandler( -+ uncatchableTask); -+ } -+ if ((appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2 || -+ appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_HYBRID) && -+ runtime->GetLanguage() == AbilityRuntime::Runtime::Language::ETS) { -+ auto expectionInfo = -+ CreateEtsExceptionInfo(bundleName, versionCode, hapPath, appRunningId, pid, processName); -+ runtime->RegisterUncaughtExceptionHandler((void*)&expectionInfo); -+ } -+ } - #ifdef CJ_FRONTEND - } else { -- auto expectionInfo = CreateCjExceptionInfo(bundleName, versionCode, hapPath); -- (static_cast(*runtime)).RegisterUncaughtExceptionHandler(expectionInfo); -+ for (const auto &runtime : runtimes) { -+ if (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0 && -+ runtime->GetLanguage() == AbilityRuntime::Runtime::Language::CJ) { -+ auto expectionInfo = CreateCjExceptionInfo(bundleName, versionCode, hapPath); -+ runtime->RegisterUncaughtExceptionHandler((void*)&expectionInfo); -+ } -+ } - } - #endif - wptr weak = this; -@@ -1733,14 +1829,21 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con - }; - applicationContext->RegisterProcessSecurityExit(callback); - -- application_->SetRuntime(std::move(runtime)); -- -+ for (auto &runtime : runtimes) { -+ application_->AddRuntime(std::move(runtime)); -+ } - 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::CODE_LANGUAGE_ARKTS_1_2) { -+ return AbilityRuntime::UIAbility::Create(app->GetRuntime( -+ AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2)); -+ } else { -+ return AbilityRuntime::UIAbility::Create(app->GetRuntime( -+ AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0)); -+ } - } - TAG_LOGE(AAFwkTag::APPKIT, "failed"); - return nullptr; -@@ -1748,33 +1851,18 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con - #ifdef CJ_FRONTEND - if (!isCJApp) { - #endif -- auto& jsEngine = (static_cast(*application_->GetRuntime())).GetNativeEngine(); - if (application_ != nullptr) { -- LoadAllExtensions(jsEngine); -+ TAG_LOGD(AAFwkTag::APPKIT, "LoadAllExtensions lan:%{public}s", appInfo.codeLanguage.c_str()); -+ LoadAllExtensions(); - } -- -- 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 (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) { -+ auto &runtime = application_->GetRuntime(appInfo.codeLanguage); - 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); -- -- auto helper = std::make_shared(application_); -- helper->SetAppFreezeFilterCallback(); -+ SetJsIdleCallback(wpApplication, runtime); -+ } - #ifdef CJ_FRONTEND - } else { - LoadAllExtensions(); -@@ -1784,7 +1872,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; - } -@@ -1876,7 +1965,9 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con - } - #endif - if (appLaunchData.IsNeedPreloadModule()) { -- PreloadModule(entryHapModuleInfo, application_->GetRuntime()); -+ for (auto &runtime : application_->GetRuntime()) { -+ PreloadModule(entryHapModuleInfo, runtime); -+ } - } - } - -@@ -1911,7 +2002,8 @@ void MainThread::InitUncatchableTask(JsEnv::UncatchableTask &uncatchableTask, co - EVENT_KEY_PROCESS_RSS_MEMINFO, std::to_string(DumpProcessHelper::GetProcRssMemInfo())); - - ErrorObject appExecErrorObj = { errorObject.name, errorObject.message, errorObject.stack}; -- auto napiEnv = (static_cast(*appThread->application_->GetRuntime())).GetNapiEnv(); -+ auto napiEnv = (static_cast( -+ *appThread->application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0))).GetNapiEnv(); - if (!isUncatchable && NapiErrorManager::GetInstance()->NotifyUncaughtException(napiEnv, summary, - appExecErrorObj.name, appExecErrorObj.message, appExecErrorObj.stack)) { - return; -@@ -2054,7 +2146,7 @@ void MainThread::ProcessMainAbility(const AbilityInfo &info, const std::unique_p - } - - void MainThread::PreloadModule(const AppExecFwk::HapModuleInfo &entryHapModuleInfo, -- const std::unique_ptr& runtime) -+ const std::unique_ptr &runtime) - { - TAG_LOGI(AAFwkTag::APPKIT, "preload module %{public}s", entryHapModuleInfo.moduleName.c_str()); - auto callback = []() {}; -@@ -2204,7 +2296,7 @@ void MainThread::HandleUpdatePluginInfoInstalled(const ApplicationInfo &pluginAp - TAG_LOGE(AAFwkTag::APPKIT, "null application_"); - return; - } -- auto& runtime = application_->GetRuntime(); -+ auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); - return; -@@ -2254,7 +2346,7 @@ void MainThread::HandleUpdateApplicationInfoInstalled(const ApplicationInfo& app - } - application_->UpdateApplicationInfoInstalled(appInfo); - -- auto& runtime = application_->GetRuntime(); -+ auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); - return; -@@ -2342,10 +2434,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; -@@ -2355,7 +2448,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) { -@@ -2365,12 +2459,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::CODE_LANGUAGE_ARKTS_1_0) { -+ TAG_LOGI(AAFwkTag::DELEGATOR, "create 1.0 testrunner"); -+ auto &runtime = application_->GetRuntime(AbilityRuntime::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, runtime->GetLanguage()); -+ delegator->SetApiTargetVersion(targetVersion); -+ delegator->Prepare(); -+ } -+ -+ if (applicationCodeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2) { -+ TAG_LOGI(AAFwkTag::DELEGATOR, "create 1.2 testrunner"); -+ auto &runtime = application_->GetRuntime(AbilityRuntime::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, runtime->GetLanguage()); -+ delegator->SetApiTargetVersion(targetVersion); -+ delegator->Prepare(); -+ } - } else { // FA model - TAG_LOGD(AAFwkTag::APPKIT, "FA model"); - AbilityRuntime::Runtime::Options options; -@@ -2400,7 +2509,7 @@ 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, AbilityRuntime::Runtime::Language::JS); - delegator->SetApiTargetVersion(targetVersion); - delegator->Prepare(); - } -@@ -2461,7 +2570,7 @@ void MainThread::HandleLaunchAbility(const std::shared_ptr & - TAG_LOGE(AAFwkTag::APPKIT, "null application"); - return; - } -- auto& runtime = application->GetRuntime(); -+ auto &runtime = application->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); - appThread->UpdateRuntimeModuleChecker(runtime); - #ifdef APP_ABILITY_USE_TWO_RUNNER - AbilityThread::AbilityThreadMain(application, abilityRecord, stageContext); -@@ -2488,7 +2597,7 @@ void MainThread::HandleLaunchAbility(const std::shared_ptr & - return; - } - SetProcessExtensionType(abilityRecord); -- auto& runtime = application_->GetRuntime(); -+ auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); - UpdateRuntimeModuleChecker(runtime); - #ifdef APP_ABILITY_USE_TWO_RUNNER - AbilityThread::AbilityThreadMain(application_, abilityRecord, stageContext); -@@ -2851,7 +2960,7 @@ void MainThread::HandleDumpHeapPrepare() - TAG_LOGE(AAFwkTag::APPKIT, "null app"); - return; - } -- auto &runtime = app->GetRuntime(); -+ auto &runtime = app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); - return; -@@ -2871,7 +2980,7 @@ void MainThread::HandleDumpHeap(bool isPrivate) - TAG_LOGE(AAFwkTag::APPKIT, "null app"); - return; - } -- auto &runtime = app->GetRuntime(); -+ auto &runtime = app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); - return; -@@ -2924,11 +3033,11 @@ void MainThread::DestroyHeapProfiler() - - auto task = [] { - auto app = applicationForDump_.lock(); -- if (app == nullptr || app->GetRuntime() == nullptr) { -+ if (app == nullptr || app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); - return; - } -- app->GetRuntime()->DestroyHeapProfiler(); -+ app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0)->DestroyHeapProfiler(); - }; - mainHandler_->PostTask(task, "MainThread:DestroyHeapProfiler"); - } -@@ -2943,11 +3052,11 @@ void MainThread::ForceFullGC() - - auto task = [] { - auto app = applicationForDump_.lock(); -- if (app == nullptr || app->GetRuntime() == nullptr) { -+ if (app == nullptr || app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); - return; - } -- app->GetRuntime()->ForceFullGC(); -+ app->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0)->ForceFullGC(); - }; - mainHandler_->PostTask(task, "MainThread:ForceFullGC"); - } -@@ -3675,7 +3784,7 @@ int32_t MainThread::ChangeAppGcState(int32_t state, uint64_t tid) - TAG_LOGE(AAFwkTag::APPKIT, "null application_"); - return ERR_INVALID_VALUE; - } -- auto &runtime = application_->GetRuntime(); -+ auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); - return ERR_INVALID_VALUE; -@@ -3727,7 +3836,7 @@ int32_t MainThread::OnAttachLocalDebug(bool isDebugFromLocal) - TAG_LOGE(AAFwkTag::APPKIT, "null application_"); - return ERR_INVALID_VALUE; - } -- auto &runtime = application_->GetRuntime(); -+ auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); - return ERR_INVALID_VALUE; -@@ -3949,7 +4058,7 @@ void MainThread::HandleCacheProcess() - - // force gc - if (application_ != nullptr) { -- auto &runtime = application_->GetRuntime(); -+ auto &runtime = application_->GetRuntime(AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0); - if (runtime == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null runtime"); - return; -@@ -3958,6 +4067,38 @@ void MainThread::HandleCacheProcess() - } - } - -+void MainThread::AddRuntimeLang(ApplicationInfo &appInfo, AbilityRuntime::Runtime::Options &options) -+{ -+ if (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2) { -+ options.langs.emplace(AbilityRuntime::Runtime::Language::ETS, true); -+ } else if (appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_HYBRID) { -+ options.langs.emplace(AbilityRuntime::Runtime::Language::ETS, true); -+ } else { -+ options.langs.emplace(AbilityRuntime::Runtime::Language::JS, true); -+ } -+} -+ -+bool MainThread::IsNeedEtsInit(const ApplicationInfo &appInfo) -+{ -+ return appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2 || -+ appInfo.codeLanguage == AbilityRuntime::CODE_LANGUAGE_ARKTS_HYBRID; -+} -+ -+const std::unique_ptr &MainThread::GetVerOneRuntime( -+ const ApplicationInfo &appInfo, const std::vector> &runtimes) -+{ -+ if (appInfo.codeLanguage != AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) { -+ return RUNTIME_NULL; -+ } -+ for (auto &runtime : runtimes) { -+ if (runtime->GetLanguage() == AbilityRuntime::Runtime::Language::JS || -+ runtime->GetLanguage() == AbilityRuntime::Runtime::Language::CJ) { -+ return runtime; -+ } -+ } -+ return RUNTIME_NULL; -+} -+ - void MainThread::HandleConfigByPlugin(Configuration &config, BundleInfo &bundleInfo) - { - if (PC_LIBRARY_PATH == nullptr) { -@@ -3980,5 +4121,33 @@ void MainThread::HandleConfigByPlugin(Configuration &config, BundleInfo &bundleI - - entry(config, bundleInfo); - } -+ -+void MainThread::SetJsIdleCallback(const std::weak_ptr &wpApplication, -+ const std::unique_ptr &runtime) -+{ -+ 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::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(); -+ -+ IdleNotifyStatusCallback cb = idleTime_->GetIdleNotifyFunc(); -+ jsEngine.NotifyIdleStatusControl(cb); -+ -+ auto helper = std::make_shared(application_); -+ helper->SetAppFreezeFilterCallback(); -+} - } // namespace AppExecFwk - } // namespace OHOS -diff --git a/frameworks/native/appkit/app/ohos_application.cpp b/frameworks/native/appkit/app/ohos_application.cpp -index 45831ff8001811c05b876e26fa10344ea10802b4..41713dde52b85c112228af397a2d7c92e0cf22f6 100644 ---- a/frameworks/native/appkit/app/ohos_application.cpp -+++ b/frameworks/native/appkit/app/ohos_application.cpp -@@ -37,6 +37,7 @@ - #include "iservice_registry.h" - #include "runtime.h" - #include "js_runtime.h" -+#include "ets_runtime.h" - #include "startup_manager.h" - #include "system_ability_definition.h" - #include "syspara/parameter.h" -@@ -51,6 +52,7 @@ namespace OHOS { - namespace AppExecFwk { - namespace { - constexpr const char* PERSIST_DARKMODE_KEY = "persist.ace.darkmode"; -+ std::unique_ptr RUNTIME_NULL = nullptr; - } - REGISTER_APPLICATION(OHOSApplication, OHOSApplication) - constexpr int32_t APP_ENVIRONMENT_OVERWRITE = 1; -@@ -77,11 +79,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 +102,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 +156,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_.emplace_back(std::move(runtime)); - } - - /** -@@ -369,6 +376,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) -@@ -413,8 +439,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); -@@ -425,7 +453,8 @@ std::shared_ptr OHOSApplication::AddAbilityStage( - stageContext->SetResourceManager(rm); - } - -- abilityStage = AbilityRuntime::AbilityStage::Create(runtime_, *hapModuleInfo); -+ auto &runtimeStage = GetRuntime(hapModuleInfo->codeLanguage); -+ abilityStage = AbilityRuntime::AbilityStage::Create(runtimeStage, *hapModuleInfo); - if (abilityStage == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null abilityStage"); - return nullptr; -@@ -608,8 +637,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; - } - -@@ -633,7 +662,8 @@ bool OHOSApplication::AddAbilityStage( - stageContext->SetResourceManager(rm); - } - -- auto abilityStage = AbilityRuntime::AbilityStage::Create(runtime_, *moduleInfo); -+ auto &runtime = GetRuntime(moduleInfo->codeLanguage); -+ auto abilityStage = AbilityRuntime::AbilityStage::Create(runtime, *moduleInfo); - if (abilityStage == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null abilityStage"); - return false; -@@ -688,9 +718,9 @@ std::shared_ptr OHOSApplication::GetAppContext() const - return abilityRuntimeContext_; - } - --const std::unique_ptr& OHOSApplication::GetRuntime() const -+const std::vector> &OHOSApplication::GetRuntime() const - { -- return runtime_; -+ return runtimes_; - } - - void OHOSApplication::SetConfiguration(const Configuration &config) -@@ -815,32 +845,60 @@ 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"); -+ 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"); -+ 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) -@@ -1080,5 +1138,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 RUNTIME_NULL; -+} -+ -+void OHOSApplication::SetCJApplication(bool isCJApplication) -+{ -+ isCJApplication_ = isCJApplication; -+} -+ -+AbilityRuntime::Runtime::Language OHOSApplication::ConvertLangToCode(const std::string &language) const -+{ -+ if (language == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0) { -+ if (isCJApplication_) { -+ return AbilityRuntime::Runtime::Language::CJ; -+ } else { -+ return AbilityRuntime::Runtime::Language::JS; -+ } -+ } else if (language == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2) { -+ return AbilityRuntime::Runtime::Language::ETS; -+ } else { -+ return AbilityRuntime::Runtime::Language::UNKNOWN; -+ } -+} - } // namespace AppExecFwk - } // namespace OHOS -diff --git a/frameworks/native/runtime/cj_runtime.cpp b/frameworks/native/runtime/cj_runtime.cpp -index ecf1697834d004eebefd5e2e51dbd930083283d0..5ac8d635e22ddc1bb1fa8bc735bfe17371fec614 100644 ---- a/frameworks/native/runtime/cj_runtime.cpp -+++ b/frameworks/native/runtime/cj_runtime.cpp -@@ -118,16 +118,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. -@@ -368,4 +358,14 @@ void CJRuntime::ForceFullGC(uint32_t tid) - return; - } - cjEnv->forceFullGC(); -+} -+ -+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/ets_data_struct_converter.cpp b/frameworks/native/runtime/ets_data_struct_converter.cpp -new file mode 100644 -index 0000000000000000000000000000000000000000..a3bf58cd7a6989203e3b92ca8413e4400d52f03a ---- /dev/null -+++ b/frameworks/native/runtime/ets_data_struct_converter.cpp -@@ -0,0 +1,106 @@ -+/* -+ * Copyright (c) 2025 Huawei Device Co., Ltd. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT 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_data_struct_converter.h" -+ -+#include "ani_enum_convert.h" -+#include "hilog_tag_wrapper.h" -+ -+namespace OHOS { -+namespace AbilityRuntime { -+namespace { -+constexpr const char *CLASSNAME_LAUNCHPARAM = "L@ohos/app/ability/AbilityConstant/LaunchParamImpl"; -+constexpr const char *CLASSNAME_LAUNCHREASON = "L@ohos/app/ability/AbilityConstant/AbilityConstant/LaunchReason;"; -+constexpr const char *CLASSNAME_LAST_EXITREASION = "L@ohos/app/ability/AbilityConstant/AbilityConstant/LastExitReason"; -+ -+ani_string GetAniString(ani_env *env, const std::string &str) -+{ -+ if (env == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env"); -+ return nullptr; -+ } -+ ani_string aniStr = nullptr; -+ ani_status status = env->String_NewUTF8(str.c_str(), str.size(), &aniStr); -+ if (status != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to getAniString, status : %{public}d", status); -+ return nullptr; -+ } -+ return aniStr; -+} -+ -+bool WrapLaunchParamInner(ani_env *env, const AAFwk::LaunchParam &launchParam, ani_object &object) -+{ -+ ani_status status = ANI_ERROR; -+ ani_enum_item launchReasonItem {}; -+ OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts( -+ env, CLASSNAME_LAUNCHREASON, launchParam.launchReason, launchReasonItem); -+ if ((status = env->Object_SetPropertyByName_Ref(object, "launchReason", launchReasonItem)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to set launchReason"); -+ return false; -+ } -+ -+ ani_enum_item lastExitReasonItem {}; -+ OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts( -+ env, CLASSNAME_LAST_EXITREASION, launchParam.lastExitReason, lastExitReasonItem); -+ if ((status = env->Object_SetPropertyByName_Ref(object, "lastExitReason", lastExitReasonItem)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to set lastExitReason"); -+ return false; -+ } -+ return true; -+} -+} // namespace -+ -+bool WrapLaunchParam(ani_env *env, const AAFwk::LaunchParam &launchParam, ani_object &object) -+{ -+ ani_method method = nullptr; -+ ani_status status = ANI_ERROR; -+ ani_class cls = nullptr; -+ if (env == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env"); -+ return false; -+ } -+ if ((status = env->FindClass(CLASSNAME_LAUNCHPARAM, &cls)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to find lanchParam Class, status : %{public}d", status); -+ return false; -+ } -+ if (cls == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null cls"); -+ return false; -+ } -+ if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to find method, status : %{public}d", status); -+ return false; -+ } -+ if (method == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null method"); -+ return false; -+ } -+ if ((status = env->Object_New(cls, method, &object)) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to create object, status : %{public}d", status); -+ return false; -+ } -+ if (object == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null object"); -+ return false; -+ } -+ if ((status = env->Object_SetPropertyByName_Ref( -+ object, "lastExitMessage", GetAniString(env, launchParam.lastExitMessage))) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed to set lastExitMessage"); -+ return false; -+ } -+ return WrapLaunchParamInner(env, launchParam, object); -+} -+} // namespace AbilityRuntime -+} // namespace OHOS -diff --git a/frameworks/native/runtime/ets_runtime.cpp b/frameworks/native/runtime/ets_runtime.cpp -new file mode 100644 -index 0000000000000000000000000000000000000000..f851bf77ffbed3214af96818595da9d936a4d1c7 ---- /dev/null -+++ b/frameworks/native/runtime/ets_runtime.cpp -@@ -0,0 +1,481 @@ -+/* -+ * Copyright (c) 2025 Huawei Device Co., Ltd. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT 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_runtime.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "accesstoken_kit.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 "module_checker_delegate.h" -+#include "parameters.h" -+#include "source_map.h" -+#include "source_map_operator.h" -+#include "ets_environment.h" -+#include "syscap_ts.h" -+#include "system_ability_definition.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 ETS_RT_PATH = SANDBOX_LIB_PATH; -+const std::string ETS_SYSLIB_PATH = -+ "/system/lib64:/system/lib64/platformsdk:/system/lib64/module:/system/lib64/ndk"; -+#else -+const std::string SANDBOX_LIB_PATH = "/system/lib"; -+const std::string ETS_RT_PATH = SANDBOX_LIB_PATH; -+const std::string ETS_SYSLIB_PATH = -+ "/system/lib:/system/lib/platformsdk:/system/lib/module:/system/lib/ndk"; -+#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"; // will deprecated -+constexpr char ENTRY_PATH_MAP_KEY[] = "entryPath"; // will deprecated -+constexpr char DEFAULT_ENTRY_ABILITY_CLASS[] = "entry/src/main/ets/entryability/EntryAbility/EntryAbility"; -+constexpr int32_t DOT_START_LEN = 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::ETSRUNTIME, "no entrypath file"); -+ return false; -+ } -+ nlohmann::json filePathsJson; -+ inFile >> filePathsJson; -+ if (filePathsJson.is_discarded()) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "json discarded error"); -+ inFile.close(); -+ return false; -+ } -+ -+ if (filePathsJson.is_null() || filePathsJson.empty()) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "invalid json"); -+ inFile.close(); -+ return false; -+ } -+ -+ if (!filePathsJson.contains(ENTRY_PATH_MAP_KEY)) { -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "no entrypath key"); -+ return false; -+ } -+ const auto &entryPathMap = filePathsJson[ENTRY_PATH_MAP_KEY]; -+ if (!entryPathMap.is_object()) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "val is not string, key: %{public}s", key.c_str()); -+ continue; -+ } -+ std::string val = entryPath.value(); -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "not found srcEntry: %{public}s", srcEntry.c_str()); -+ return DEFAULT_ENTRY_ABILITY_CLASS; -+ } -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "srcEntry as class: %{public}s", srcEntry.c_str()); -+ return HandleOhmUrlSrcEntry(srcEntry); -+ } -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "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() < DOT_START_LEN) { -+ return false; -+ } -+ std::string prefix = str.substr(0, DOT_START_LEN); -+ 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 ETSRuntime::appLibPaths_; -+ -+std::unique_ptr ETSRuntime::Create(const Options &options, Runtime *jsRuntime) -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "Create called"); -+ if (jsRuntime == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null jsRuntime"); -+ return std::unique_ptr(); -+ } -+ std::unique_ptr instance; -+ if (!options.preload) { -+ auto preloadedInstance = Runtime::GetPreloaded(); -+#ifdef SUPPORT_SCREEN -+ // reload ace if compatible mode changes -+ if (Ace::AceForwardCompatibility::PipelineChanged() && preloadedInstance) { -+ preloadedInstance.reset(); -+ } -+#endif -+ if (preloadedInstance && preloadedInstance->GetLanguage() == Runtime::Language::ETS) { -+ instance.reset(static_cast(preloadedInstance.release())); -+ } else { -+ instance = std::make_unique(); -+ } -+ } else { -+ instance = std::make_unique(); -+ } -+ -+ if (!instance->Initialize(options, jsRuntime)) { -+ return std::unique_ptr(); -+ } -+ EntryPathManager::GetInstance().Init(); -+ -+ return instance; -+} -+ -+void ETSRuntime::SetAppLibPath(const AppLibPathMap &appLibPaths) -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "SetAppLibPath called"); -+ EtsEnv::ETSEnvironment::InitETSSDKNS(ETS_RT_PATH); -+ EtsEnv::ETSEnvironment::InitETSSysNS(ETS_SYSLIB_PATH); -+} -+ -+bool ETSRuntime::Initialize(const Options &options, Runtime *jsRuntime) -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "Initialize called"); -+ if (options.lang != GetLanguage()) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "language mismatch"); -+ return false; -+ } -+ -+ if (!CreateEtsEnv(options, jsRuntime)) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Create etsEnv failed"); -+ return false; -+ } -+ -+ apiTargetVersion_ = options.apiTargetVersion; -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "Initialize: %{public}d", apiTargetVersion_); -+ -+ return true; -+} -+ -+void ETSRuntime::RegisterUncaughtExceptionHandler(void *uncaughtExceptionInfo) -+{ -+ if (etsEnv_ == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null etsEnv_"); -+ return; -+ } -+ -+ if (uncaughtExceptionInfo == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null uncaughtExceptionInfo"); -+ return; -+ } -+ -+ auto handle = static_cast(uncaughtExceptionInfo); -+ if (handle != nullptr) { -+ etsEnv_->RegisterUncaughtExceptionHandler(*handle); -+ } -+} -+ -+ETSRuntime::~ETSRuntime() -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "~ETSRuntime called"); -+ Deinitialize(); -+} -+ -+void ETSRuntime::Deinitialize() -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "Deinitialize called"); -+} -+ -+bool ETSRuntime::CreateEtsEnv(const Options &options, Runtime *jsRuntime) -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "CreateEtsEnv called"); -+ etsEnv_ = std::make_shared(); -+ std::vector aniOptions; -+ 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::ETSRUNTIME, "aotFileString: %{public}s", aotFileString.c_str()); -+ aniOptions.push_back(ani_option { "--ext:--enable-an", nullptr }); -+ } -+ -+ if (!etsEnv_->Initialize(static_cast(jsRuntime)->GetNapiEnv(), aniOptions)) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Init EtsEnv failed"); -+ return false; -+ } -+ -+ return true; -+} -+ -+ani_env *ETSRuntime::GetAniEnv() -+{ -+ if (etsEnv_ == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null etsEnv_"); -+ return nullptr; -+ } -+ return etsEnv_->GetAniEnv(); -+} -+ -+void ETSRuntime::PreloadModule(const std::string &moduleName, const std::string &hapPath, -+ bool isEsMode, bool useCommonTrunk) -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "moduleName: %{public}s", moduleName.c_str()); -+ ani_env *aniEnv = GetAniEnv(); -+ if (aniEnv == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetAniEnv failed"); -+ return; -+ } -+ -+ ani_class cls = nullptr; -+ ani_object object = nullptr; -+ if (!LoadAbcLinker(aniEnv, moduleName, cls, object)) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "LoadAbcLinker failed"); -+ return; -+ } -+ return; -+} -+ -+std::unique_ptr ETSRuntime::LoadModule(const std::string &moduleName, -+ const std::string &modulePath, const std::string &hapPath, bool esmodule, bool useCommonChunk, -+ const std::string &srcEntrance) -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "Load module(%{public}s, %{public}s, %{public}s, %{public}s)", -+ moduleName.c_str(), modulePath.c_str(), hapPath.c_str(), srcEntrance.c_str()); -+ -+ std::string path = moduleName; -+ auto pos = path.find("::"); -+ if (pos != std::string::npos) { -+ path.erase(pos, path.size() - pos); -+ moduleName_ = path; -+ } -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "make module file path: %{public}s failed", modulePath.c_str()); -+ return nullptr; -+ } -+ } -+ std::unique_ptr etsNativeReference = LoadEtsModule(moduleName, fileName, hapPath, srcEntrance); -+ return etsNativeReference; -+} -+ -+bool ETSRuntime::LoadAbcLinker(ani_env *env, const std::string &moduleName, ani_class &abcCls, ani_object &abcObj) -+{ -+ if (env == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env"); -+ return false; -+ } -+ ani_class stringCls = nullptr; -+ if (env->FindClass("Lstd/core/String;", &stringCls) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "FindClass Lstd/core/String Failed"); -+ return false; -+ } -+ std::string modulePath = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_PATH; -+ ani_string aniStr; -+ if (env->String_NewUTF8(modulePath.c_str(), modulePath.size(), &aniStr) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "String_NewUTF8 modulePath Failed"); -+ return false; -+ } -+ ani_ref undefinedRef; -+ if (env->GetUndefined(&undefinedRef) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetUndefined failed"); -+ return false; -+ } -+ ani_array_ref refArray; -+ if (env->Array_New_Ref(stringCls, 1, undefinedRef, &refArray) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Array_New_Ref Failed"); -+ return false; -+ } -+ if (env->Array_Set_Ref(refArray, 0, aniStr) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Array_Set_Ref Failed"); -+ return false; -+ } -+ if (env->FindClass("Lstd/core/AbcRuntimeLinker;", &abcCls) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "FindClass AbcRuntimeLinker failed"); -+ return false; -+ } -+ ani_method method = nullptr; -+ if (env->Class_FindMethod(abcCls, "", "Lstd/core/RuntimeLinker;[Lstd/core/String;:V", &method) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Class_FindMethod ctor failed"); -+ return false; -+ } -+ env->ResetError(); -+ if (env->Object_New(abcCls, method, &abcObj, undefinedRef, refArray) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Object_New AbcRuntimeLinker failed"); -+ HandleUncaughtError(); -+ return false; -+ } -+ return true; -+} -+ -+std::unique_ptr ETSRuntime::LoadEtsModule(const std::string &moduleName, -+ const std::string &fileName, const std::string &hapPath, const std::string &srcEntrance) -+{ -+ auto etsNativeReference = std::make_unique(); -+ ani_env *aniEnv = GetAniEnv(); -+ if (aniEnv == nullptr) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetAniEnv failed"); -+ return std::make_unique(); -+ } -+ ani_class cls = nullptr; -+ ani_object object = nullptr; -+ if (!LoadAbcLinker(aniEnv, moduleName_, cls, object)) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "LoadAbcLinker failed"); -+ return std::make_unique(); -+ } -+ ani_method loadClassMethod = nullptr; -+ if (aniEnv->Class_FindMethod(cls, "loadClass", "Lstd/core/String;Z:Lstd/core/Class;", &loadClassMethod) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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; -+ if (aniEnv->Object_CallMethod_Ref(object, loadClassMethod, &entryClassRef, entryClassStr, false) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "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::ETSRUNTIME, "Class_FindMethod ctor failed"); -+ return std::make_unique(); -+ } -+ ani_object entryObject = nullptr; -+ if (aniEnv->Object_New(entryClass, entryMethod, &entryObject) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "Object_New AbcRuntimeLinker failed"); -+ return std::make_unique(); -+ } -+ ani_ref entryObjectRef = nullptr; -+ if (aniEnv->GlobalReference_Create(entryObject, &entryObjectRef) != ANI_OK) { -+ TAG_LOGE(AAFwkTag::ETSRUNTIME, "GlobalReference_Create failed"); -+ return std::make_unique(); -+ } -+ etsNativeReference->aniCls = entryClass; -+ etsNativeReference->aniObj = entryObject; -+ etsNativeReference->aniRef = entryObjectRef; -+ return etsNativeReference; -+} -+ -+void ETSRuntime::HandleUncaughtError() -+{ -+ TAG_LOGD(AAFwkTag::ETSRUNTIME, "HandleUncaughtError called"); -+ if (etsEnv_ == nullptr) { -+ return; -+ } -+ etsEnv_->HandleUncaughtError(); -+} -+} // namespace AbilityRuntime -+} // namespace OHOS -\ No newline at end of file -diff --git a/frameworks/native/runtime/js_runtime.cpp b/frameworks/native/runtime/js_runtime.cpp -index 4b04f031c12904c7d98a7d13b749f99b2dd9f16b..cb7c9a217e7b2f69311463c804193995c8ffdecf 100644 ---- a/frameworks/native/runtime/js_runtime.cpp -+++ b/frameworks/native/runtime/js_runtime.cpp -@@ -1765,5 +1765,12 @@ 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/runtime.cpp b/frameworks/native/runtime/runtime.cpp -index 26362dd0dbbe6724c623e7a42581ceee0bdb3892..0beb1b4395345e2673aecb38702be5b990642801 100644 ---- a/frameworks/native/runtime/runtime.cpp -+++ b/frameworks/native/runtime/runtime.cpp -@@ -19,6 +19,7 @@ - #include "cj_runtime.h" - #endif - #include "js_runtime.h" -+#include "ets_runtime.h" - - namespace OHOS { - namespace AbilityRuntime { -@@ -26,8 +27,45 @@ namespace { - std::unique_ptr g_preloadedInstance; - } - --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.emplace_back(JsRuntime::Create(options)); -+ break; -+#ifdef CJ_FRONTEND -+ case Runtime::Language::CJ: -+ options.lang = Runtime::Language::CJ; -+ runtimes.emplace_back(CJRuntime::Create(options)); -+ break; -+#endif -+ case Runtime::Language::ETS: { -+ options.lang = Runtime::Language::JS; -+ auto &jsRuntime = runtimes.emplace_back(JsRuntime::Create(options)); -+ options.lang = Runtime::Language::ETS; -+ runtimes.emplace_back(ETSRuntime::Create(options, -+ static_cast(jsRuntime.get()))); -+ break; -+ } -+ default: -+ runtimes.emplace_back(std::unique_ptr()); -+ break; -+ } -+ } -+ return runtimes; -+} -+ -+std::unique_ptr Runtime::Create(Runtime::Options &options) -+{ -+ std::unique_ptr jsRuntime; -+ if (options.lang == Runtime::Language::ETS) { -+ options.lang = Runtime::Language::JS; -+ jsRuntime = JsRuntime::Create(options); -+ options.lang = Runtime::Language::ETS; -+ } - switch (options.lang) { - case Runtime::Language::JS: - return JsRuntime::Create(options); -@@ -35,6 +73,8 @@ std::unique_ptr Runtime::Create(const Runtime::Options& options) - case Runtime::Language::CJ: - return CJRuntime::Create(options); - #endif -+ case Runtime::Language::ETS: -+ return ETSRuntime::Create(options, jsRuntime.get()); - default: - return std::unique_ptr(); - } -diff --git a/frameworks/simulator/ability_simulator/src/js_runtime.cpp b/frameworks/simulator/ability_simulator/src/js_runtime.cpp -index 7e173d8a07c02d6a7e8b4b074b6642a97dd33f1b..3bed249733a419884556d1f715175eaeb43bb774 100644 ---- a/frameworks/simulator/ability_simulator/src/js_runtime.cpp -+++ b/frameworks/simulator/ability_simulator/src/js_runtime.cpp -@@ -158,5 +158,8 @@ std::unique_ptr JsRuntime::LoadSystemModuleByEngine( - napi_create_reference(env, instanceValue, 1, &result); - return std::unique_ptr(reinterpret_cast(result)); - } -+ -+void JsRuntime::RegisterUncaughtExceptionHandler(void *uncaughtExceptionInfo) -+{} - } // namespace AbilityRuntime - } // namespace OHOS -diff --git a/interfaces/inner_api/runtime/BUILD.gn b/interfaces/inner_api/runtime/BUILD.gn -index 836d126b83bdd2b6b003f52e584aaee97e588774..9b78f45490fd2368da7553467750c89ae3e6ffb6 100644 ---- a/interfaces/inner_api/runtime/BUILD.gn -+++ b/interfaces/inner_api/runtime/BUILD.gn -@@ -52,6 +52,7 @@ ohos_shared_library("runtime") { - branch_protector_ret = "pac_ret" - - include_dirs = [ -+ "${ability_runtime_path}/ets_environment/interfaces/inner_api", - "${ability_runtime_path}/services/abilitymgr/include", - "${ability_runtime_path}/interfaces/kits/native/appkit/ability_bundle_manager_helper", - "${ability_runtime_path}/frameworks/ets/ani/enum_convert", -@@ -60,6 +61,8 @@ ohos_shared_library("runtime") { - - sources = [ - "${ability_runtime_native_path}/appkit/ability_bundle_manager_helper/bundle_mgr_helper.cpp", -+ "${ability_runtime_native_path}/runtime/ets_data_struct_converter.cpp", -+ "${ability_runtime_native_path}/runtime/ets_runtime.cpp", - "${ability_runtime_native_path}/runtime/hdc_register.cpp", - "${ability_runtime_native_path}/runtime/js_app_process_state.cpp", - "${ability_runtime_native_path}/runtime/js_data_struct_converter.cpp", -@@ -90,6 +93,7 @@ ohos_shared_library("runtime") { - "${ability_runtime_innerkits_path}/connect_server_manager:connect_server_manager", - "${ability_runtime_native_path}/ability/native:ability_business_error", - "${ability_runtime_native_path}/appkit:appkit_manager_helper", -+ "${ability_runtime_path}/ets_environment/frameworks/ets_environment:ets_environment", - "${ability_runtime_path}/js_environment/frameworks/js_environment:js_environment", - "${ability_runtime_services_path}/common:app_util", - "${ability_runtime_services_path}/common:record_cost_time_util", -@@ -122,6 +126,7 @@ ohos_shared_library("runtime") { - "jsoncpp:jsoncpp", - "napi:ace_napi", - "resource_management:global_resmgr", -+ "runtime_core:ani", - "samgr:samgr_proxy", - "zlib:shared_libz", - "faultloggerd:libfaultloggerd", -diff --git a/interfaces/inner_api/runtime/include/cj_runtime.h b/interfaces/inner_api/runtime/include/cj_runtime.h -index 0d406dc6f33831c5cb9d87bdf67ff7716a125292..04778b740086e49638f4e4ad07afd4a2051d6168 100644 ---- a/interfaces/inner_api/runtime/include/cj_runtime.h -+++ b/interfaces/inner_api/runtime/include/cj_runtime.h -@@ -55,6 +55,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; } -@@ -72,8 +74,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(); -diff --git a/interfaces/inner_api/runtime/include/ets_data_struct_converter.h b/interfaces/inner_api/runtime/include/ets_data_struct_converter.h -new file mode 100644 -index 0000000000000000000000000000000000000000..1f196768185cd4881b89b7fc3874b6c709a3e3f7 ---- /dev/null -+++ b/interfaces/inner_api/runtime/include/ets_data_struct_converter.h -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (c) 2025 Huawei Device Co., Ltd. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#ifndef OHOS_ABILITY_RUNTIME_ETS_DATA_STRUCT_CONVERTER_H -+#define OHOS_ABILITY_RUNTIME_ETS_DATA_STRUCT_CONVERTER_H -+ -+#include "ani.h" -+#include "launch_param.h" -+ -+namespace OHOS { -+namespace AbilityRuntime { -+bool WrapLaunchParam(ani_env *env, const AAFwk::LaunchParam &launchParam, ani_object &object); -+} // namespace AbilityRuntime -+} // namespace OHOS -+#endif // OHOS_ABILITY_RUNTIME_ETS_DATA_STRUCT_CONVERTER_H -diff --git a/interfaces/inner_api/runtime/include/ets_runtime.h b/interfaces/inner_api/runtime/include/ets_runtime.h -new file mode 100644 -index 0000000000000000000000000000000000000000..7b1126f1c0e9e032c31eb13a1523b352b6095038 ---- /dev/null -+++ b/interfaces/inner_api/runtime/include/ets_runtime.h -@@ -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. -+ */ -+ -+#ifndef OHOS_ABILITY_RUNTIME_ETS_RUNTIME_H -+#define OHOS_ABILITY_RUNTIME_ETS_RUNTIME_H -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "runtime.h" -+#include "js_runtime.h" -+#include "ets_exception_callback.h" -+#include "ani.h" -+ -+using AppLibPathMap = std::map>; -+using AppLibPathVec = std::vector; -+ -+namespace OHOS { -+namespace EtsEnv { -+class ETSEnvironment; -+} // namespace EtsEnv -+ -+namespace AbilityRuntime { -+struct ETSNativeReference { -+ ani_class aniCls = nullptr; -+ ani_object aniObj = nullptr; -+ ani_ref aniRef = nullptr; -+}; -+ -+class ETSRuntime : public Runtime { -+public: -+ static std::unique_ptr Create(const Options &options, Runtime *jsRuntime); -+ static void SetAppLibPath(const AppLibPathMap &appLibPaths); -+ ~ETSRuntime() override; -+ Language GetLanguage() const override -+ { -+ return Language::ETS; -+ } -+ -+ 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 {}; -+ 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; -+ 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 LoadEtsModule(const std::string &moduleName, const std::string &fileName, -+ const std::string &hapPath, const std::string &srcEntrance); -+ void HandleUncaughtError(); -+ -+private: -+ bool Initialize(const Options &options, Runtime *jsRuntime); -+ void Deinitialize(); -+ bool CreateEtsEnv(const Options &options, Runtime *jsRuntime); -+ bool LoadAbcLinker(ani_env *env, const std::string &moduleName, ani_class &abcCls, ani_object &abcObj); -+ std::shared_ptr etsEnv_; -+ int32_t apiTargetVersion_ = 0; -+ std::string codePath_; -+ static AppLibPathVec appLibPaths_; -+ std::string moduleName_; -+}; -+} // namespace AbilityRuntime -+} // namespace OHOS -+#endif // OHOS_ABILITY_RUNTIME_ETS_RUNTIME_H -diff --git a/interfaces/inner_api/runtime/include/js_runtime.h b/interfaces/inner_api/runtime/include/js_runtime.h -index d573886e3c6ebcf7164668e9129cedb044bedfed..dcc410a2cf06f39e99a6cb99bf728dbb3a9483a3 100644 ---- a/interfaces/inner_api/runtime/include/js_runtime.h -+++ b/interfaces/inner_api/runtime/include/js_runtime.h -@@ -103,6 +103,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 {} - bool PopPreloadObj(const std::string& key, std::unique_ptr& obj); - void StartDebugMode(const DebugOption debugOption) override; - void SetDebugOption(const DebugOption debugOption) override; -@@ -156,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 5b3312752f12c526bc9eac08395af8e769c84cc4..faf6685bbd2e6e2d5159820a1b539585682e7f1b 100644 ---- a/interfaces/inner_api/runtime/include/runtime.h -+++ b/interfaces/inner_api/runtime/include/runtime.h -@@ -27,14 +27,23 @@ namespace AppExecFwk { - class EventRunner; - } // namespace AppExecFwk - namespace AbilityRuntime { -+namespace { -+const std::string CODE_LANGUAGE_ARKTS_1_0 = "1.1"; -+const std::string CODE_LANGUAGE_ARKTS_1_2 = "1.2"; -+const std::string CODE_LANGUAGE_ARKTS_HYBRID = "hybrid"; -+} // namespace -+ - class Runtime { - public: - enum class Language { - JS = 0, -- CJ -+ CJ, -+ ETS, -+ UNKNOWN, - }; - - struct Options { -+ std::map langs; - Language lang = Language::JS; - std::string bundleName; - std::string moduleName; -@@ -80,7 +89,8 @@ public: - bool isDeveloperMode; - }; - -- static std::unique_ptr Create(const Options& options); -+ static std::vector> CreateRuntimes(Options &options); -+ static std::unique_ptr Create(Options &options); - static void SavePreloaded(std::unique_ptr&& instance); - static std::unique_ptr GetPreloaded(); - -@@ -108,6 +118,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; -@@ -122,6 +134,7 @@ public: - Runtime(Runtime&&) = delete; - Runtime& operator=(const Runtime&) = delete; - Runtime& operator=(Runtime&&) = delete; -+ virtual void RegisterUncaughtExceptionHandler(void *uncaughtExceptionInfo) {} - }; - } // namespace AbilityRuntime - } // namespace OHOS -diff --git a/interfaces/kits/native/ability/native/ability_loader.h b/interfaces/kits/native/ability/native/ability_loader.h -index 23947ec898c2169a47b0bfab43365a590337d66b..18fd34818d50bb9987e01b62b66220331fc1f784 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::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/ets_ui_ability.h b/interfaces/kits/native/ability/native/ability_runtime/ets_ui_ability.h -new file mode 100644 -index 0000000000000000000000000000000000000000..cecb7e7a835c7cfd6d908adde75cc8033c6135ab ---- /dev/null -+++ b/interfaces/kits/native/ability/native/ability_runtime/ets_ui_ability.h -@@ -0,0 +1,168 @@ -+/* -+ * Copyright (c) 2025 Huawei Device Co., Ltd. -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#ifndef OHOS_ABILITY_RUNTIME_ETS_UI_ABILITY_H -+#define OHOS_ABILITY_RUNTIME_ETS_UI_ABILITY_H -+ -+#include "ets_runtime.h" -+#include "ui_ability.h" -+ -+namespace OHOS { -+namespace AbilityRuntime { -+using AbilityHandler = AppExecFwk::AbilityHandler; -+using AbilityInfo = AppExecFwk::AbilityInfo; -+using OHOSApplication = AppExecFwk::OHOSApplication; -+using Want = AppExecFwk::Want; -+ -+class EtsUIAbility : public UIAbility { -+public: -+ /** -+ * @brief Create a EtsUIAbility instance through the singleton pattern -+ * @param runtime The runtime of the ability -+ * @return Returns the EtsUIability Instance point -+ */ -+ static UIAbility *Create(const std::unique_ptr &runtime); -+ -+ explicit EtsUIAbility(ETSRuntime &etsRuntime); -+ ~EtsUIAbility() 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 EtssUIability -+ * @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 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 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; -+ -+#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 onSceneDestroyed() 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" ets function barely. -+ * -+ * @param want Want -+ */ -+ void CallOnForegroundFunc(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; -+ -+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 UpdateEtsWindowStage(ani_ref windowStage); -+ -+ std::shared_ptr etsWindowStageObj_; -+ int32_t windowMode_ = 0; -+#endif -+ -+private: -+ bool CallObjectMethod(bool withResult, const char *name, const char *signature, ...); -+ ani_object CreateAppWindowStage(); -+ void SetAbilityContext(std::shared_ptr abilityInfo, std::shared_ptr want, -+ const std::string &moduleName, const std::string &srcPath, const std::shared_ptr &application); -+ void DoOnForegroundForSceneIsNull(const Want &want); -+ void UpdateAbilityObj(std::shared_ptr abilityInfo, -+ const std::string &moduleName, const std::string &srcPath); -+ bool BindNativeMethods(); -+ -+ ETSRuntime &etsRuntime_; -+ std::shared_ptr shellContextRef_; -+ std::shared_ptr etsAbilityObj_; -+ static std::once_flag singletonFlag_; -+}; -+} // namespace AbilityRuntime -+} // namespace OHOS -+#endif // OHOS_ABILITY_RUNTIME_ETS_UI_ABILITY_H -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/app/application_data_manager.h b/interfaces/kits/native/appkit/app/application_data_manager.h -index 3f8bb01b4e78f8521570be79cb8903df71347d6f..08ddb478a740ecafb472a6d10f3cc96fda3c749b 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 NotifyETSUnhandledException(const std::string &errMsg); - void RemoveErrorObserver(); - bool NotifyExceptionObject(const AppExecFwk::ErrorObject &errorObj); - bool NotifyCJExceptionObject(const AppExecFwk::ErrorObject &errorObj); -+ bool NotifyETSExceptionObject(const AppExecFwk::ErrorObject &errorObj); - - private: - ApplicationDataManager(); -diff --git a/interfaces/kits/native/appkit/app/main_thread.h b/interfaces/kits/native/appkit/app/main_thread.h -index cd5a86a89c5cbfb55f5c95dc2c01fbc909339670..a7e7e7f94156d3490723c2b04222bc51170ae840 100644 ---- a/interfaces/kits/native/appkit/app/main_thread.h -+++ b/interfaces/kits/native/appkit/app/main_thread.h -@@ -40,6 +40,7 @@ - #include "resource_manager.h" - #include "runtime.h" - #include "watchdog.h" -+#include "ets_runtime.h" - - #ifdef CJ_FRONTEND - #include "cj_envsetup.h" -@@ -323,6 +324,8 @@ public: - CJUncaughtExceptionInfo CreateCjExceptionInfo(const std::string &bundleName, uint32_t versionCode, - const std::string &hapPath); - #endif -+ EtsEnv::ETSUncaughtExceptionInfo CreateEtsExceptionInfo(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. - * -@@ -622,7 +625,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 -@@ -797,6 +801,12 @@ private: - void SetAppDebug(uint32_t modeFlag, bool isDebug); - void GetPluginNativeLibPath(std::vector &pluginBundleInfos, - AppLibPathMap &appLibPaths); -+ void AddRuntimeLang(ApplicationInfo &appInfo, AbilityRuntime::Runtime::Options &options); -+ bool IsNeedEtsInit(const ApplicationInfo &appInfo); -+ const std::unique_ptr &GetVerOneRuntime( -+ const ApplicationInfo &appInfo, const std::vector> &runtimes); -+ void SetJsIdleCallback(const std::weak_ptr &wpApplication, -+ const std::unique_ptr &runtime); - - std::vector fileEntries_; - std::vector nativeFileEntries_; -diff --git a/interfaces/kits/native/appkit/app/ohos_application.h b/interfaces/kits/native/appkit/app/ohos_application.h -index 783bd601495d60835ba55080a9bf51a95ec5992d..3bc1c5697a8c5f78a57f34fd5c3b3fb2850cd708 100644 ---- a/interfaces/kits/native/appkit/app/ohos_application.h -+++ b/interfaces/kits/native/appkit/app/ohos_application.h -@@ -27,6 +27,7 @@ - #include "ability_stage_context.h" - #include "application_configuration_manager.h" - #include "app_launch_data.h" -+#include "runtime.h" - - namespace OHOS { - namespace AbilityRuntime { -@@ -49,11 +50,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 -@@ -168,12 +169,19 @@ public: - */ - std::shared_ptr GetAppContext() const; - -+ /** -+ * @brief return the application runtimes -+ * -+ * @param runtime -+ */ -+ const std::vector> &GetRuntime() const; -+ - /** - * @brief return the application runtime - * - * @param runtime - */ -- const std::unique_ptr& GetRuntime() const; -+ const std::unique_ptr &GetRuntime(const std::string &language) const; - - /* - * -@@ -236,6 +244,8 @@ public: - void PreloadAppStartup(const BundleInfo &bundleInfo, const std::string &preloadModuleName, - std::shared_ptr startupTaskData); - -+ void SetCJApplication(bool isCJApplication = false); -+ - private: - void UpdateAppContextResMgr(const Configuration &config); - bool IsUpdateColorNeeded(Configuration &config, AbilityRuntime::SetLevel level); -@@ -251,14 +261,17 @@ 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::shared_ptr configuration_ = nullptr; - std::map extensionTypeMap_; -+ bool isCJApplication_ = false; - }; - } // namespace AppExecFwk - } // namespace OHOS -- Gitee From fc1fd599408e253a9150b54011e01507f2079880 Mon Sep 17 00:00:00 2001 From: zhangzezhong Date: Mon, 9 Jun 2025 22:39:30 +0800 Subject: [PATCH 3/3] modify gn Signed-off-by: zhangzezhong --- frameworks/native/appkit/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/frameworks/native/appkit/BUILD.gn b/frameworks/native/appkit/BUILD.gn index 11863d7b8bd..f0d40ede7ce 100644 --- a/frameworks/native/appkit/BUILD.gn +++ b/frameworks/native/appkit/BUILD.gn @@ -513,6 +513,7 @@ ohos_shared_library("appkit_delegator") { "image_framework:image_native", "ipc:ipc_core", "json:nlohmann_json_static", + "runtime_core:ani", "napi:ace_napi", "samgr:samgr_proxy", ] -- Gitee