diff --git a/frameworks/native/runtime/ohos_js_environment_impl.cpp b/frameworks/native/runtime/ohos_js_environment_impl.cpp index b6dd34dbb8..83acdd47a0 100644 --- a/frameworks/native/runtime/ohos_js_environment_impl.cpp +++ b/frameworks/native/runtime/ohos_js_environment_impl.cpp @@ -22,29 +22,29 @@ #include "ohos_loop_handler.h" #include "sys_timer.h" #include "worker_info.h" +#include "parameters.h" namespace OHOS { namespace AbilityRuntime { namespace { std::shared_ptr g_eventHandler = nullptr; } -void OHOSJsEnvironmentImpl::PostTaskToHandler(const char* taskName, uv_io_cb func, void* work, int status, - int priority) +void OHOSJsEnvironmentImpl::PostTaskToHandler(const uv_task_info_t* taskInfo) { TAG_LOGD(AAFwkTag::JSRUNTIME, "called"); - if (!func || !work) { + if (!taskInfo || !taskInfo->func || !taskInfo->work) { TAG_LOGE(AAFwkTag::JSRUNTIME, "Invalid parameters"); return; } - auto task = [func, work, status]() { + auto task = [func = taskInfo->func, work = taskInfo->work, status = taskInfo->status]() { TAG_LOGD(AAFwkTag::JSRUNTIME, "Do uv work"); func(work, status); TAG_LOGD(AAFwkTag::JSRUNTIME, "Do uv work end"); }; AppExecFwk::EventQueue::Priority prio = AppExecFwk::EventQueue::Priority::IMMEDIATE; - switch (priority) { + switch (taskInfo->prio) { case uv_qos_t::uv_qos_user_interactive: prio = AppExecFwk::EventQueue::Priority::VIP; break; @@ -66,12 +66,23 @@ void OHOSJsEnvironmentImpl::PostTaskToHandler(const char* taskName, uv_io_cb fun TAG_LOGE(AAFwkTag::JSRUNTIME, "Invalid parameters"); return; } - if (taskName == nullptr) { - g_eventHandler->PostTask(task, "uv_io_cb", 0, prio); + if (taskInfo->location == UV_POST_TASK_TO_HEAD) { + g_eventHandler->PostTaskAtFront(task, taskInfo->name ? taskInfo->name : "uv_loop_task", prio); } else { - g_eventHandler->PostTask(task, taskName, 0, prio); + g_eventHandler->PostTask(task, taskInfo->name ? taskInfo->name : "uv_io_cb", 0, prio); } } + +int OHOSJsEnvironmentImpl::CheckPendingHigherEvent(int priority) +{ + TAG_LOGD(AAFwkTag::JSRUNTIME, "called"); + if (g_eventHandler == nullptr) { + TAG_LOGE(AAFwkTag::JSRUNTIME, "g_eventHandler is null"); + return -1; + } + return g_eventHandler->HasPendingHigherEvent(priority) ? 0 : -1; +} + OHOSJsEnvironmentImpl::OHOSJsEnvironmentImpl() { TAG_LOGD(AAFwkTag::JSRUNTIME, "called"); @@ -153,7 +164,9 @@ bool OHOSJsEnvironmentImpl::InitLoop(NativeEngine* engine, bool isStage) eventHandler_->AddFileDescriptorListener(fd, events, std::make_shared(uvLoop), "uvLoopTask"); TAG_LOGD(AAFwkTag::JSRUNTIME, "uv_register_task_to_event, isStage: %{public}d", isStage); if (isStage && (eventHandler_->GetEventRunner()).get() == AppExecFwk::EventRunner::GetMainEventRunner().get()) { - uv_register_task_to_event(uvLoop, PostTaskToHandler, nullptr); + static const bool canInterrupt = system::GetBoolParameter("persist.sys.uv_can_interrupt", true); + TAG_LOGD(AAFwkTag::JSRUNTIME, "uv_register_task_to_event with canInterrupt: %{public}d", canInterrupt); + uv_register_task_to_event(uvLoop, PostTaskToHandler, canInterrupt ? CheckPendingHigherEvent : nullptr); // send signal here to trigger uv tasks generated during initialization. uv_async_send(&uvLoop->wq_async); } diff --git a/frameworks/native/runtime/ohos_js_environment_impl.h b/frameworks/native/runtime/ohos_js_environment_impl.h index 8e51190e98..10c9e9ec92 100644 --- a/frameworks/native/runtime/ohos_js_environment_impl.h +++ b/frameworks/native/runtime/ohos_js_environment_impl.h @@ -45,7 +45,8 @@ public: void InitSyscapModule() override; private: - static void PostTaskToHandler(const char* taskName, uv_io_cb func, void* work, int status, int priority); + static void PostTaskToHandler(const uv_task_info_t* taskInfo); + static int CheckPendingHigherEvent(int priority); std::shared_ptr eventHandler_; }; diff --git a/test/unittest/runtime_test/BUILD.gn b/test/unittest/runtime_test/BUILD.gn index 090a55bd31..47b58bf76f 100644 --- a/test/unittest/runtime_test/BUILD.gn +++ b/test/unittest/runtime_test/BUILD.gn @@ -211,6 +211,11 @@ ohos_unittest("ohos_js_environment_test") { configs = [] + cflags = [ + "-Dprivate = public", + "-Dprotected = public", + ] + external_deps = [ "ability_runtime:js_environment", "ability_runtime:runtime", diff --git a/test/unittest/runtime_test/ohos_js_environment_test.cpp b/test/unittest/runtime_test/ohos_js_environment_test.cpp index 9939c045b7..cf87df9cf3 100644 --- a/test/unittest/runtime_test/ohos_js_environment_test.cpp +++ b/test/unittest/runtime_test/ohos_js_environment_test.cpp @@ -150,5 +150,94 @@ HWTEST_F(OHOSJsEnvironmentTest, InitSyscapModule_0100, TestSize.Level0) jsEnvImpl->InitSyscapModule(); } + +void UvTaskWrapper(void* work, int status) {} + +/** + * @tc.name: PostTaskToHandler_0100 + * @tc.desc: Test basic functionality of PostTaskToHandler with valid task info. + * @tc.type: FUNC + * @tc.require: issueI6KODF + */ +HWTEST_F(OHOSJsEnvironmentTest, PostTaskToHandler_0100, TestSize.Level0) +{ + uv_task_info_t taskInfo; + uv_loop_s uvLoop; + taskInfo.func = UvTaskWrapper; + taskInfo.work = (void*)&uvLoop; + taskInfo.prio = uv_qos_t::uv_qos_user_interactive; + taskInfo.location = UV_POST_TASK_TO_HEAD; + ASSERT_NE(taskInfo.func, nullptr); + ASSERT_NE(taskInfo.work, nullptr); + OHOSJsEnvironmentImpl::PostTaskToHandler(&taskInfo); +} + +/** + * @tc.name: PostTaskToHandler_0200 + * @tc.desc: Test PostTaskToHandler with null and different task locations (head/tail). + * @tc.type: FUNC + * @tc.require: issueI6KODF + */ +HWTEST_F(OHOSJsEnvironmentTest, PostTaskToHandler_0200, TestSize.Level0) +{ + auto jsEnvImpl = std::make_shared(); + ASSERT_NE(jsEnvImpl, nullptr); + + uv_task_info_t taskInfo; + uv_loop_s uvLoop; + OHOSJsEnvironmentImpl::PostTaskToHandler(nullptr); + OHOSJsEnvironmentImpl::PostTaskToHandler(&taskInfo); + taskInfo.func = UvTaskWrapper; + taskInfo.work = (void*)&uvLoop; + taskInfo.prio = uv_qos_t::uv_qos_user_interactive; + taskInfo.location = UV_POST_TASK_TO_HEAD; + OHOSJsEnvironmentImpl::PostTaskToHandler(&taskInfo); + taskInfo.location = UV_POST_TASK_TO_TAIL; + OHOSJsEnvironmentImpl::PostTaskToHandler(&taskInfo); +} + +/** + * @tc.name: PostTaskToHandler_0300 + * @tc.desc: Test PostTaskToHandler with different task priorities. + * @tc.type: FUNC + * @tc.require: issueI6KODF + */ +HWTEST_F(OHOSJsEnvironmentTest, PostTaskToHandler_0300, TestSize.Level0) +{ + auto jsEnvImpl = std::make_shared(); + ASSERT_NE(jsEnvImpl, nullptr); + + uv_task_info_t taskInfo; + uv_loop_s uvLoop; + taskInfo.func = UvTaskWrapper; + taskInfo.work = (void*)&uvLoop; + taskInfo.location = UV_POST_TASK_TO_HEAD; + taskInfo.prio = uv_qos_t::uv_qos_user_interactive; + OHOSJsEnvironmentImpl::PostTaskToHandler(&taskInfo); + taskInfo.prio = uv_qos_t::uv_qos_user_initiated; + OHOSJsEnvironmentImpl::PostTaskToHandler(&taskInfo); + taskInfo.prio = uv_qos_t::uv_qos_utility; + OHOSJsEnvironmentImpl::PostTaskToHandler(&taskInfo); + taskInfo.prio = uv_qos_t::uv_qos_background; + OHOSJsEnvironmentImpl::PostTaskToHandler(&taskInfo); + taskInfo.prio = uv_qos_t::uv_qos_default; + OHOSJsEnvironmentImpl::PostTaskToHandler(&taskInfo); +} + +/** + * @tc.name: CheckPendingHigherEvent_0100 + * @tc.desc: Test CheckPendingHigherEvent with different input values. + * @tc.type: FUNC + * @tc.require: issueI6KODF + */ +HWTEST_F(OHOSJsEnvironmentTest, CheckPendingHigherEvent_0100, TestSize.Level0) +{ + ASSERT_EQ(OHOSJsEnvironmentImpl::CheckPendingHigherEvent(0), -1); + auto jsEnvImpl = std::make_shared(); + ASSERT_NE(jsEnvImpl, nullptr); + + ASSERT_EQ(OHOSJsEnvironmentImpl::CheckPendingHigherEvent(0), -1); + ASSERT_EQ(OHOSJsEnvironmentImpl::CheckPendingHigherEvent(1), -1); +} } // namespace AbilityRuntime } // namespace OHOS