diff --git a/ets_environment/frameworks/ets_environment/BUILD.gn b/ets_environment/frameworks/ets_environment/BUILD.gn index 32cc779fb52836d7c206faa339cb8411df87faf7..1c67d800122633704574c09186d75869cc286013 100644 --- a/ets_environment/frameworks/ets_environment/BUILD.gn +++ b/ets_environment/frameworks/ets_environment/BUILD.gn @@ -46,6 +46,10 @@ ohos_shared_library("ets_environment") { defines = [] + deps = [ + "${ability_runtime_innerkits_path}/connect_server_manager:connect_server_manager", + ] + external_deps = [ "c_utils:utils", "eventhandler:libeventhandler", diff --git a/ets_environment/frameworks/ets_environment/src/ets_environment.cpp b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp index 21544ecdc582becc06bf63f0b819d003c6218f51..f08d98593914e2025bbfd00e08cc48c139225d98 100644 --- a/ets_environment/frameworks/ets_environment/src/ets_environment.cpp +++ b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp @@ -25,6 +25,7 @@ #include #include "static_core/plugins/ets/runtime/ets_namespace_manager.h" +#include "static_core/runtime/tooling/inspector/debugger_arkapi.h" #include "ets_ani_expo.h" #ifdef LIKELY #undef LIKELY @@ -32,6 +33,7 @@ #ifdef UNLIKELY #undef UNLIKELY #endif +#include "connect_server_manager.h" #include "dynamic_loader.h" #include "elf_factory.h" #include "event_handler.h" @@ -50,9 +52,11 @@ 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========================"; +static const std::string DEBUGGER = "@Debugger"; 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); +using DebuggerPostTask = std::function &&)>; const char ETS_SDK_NSNAME[] = "ets_sdk"; const char ETS_SYS_NSNAME[] = "ets_system"; @@ -214,7 +218,7 @@ void ETSEnvironment::InitETSSysNS(const std::string &path) dlns_inherit(&ns, &ndk, "allow_all_shared_libs"); } -bool ETSEnvironment::Initialize() +bool ETSEnvironment::Initialize(const std::shared_ptr eventRunner, bool isStartWithDebug) { TAG_LOGD(AAFwkTag::ETSRUNTIME, "Initialize called"); if (!LoadRuntimeApis()) { @@ -227,6 +231,8 @@ bool ETSEnvironment::Initialize() return false; } + InitEventHandler(eventRunner); + std::vector options; // Create boot-panda-files options std::string bootString = "--ext:--boot-panda-files=" + bootfiles; @@ -234,6 +240,16 @@ bool ETSEnvironment::Initialize() options.push_back(ani_option { "--ext:--compiler-enable-jit=false", nullptr }); options.push_back(ani_option { "--ext:--log-level=info", nullptr }); options.push_back(ani_option { "--ext:taskpool-support-interop=true", nullptr }); + std::string interpreerMode = "--ext:--interpreter-type=cpp"; + std::string debugEnalbeMode = "--ext:--debugger-enable=true"; + std::string debugLibraryPathMode = "--ext:--debugger-library-path=/system/lib64/libarkinspector.so"; + std::string breadonstartMode = "--ext:--debugger-break-on-start"; + if (isStartWithDebug) { + options.push_back(ani_option { interpreerMode.data(), nullptr }); + options.push_back(ani_option { debugEnalbeMode.data(), nullptr }); + options.push_back(ani_option { debugLibraryPathMode.data(), nullptr }); + options.push_back(ani_option { breadonstartMode.data(), nullptr }); + } 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) { @@ -545,8 +561,8 @@ ETSEnvFuncs *ETSEnvironment::RegisterFuncs() .InitETSSysNS = [](const std::string &path) { ETSEnvironment::InitETSSysNS(path); }, - .Initialize = []() { - return ETSEnvironment::GetInstance()->Initialize(); + .Initialize = [](const std::shared_ptr eventRunner, bool isStartWithDebug) { + return ETSEnvironment::GetInstance()->Initialize(eventRunner, isStartWithDebug); }, .RegisterUncaughtExceptionHandler = [](const ETSUncaughtExceptionInfo &exceptionInfo) { ETSEnvironment::GetInstance()->RegisterUncaughtExceptionHandler(exceptionInfo); @@ -573,10 +589,114 @@ ETSEnvFuncs *ETSEnvironment::RegisterFuncs() }, .PreloadSystemClass = [](const char *className) { ETSEnvironment::GetInstance()->PreloadSystemClass(className); + }, + .RemoveInstance = [](uint32_t instanceId) { + return ETSEnvironment::GetInstance()->RemoveInstance(instanceId); + }, + .StopDebugMode = [](void *jsVm) { + return ETSEnvironment::GetInstance()->StopDebugMode(jsVm); + }, + .StartDebuggerForSocketPair = [](std::string &option, int32_t socketFd) { + return ETSEnvironment::GetInstance()->StartDebuggerForSocketPair(option, socketFd); + }, + .NotifyDebugMode = [](uint32_t tid, uint32_t instanceId, bool isStartWithDebug, void *jsVm) { + return ETSEnvironment::GetInstance()->NotifyDebugMode(tid, instanceId, isStartWithDebug, jsVm); + }, + .BroadcastAndConnect = [](const std::string& bundleName, int socketFd) { + return ETSEnvironment::GetInstance()->BroadcastAndConnect(bundleName, socketFd); } }; return &funcs; } + +void ETSEnvironment::NotifyDebugMode(uint32_t tid, uint32_t instanceId, bool isStartWithDebug, void *jsVm) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "Start"); + AbilityRuntime::ConnectServerManager::Get().StoreInstanceMessage(getproctid(), instanceId, "Debugger"); + auto task = GetDebuggerPostTask(); + ark::ArkDebugNativeAPI::NotifyDebugMode(tid, instanceId, isStartWithDebug, jsVm, task); +} + +void ETSEnvironment::RemoveInstance(uint32_t instanceId) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "Start"); + AbilityRuntime::ConnectServerManager::Get().RemoveInstance(instanceId); +} + +void ETSEnvironment::StopDebugMode(void *jsVm) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "Start"); + if (debugMode_) { + ark::ArkDebugNativeAPI::StopDebugger(jsVm); + } +} + +void ETSEnvironment::StartDebuggerForSocketPair(std::string &option, int32_t socketFd) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "Start"); + int32_t identifierId = ParseHdcRegisterOption(option); + if (identifierId == -1) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Abnormal parsing of tid results"); + return; + } + debugMode_ = ark::ArkDebugNativeAPI::StartDebuggerForSocketPair(ParseHdcRegisterOption(option), socketFd); +} + +DebuggerPostTask ETSEnvironment::GetDebuggerPostTask() +{ + auto debuggerPostTask = [weak = weak_from_this()](std::function&& task) { + auto etsEnv = weak.lock(); + if (etsEnv == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "StsEnv is invalid"); + return; + } + etsEnv->PostTask(task, "ETSEnvironment:GetDebuggerPostTask", 0); + }; + return debuggerPostTask; +} + +int32_t ETSEnvironment::ParseHdcRegisterOption(std::string& option) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "Start"); + std::size_t pos = option.find_first_of(":"); + if (pos == std::string::npos) { + return -1; + } + std::string idStr = option.substr(pos + 1); + pos = idStr.find(DEBUGGER); + if (pos == std::string::npos) { + return -1; + } + idStr = idStr.substr(0, pos); + pos = idStr.find("@"); + if (pos != std::string::npos) { + idStr = idStr.substr(pos + 1); + } + return std::atoi(idStr.c_str()); +} + +void ETSEnvironment::InitEventHandler(const std::shared_ptr &eventRunner) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "InitEventHandler called"); + if (eventRunner != nullptr) { + eventHandler_ = std::make_shared(eventRunner); + } +} + +void ETSEnvironment::PostTask(const std::function &task, const std::string &name, int64_t delayTime) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "PostTask called"); + if (eventHandler_ != nullptr) { + eventHandler_->PostTask(task, name, delayTime); + } +} + +void ETSEnvironment::BroadcastAndConnect(const std::string& bundleName, int socketFd) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "BroadcastAndConnect called"); + AbilityRuntime::ConnectServerManager::Get().SendInstanceMessageAll(nullptr); + AbilityRuntime::ConnectServerManager::Get().StartConnectServer(bundleName, socketFd, false); +} } // namespace EtsEnv } // namespace OHOS diff --git a/ets_environment/interfaces/inner_api/ets_environment.h b/ets_environment/interfaces/inner_api/ets_environment.h index 4422257e274c015e090a1c3724ea3abc54de6311..c7a79c5f5708849150ee2c2fe720ed5d2877f1a1 100644 --- a/ets_environment/interfaces/inner_api/ets_environment.h +++ b/ets_environment/interfaces/inner_api/ets_environment.h @@ -41,6 +41,8 @@ struct ETSRuntimeAPI { ani_status (*ANI_CreateVM)(const ani_options *options, uint32_t version, ani_vm **result); }; +using DebuggerPostTask = std::function&&)>; + class ETSEnvironment final : public std::enable_shared_from_this { public: ETSEnvironment() {}; @@ -50,7 +52,7 @@ public: static void InitETSSysNS(const std::string &path); static ETSEnvFuncs *RegisterFuncs(); - bool Initialize(); + bool Initialize(const std::shared_ptr eventRunner, bool isDebug); void RegisterUncaughtExceptionHandler(const ETSUncaughtExceptionInfo &handle); ani_env *GetAniEnv(); bool HandleUncaughtError(); @@ -61,6 +63,15 @@ public: void PostFork(void *napiEnv, const std::string &aotPath); void PreloadSystemClass(const char *className); + void RemoveInstance(uint32_t instanceId); + void StopDebugMode(void *jsVm); + void StartDebuggerForSocketPair(std::string &option, int32_t socketFd); + void NotifyDebugMode(uint32_t tid, uint32_t instanceId, bool isStartWithDebug, void *jsVm); + void PostTask(const std::function &task, const std::string &name, int64_t delayTime); + void BroadcastAndConnect(const std::string& bundleName, int socketFd); + + DebuggerPostTask GetDebuggerPostTask(); + struct VMEntry { ani_vm *aniVm_; ani_env *aniEnv_; @@ -80,9 +91,13 @@ private: EtsEnv::ETSErrorObject GetETSErrorObject(); std::string GetErrorProperty(ani_error aniError, const char *property); bool LoadAbcLinker(ani_env *env, const std::string &modulePath, ani_class &abcCls, ani_object &abcObj); + void InitEventHandler(const std::shared_ptr &eventRunner); + int32_t ParseHdcRegisterOption(std::string& option); static ETSRuntimeAPI lazyApis_; VMEntry vmEntry_; ETSUncaughtExceptionInfo uncaughtExceptionInfo_; + std::shared_ptr eventHandler_; + bool debugMode_ = false; }; } // namespace EtsEnv } // namespace OHOS diff --git a/ets_environment/interfaces/inner_api/ets_interface.h b/ets_environment/interfaces/inner_api/ets_interface.h index ea3ebe495d26ebf2a5973a65f4d88bafc86d6e05..fa6fcc369d22bb4102fac29fb8b1634ba3edb03c 100644 --- a/ets_environment/interfaces/inner_api/ets_interface.h +++ b/ets_environment/interfaces/inner_api/ets_interface.h @@ -23,12 +23,18 @@ #include "ets_native_reference.h" #include "napi/native_api.h" +namespace OHOS { +namespace AppExecFwk { + class EventRunner; +} +} + extern "C" { struct ETSEnvFuncs { void (*InitETSSDKNS)(const std::string &path) = nullptr; void (*InitETSSysNS)(const std::string &path) = nullptr; - bool (*Initialize)() = nullptr; + bool (*Initialize)(const std::shared_ptr eventRunner, bool isDebug) = nullptr; void (*RegisterUncaughtExceptionHandler)( const OHOS::EtsEnv::ETSUncaughtExceptionInfo &uncaughtExceptionInfo) = nullptr; ani_env *(*GetAniEnv)() = nullptr; @@ -41,6 +47,12 @@ struct ETSEnvFuncs { void (*FinishPreload)() = nullptr; void (*PostFork)(void *napiEnv, const std::string &aotPath) = nullptr; void (*PreloadSystemClass)(const char *className) = nullptr; + void (*RemoveInstance)(uint32_t instanceId) = nullptr; + void (*StopDebugMode)(void *jsVm) = nullptr; + void (*StartDebuggerForSocketPair)(std::string &option, int32_t socketFd) = nullptr; + void (*NotifyDebugMode)(uint32_t tid, uint32_t instanceId, bool isStartWithDebug, + void *jsVm) = nullptr; + void (*BroadcastAndConnect)(const std::string& bundleName, int socketFd) = nullptr; }; } #endif // OHOS_ABILITY_RUNTIME_ETS_INTERFACE_H diff --git a/ets_environment/test/unittest/ets_environment_test/BUILD.gn b/ets_environment/test/unittest/ets_environment_test/BUILD.gn index 470009ccaa22072b432f557ee6ce7da4f944ae88..5adacb33093ce8771571d1d929081ce0cc7cebd1 100644 --- a/ets_environment/test/unittest/ets_environment_test/BUILD.gn +++ b/ets_environment/test/unittest/ets_environment_test/BUILD.gn @@ -32,7 +32,9 @@ template("ets_environment_test_template") { configs = [] - deps = [] + deps = [ + "${ability_runtime_innerkits_path}/connect_server_manager:connect_server_manager", + ] external_deps = [ "ability_runtime:runtime", diff --git a/ets_environment/test/unittest/ets_environment_test/ets_environment_test.cpp b/ets_environment/test/unittest/ets_environment_test/ets_environment_test.cpp index 1d794e695334e2141e5c1555775d4cdb0a920046..63ab15878ebebbdf05e33807ab407cbc55daf86f 100644 --- a/ets_environment/test/unittest/ets_environment_test/ets_environment_test.cpp +++ b/ets_environment/test/unittest/ets_environment_test/ets_environment_test.cpp @@ -251,7 +251,7 @@ HWTEST_F(EtsEnvironmentTest, Initialize_0100, TestSize.Level0) { auto etsEnv = std::make_shared(); ASSERT_NE(etsEnv, nullptr); - bool result = etsEnv->Initialize(); + bool result = etsEnv->Initialize(nullptr, false); EXPECT_FALSE(result); } @@ -311,5 +311,18 @@ HWTEST_F(EtsEnvironmentTest, LoadModule_0100, TestSize.Level0) bool result = etsEnv->LoadModule("testModule", "testModule", cls, obj, ref); EXPECT_FALSE(result); } + +/** + * @tc.name: GetDebuggerPostTask_0100 + * @tc.desc: Sts environment GetDebuggerPostTask. + * @tc.type: FUNC + */ +HWTEST_F(EtsEnvironmentTest, GetDebuggerPostTask_0100, TestSize.Level0) +{ + auto etsEnv = std::make_shared(); + ASSERT_NE(etsEnv, nullptr); + auto task = etsEnv->GetDebuggerPostTask(); + ASSERT_NE(task, nullptr); +} } // namespace StsEnv } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/appkit/app/main_thread.cpp b/frameworks/native/appkit/app/main_thread.cpp index 2821b75ebd42161ddad3468f2d73c16141c73688..e5ceb9110c429634d075e3e17ec81f9af2407e25 100644 --- a/frameworks/native/appkit/app/main_thread.cpp +++ b/frameworks/native/appkit/app/main_thread.cpp @@ -1673,6 +1673,7 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con options.uid = bundleInfo.applicationInfo.uid; options.apiTargetVersion = appInfo.apiTargetVersion; options.pkgContextInfoJsonStringMap = pkgContextInfoJsonStringMap; + options.isStartWithDebug = appLaunchData.GetDebugApp(); options.allowArkTsLargeHeap = appInfo.allowArkTsLargeHeap; options.versionCode = appInfo.versionCode; #ifdef CJ_FRONTEND @@ -1754,6 +1755,7 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con ResHelper::ReportLoadAbcCompletedInfoToRss(uid, currentPid, bundleName); }); AbilityRuntime::Runtime::DebugOption debugOption; + debugOption.arkTSMode = appInfo.arkTSMode; debugOption.isStartWithDebug = appLaunchData.GetDebugApp(); debugOption.processName = processName; debugOption.isDebugApp = appInfo.debug; @@ -1762,6 +1764,7 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con debugOption.isDebugFromLocal = appLaunchData.GetDebugFromLocal(); debugOption.perfCmd = perfCmd; debugOption.isDeveloperMode = isDeveloperMode_; + debugOption.bundleName = appInfo.bundleName; runtime->SetDebugOption(debugOption); if (perfCmd.find(PERFCMD_PROFILE) != std::string::npos || perfCmd.find(PERFCMD_DUMPHEAP) != std::string::npos) { diff --git a/frameworks/native/runtime/cj_runtime.cpp b/frameworks/native/runtime/cj_runtime.cpp index ecf1697834d004eebefd5e2e51dbd930083283d0..da7e102e50e4aad9fbb674ce7f0b4deaad2bcf22 100644 --- a/frameworks/native/runtime/cj_runtime.cpp +++ b/frameworks/native/runtime/cj_runtime.cpp @@ -31,11 +31,6 @@ using namespace OHOS::AbilityRuntime; - -namespace { -const std::string DEBUGGER = "@Debugger"; -} // namespace - #define LIB_NAME "libcj_environment.z.so" #define GET_ENV_INS_NAME "OHOS_GetCJEnvInstance" diff --git a/frameworks/native/runtime/ets_runtime.cpp b/frameworks/native/runtime/ets_runtime.cpp index 35a40d191751d2666774a18405c2f764966c7eac..06af1a7dfd86cc2d3a185c9e636a9909f7bdcf55 100644 --- a/frameworks/native/runtime/ets_runtime.cpp +++ b/frameworks/native/runtime/ets_runtime.cpp @@ -23,12 +23,16 @@ #include #include +#include "bundle_constants.h" #include "constants.h" #include "ets_interface.h" #include "file_path_utils.h" #include "hilog_tag_wrapper.h" +#include "hdc_register.h" #include "hybrid_js_module_reader.h" +#include "js_utils.h" #include "nocopyable.h" +#include "parameters.h" #ifdef SUPPORT_SCREEN #include "ace_forward_compatibility.h" @@ -296,6 +300,7 @@ ETSRuntime::~ETSRuntime() { TAG_LOGD(AAFwkTag::ETSRUNTIME, "~ETSRuntime called"); Deinitialize(); + StopDebugMode(); } void ETSRuntime::Deinitialize() @@ -312,7 +317,7 @@ bool ETSRuntime::CreateEtsEnv(const Options &options) return false; } - if (!g_etsEnvFuncs->Initialize()) { + if (!g_etsEnvFuncs->Initialize(options.eventRunner, options.isStartWithDebug)) { TAG_LOGE(AAFwkTag::ETSRUNTIME, "Initialize failed"); return false; } @@ -469,5 +474,110 @@ void ETSRuntime::HandleOhmUrlFileName(std::string &fileName) fileName = fileName + "/" + fileName; } } + +void ETSRuntime::StartDebugMode(const DebugOption dOption) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "localDebug %{public}d", dOption.isDebugFromLocal); + if (!dOption.isDebugFromLocal && !dOption.isDeveloperMode) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "developer Mode false"); + return; + } + // Set instance id to tid after the first instance. + instanceId_ = static_cast(getproctid()); + + bool isStartWithDebug = dOption.isStartWithDebug; + bool isDebugApp = dOption.isDebugApp; + std::string appProvisionType = dOption.appProvisionType; + TAG_LOGD(AAFwkTag::ETSRUNTIME, "Ark VM is starting debug mode [%{public}s]", isStartWithDebug ? "break" : "normal"); + const std::string bundleName = dOption.bundleName; + uint32_t instanceId = instanceId_; + std::string inputProcessName = bundleName != dOption.processName ? dOption.processName : ""; + HdcRegister::DebugRegisterMode debugMode = HdcRegister::DebugRegisterMode::HDC_DEBUG_REG; + HdcRegister::Get().StartHdcRegister(bundleName, inputProcessName, isDebugApp, debugMode, + [bundleName, isStartWithDebug, instanceId, isDebugApp, appProvisionType] + (int socketFd, std::string option) { + TAG_LOGI(AAFwkTag::ETSRUNTIME, "HdcRegister msg, fd= %{public}d, option= %{public}s", socketFd, option.c_str()); + // system is debuggable when const.secure is false and const.debuggable is true + bool isSystemDebuggable = system::GetBoolParameter("const.secure", true) == false && + system::GetBoolParameter("const.debuggable", false) == true; + // Don't start any server if (system not in debuggable mode) and app is release version + // Starting ConnectServer in release app on debuggable system is only for debug mode, not for profiling mode. + if ((!isSystemDebuggable) && appProvisionType == AppExecFwk::Constants::APP_PROVISION_TYPE_RELEASE) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "not support release app"); + return; + } + if (option.find(DEBUGGER) == std::string::npos) { + // if has old connect server, stop it + if (g_etsEnvFuncs == nullptr || g_etsEnvFuncs->BroadcastAndConnect == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or BroadcastAndConnect"); + return; + } + g_etsEnvFuncs->BroadcastAndConnect(bundleName, socketFd); + } else { + if (appProvisionType == AppExecFwk::Constants::APP_PROVISION_TYPE_RELEASE) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "not support release app"); + return; + } + if (g_etsEnvFuncs == nullptr || g_etsEnvFuncs->StartDebuggerForSocketPair == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or StartDebuggerForSocketPair"); + return; + } + g_etsEnvFuncs->StartDebuggerForSocketPair(option, socketFd); + } + }); + DebuggerConnectionHandler(isDebugApp, isStartWithDebug); +} + +void ETSRuntime::DebuggerConnectionHandler(bool isDebugApp, bool isStartWithDebug) +{ + auto dTask = nullptr; + if (jsRuntime_ == nullptr) { + TAG_LOGD(AAFwkTag::ETSRUNTIME, "jsRuntime_ is nullptr"); + return; + } + if (g_etsEnvFuncs == nullptr || g_etsEnvFuncs->NotifyDebugMode == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or NotifyDebugMode"); + return; + } + if (jsRuntime_ == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null js runtime"); + return; + } + auto &jsRuntimePoint = (static_cast(*jsRuntime_)); + auto vm = jsRuntimePoint.GetEcmaVm(); + if (vm == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null js vm"); + return; + } + g_etsEnvFuncs->NotifyDebugMode(getproctid(), instanceId_, isStartWithDebug, vm); +} + +void ETSRuntime::StopDebugMode() +{ + if (g_etsEnvFuncs == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs"); + return; + } + if (g_etsEnvFuncs->RemoveInstance == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null RemoveInstance"); + return; + } + g_etsEnvFuncs->RemoveInstance(instanceId_); + if (g_etsEnvFuncs->StopDebugMode == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null StopDebugMode"); + return; + } + if (jsRuntime_ == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null js runtime"); + return; + } + auto &jsRuntimePoint = (static_cast(*jsRuntime_)); + auto vm = jsRuntimePoint.GetEcmaVm(); + if (vm == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null js vm"); + return; + } + g_etsEnvFuncs->StopDebugMode(vm); +} } // 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 e0df21d06e8bb2d179edca48b95cb783b6fdbecd..8af824130c3156219d2bed8729b7552122b2d8a1 100644 --- a/frameworks/native/runtime/js_runtime.cpp +++ b/frameworks/native/runtime/js_runtime.cpp @@ -85,7 +85,6 @@ constexpr int32_t DEFAULT_INTER_VAL = 500; constexpr int32_t API8 = 8; const std::string SANDBOX_ARK_CACHE_PATH = "/data/storage/ark-cache/"; const std::string SANDBOX_ARK_PROIFILE_PATH = "/data/storage/ark-profile"; -const std::string DEBUGGER = "@Debugger"; constexpr char MERGE_ABC_PATH[] = "/ets/modules.abc"; constexpr char BUNDLE_INSTALL_PATH[] = "/data/storage/el1/bundle/"; @@ -164,8 +163,8 @@ void JsRuntime::StartDebugMode(const DebugOption dOption) { HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); TAG_LOGD(AAFwkTag::JSRUNTIME, "localDebug %{public}d", dOption.isDebugFromLocal); - if (!dOption.isDebugFromLocal && !dOption.isDeveloperMode) { - TAG_LOGE(AAFwkTag::JSRUNTIME, "developer Mode false"); + if (!ShouldSkipDebugMode(dOption)) { + TAG_LOGE(AAFwkTag::JSRUNTIME, "not start debug"); return; } CHECK_POINTER(jsEnv_); @@ -213,10 +212,16 @@ void JsRuntime::StartDebugMode(const DebugOption dOption) TAG_LOGE(AAFwkTag::JSRUNTIME, "not support release app"); return; } + auto callback = [weak, isDebugApp, isStartWithDebug](int32_t tid, const DebuggerPostTask& task) { + panda::JSNApi::DebugOption debugOption = {ARK_DEBUGGER_LIB_PATH, isDebugApp ? isStartWithDebug : false}; + if (weak != nullptr) { + panda::JSNApi::StoreDebugInfo(tid, weak->GetVM(), debugOption, task, isDebugApp); + } + }; if (option.find(DEBUGGER) == std::string::npos) { // if has old connect server, stop it ConnectServerManager::Get().StopConnectServer(false); - ConnectServerManager::Get().SendDebuggerInfo(isStartWithDebug, isDebugApp); + ConnectServerManager::Get().SendInstanceMessageAll(callback); ConnectServerManager::Get().StartConnectServer(bundleName, socketFd, false); } else { // if has old debugger server, stop it @@ -231,6 +236,19 @@ void JsRuntime::StartDebugMode(const DebugOption dOption) DebuggerConnectionHandler(isDebugApp, isStartWithDebug); } +bool JsRuntime::ShouldSkipDebugMode(const DebugOption dOption) +{ + if (!dOption.isDebugFromLocal && !dOption.isDeveloperMode) { + TAG_LOGE(AAFwkTag::JSRUNTIME, "developer Mode false"); + return false; + } + if (!(dOption.arkTSMode == AbilityRuntime::CODE_LANGUAGE_ARKTS_1_2)) { + TAG_LOGE(AAFwkTag::JSRUNTIME, "developer register in sts"); + return false; + } + return true; +} + void JsRuntime::DebuggerConnectionHandler(bool isDebugApp, bool isStartWithDebug) { ConnectServerManager::Get().StoreInstanceMessage(getproctid(), instanceId_); diff --git a/frameworks/native/runtime/ohos_js_environment_impl.cpp b/frameworks/native/runtime/ohos_js_environment_impl.cpp index 6f77792c827d0a27dbb3adb6887609c4a1f2e805..b6dd34dbb8ca0505236c285f233aa762f9601d10 100644 --- a/frameworks/native/runtime/ohos_js_environment_impl.cpp +++ b/frameworks/native/runtime/ohos_js_environment_impl.cpp @@ -97,9 +97,11 @@ OHOSJsEnvironmentImpl::~OHOSJsEnvironmentImpl() void OHOSJsEnvironmentImpl::PostTask(const std::function& task, const std::string& name, int64_t delayTime) { TAG_LOGD(AAFwkTag::JSRUNTIME, "called"); - if (eventHandler_ != nullptr) { - eventHandler_->PostTask(task, name, delayTime); + if (eventHandler_ == nullptr) { + TAG_LOGE(AAFwkTag::JSRUNTIME, "null eventHandler_"); + return; } + eventHandler_->PostTask(task, name, delayTime); } void OHOSJsEnvironmentImpl::PostSyncTask(const std::function& task, const std::string& name) diff --git a/interfaces/inner_api/connect_server_manager/BUILD.gn b/interfaces/inner_api/connect_server_manager/BUILD.gn index c2c684462c3aa841d1cc7b8b242102147ddd9f05..3f285a6fd25b1ad26c81bf7144635517eb4127d8 100644 --- a/interfaces/inner_api/connect_server_manager/BUILD.gn +++ b/interfaces/inner_api/connect_server_manager/BUILD.gn @@ -53,6 +53,7 @@ ohos_shared_library("connect_server_manager") { external_deps = [ "ets_runtime:libark_jsruntime", "hilog:libhilog", + "runtime_core:libarkruntime", ] configs = [ diff --git a/interfaces/inner_api/connect_server_manager/include/connect_server_manager.h b/interfaces/inner_api/connect_server_manager/include/connect_server_manager.h index 8f1f12a09360d5ca5c2291939279a859155436c8..bdcb2d2d58558a18ee769fcd882a7a8a5060db70 100644 --- a/interfaces/inner_api/connect_server_manager/include/connect_server_manager.h +++ b/interfaces/inner_api/connect_server_manager/include/connect_server_manager.h @@ -52,6 +52,7 @@ public: void SetConnectedCallback(); bool SendInstanceMessage(int32_t tid, int32_t instanceId, const std::string& instanceName); void SendDebuggerInfo(bool needBreakPoint, bool isDebugApp); + void SendInstanceMessageAll(std::function callback); void LoadConnectServerDebuggerSo(); bool SetRecordCallback(const std::function &startRecordFunc, const std::function &stopRecordFunc); diff --git a/interfaces/inner_api/connect_server_manager/src/connect_server_manager.cpp b/interfaces/inner_api/connect_server_manager/src/connect_server_manager.cpp index 73a75f3f6a61e73725f46fa5f69a11725f9d8dad..f9b313200f1e79aa33ba0643b1c7cb4de6ffc3c8 100644 --- a/interfaces/inner_api/connect_server_manager/src/connect_server_manager.cpp +++ b/interfaces/inner_api/connect_server_manager/src/connect_server_manager.cpp @@ -467,4 +467,24 @@ void ConnectServerManager::AddInstanceCallback(const int32_t instanceId) } } } + +void ConnectServerManager::SendInstanceMessageAll(std::function callback) +{ + ConnectServerManager::Get().SetConnectedCallback(); + std::lock_guard lock(mutex_); + for (const auto& instance : instanceMap_) { + auto instanceId = instance.first; + auto instanceName = instance.second.first; + auto tid = instance.second.second; + std::lock_guard lock(g_debuggerMutex); + ConnectServerManager::Get().SendInstanceMessage(tid, instanceId, instanceName); + const auto &debuggerPostTask = g_debuggerInfo[tid].second; + if (!debuggerPostTask) { + continue; + } + if (callback != nullptr) { + callback(tid, debuggerPostTask); + } + } +} } // namespace OHOS::AbilityRuntime \ No newline at end of file diff --git a/interfaces/inner_api/runtime/include/ets_runtime.h b/interfaces/inner_api/runtime/include/ets_runtime.h index 56d71c152ccf434935c4a654dfb482f6562587cf..e0df1e4e0cceb78aec232e6b7d76101ed3a059d2 100644 --- a/interfaces/inner_api/runtime/include/ets_runtime.h +++ b/interfaces/inner_api/runtime/include/ets_runtime.h @@ -54,7 +54,7 @@ public: return Language::ETS; } - void StartDebugMode(const DebugOption debugOption) override {} + void StartDebugMode(const DebugOption debugOption) override; void DumpHeapSnapshot(bool isPrivate) override {} void NotifyApplicationState(bool isBackground) override {} bool SuspendVM(uint32_t tid) override { return false; } @@ -91,6 +91,9 @@ public: std::unique_ptr MoveJsRuntime(); static std::unique_ptr PreFork(const Options &options, std::unique_ptr &jsRuntime); void PreloadSystemClass(const char *className) override; + void DebuggerConnectionHandler(bool isDebugApp, bool isStartWithDebug); + void StopDebugMode(); + uint32_t instanceId_ = 0; private: bool Initialize(const Options &options, std::unique_ptr &jsRuntime); @@ -105,6 +108,7 @@ private: std::string codePath_; std::string moduleName_; std::unique_ptr jsRuntime_ = nullptr; + bool debugMode_ = false; }; } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/inner_api/runtime/include/js_runtime.h b/interfaces/inner_api/runtime/include/js_runtime.h index 7e514e2ee6aab14d32d145805c09d183e055fd1c..aa916bc882c98d4e87b3e77af795a85a700bf830 100644 --- a/interfaces/inner_api/runtime/include/js_runtime.h +++ b/interfaces/inner_api/runtime/include/js_runtime.h @@ -52,6 +52,14 @@ using UncatchableTask = std::function>; +#ifdef APP_USE_ARM +constexpr char ARK_DEBUGGER_LIB_PATH[] = "libark_inspector.z.so"; +#elif defined(APP_USE_X86_64) +constexpr char ARK_DEBUGGER_LIB_PATH[] = "libark_inspector.z.so"; +#else +constexpr char ARK_DEBUGGER_LIB_PATH[] = "libark_inspector.z.so"; +#endif + namespace AbilityRuntime { class TimerTask; @@ -107,6 +115,7 @@ public: bool isEsMode, bool useCommonTrunk) override {} bool PopPreloadObj(const std::string& key, std::unique_ptr& obj); void StartDebugMode(const DebugOption debugOption) override; + bool ShouldSkipDebugMode(const DebugOption debugOption); void SetDebugOption(const DebugOption debugOption) override; void StartLocalDebugMode(bool isDebugFromLocal) override; void DebuggerConnectionHandler(bool isDebugApp, bool isStartWithDebug); diff --git a/interfaces/inner_api/runtime/include/runtime.h b/interfaces/inner_api/runtime/include/runtime.h index e08e4428cff763de0d34baf2cfcee77d72f05877..0a0bd6ebd28bd15cb860b2cfb263ff251d6342c6 100644 --- a/interfaces/inner_api/runtime/include/runtime.h +++ b/interfaces/inner_api/runtime/include/runtime.h @@ -31,6 +31,7 @@ namespace { const std::string CODE_LANGUAGE_ARKTS_1_0 = "dynamic"; const std::string CODE_LANGUAGE_ARKTS_1_2 = "static"; const std::string CODE_LANGUAGE_ARKTS_HYBRID = "hybrid"; +const std::string DEBUGGER = "@Debugger"; } // namespace class Runtime { @@ -74,6 +75,7 @@ public: std::map pkgContextInfoJsonStringMap; std::map packageNameList; std::map aotCompileStatusMap; + bool isStartWithDebug = false; uint32_t versionCode = 0; bool enableWarmStartupSmartGC = false; }; @@ -88,6 +90,7 @@ public: bool isStartWithNative = false; bool isDebugFromLocal = false; bool isDeveloperMode; + std::string arkTSMode = CODE_LANGUAGE_ARKTS_1_2; }; static std::unique_ptr Create(Options &options); diff --git a/test/unittest/runtime_test/BUILD.gn b/test/unittest/runtime_test/BUILD.gn index e4f1504fa7338cfba09c11d13948606e57cbec80..709cca198469e7e10a8adf232458cb9c80a764e0 100644 --- a/test/unittest/runtime_test/BUILD.gn +++ b/test/unittest/runtime_test/BUILD.gn @@ -284,7 +284,9 @@ ohos_unittest("ets_runtime_test") { ] configs = [ "${ability_runtime_services_path}/abilitymgr:abilityms_config" ] - deps = [] + deps = [ + "${ability_runtime_innerkits_path}/connect_server_manager:connect_server_manager", + ] external_deps = [ "ability_runtime:runtime",