From 7577d92ef56a8a6f1e3ed35c77c9b05046a35d42 Mon Sep 17 00:00:00 2001 From: xuliang <15609287+xuliang101@user.noreply.gitee.com> Date: Wed, 16 Apr 2025 11:43:12 +0800 Subject: [PATCH] add subscribe input active interface Signed-off-by: xuliang --- BUILD.gn | 1 + frameworks/proxy/BUILD.gn | 2 + .../include/client_msg_handler.h | 1 + .../include/input_active_subscribe_manager.h | 61 +++ .../include/input_manager_impl.h | 2 + .../include/multimodal_event_handler.h | 1 + .../event_handler/src/client_msg_handler.cpp | 40 +- .../src/input_active_subscribe_manager.cpp | 162 ++++++++ .../event_handler/src/input_manager_impl.cpp | 30 ++ .../src/multimodal_event_handler.cpp | 1 + frameworks/proxy/event_handler/test/BUILD.gn | 59 +++ .../input_active_subscribe_manager_test.cpp | 207 ++++++++++ frameworks/proxy/events/src/input_manager.cpp | 10 + interfaces/native/innerkits/libmmi-client-map | 1 + .../innerkits/proxy/include/input_manager.h | 26 ++ multimodalinput_mini.gni | 2 + .../include/i_multimodal_input_connect.h | 2 + .../multimodal_input_connect_manager.h | 2 + .../include/multimodal_input_connect_proxy.h | 2 + .../include/multimodal_input_connect_stub.h | 2 + .../multimodalinput_ipc_interface_code.h | 2 + .../src/multimodal_input_connect_manager.cpp | 22 ++ .../src/multimodal_input_connect_proxy.cpp | 47 +++ .../src/multimodal_input_connect_stub.cpp | 53 +++ .../test/mock_multimodal_input_connect_stub.h | 2 + .../multimodal_input_connect_stub_ex_test.cpp | 2 + .../include/input_event_handler.h | 3 + .../event_handler/src/input_event_handler.cpp | 12 + .../fingerprint_event_processor/test/BUILD.gn | 1 + service/libmmi-server-map | 1 + service/module_loader/include/mmi_service.h | 2 + service/module_loader/src/mmi_service.cpp | 40 ++ .../include/input_active_subscriber_handler.h | 82 ++++ .../src/input_active_subscriber_handler.cpp | 361 ++++++++++++++++++ service/subscriber/test/BUILD.gn | 39 +- .../input_active_subscriber_handler_test.cpp | 66 ++++ util/common/include/error_multimodal.h | 15 + util/common/include/proto.h | 1 + 38 files changed, 1362 insertions(+), 3 deletions(-) create mode 100644 frameworks/proxy/event_handler/include/input_active_subscribe_manager.h create mode 100644 frameworks/proxy/event_handler/src/input_active_subscribe_manager.cpp create mode 100644 frameworks/proxy/event_handler/test/BUILD.gn create mode 100644 frameworks/proxy/event_handler/test/input_active_subscribe_manager_test.cpp create mode 100644 service/subscriber/include/input_active_subscriber_handler.h create mode 100644 service/subscriber/src/input_active_subscriber_handler.cpp create mode 100644 service/subscriber/test/input_active_subscriber_handler_test.cpp diff --git a/BUILD.gn b/BUILD.gn index 173c8d454..23b08404a 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -152,6 +152,7 @@ group("mmi_tests") { "frameworks/proxy:LongPressEventSubscribeManagerTest", "frameworks/proxy:PointerEventTest", "frameworks/proxy:ut-mmi-proxy-out", + "frameworks/proxy/event_handler/test:InputActiveSubscribeManagerTest", "libudev:test", "service:AccountManagerTest", "service:ApplicationStateObserverTest", diff --git a/frameworks/proxy/BUILD.gn b/frameworks/proxy/BUILD.gn index b45ce9d0a..53e1155a7 100644 --- a/frameworks/proxy/BUILD.gn +++ b/frameworks/proxy/BUILD.gn @@ -312,6 +312,7 @@ ohos_unittest("SwitchEventInputSubscribeManagerTest") { "${mmi_path}/service/connect_manager/src/input_binder_client_stub.cpp", "${mmi_path}/service/connect_manager/src/multimodal_input_connect_death_recipient.cpp", "${mmi_path}/service/connect_manager/src/multimodal_input_connect_manager.cpp", + "event_handler/src/input_active_subscribe_manager.cpp", "event_handler/src/input_handler_manager.cpp", "event_handler/src/multimodal_event_handler.cpp", "event_handler/src/switch_event_input_subscribe_manager.cpp", @@ -446,6 +447,7 @@ ohos_unittest("InputManagerImplTest") { "${mmi_path}/service/filter/src/event_filter_stub.cpp", "event_handler/src/anr_handler.cpp", "event_handler/src/bytrace_adapter.cpp", + "event_handler/src/input_active_subscribe_manager.cpp", "event_handler/src/input_handler_manager.cpp", "event_handler/src/input_manager_impl.cpp", "event_handler/src/key_event_input_subscribe_manager.cpp", diff --git a/frameworks/proxy/event_handler/include/client_msg_handler.h b/frameworks/proxy/event_handler/include/client_msg_handler.h index 89e93124c..1ed8891b2 100644 --- a/frameworks/proxy/event_handler/include/client_msg_handler.h +++ b/frameworks/proxy/event_handler/include/client_msg_handler.h @@ -68,6 +68,7 @@ protected: int32_t OnAnr(const UDSClient &client, NetPacket &pkt); int32_t NotifyWindowStateError(const UDSClient& client, NetPacket& pkt); int32_t OnSetInputDeviceAck(const UDSClient& client, NetPacket& pkt); + int32_t OnSubscribeInputActiveCallback(const UDSClient& client, NetPacket& pkt); private: static void OnDispatchEventProcessed(int32_t eventId, int64_t actionTime); diff --git a/frameworks/proxy/event_handler/include/input_active_subscribe_manager.h b/frameworks/proxy/event_handler/include/input_active_subscribe_manager.h new file mode 100644 index 000000000..f8bc5c86a --- /dev/null +++ b/frameworks/proxy/event_handler/include/input_active_subscribe_manager.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INPUT_ACTIVE_SUBSCRIBE_MANAGER_H +#define INPUT_ACTIVE_SUBSCRIBE_MANAGER_H + +#include +#include +#include "i_input_event_consumer.h" + +namespace OHOS { +namespace MMI { +class InputActiveSubscribeManager final { + DECLARE_SINGLETON(InputActiveSubscribeManager); +public: + class SubscribeInputActiveInfo { + public: + SubscribeInputActiveInfo(std::shared_ptr inputEventConsumer, int64_t interval) + : inputActiveInterval_(interval), callback_(inputEventConsumer) {}; + ~SubscribeInputActiveInfo() = default; + int64_t GetInputActiveInterval() const + { + return inputActiveInterval_; + } + std::shared_ptr GetCallback() const + { + return callback_; + } + private: + int64_t inputActiveInterval_ { 0 }; + std::shared_ptr callback_ { nullptr }; + }; +public: + DISALLOW_MOVE(InputActiveSubscribeManager); + int32_t SubscribeInputActive(std::shared_ptr inputEventConsumer, int64_t interval); + int32_t UnsubscribeInputActive(int32_t subscribeId); + + int32_t OnSubscribeInputActiveCallback(std::shared_ptr keyEvent, int32_t subscribeId); + int32_t OnSubscribeInputActiveCallback(std::shared_ptr pointerEvent, int32_t subscribeId); + void OnConnected(); + +private: + std::shared_ptr subscribeInfo_ = nullptr; + std::mutex mtx_; +}; +#define INPUT_ACTIVE_SUBSCRIBE_MGR ::OHOS::Singleton::GetInstance() +} // namespace MMI +} // namespace OHOS +#endif // INPUT_ACTIVE_SUBSCRIBE_MANAGER_H \ No newline at end of file diff --git a/frameworks/proxy/event_handler/include/input_manager_impl.h b/frameworks/proxy/event_handler/include/input_manager_impl.h index 30495e197..a1b3cee05 100644 --- a/frameworks/proxy/event_handler/include/input_manager_impl.h +++ b/frameworks/proxy/event_handler/include/input_manager_impl.h @@ -242,6 +242,8 @@ public: int32_t ShiftAppPointerEvent(const ShiftWindowParam ¶m, bool autoGenDown); int32_t CheckKnuckleEvent(float pointX, float pointY, bool &touchType); int32_t LaunchAiScreenAbility(); + int32_t SubscribeInputActive(std::shared_ptr inputEventConsumer, int64_t interval); + void UnsubscribeInputActive(int32_t subscribeId); private: int32_t PackWindowInfo(NetPacket &pkt, DisplayGroupInfo &displayGroupInfo); diff --git a/frameworks/proxy/event_handler/include/multimodal_event_handler.h b/frameworks/proxy/event_handler/include/multimodal_event_handler.h index 7e3c278e9..9b75c5f78 100644 --- a/frameworks/proxy/event_handler/include/multimodal_event_handler.h +++ b/frameworks/proxy/event_handler/include/multimodal_event_handler.h @@ -16,6 +16,7 @@ #define MULTIMODAL_EVENT_HANDLER_H #include "if_mmi_client.h" +#include "input_active_subscribe_manager.h" #include "key_event_input_subscribe_manager.h" #include "long_press_event.h" #include "pointer_event.h" diff --git a/frameworks/proxy/event_handler/src/client_msg_handler.cpp b/frameworks/proxy/event_handler/src/client_msg_handler.cpp index 0019d7112..18235f8d6 100644 --- a/frameworks/proxy/event_handler/src/client_msg_handler.cpp +++ b/frameworks/proxy/event_handler/src/client_msg_handler.cpp @@ -16,6 +16,7 @@ #include "anr_handler.h" #include "bytrace_adapter.h" #include "event_log_helper.h" +#include "input_active_subscribe_manager.h" #include "input_event_data_transformation.h" #include "input_manager_impl.h" #ifdef OHOS_BUILD_ENABLE_MONITOR @@ -36,6 +37,7 @@ namespace MMI { namespace { constexpr int32_t PRINT_INTERVAL_COUNT { 50 }; } // namespace + void ClientMsgHandler::Init() { MsgCallback funs[] = { @@ -80,7 +82,10 @@ void ClientMsgHandler::Init() { MmiMessageId::WINDOW_STATE_ERROR_NOTIFY, [this] (const UDSClient& client, NetPacket& pkt) { return this->NotifyWindowStateError(client, pkt); }}, { MmiMessageId::SET_INPUT_DEVICE_ENABLED, [this] (const UDSClient& client, NetPacket& pkt) { - return this->OnSetInputDeviceAck(client, pkt); }} }; + return this->OnSetInputDeviceAck(client, pkt); }}, + { MmiMessageId::ON_SUBSCRIBE_INPUT_ACTIVE, [this] (const UDSClient &client, NetPacket &pkt) { + return this->OnSubscribeInputActiveCallback(client, pkt); }}, + }; for (auto &it : funs) { if (!RegistrationEvent(it)) { MMI_HILOGW("Failed to register event errCode:%{public}d", EVENT_REG_FAIL); @@ -502,5 +507,38 @@ int32_t ClientMsgHandler::OnSetInputDeviceAck(const UDSClient& client, NetPacket INPUT_DEVICE_IMPL.OnSetInputDeviceAck(index, result); return RET_OK; } + +int32_t ClientMsgHandler::OnSubscribeInputActiveCallback(const UDSClient& client, NetPacket& pkt) +{ + CALL_DEBUG_ENTER; + HandleEventType handleEventType = HANDLE_EVENT_TYPE_NONE; + auto keyEvent = KeyEvent::Create(); + auto pointerEvent = PointerEvent::Create(); + CHKPR(keyEvent, RET_ERR); + CHKPR(pointerEvent, RET_ERR); + pkt >> handleEventType; + int32_t ret = RET_ERR; + if (handleEventType == HANDLE_EVENT_TYPE_KEY) { + ret = InputEventDataTransformation::NetPacketToKeyEvent(pkt, keyEvent); + } else if (handleEventType == HANDLE_EVENT_TYPE_POINTER) { + ret = InputEventDataTransformation::Unmarshalling(pkt, pointerEvent); + } else { + MMI_HILOGE("handleEventType(%{public}d) error", handleEventType); + return RET_ERR; + } + if (ret != RET_OK) { + MMI_HILOGE("Read net packet failed, ret = %{%public}d", ret); + return RET_ERR; + } + int32_t subscribeId = -1; + pkt >> subscribeId; + if (pkt.ChkRWError()) { + MMI_HILOGE("Packet read subscribeId failed"); + return RET_ERR; + } + return handleEventType == HANDLE_EVENT_TYPE_KEY ? + INPUT_ACTIVE_SUBSCRIBE_MGR.OnSubscribeInputActiveCallback(keyEvent, subscribeId) : + INPUT_ACTIVE_SUBSCRIBE_MGR.OnSubscribeInputActiveCallback(pointerEvent, subscribeId); +} } // namespace MMI } // namespace OHOS diff --git a/frameworks/proxy/event_handler/src/input_active_subscribe_manager.cpp b/frameworks/proxy/event_handler/src/input_active_subscribe_manager.cpp new file mode 100644 index 000000000..5ca8acf74 --- /dev/null +++ b/frameworks/proxy/event_handler/src/input_active_subscribe_manager.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "input_active_subscribe_manager.h" +#include "define_multimodal.h" +#include "error_multimodal.h" +#include "multimodal_event_handler.h" +#include "multimodal_input_connect_manager.h" + +#undef MMI_LOG_TAG +#define MMI_LOG_TAG "InputActiveSubscribeManager" + +namespace OHOS { +namespace MMI { +namespace { +constexpr int32_t INVALID_SUBSCRIBE_ID { -1 }; +constexpr int32_t CURRENT_SUBSCRIBE_ID { 0 }; +} + +InputActiveSubscribeManager::InputActiveSubscribeManager() {} +InputActiveSubscribeManager::~InputActiveSubscribeManager() {} + +int32_t InputActiveSubscribeManager::SubscribeInputActive( + std::shared_ptr inputEventConsumer, int64_t interval) +{ + CALL_DEBUG_ENTER; + CHKPR(inputEventConsumer, INVALID_SUBSCRIBE_ID); + CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, INVALID_SUBSCRIBE_ID); + if (!MMIEventHdl.InitClient()) { + MMI_HILOGE("Client init failed"); + return ERROR_INIT_CLIENT_FAILED; + } + std::shared_ptr subscribeInfo = nullptr; + { + std::lock_guard guard(mtx_); + if (subscribeInfo_) { + MMI_HILOGE("A process only supports one interface call"); + return ERROR_ONE_PROCESS_ONLY_SUPPORT_ONE; + } + subscribeInfo = std::make_shared(inputEventConsumer, interval); + CHKPR(subscribeInfo, ERROR_ALLOC_SUBSCRIBEINFO_FAILED); + } + int32_t ret = MULTIMODAL_INPUT_CONNECT_MGR->SubscribeInputActive(CURRENT_SUBSCRIBE_ID, interval); + if (ret != RET_OK) { + MMI_HILOGE("Subscribing input active failed, ret:%{public}d", ret); + return ERROR_SUBSCRIBE_SERVER_FAILED; + } + std::lock_guard guard(mtx_); + subscribeInfo_ = subscribeInfo; + MMI_HILOGI("The subscribeId:%{public}d, inputActiveInterval:%{public}" PRId64, CURRENT_SUBSCRIBE_ID, interval); + return CURRENT_SUBSCRIBE_ID; +} + +int32_t InputActiveSubscribeManager::UnsubscribeInputActive(int32_t subscribeId) +{ + CALL_INFO_TRACE; + CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR); + if (subscribeId != CURRENT_SUBSCRIBE_ID) { + MMI_HILOGE("The subscribeId(%{public}d) is invalid", subscribeId); + return ERROR_INVALID_SUBSCRIBE_ID; + } + + if (!MMIEventHdl.InitClient()) { + MMI_HILOGE("Client init failed"); + return ERROR_INIT_CLIENT_FAILED; + } + { + std::lock_guard guard(mtx_); + if (!subscribeInfo_) { + MMI_HILOGE("no SubscribeInputActive"); + return ERROR_NO_SUBSCRIBE_INPUT_ACTIVE; + } + } + if (MULTIMODAL_INPUT_CONNECT_MGR->UnsubscribeInputActive(subscribeId) != RET_OK) { + MMI_HILOGE("Leave, unsubscribe input active failed"); + return ERROR_UNSUBSCRIBE_SERVER_FAILED; + } + std::lock_guard guard(mtx_); + subscribeInfo_ = nullptr; + return RET_OK; +} + +int32_t InputActiveSubscribeManager::OnSubscribeInputActiveCallback( + std::shared_ptr keyEvent, int32_t subscribeId) +{ + CHK_PID_AND_TID(); + CHKPR(keyEvent, RET_ERR); + if (subscribeId != CURRENT_SUBSCRIBE_ID) { + MMI_HILOGE("The subscribeId(%{public}d) is invalid", subscribeId); + return ERROR_INVALID_SUBSCRIBE_ID; + } + std::shared_ptr inputEventConsumer = nullptr; + { + std::lock_guard guard(mtx_); + if (!subscribeInfo_) { + MMI_HILOGE("had UnsubscribeInputActive"); + return ERROR_HAD_UNSUBSCRIBE_INPUT_ACTIVE; + } + inputEventConsumer = subscribeInfo_->GetCallback(); + } + CHKPR(inputEventConsumer, RET_ERR); + inputEventConsumer->OnInputEvent(keyEvent); + MMI_HILOGD("subscribeId: %{public}d, keycode:%{private}d", subscribeId, keyEvent->GetKeyCode()); + return RET_OK; +} + +int32_t InputActiveSubscribeManager::OnSubscribeInputActiveCallback( + std::shared_ptr pointerEvent, int32_t subscribeId) +{ + CHK_PID_AND_TID(); + CHKPR(pointerEvent, RET_ERR); + if (subscribeId != CURRENT_SUBSCRIBE_ID) { + MMI_HILOGE("The subscribeId(%{public}d) is invalid", subscribeId); + return ERROR_INVALID_SUBSCRIBE_ID; + } + std::shared_ptr inputEventConsumer = nullptr; + { + std::lock_guard guard(mtx_); + if (!subscribeInfo_) { + MMI_HILOGE("had UnsubscribeInputActive"); + return ERROR_HAD_UNSUBSCRIBE_INPUT_ACTIVE; + } + inputEventConsumer = subscribeInfo_->GetCallback(); + } + CHKPR(inputEventConsumer, RET_ERR); + inputEventConsumer->OnInputEvent(pointerEvent); + MMI_HILOGD("subscribeId: %{public}d, keycode:%{private}d", subscribeId, pointerEvent->GetPointerId()); + return RET_OK; +} + +void InputActiveSubscribeManager::OnConnected() +{ + CALL_DEBUG_ENTER; + CHKPV(MULTIMODAL_INPUT_CONNECT_MGR); + std::shared_ptr subscribeInfo = nullptr; + { + std::lock_guard guard(mtx_); + if (!subscribeInfo_) { + return; + } + subscribeInfo = subscribeInfo_; + } + int32_t ret = MULTIMODAL_INPUT_CONNECT_MGR->SubscribeInputActive( + CURRENT_SUBSCRIBE_ID, subscribeInfo->GetInputActiveInterval()); + if (ret != RET_OK) { + MMI_HILOGE("SubscribeInputActive failed, subscribeId_:%{public}d, ret:%{public}d", CURRENT_SUBSCRIBE_ID, ret); + } +} +} // namespace MMI +} // namespace OHOS diff --git a/frameworks/proxy/event_handler/src/input_manager_impl.cpp b/frameworks/proxy/event_handler/src/input_manager_impl.cpp index a6feaee7e..ecd4b1932 100644 --- a/frameworks/proxy/event_handler/src/input_manager_impl.cpp +++ b/frameworks/proxy/event_handler/src/input_manager_impl.cpp @@ -2821,5 +2821,35 @@ int32_t InputManagerImpl::LaunchAiScreenAbility() CALL_INFO_TRACE; return MULTIMODAL_INPUT_CONNECT_MGR->LaunchAiScreenAbility(); } + +int32_t InputManagerImpl::SubscribeInputActive( + std::shared_ptr inputEventConsumer, int64_t interval) +{ + CALL_INFO_TRACE; + CHK_PID_AND_TID(); + CHKPR(inputEventConsumer, RET_ERR); + if (interval < 0) { + MMI_HILOGE("Interval time error, interval: %{public}" PRId64, interval); + return RET_ERR; + } + constexpr int64_t SUBSCRIBE_INPUT_ACTIVE_MIN_INTERVAL = 500; // ms + constexpr int64_t SUBSCRIBE_INPUT_ACTIVE_MAX_INTERVAL = 2000; // ms + // interval : 0 is a normal value, no filtering + if (interval > 0 && interval < SUBSCRIBE_INPUT_ACTIVE_MIN_INTERVAL) { + MMI_HILOGE("Interval(%{public}" PRId64 ") is less than minimum threshold(500ms)", interval); + interval = SUBSCRIBE_INPUT_ACTIVE_MIN_INTERVAL; + } else if (interval > SUBSCRIBE_INPUT_ACTIVE_MAX_INTERVAL) { + MMI_HILOGE("Interval(%{public}" PRId64 ") is greater than maximum threshold(2000ms)", interval); + interval = SUBSCRIBE_INPUT_ACTIVE_MAX_INTERVAL; + } + return INPUT_ACTIVE_SUBSCRIBE_MGR.SubscribeInputActive(inputEventConsumer, interval); +} + +void InputManagerImpl::UnsubscribeInputActive(int32_t subscribeId) +{ + CALL_INFO_TRACE; + CHK_PID_AND_TID(); + INPUT_ACTIVE_SUBSCRIBE_MGR.UnsubscribeInputActive(subscribeId); +} } // namespace MMI } // namespace OHOS \ No newline at end of file diff --git a/frameworks/proxy/event_handler/src/multimodal_event_handler.cpp b/frameworks/proxy/event_handler/src/multimodal_event_handler.cpp index 4dc283ee7..8dfbab336 100644 --- a/frameworks/proxy/event_handler/src/multimodal_event_handler.cpp +++ b/frameworks/proxy/event_handler/src/multimodal_event_handler.cpp @@ -49,6 +49,7 @@ void OnConnected(const IfMMIClient& client) #ifdef OHOS_BUILD_ENABLE_INTERCEPTOR InputInterMgr->OnConnected(); #endif // OHOS_BUILD_ENABLE_INTERCEPTOR + INPUT_ACTIVE_SUBSCRIBE_MGR.OnConnected(); } void OnDisconnected(const IfMMIClient &client) diff --git a/frameworks/proxy/event_handler/test/BUILD.gn b/frameworks/proxy/event_handler/test/BUILD.gn new file mode 100644 index 000000000..d5c2d638c --- /dev/null +++ b/frameworks/proxy/event_handler/test/BUILD.gn @@ -0,0 +1,59 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("../../../../multimodalinput_mini.gni") + +module_output_path = "input/input" + +ohos_unittest("InputActiveSubscribeManagerTest") { + module_out_path = module_output_path + include_dirs = [ + "$root_out_dir/diff_libinput_mmi/export_include", + "${mmi_path}/service/filter/include", + "${mmi_path}/service/nap_process/include", + "${mmi_path}/service/module_loader//include", + "${mmi_path}/service/connect_manager/include", + ] + + sources = [ "input_active_subscribe_manager_test.cpp" ] + + configs = [ + "${mmi_path}:coverage_flags", + "${mmi_path}/frameworks/proxy:libmmi_test_util", + ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + + deps = [ + "${mmi_path}/frameworks/proxy:libmmi-client", + "${mmi_path}/service/connect_manager:mmi_connect_manager_proxy", + "${mmi_path}/util:libmmi-util", + ] + external_deps = [ + "ability_runtime:abilitykit_native", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtokensetproc_shared", + "c_utils:utils", + "eventhandler:libeventhandler", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] +} diff --git a/frameworks/proxy/event_handler/test/input_active_subscribe_manager_test.cpp b/frameworks/proxy/event_handler/test/input_active_subscribe_manager_test.cpp new file mode 100644 index 000000000..260ac4ef7 --- /dev/null +++ b/frameworks/proxy/event_handler/test/input_active_subscribe_manager_test.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "input_active_subscribe_manager.h" +#include "input_handler_type.h" +#include "mmi_log.h" +#include "multimodal_event_handler.h" +#include "multimodal_input_connect_manager.h" + +#undef MMI_LOG_TAG +#define MMI_LOG_TAG "InputActiveSubscribeManagerTest" + +namespace OHOS { +namespace MMI { +namespace { +using namespace testing::ext; +} // namespace + +class InputActiveSubscribeManagerTest : public testing::Test { +public: + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} +}; + +class TestInputEventConsumer : public IInputEventConsumer { +public: + TestInputEventConsumer() = default; + ~TestInputEventConsumer() = default; + void OnInputEvent(std::shared_ptr keyEvent) const override + { + MMI_HILOGI("OnInputEvent KeyEvent enter"); + } + void OnInputEvent(std::shared_ptr pointerEvent) const override + { + MMI_HILOGI("OnInputEvent PointerEvent enter"); + } + void OnInputEvent(std::shared_ptr axisEvent) const override + {} +}; + +/** + * @tc.name: SubscribeInputActive_Test_001 + * @tc.desc: Test SubscribeInputActive + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InputActiveSubscribeManagerTest, SubscribeInputActive_Test_001, TestSize.Level1) +{ + CALL_TEST_DEBUG; + std::shared_ptr inputEventConsumer = std::make_shared(); + int64_t interval = 500; // ms + int32_t subscriberInput = INPUT_ACTIVE_SUBSCRIBE_MGR.SubscribeInputActive( + std::static_pointer_cast(inputEventConsumer), interval); + EXPECT_GE(subscriberInput, 0); + int32_t result = INPUT_ACTIVE_SUBSCRIBE_MGR.UnsubscribeInputActive(subscriberInput); + EXPECT_EQ(result, RET_OK); +} + +/** + * @tc.name: SubscribeInputActive_Test_002 + * @tc.desc: Test SubscribeInputActive + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InputActiveSubscribeManagerTest, SubscribeInputActive_Test_002, TestSize.Level1) +{ + CALL_TEST_DEBUG; + std::shared_ptr inputEventConsumer = std::make_shared(); + int64_t interval = 500; // ms + int32_t subscriberInput = INPUT_ACTIVE_SUBSCRIBE_MGR.SubscribeInputActive(inputEventConsumer, interval); + EXPECT_GE(subscriberInput, 0); + int32_t subscriberInput1 = INPUT_ACTIVE_SUBSCRIBE_MGR.SubscribeInputActive(inputEventConsumer, interval); + EXPECT_GE(subscriberInput1, 0); + int32_t subscriberInput2 = INPUT_ACTIVE_SUBSCRIBE_MGR.SubscribeInputActive(inputEventConsumer, interval); + EXPECT_GE(subscriberInput2, 0); + int32_t result = INPUT_ACTIVE_SUBSCRIBE_MGR.UnsubscribeInputActive(subscriberInput); + EXPECT_EQ(result, RET_OK); + result = INPUT_ACTIVE_SUBSCRIBE_MGR.UnsubscribeInputActive(subscriberInput1); + EXPECT_EQ(result, RET_OK); + result = INPUT_ACTIVE_SUBSCRIBE_MGR.UnsubscribeInputActive(subscriberInput2); + EXPECT_EQ(result, RET_OK); +} + +/** + * @tc.name: SubscribeInputActive_Test_003 + * @tc.desc: Test SubscribeInputActive + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InputActiveSubscribeManagerTest, SubscribeInputActive_Test_003, TestSize.Level1) +{ + CALL_TEST_DEBUG; + int64_t interval = 500; // ms + int32_t subscriberInput = INPUT_ACTIVE_SUBSCRIBE_MGR.SubscribeInputActive(nullptr, interval); + EXPECT_LT(subscriberInput, 0); +} + +/** + * @tc.name: OnSubscribeInputActiveCallback_Test_001 + * @tc.desc: Test OnSubscribeInputActiveCallback + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InputActiveSubscribeManagerTest, OnSubscribeInputActiveCallback_Test_001, TestSize.Level1) +{ + CALL_TEST_DEBUG; + std::shared_ptr inputEventConsumer = std::make_shared(); + int64_t interval = 500; // ms + int32_t subscriberInput = INPUT_ACTIVE_SUBSCRIBE_MGR.SubscribeInputActive( + std::static_pointer_cast(inputEventConsumer), interval); + EXPECT_GE(subscriberInput, 0); + + std::shared_ptr keyEvent = KeyEvent::Create(); + ASSERT_NE(keyEvent, nullptr); + int32_t result = INPUT_ACTIVE_SUBSCRIBE_MGR.OnSubscribeInputActiveCallback(keyEvent, subscriberInput); + EXPECT_EQ(result, RET_OK); + result = INPUT_ACTIVE_SUBSCRIBE_MGR.UnsubscribeInputActive(subscriberInput); + EXPECT_EQ(result, RET_OK); +} + +/** + * @tc.name: OnSubscribeInputActiveCallback_Test_002 + * @tc.desc: Test OnSubscribeInputActiveCallback + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InputActiveSubscribeManagerTest, OnSubscribeInputActiveCallback_Test_002, TestSize.Level1) +{ + CALL_TEST_DEBUG; + std::shared_ptr inputEventConsumer = std::make_shared(); + int64_t interval = 500; // ms + int32_t subscriberInput = INPUT_ACTIVE_SUBSCRIBE_MGR.SubscribeInputActive( + std::static_pointer_cast(inputEventConsumer), interval); + EXPECT_GE(subscriberInput, 0); + + auto pointerEvent = PointerEvent::Create(); + ASSERT_NE(pointerEvent, nullptr); + int32_t result = INPUT_ACTIVE_SUBSCRIBE_MGR.OnSubscribeInputActiveCallback(pointerEvent, subscriberInput); + EXPECT_EQ(result, RET_OK); + result = INPUT_ACTIVE_SUBSCRIBE_MGR.UnsubscribeInputActive(subscriberInput); + EXPECT_EQ(result, RET_OK); +} + +/** + * @tc.name: OnSubscribeInputActiveCallback_Test_003 + * @tc.desc: Test OnSubscribeInputActiveCallback + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InputActiveSubscribeManagerTest, OnSubscribeInputActiveCallback_Test_003, TestSize.Level1) +{ + CALL_TEST_DEBUG; + std::shared_ptr inputEventConsumer = std::make_shared(); + int64_t interval = 500; // ms + int32_t subscriberInput = INPUT_ACTIVE_SUBSCRIBE_MGR.SubscribeInputActive( + std::static_pointer_cast(inputEventConsumer), interval); + EXPECT_GE(subscriberInput, 0); + + std::shared_ptr keyEvent = nullptr; + int32_t result = INPUT_ACTIVE_SUBSCRIBE_MGR.OnSubscribeInputActiveCallback(keyEvent, subscriberInput); + EXPECT_NE(result, RET_OK); + keyEvent = KeyEvent::Create(); + result = INPUT_ACTIVE_SUBSCRIBE_MGR.OnSubscribeInputActiveCallback(keyEvent, -1); + EXPECT_NE(result, RET_OK); + result = INPUT_ACTIVE_SUBSCRIBE_MGR.UnsubscribeInputActive(subscriberInput); + EXPECT_EQ(result, RET_OK); +} + +/** + * @tc.name: OnSubscribeInputActiveCallback_Test_004 + * @tc.desc: Test OnSubscribeInputActiveCallback + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InputActiveSubscribeManagerTest, OnSubscribeInputActiveCallback_Test_004, TestSize.Level1) +{ + CALL_TEST_DEBUG; + std::shared_ptr inputEventConsumer = std::make_shared(); + int64_t interval = 500; // ms + int32_t subscriberInput = INPUT_ACTIVE_SUBSCRIBE_MGR.SubscribeInputActive( + std::static_pointer_cast(inputEventConsumer), interval); + EXPECT_GE(subscriberInput, 0); + + std::shared_ptr pointerEvent = nullptr; + int32_t result = INPUT_ACTIVE_SUBSCRIBE_MGR.OnSubscribeInputActiveCallback(pointerEvent, subscriberInput); + EXPECT_NE(result, RET_OK); + pointerEvent = PointerEvent::Create(); + result = INPUT_ACTIVE_SUBSCRIBE_MGR.OnSubscribeInputActiveCallback(pointerEvent, -1); + EXPECT_NE(result, RET_OK); + result = INPUT_ACTIVE_SUBSCRIBE_MGR.UnsubscribeInputActive(subscriberInput); + EXPECT_EQ(result, RET_OK); +} +} // namespace MMI +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/proxy/events/src/input_manager.cpp b/frameworks/proxy/events/src/input_manager.cpp index f5c64b350..4493bf08b 100644 --- a/frameworks/proxy/events/src/input_manager.cpp +++ b/frameworks/proxy/events/src/input_manager.cpp @@ -913,5 +913,15 @@ int32_t InputManager::LaunchAiScreenAbility() { return InputMgrImpl.LaunchAiScreenAbility(); } + +int32_t InputManager::SubscribeInputActive(std::shared_ptr inputEventConsumer, int64_t interval) +{ + return InputMgrImpl.SubscribeInputActive(inputEventConsumer, interval); +} + +void InputManager::UnsubscribeInputActive(int32_t subscribeId) +{ + InputMgrImpl.UnsubscribeInputActive(subscribeId); +} } // namespace MMI } // namespace OHOS diff --git a/interfaces/native/innerkits/libmmi-client-map b/interfaces/native/innerkits/libmmi-client-map index ae3e71165..359622ffd 100644 --- a/interfaces/native/innerkits/libmmi-client-map +++ b/interfaces/native/innerkits/libmmi-client-map @@ -17,6 +17,7 @@ extern "C++" { OHOS::MMI::AxisEvent*; OHOS::MMI::BytraceAdapter*; + OHOS::MMI::InputActiveSubscribeManager*; OHOS::MMI::InputDevice*; OHOS::MMI::InputEvent*; OHOS::MMI::InputInterceptorManager*; diff --git a/interfaces/native/innerkits/proxy/include/input_manager.h b/interfaces/native/innerkits/proxy/include/input_manager.h index 6fb604a42..945d72337 100644 --- a/interfaces/native/innerkits/proxy/include/input_manager.h +++ b/interfaces/native/innerkits/proxy/include/input_manager.h @@ -1173,6 +1173,32 @@ public: */ int32_t LaunchAiScreenAbility(); + /** + * @brief Subscribes to the input active that mmets a specific condition. When such an event occurs, + * the callback specified is invoked to process the event. + * A process can only support a maximum of one interface call. + * @param inputEventConsumer Indicates the callback. + * @param interval Indicate the interval time. + * When the interval value is less than 0, the value is invalid. + * When it is equal to 0, no filtering is performed. + * The effective range of filtering values is greater than or equal to 500ms and less than or equal to 2000ms. + * If the filtering value is greater than 0 and less than 500ms, the filtering interval is 500ms. + * If the filtering value is greater than 2000ms, the filtering interval is 2000ms. + * @return Returns the subscribe ID, which uniquely identifies a subscribe id in the process. + * If the value is greater than or equal to 0 + * the subscription is successful. Otherwise, the subscription fails. + * @since 20 + */ + int32_t SubscribeInputActive(std::shared_ptr inputEventConsumer, int64_t interval); + + /** + * @brief Unsubscribes from input active. + * @param subscribeId. Indicates the subscription ID, which is the return value of SubscribeInputActive. + * @return void. + * @since 20 + */ + void UnsubscribeInputActive(int32_t subscribeId); + private: InputManager() = default; DISALLOW_COPY_AND_MOVE(InputManager); diff --git a/multimodalinput_mini.gni b/multimodalinput_mini.gni index 779be30f1..771fc84f2 100644 --- a/multimodalinput_mini.gni +++ b/multimodalinput_mini.gni @@ -97,6 +97,7 @@ declare_args() { "event_handler/src/anr_handler.cpp", "event_handler/src/bytrace_adapter.cpp", "event_handler/src/client_msg_handler.cpp", + "event_handler/src/input_active_subscribe_manager.cpp", "event_handler/src/input_device_impl.cpp", "event_handler/src/input_handler_manager.cpp", "event_handler/src/input_manager_impl.cpp", @@ -147,6 +148,7 @@ declare_args() { "module_loader/src/watchdog_task.cpp", "nap_process/src/nap_process.cpp", "permission_helper/src/permission_helper.cpp", + "subscriber/src/input_active_subscriber_handler.cpp", "timer_manager/src/timer_manager.cpp", "window_manager/src/input_display_bind_helper.cpp", "window_manager/src/input_windows_manager.cpp", diff --git a/service/connect_manager/include/i_multimodal_input_connect.h b/service/connect_manager/include/i_multimodal_input_connect.h index 842174206..e8008a402 100644 --- a/service/connect_manager/include/i_multimodal_input_connect.h +++ b/service/connect_manager/include/i_multimodal_input_connect.h @@ -187,6 +187,8 @@ public: virtual int32_t SetMultiWindowScreenId(uint64_t screenId, uint64_t displayNodeScreenId) = 0; virtual int32_t SetKnuckleSwitch(bool knuckleSwitch) = 0; virtual int32_t LaunchAiScreenAbility() = 0; + virtual int32_t SubscribeInputActive(int32_t subscribeId, int64_t interval) = 0; + virtual int32_t UnsubscribeInputActive(int32_t subscribeId) = 0; }; } // namespace MMI } // namespace OHOS diff --git a/service/connect_manager/include/multimodal_input_connect_manager.h b/service/connect_manager/include/multimodal_input_connect_manager.h index dfecf926e..141a67467 100644 --- a/service/connect_manager/include/multimodal_input_connect_manager.h +++ b/service/connect_manager/include/multimodal_input_connect_manager.h @@ -175,6 +175,8 @@ public: int32_t SetMultiWindowScreenId(uint64_t screenId, uint64_t displayNodeScreenId); int32_t SetKnuckleSwitch(bool knuckleSwitch); int32_t LaunchAiScreenAbility(); + int32_t SubscribeInputActive(int32_t subscribeId, int64_t interval); + int32_t UnsubscribeInputActive(int32_t subscribeId); private: MultimodalInputConnectManager() = default; diff --git a/service/connect_manager/include/multimodal_input_connect_proxy.h b/service/connect_manager/include/multimodal_input_connect_proxy.h index dfecb7f25..10b648098 100644 --- a/service/connect_manager/include/multimodal_input_connect_proxy.h +++ b/service/connect_manager/include/multimodal_input_connect_proxy.h @@ -173,6 +173,8 @@ public: int32_t SetMultiWindowScreenId(uint64_t screenId, uint64_t displayNodeScreenId) override; int32_t SetKnuckleSwitch(bool knuckleSwitch) override; int32_t LaunchAiScreenAbility() override; + int32_t SubscribeInputActive(int32_t subscribeId, int64_t interval) override; + int32_t UnsubscribeInputActive(int32_t subscribeId) override; private: static inline BrokerDelegator delegator_; diff --git a/service/connect_manager/include/multimodal_input_connect_stub.h b/service/connect_manager/include/multimodal_input_connect_stub.h index 934e48326..208ba50d5 100644 --- a/service/connect_manager/include/multimodal_input_connect_stub.h +++ b/service/connect_manager/include/multimodal_input_connect_stub.h @@ -187,6 +187,8 @@ protected: int32_t StubSetMultiWindowScreenId(MessageParcel& data, MessageParcel& reply); int32_t StubSetKnuckleSwitch(MessageParcel& data, MessageParcel& reply); int32_t StubLaunchAiScreenAbility(MessageParcel& data, MessageParcel& reply); + int32_t StubSubscribeInputActive(MessageParcel& data, MessageParcel& reply); + int32_t StubUnsubscribeInputActive(MessageParcel& data, MessageParcel& reply); private: int32_t VerifyTouchPadSetting(void); diff --git a/service/connect_manager/include/multimodalinput_ipc_interface_code.h b/service/connect_manager/include/multimodalinput_ipc_interface_code.h index 01bb07fbc..42022b8f6 100644 --- a/service/connect_manager/include/multimodalinput_ipc_interface_code.h +++ b/service/connect_manager/include/multimodalinput_ipc_interface_code.h @@ -139,6 +139,8 @@ enum class MultimodalinputConnectInterfaceCode { SET_MUILT_WINDOW_SCREEN_ID = 123, SET_KNUCKLE_SWITCH = 124, LAUNCH_AI_SCREEN_ABILITY = 125, + SUBSCRIBE_INPUT_ACTIVE = 126, + UNSUBSCRIBE_INPUT_ACTIVE = 127, #ifdef OHOS_BUILD_ENABLE_VKEYBOARD CREATE_VKEYBOARD_DEVICE = 153, #endif // OHOS_BUILD_ENABLE_VKEYBOARD diff --git a/service/connect_manager/src/multimodal_input_connect_manager.cpp b/service/connect_manager/src/multimodal_input_connect_manager.cpp index 6ebcc3e50..e566297fb 100644 --- a/service/connect_manager/src/multimodal_input_connect_manager.cpp +++ b/service/connect_manager/src/multimodal_input_connect_manager.cpp @@ -1073,5 +1073,27 @@ int32_t MultimodalInputConnectManager::LaunchAiScreenAbility() CHKPR(multimodalInputConnectService_, INVALID_HANDLER_ID); return multimodalInputConnectService_->LaunchAiScreenAbility(); } + +int32_t MultimodalInputConnectManager::SubscribeInputActive(int32_t subscribeId, int64_t interval) +{ + sptr multimodalInputConnectService = nullptr; + { + std::lock_guard guard(lock_); + CHKPR(multimodalInputConnectService_, INVALID_HANDLER_ID); + multimodalInputConnectService = multimodalInputConnectService_; + } + return multimodalInputConnectService->SubscribeInputActive(subscribeId, interval); +} + +int32_t MultimodalInputConnectManager::UnsubscribeInputActive(int32_t subscribeId) +{ + sptr multimodalInputConnectService = nullptr; + { + std::lock_guard guard(lock_); + CHKPR(multimodalInputConnectService_, INVALID_HANDLER_ID); + multimodalInputConnectService = multimodalInputConnectService_; + } + return multimodalInputConnectService->UnsubscribeInputActive(subscribeId); +} } // namespace MMI } // namespace OHOS diff --git a/service/connect_manager/src/multimodal_input_connect_proxy.cpp b/service/connect_manager/src/multimodal_input_connect_proxy.cpp index eb0e6cf22..08edbc21f 100644 --- a/service/connect_manager/src/multimodal_input_connect_proxy.cpp +++ b/service/connect_manager/src/multimodal_input_connect_proxy.cpp @@ -3051,5 +3051,52 @@ int32_t MultimodalInputConnectProxy::LaunchAiScreenAbility() } return ret; } + +int32_t MultimodalInputConnectProxy::SubscribeInputActive(int32_t subscribeId, int64_t interval) +{ + CALL_DEBUG_ENTER; + MessageParcel data; + if (!data.WriteInterfaceToken(MultimodalInputConnectProxy::GetDescriptor())) { + MMI_HILOGE("Failed to write descriptor"); + return ERR_INVALID_VALUE; + } + WRITEINT32(data, subscribeId, ERR_INVALID_VALUE); + WRITEINT64(data, interval, ERR_INVALID_VALUE); + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + CHKPR(remote, RET_ERR); + int32_t ret = remote->SendRequest( + static_cast(MultimodalinputConnectInterfaceCode::SUBSCRIBE_INPUT_ACTIVE), + data, reply, option); + if (ret != RET_OK) { + MMI_HILOGE("Send request failed, ret:%{public}d", ret); + } + return ret; +} + +int32_t MultimodalInputConnectProxy::UnsubscribeInputActive(int32_t subscribeId) +{ + CALL_DEBUG_ENTER; + MessageParcel data; + if (!data.WriteInterfaceToken(MultimodalInputConnectProxy::GetDescriptor())) { + MMI_HILOGE("Failed to write descriptor"); + return ERR_INVALID_VALUE; + } + WRITEUINT32(data, subscribeId, ERR_INVALID_VALUE); + + MessageParcel reply; + MessageOption option; + sptr remote = Remote(); + CHKPR(remote, RET_ERR); + int32_t ret = remote->SendRequest( + static_cast(MultimodalinputConnectInterfaceCode::UNSUBSCRIBE_INPUT_ACTIVE), + data, reply, option); + if (ret != RET_OK) { + MMI_HILOGE("Send request failed, ret:%{public}d", ret); + } + return ret; +} } // namespace MMI } // namespace OHOS diff --git a/service/connect_manager/src/multimodal_input_connect_stub.cpp b/service/connect_manager/src/multimodal_input_connect_stub.cpp index e9aacfae9..9761b3f29 100644 --- a/service/connect_manager/src/multimodal_input_connect_stub.cpp +++ b/service/connect_manager/src/multimodal_input_connect_stub.cpp @@ -510,6 +510,12 @@ int32_t MultimodalInputConnectStub::OnRemoteRequest(uint32_t code, MessageParcel case static_cast(MultimodalinputConnectInterfaceCode::QUERY_SWITCH_STATE_EVENT): ret = StubQuerySwitchStatus(data, reply); break; + case static_cast(MultimodalinputConnectInterfaceCode::SUBSCRIBE_INPUT_ACTIVE): + ret = StubSubscribeInputActive(data, reply); + break; + case static_cast(MultimodalinputConnectInterfaceCode::UNSUBSCRIBE_INPUT_ACTIVE): + ret = StubUnsubscribeInputActive(data, reply); + break; default: { MMI_HILOGE("Unknown code:%{public}u, go switch default", code); ret = IPCObjectStub::OnRemoteRequest(code, data, reply, option); @@ -3515,5 +3521,52 @@ int32_t MultimodalInputConnectStub::StubLaunchAiScreenAbility(MessageParcel& dat } return RET_OK; } + +int32_t MultimodalInputConnectStub::StubSubscribeInputActive(MessageParcel& data, MessageParcel& reply) +{ + CALL_DEBUG_ENTER; + if (!PER_HELPER->VerifySystemApp()) { + MMI_HILOGE("Verify system APP failed"); + return ERROR_NOT_SYSAPI; + } + + if (!IsRunning()) { + MMI_HILOGE("Service is not running"); + return MMISERVICE_NOT_RUNNING; + } + int32_t subscribeId = 0; + int64_t interval = 0; + READINT32(data, subscribeId, IPC_PROXY_DEAD_OBJECT_ERR); + READINT64(data, interval, IPC_PROXY_DEAD_OBJECT_ERR); + int32_t ret = SubscribeInputActive(subscribeId, interval); + if (ret != RET_OK) { + MMI_HILOGE("SubscribeInputActive failed, ret:%{public}d", ret); + } + return ret; +} + +int32_t MultimodalInputConnectStub::StubUnsubscribeInputActive(MessageParcel& data, MessageParcel& reply) +{ + CALL_DEBUG_ENTER; + if (!PER_HELPER->VerifySystemApp()) { + MMI_HILOGE("Verify system APP failed"); + return ERROR_NOT_SYSAPI; + } + if (!IsRunning()) { + MMI_HILOGE("Service is not running"); + return MMISERVICE_NOT_RUNNING; + } + int32_t subscribeId = 0; + READINT32(data, subscribeId, IPC_PROXY_DEAD_OBJECT_ERR); + if (subscribeId < 0) { + MMI_HILOGE("Invalid subscribeId"); + return RET_ERR; + } + int32_t ret = UnsubscribeInputActive(subscribeId); + if (ret != RET_OK) { + MMI_HILOGE("UnsubscribeInputActive failed, ret:%{public}d", ret); + } + return ret; +} } // namespace MMI } // namespace OHOS diff --git a/service/connect_manager/test/mock_multimodal_input_connect_stub.h b/service/connect_manager/test/mock_multimodal_input_connect_stub.h index f38287bc2..2a7b83b5b 100644 --- a/service/connect_manager/test/mock_multimodal_input_connect_stub.h +++ b/service/connect_manager/test/mock_multimodal_input_connect_stub.h @@ -199,6 +199,8 @@ public: MOCK_METHOD(int32_t, SetMultiWindowScreenId, (uint64_t screenId, uint64_t displayNodeScreenId), (override)); MOCK_METHOD(int32_t, SetKnuckleSwitch, (bool knuckleSwitch), (override)); MOCK_METHOD(int32_t, LaunchAiScreenAbility, (), (override)); + MOCK_METHOD(int32_t, SubscribeInputActive, (int32_t subscribeId, int64_t interval), (override)); + MOCK_METHOD(int32_t, UnsubscribeInputActive, (int32_t subscribeId), (override)); MOCK_METHOD(bool, IsRunning, (), (const override)); }; diff --git a/service/connect_manager/test/multimodal_input_connect_stub_ex_test.cpp b/service/connect_manager/test/multimodal_input_connect_stub_ex_test.cpp index 66f5d09aa..c4c4601e6 100644 --- a/service/connect_manager/test/multimodal_input_connect_stub_ex_test.cpp +++ b/service/connect_manager/test/multimodal_input_connect_stub_ex_test.cpp @@ -385,6 +385,8 @@ public: return static_cast(knuckleSwitch); }; int32_t LaunchAiScreenAbility() override { return RET_OK; } + int32_t SubscribeInputActive(int32_t subscribeId, int64_t interval) override { return 0; } + int32_t UnsubscribeInputActive(int32_t subscribeId) override { return 0; } std::atomic state_ = ServiceRunningState::STATE_NOT_START; int32_t rows_ = 0; diff --git a/service/event_handler/include/input_event_handler.h b/service/event_handler/include/input_event_handler.h index e6dad5112..6021c2f15 100644 --- a/service/event_handler/include/input_event_handler.h +++ b/service/event_handler/include/input_event_handler.h @@ -21,6 +21,7 @@ #include "event_interceptor_handler.h" #include "event_monitor_handler.h" #include "event_normalize_handler.h" +#include "input_active_subscriber_handler.h" #include "key_command_handler.h" #include "key_subscriber_handler.h" #ifdef OHOS_BUILD_ENABLE_POINTER @@ -54,6 +55,7 @@ public: std::shared_ptr GetFilterHandler() const; std::shared_ptr GetEventDispatchHandler() const; std::shared_ptr GetEventPreMonitorHandler() const; + std::shared_ptr GetInputActiveSubscriberHandler() const; private: int32_t BuildInputHandlerChain(); @@ -80,6 +82,7 @@ private: std::shared_ptr eventMonitorHandler_ { nullptr }; std::shared_ptr eventDispatchHandler_ { nullptr }; std::shared_ptr eventPreMonitorHandler_ { nullptr }; + std::shared_ptr inputActiveSubscriberHandler_ { nullptr }; uint64_t idSeed_ { 0 }; diff --git a/service/event_handler/src/input_event_handler.cpp b/service/event_handler/src/input_event_handler.cpp index 55da80637..07334d445 100644 --- a/service/event_handler/src/input_event_handler.cpp +++ b/service/event_handler/src/input_event_handler.cpp @@ -385,6 +385,13 @@ int32_t InputEventHandler::BuildInputHandlerChain() #endif // !OHOS_BUILD_ENABLE_KEYBOARD && !OHOS_BUILD_ENABLE_POINTER && !OHOS_BUILD_ENABLE_TOUCH std::shared_ptr handler = eventNormalizeHandler_; + inputActiveSubscriberHandler_ = std::make_shared(); + if (inputActiveSubscriberHandler_) { + handler->SetNext(inputActiveSubscriberHandler_); + handler = inputActiveSubscriberHandler_; + } else { + MMI_HILOGE("failed to alloc InputActiveSubscriberHandler"); + } #if defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH) eventFilterHandler_ = std::make_shared(); handler->SetNext(eventFilterHandler_); @@ -493,5 +500,10 @@ int32_t InputEventHandler::SetMoveEventFilters(bool flag) return ERROR_UNSUPPORT; #endif // OHOS_BUILD_ENABLE_MOVE_EVENT_FILTERS } + +std::shared_ptr InputEventHandler::GetInputActiveSubscriberHandler() const +{ + return inputActiveSubscriberHandler_; +} } // namespace MMI } // namespace OHOS \ No newline at end of file diff --git a/service/fingerprint_event_processor/test/BUILD.gn b/service/fingerprint_event_processor/test/BUILD.gn index f6499ba96..a49fa8dcb 100644 --- a/service/fingerprint_event_processor/test/BUILD.gn +++ b/service/fingerprint_event_processor/test/BUILD.gn @@ -57,6 +57,7 @@ ohos_unittest("FingerprintEventProcessorTest") { "${mmi_path}/service/fingerprint_event_processor/src/fingerprint_event_processor.cpp", "${mmi_path}/service/monitor/src/event_monitor_handler.cpp", "${mmi_path}/service/monitor/src/event_pre_monitor_handler.cpp", + "${mmi_path}/service/subscriber/src/input_active_subscriber_handler.cpp", "${mmi_path}/util/common/src/input_event_data_transformation.cpp", "${mmi_path}/util/network/src/stream_buffer.cpp", "src/fingerprint_event_processor_test.cpp", diff --git a/service/libmmi-server-map b/service/libmmi-server-map index 919eadf75..293cf5f82 100644 --- a/service/libmmi-server-map +++ b/service/libmmi-server-map @@ -18,6 +18,7 @@ OHOS::MMI::*; "vtable for OHOS::MMI::EventDispatchHandler"; "vtable for OHOS::MMI::UDSServer"; + "vtable for OHOS::MMI::InputActiveSubscriberHandler"; "vtable for OHOS::MMI::InputDeviceManager"; "vtable for OHOS::MMI::EventFilterHandler"; "vtable for OHOS::MMI::DelegateInterface"; diff --git a/service/module_loader/include/mmi_service.h b/service/module_loader/include/mmi_service.h index fc8100a6e..9b1c94ae1 100644 --- a/service/module_loader/include/mmi_service.h +++ b/service/module_loader/include/mmi_service.h @@ -207,6 +207,8 @@ public: int32_t SetMultiWindowScreenIdInner(uint64_t screenId, uint64_t displayNodeScreenId); int32_t SetKnuckleSwitch(bool knuckleSwitch) override; int32_t LaunchAiScreenAbility() override; + int32_t SubscribeInputActive(int32_t subscribeId, int64_t interval) override; + int32_t UnsubscribeInputActive(int32_t subscribeId) override; protected: void OnConnected(SessionPtr s) override; diff --git a/service/module_loader/src/mmi_service.cpp b/service/module_loader/src/mmi_service.cpp index fa59185f0..466c423e1 100644 --- a/service/module_loader/src/mmi_service.cpp +++ b/service/module_loader/src/mmi_service.cpp @@ -3855,5 +3855,45 @@ int32_t MMIService::LaunchAiScreenAbility() } return ret; } + +int32_t MMIService::SubscribeInputActive(int32_t subscribeId, int64_t interval) +{ + CALL_INFO_TRACE; + int32_t pid = GetCallingPid(); + int32_t ret = delegateTasks_.PostSyncTask( + [this, pid, subscribeId, interval] { + auto sess = this->GetSessionByPid(pid); + CHKPR(sess, RET_ERR); + auto subscriberHandler = InputHandler->GetInputActiveSubscriberHandler(); + CHKPR(subscriberHandler, RET_ERR); + return subscriberHandler->SubscribeInputActive(sess, subscribeId, interval); + } + ); + if (ret != RET_OK) { + MMI_HILOGE("The subscribe input active processed failed, ret:%{public}d", ret); + return ret; + } + return RET_OK; +} + +int32_t MMIService::UnsubscribeInputActive(int32_t subscribeId) +{ + CALL_INFO_TRACE; + int32_t pid = GetCallingPid(); + int32_t ret = delegateTasks_.PostSyncTask( + [this, pid, subscribeId] { + auto sess = this->GetSessionByPid(pid); + CHKPR(sess, RET_ERR); + auto subscriberHandler = InputHandler->GetInputActiveSubscriberHandler(); + CHKPR(subscriberHandler, RET_ERR); + return subscriberHandler->UnsubscribeInputActive(sess, subscribeId); + } + ); + if (ret != RET_OK) { + MMI_HILOGE("The unsubscribe input active processed failed, ret:%{public}d", ret); + return ret; + } + return RET_OK; +} } // namespace MMI } // namespace OHOS diff --git a/service/subscriber/include/input_active_subscriber_handler.h b/service/subscriber/include/input_active_subscriber_handler.h new file mode 100644 index 000000000..1bb36e32b --- /dev/null +++ b/service/subscriber/include/input_active_subscriber_handler.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INPUT_ACTIVE_SUBSCRIBER_HANDLER_H +#define INPUT_ACTIVE_SUBSCRIBER_HANDLER_H + +#include +#include "i_input_event_handler.h" +#include "uds_server.h" + +namespace OHOS { +namespace MMI { +class InputActiveSubscriberHandler final : public IInputEventHandler { +public: + InputActiveSubscriberHandler() = default; + DISALLOW_COPY_AND_MOVE(InputActiveSubscriberHandler); + ~InputActiveSubscriberHandler() = default; +#ifdef OHOS_BUILD_ENABLE_KEYBOARD + void HandleKeyEvent(const std::shared_ptr keyEvent) override; +#endif // OHOS_BUILD_ENABLE_KEYBOARD +#ifdef OHOS_BUILD_ENABLE_POINTER + void HandlePointerEvent(const std::shared_ptr pointerEvent) override; +#endif // OHOS_BUILD_ENABLE_POINTER +#ifdef OHOS_BUILD_ENABLE_TOUCH + void HandleTouchEvent(const std::shared_ptr pointerEvent) override; +#endif // OHOS_BUILD_ENABLE_TOUCH +#ifdef OHOS_BUILD_ENABLE_SWITCH + void HandleSwitchEvent(const std::shared_ptr switchEvent) override; +#endif // OHOS_BUILD_ENABLE_SWITCH + int32_t SubscribeInputActive(SessionPtr sess, int32_t subscribeId, int64_t interval); + int32_t UnsubscribeInputActive(SessionPtr sess, int32_t subscribeId); + void Dump(int32_t fd, const std::vector &args); +private: + enum EventType : uint32_t { + EVENTTYPE_INVALID = 0, + EVENTTYPE_KEY, + EVENTTYPE_POINTER, + }; + struct Subscriber { + Subscriber(int32_t id, SessionPtr sess, int64_t interval) : id_(id), sess_(sess), interval_(interval) {} + int32_t id_ { -1 }; + SessionPtr sess_ { nullptr }; + int32_t timerId_ { INVALID_TIMERID }; + int64_t interval_ { 0 }; + EventType lastEventType_ { EVENTTYPE_INVALID }; + int64_t sendEventLastTime_ { 0 }; + std::shared_ptr keyEvent_ { nullptr }; + std::shared_ptr pointerEvent_ { nullptr }; + }; + + void InsertSubscriber(std::shared_ptr subscriber); + void OnSubscribeInputActive(const std::shared_ptr keyEvent); + void OnSubscribeInputActive(const std::shared_ptr pointerEvent); + void NotifySubscriber(const std::shared_ptr keyEvent, const std::shared_ptr subscriber); + void NotifySubscriber( + const std::shared_ptr pointerEvent, const std::shared_ptr subscriber); + void OnSessionDelete(SessionPtr sess); + bool InitSessionDeleteCallback(); + bool IsImmediateNotifySubscriber(std::shared_ptr subscriber, int64_t eventTime); + void StartIntervalTimer(std::shared_ptr subscriber, int64_t eventTime); + void CleanSubscribeInfo(std::shared_ptr subscriber, int64_t eventTime); +private: + std::mutex subscriberMutex_; + std::list> subscribers_; + std::atomic_bool callbackInitialized_ { false }; + static constexpr int32_t INVALID_TIMERID = -1; +}; +} // namespace MMI +} // namespace OHOS +#endif // INPUT_ACTIVE_SUBSCRIBER_HANDLER_H \ No newline at end of file diff --git a/service/subscriber/src/input_active_subscriber_handler.cpp b/service/subscriber/src/input_active_subscriber_handler.cpp new file mode 100644 index 000000000..6a577f8d5 --- /dev/null +++ b/service/subscriber/src/input_active_subscriber_handler.cpp @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "input_active_subscriber_handler.h" +#include +#include +#include +#include "dfx_hisysevent.h" +#include "input_event_data_transformation.h" +#include "input_event_handler.h" +#include "util_ex.h" + +#undef MMI_LOG_DOMAIN +#define MMI_LOG_DOMAIN MMI_LOG_HANDLER +#undef MMI_LOG_TAG +#define MMI_LOG_TAG "InputActiveSubscriberHandler" + +namespace OHOS { +namespace MMI { +#ifdef OHOS_BUILD_ENABLE_KEYBOARD +void InputActiveSubscriberHandler::HandleKeyEvent(const std::shared_ptr keyEvent) +{ + CHKPV(keyEvent); + CHKPV(nextHandler_); + OnSubscribeInputActive(keyEvent); + nextHandler_->HandleKeyEvent(keyEvent); +} +#endif // OHOS_BUILD_ENABLE_KEYBOARD + +#ifdef OHOS_BUILD_ENABLE_POINTER +void InputActiveSubscriberHandler::HandlePointerEvent(const std::shared_ptr pointerEvent) +{ + CHKPV(pointerEvent); + CHKPV(nextHandler_); + OnSubscribeInputActive(pointerEvent); + nextHandler_->HandlePointerEvent(pointerEvent); +} +#endif // OHOS_BUILD_ENABLE_POINTER + +#ifdef OHOS_BUILD_ENABLE_TOUCH +void InputActiveSubscriberHandler::HandleTouchEvent(const std::shared_ptr pointerEvent) +{ + CHKPV(pointerEvent); + CHKPV(nextHandler_); + OnSubscribeInputActive(pointerEvent); + nextHandler_->HandleTouchEvent(pointerEvent); +} +#endif // OHOS_BUILD_ENABLE_TOUCH + +#ifdef OHOS_BUILD_ENABLE_SWITCH +void InputActiveSubscriberHandler::HandleSwitchEvent(const std::shared_ptr switchEvent) +{ + CHKPV(switchEvent); + CHKPV(nextHandler_); + nextHandler_->HandleSwitchEvent(switchEvent); +} +#endif // OHOS_BUILD_ENABLE_SWITCH + +int32_t InputActiveSubscriberHandler::SubscribeInputActive(SessionPtr sess, int32_t subscribeId, int64_t interval) +{ + CALL_INFO_TRACE; + if (subscribeId < 0) { + MMI_HILOGE("Invalid subscribeId"); + return ERROR_INVALID_SUBSCRIBE_ID; + } + { + const int SUBSCRIBER_MAX_NUMBERS = 16; + std::lock_guard guard(subscriberMutex_); + if (subscribers_.size() >= SUBSCRIBER_MAX_NUMBERS) { + MMI_HILOGE("The number of subscribers exceeds the maximum(%{public}d) supported by the server", + SUBSCRIBER_MAX_NUMBERS); + return ERROR_EXCEED_SUBSCRIBE_SUPPORTED_MAXIMUM; + } + } + CHKPR(sess, ERROR_NULL_POINTER); + MMI_HILOGD("subscribeId: %{public}d interval: %{public}" PRId64, subscribeId, interval); + auto subscriber = std::make_shared(subscribeId, sess, interval); + InsertSubscriber(subscriber); + InitSessionDeleteCallback(); + return RET_OK; +} + +int32_t InputActiveSubscriberHandler::UnsubscribeInputActive(SessionPtr sess, int32_t subscribeId) +{ + CALL_INFO_TRACE; + MMI_HILOGD("subscribeId: %{public}d", subscribeId); + std::lock_guard guard(subscriberMutex_); + auto findResult = std::find_if( + subscribers_.begin(), subscribers_.end(), [subscribeId, sess](std::shared_ptr subscribe) { + if (subscribe && subscribe->id_ == subscribeId && subscribe->sess_ == sess) { + return true; + } + return false; + }); + if (findResult != subscribers_.end()) { + subscribers_.erase(findResult); + } else { + MMI_HILOGE("UnsubscribeInputActive failed with subscribeId(%{public}d)", subscribeId); + return ERROR_FIND_SUBSCRIBEID_FAILED; + } + return RET_OK; +} + +bool InputActiveSubscriberHandler::IsImmediateNotifySubscriber( + std::shared_ptr subscriber, int64_t eventTime) +{ + if (subscriber->interval_ <= 0) { + return true; + } + if (subscriber->sendEventLastTime_ <= 0) { + return true; + } + if (subscriber->sendEventLastTime_ > eventTime) { + subscriber->sendEventLastTime_ = 0; + return true; + } + if (eventTime - subscriber->sendEventLastTime_ >= subscriber->interval_) { + return true; + } + return false; +} + +void InputActiveSubscriberHandler::StartIntervalTimer(std::shared_ptr subscriber, int64_t eventTime) +{ + if (subscriber->timerId_ >= 0) { + return; + } + auto timerIntervalMs = subscriber->interval_ - (eventTime - subscriber->sendEventLastTime_); + auto timerId = TimerMgr->AddTimer(timerIntervalMs, 1, [this, subscriber] { + auto currentTime = GetMillisTime(); + if (subscriber->lastEventType_ == EVENTTYPE_KEY) { + if (subscriber->keyEvent_) { + NotifySubscriber(subscriber->keyEvent_, subscriber); + } else { + currentTime = 0; + MMI_HILOGE("lastKeyEvent is null"); + } + } else if (subscriber->lastEventType_ == EVENTTYPE_POINTER) { + if (subscriber->pointerEvent_) { + NotifySubscriber(subscriber->pointerEvent_, subscriber); + } else { + currentTime = 0; + MMI_HILOGE("lastPointerEvent is null"); + } + } else { + currentTime = 0; + MMI_HILOGE("lastEventType_ is invalid"); + } + subscriber->timerId_ = INVALID_TIMERID; + CleanSubscribeInfo(subscriber, currentTime); + }); + if (timerId < 0) { + MMI_HILOGE("AddTimer fail, setting will not work"); + } else { + subscriber->timerId_ = timerId; + } +} + +void InputActiveSubscriberHandler::CleanSubscribeInfo(std::shared_ptr subscriber, int64_t eventTime) +{ + if (subscriber->timerId_ >= 0) { + TimerMgr->RemoveTimer(subscriber->timerId_); + subscriber->timerId_ = INVALID_TIMERID; + } + subscriber->lastEventType_ = EVENTTYPE_INVALID; + subscriber->keyEvent_ = nullptr; + subscriber->pointerEvent_ = nullptr; + subscriber->sendEventLastTime_ = eventTime; +} + +void InputActiveSubscriberHandler::OnSubscribeInputActive(const std::shared_ptr keyEvent) +{ + CHKPV(keyEvent); + MMI_HILOGD("The Subscribe InputActive keycode: %{private}d", keyEvent->GetKeyCode()); + std::lock_guard guard(subscriberMutex_); + for (const auto &subscriber : subscribers_) { + if (!subscriber) { + MMI_HILOGE("subscriber is null"); + continue; + } + MMI_HILOGD("subscriber interval = %{public}" PRId64 ", id = %{public}d, pid = %{public}d", + subscriber->interval_, subscriber->id_, subscriber->sess_ ? subscriber->sess_->GetPid() : -1); + auto currentTime = GetMillisTime(); + if (IsImmediateNotifySubscriber(subscriber, currentTime)) { + CleanSubscribeInfo(subscriber, currentTime); + NotifySubscriber(keyEvent, subscriber); + } else { + subscriber->keyEvent_ = keyEvent; + subscriber->lastEventType_ = EVENTTYPE_KEY; + StartIntervalTimer(subscriber, currentTime); + } + } +} + +void InputActiveSubscriberHandler::OnSubscribeInputActive(const std::shared_ptr pointerEvent) +{ + CHKPV(pointerEvent); + MMI_HILOGD("The Subscribe InputActive pointerId: %{private}d", pointerEvent->GetPointerId()); + std::lock_guard guard(subscriberMutex_); + for (const auto &subscriber : subscribers_) { + if (!subscriber) { + MMI_HILOGE("subscriber is null"); + continue; + } + MMI_HILOGD("subscriber interval = %{public}" PRId64 ", id = %{public}d, pid = %{public}d", + subscriber->interval_, subscriber->id_, subscriber->sess_ ? subscriber->sess_->GetPid() : -1); + auto currentTime = GetMillisTime(); + if (IsImmediateNotifySubscriber(subscriber, currentTime)) { + CleanSubscribeInfo(subscriber, currentTime); + NotifySubscriber(pointerEvent, subscriber); + } else { + subscriber->pointerEvent_ = pointerEvent; + subscriber->lastEventType_ = EVENTTYPE_POINTER; + StartIntervalTimer(subscriber, currentTime); + } + } +} + +void InputActiveSubscriberHandler::InsertSubscriber(std::shared_ptr subscriber) +{ + CALL_DEBUG_ENTER; + CHKPV(subscriber); + MMI_HILOGI("InsertSubscriber id = %{public}d", subscriber->id_); + std::lock_guard guard(subscriberMutex_); + auto findResult = std::find_if( + subscribers_.begin(), subscribers_.end(), [subscriber](std::shared_ptr tmpSubscriber) { + if (tmpSubscriber && tmpSubscriber->id_ == subscriber->id_ && tmpSubscriber->sess_ == subscriber->sess_) { + return true; + } + return false; + }); + if (findResult != subscribers_.end()) { + MMI_HILOGW("Repeat registration id: %{public}d, desc:%{public}s", subscriber->id_, + subscriber->sess_ ? subscriber->sess_->GetDescript().c_str() : "invalid session"); + } else { + subscribers_.push_back(subscriber); + } +} + +void InputActiveSubscriberHandler::OnSessionDelete(SessionPtr sess) +{ + CALL_DEBUG_ENTER; + CHKPV(sess); + std::lock_guard guard(subscriberMutex_); + auto newEnd = std::remove_if( + subscribers_.begin(), subscribers_.end(), [sess](std::shared_ptr subscribe) { + if (subscribe && subscribe->sess_ == sess) { + return true; + } + return false; + }); + subscribers_.erase(newEnd, subscribers_.end()); +} + +void InputActiveSubscriberHandler::NotifySubscriber( + const std::shared_ptr keyEvent, const std::shared_ptr subscriber) +{ + CALL_DEBUG_ENTER; + CHKPV(keyEvent); + CHKPV(subscriber); + CHKPV(InputHandler); + auto udsServerPtr = InputHandler->GetUDSServer(); + CHKPV(udsServerPtr); + NetPacket pkt(MmiMessageId::ON_SUBSCRIBE_INPUT_ACTIVE); + pkt << HANDLE_EVENT_TYPE_KEY; + InputEventDataTransformation::KeyEventToNetPacket(keyEvent, pkt); + if (subscriber->sess_ == nullptr) { + MMI_HILOGE("Subscriber's sess is null"); + return; + } + int32_t fd = subscriber->sess_->GetFd(); + pkt << fd << subscriber->id_; + MMI_HILOGI("Notify subscriber id: %{public}d, keycode:%{private}d, pid: %{public}d", + subscriber->id_, keyEvent->GetKeyCode(), subscriber->sess_->GetPid()); + if (pkt.ChkRWError()) { + MMI_HILOGE("Packet write dispatch subscriber failed"); + return; + } + if (!udsServerPtr->SendMsg(fd, pkt)) { + MMI_HILOGE("Leave, server dispatch subscriber failed"); + } +} + +void InputActiveSubscriberHandler::NotifySubscriber( + const std::shared_ptr pointerEvent, const std::shared_ptr subscriber) +{ + CALL_DEBUG_ENTER; + CHKPV(pointerEvent); + CHKPV(subscriber); + CHKPV(InputHandler); + auto udsServerPtr = InputHandler->GetUDSServer(); + CHKPV(udsServerPtr); + NetPacket pkt(MmiMessageId::ON_SUBSCRIBE_INPUT_ACTIVE); + pkt << HANDLE_EVENT_TYPE_POINTER; + InputEventDataTransformation::Marshalling(pointerEvent, pkt); + if (subscriber->sess_ == nullptr) { + MMI_HILOGE("Subscriber's sess is null"); + return; + } + int32_t fd = subscriber->sess_->GetFd(); + pkt << subscriber->id_; + MMI_HILOGI("Notify subscriber id: %{public}d, pointerId:%{private}d, pid: %{public}d", + subscriber->id_, pointerEvent->GetPointerId(), subscriber->sess_->GetPid()); + if (pkt.ChkRWError()) { + MMI_HILOGE("Packet write dispatch subscriber failed"); + return; + } + if (!udsServerPtr->SendMsg(fd, pkt)) { + MMI_HILOGE("Leave, server dispatch subscriber failed"); + } +} + +bool InputActiveSubscriberHandler::InitSessionDeleteCallback() +{ + CALL_DEBUG_ENTER; + if (callbackInitialized_) { + MMI_HILOGD("Session delete callback has already been initialized"); + return true; + } + CHKPF(InputHandler); + auto udsServerPtr = InputHandler->GetUDSServer(); + CHKPF(udsServerPtr); + std::function callback = + [this] (SessionPtr sess) { return this->OnSessionDelete(sess); }; + udsServerPtr->AddSessionDeletedCallback(callback); + callbackInitialized_ = true; + return true; +} + +void InputActiveSubscriberHandler::Dump(int32_t fd, const std::vector &args) +{ + CALL_DEBUG_ENTER; + mprintf(fd, "Subscriber information:\t"); + mprintf(fd, "subscribers: count = %zu", subscribers_.size()); + std::lock_guard guard(subscriberMutex_); + for (const auto& subscriber : subscribers_) { + if (subscriber == nullptr) { + continue; + } + SessionPtr session = subscriber->sess_; + if (session == nullptr) { + continue; + } + mprintf(fd, "subscriber id:%d | Pid:%d | Uid:%d | Fd:%d\t", subscriber->id_, + session->GetPid(), session->GetUid(), session->GetFd()); + } +} +} // namespace MMI +} // namespace OHOS \ No newline at end of file diff --git a/service/subscriber/test/BUILD.gn b/service/subscriber/test/BUILD.gn index 3ef0b9ab1..1d14ec5bb 100644 --- a/service/subscriber/test/BUILD.gn +++ b/service/subscriber/test/BUILD.gn @@ -43,10 +43,45 @@ ohos_unittest("key_shortcut_rules_test") { ] } +ohos_unittest("InputActiveSubscriberHandlerTest") { + module_out_path = module_output_path + + include_dirs = [ + "${mmi_path}/service/connect_manager/include", + "${mmi_path}/service/event_handler/include", + "${mmi_path}/service/module_loader/include", + "${mmi_path}/service/subscriber/include", + ] + + configs = [ "${mmi_path}:coverage_flags" ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + + sources = [ "input_active_subscriber_handler_test.cpp" ] + + deps = [ + "${mmi_path}/service:libmmi-server", + "${mmi_path}/util:libmmi-util", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "googletest:gmock_main", + "googletest:gtest_main", + "hisysevent:libhisysevent", + "ipc:ipc_core", + "libinput:libinput-third-mmi", + ] +} + group("mmi_subscriber_tests") { testonly = true - + deps = [ ":InputActiveSubscriberHandlerTest" ] if (input_shortcut_key_rules_enabled) { - deps = [ ":key_shortcut_rules_test" ] + deps += [ ":key_shortcut_rules_test" ] } } diff --git a/service/subscriber/test/input_active_subscriber_handler_test.cpp b/service/subscriber/test/input_active_subscriber_handler_test.cpp new file mode 100644 index 000000000..292e81feb --- /dev/null +++ b/service/subscriber/test/input_active_subscriber_handler_test.cpp @@ -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. + */ + +#include + +#include "input_active_subscriber_handler.h" + +#undef MMI_LOG_TAG +#define MMI_LOG_TAG "InputActiveSubscriberHandlerTest" + +namespace OHOS { +namespace MMI { +namespace { +using namespace testing::ext; +} // namespace + +class InputActiveSubscriberHandlerTest : public testing::Test { +public: + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} +}; + +/** + * @tc.name: InputActiveSubscriberHandlerTest_SubscribeInputActive_001 + * @tc.desc: Verify SubscribeInputActive + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InputActiveSubscriberHandlerTest, InputActiveSubscriberHandlerTest_SubscribeInputActive_001, TestSize.Level1) +{ + InputActiveSubscriberHandler handler; + auto session = std::make_shared("test_program", 1, 123, 1000, 2000); + int32_t subscribeId = 1001; + + auto ret = handler.SubscribeInputActive(session, subscribeId, 500); + EXPECT_EQ(ret, RET_OK); + ret = handler.UnsubscribeInputActive(session, subscribeId); + EXPECT_EQ(ret, RET_OK); +} + +/** + * @tc.name: InputActiveSubscriberHandlerTest_OnSubscribeInputActive_001 + * @tc.desc: Verify SubscribeInputActive + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InputActiveSubscriberHandlerTest, InputActiveSubscriberHandlerTest_OnSubscribeInputActive_001, TestSize.Level1) +{ + int ret = RET_OK; + EXPECT_EQ(ret, RET_OK); +} + +} // namespace MMI +} // namespace OHOS \ No newline at end of file diff --git a/util/common/include/error_multimodal.h b/util/common/include/error_multimodal.h index 8324ca303..6e9d03621 100644 --- a/util/common/include/error_multimodal.h +++ b/util/common/include/error_multimodal.h @@ -16,6 +16,7 @@ #ifndef ERROR_MULTIMODAL_H #define ERROR_MULTIMODAL_H +#include #include namespace OHOS { @@ -34,6 +35,20 @@ enum { MODULE_UTIL = 0x03 }; +enum : int32_t { + ERROR_INVALID_SUBSCRIBE_ID = INT_MIN, + ERROR_INIT_CLIENT_FAILED, + ERROR_SUBSCRIBE_SERVER_FAILED, + ERROR_SUBSCRIBEID_NOT_EXIST, + ERROR_UNSUBSCRIBE_SERVER_FAILED, + ERROR_FIND_SUBSCRIBEID_FAILED, + ERROR_EXCEED_SUBSCRIBE_SUPPORTED_MAXIMUM, + ERROR_ONE_PROCESS_ONLY_SUPPORT_ONE, + ERROR_ALLOC_SUBSCRIBEINFO_FAILED, + ERROR_NO_SUBSCRIBE_INPUT_ACTIVE, + ERROR_HAD_UNSUBSCRIBE_INPUT_ACTIVE, +}; + enum { // 文件打开失败 FILE_OPEN_FAIL = ErrCodeOffset(SUBSYS_MULTIMODAINPUT, MODULE_EVENT_SIMULATE), diff --git a/util/common/include/proto.h b/util/common/include/proto.h index 5c26d540e..089ba97ca 100644 --- a/util/common/include/proto.h +++ b/util/common/include/proto.h @@ -43,6 +43,7 @@ enum class MmiMessageId : int32_t { SET_INPUT_DEVICE_ENABLED, ON_PRE_KEY_EVENT, ON_SUBSCRIBE_TABLET, + ON_SUBSCRIBE_INPUT_ACTIVE, }; enum TokenType : int32_t { -- Gitee