diff --git a/frameworks/native/inputmethod_controller/include/event_status_manager.h b/frameworks/native/inputmethod_controller/include/event_status_manager.h index 3061a1dd..1b29d71c 100644 --- a/frameworks/native/inputmethod_controller/include/event_status_manager.h +++ b/frameworks/native/inputmethod_controller/include/event_status_manager.h @@ -34,6 +34,10 @@ public: { return (eventFlag & EVENT_IME_HIDE_MASK) == EVENT_IME_HIDE_MASK; } + inline static bool IsInputStatusChangedOn(uint32_t eventFlag) + { + return (eventFlag & EVENT_INPUT_STATUS_CHANGED_MASK) == EVENT_INPUT_STATUS_CHANGED_MASK; + } }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_controller/include/i_input_client.h b/frameworks/native/inputmethod_controller/include/i_input_client.h index b9d59463..5e0d2fc1 100644 --- a/frameworks/native/inputmethod_controller/include/i_input_client.h +++ b/frameworks/native/inputmethod_controller/include/i_input_client.h @@ -33,6 +33,8 @@ public: ON_INPUT_STOP, ON_SWITCH_INPUT, ON_PANEL_STATUS_CHANGE, + ON_NOTIFY_INPUT_START, // IME start to input, no bind + ON_NOTIFY_INPUT_STOP, // IME stop to input DEACTIVATE_CLIENT }; @@ -42,6 +44,8 @@ public: virtual int32_t OnInputStop(bool isStopInactiveClient) = 0; virtual int32_t OnSwitchInput(const Property &property, const SubProperty &subProperty) = 0; virtual int32_t OnPanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info) = 0; + virtual int32_t NotifyInputStart(uint32_t callingWndId) = 0; + virtual int32_t NotifyInputStop() = 0; virtual void DeactivateClient() = 0; }; } // namespace MiscServices diff --git a/frameworks/native/inputmethod_controller/include/ime_event_monitor_manager_impl.h b/frameworks/native/inputmethod_controller/include/ime_event_monitor_manager_impl.h index 63659dfb..2a58911c 100644 --- a/frameworks/native/inputmethod_controller/include/ime_event_monitor_manager_impl.h +++ b/frameworks/native/inputmethod_controller/include/ime_event_monitor_manager_impl.h @@ -32,16 +32,20 @@ public: IMF_API int32_t UnRegisterImeEventListener(uint32_t eventFlag, const std::shared_ptr &listener); int32_t OnImeChange(const Property &property, const SubProperty &subProperty); int32_t OnPanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info); + int32_t OnInputStart(uint32_t callingWndId); + int32_t OnInputStop(); private: ImeEventMonitorManagerImpl(); ~ImeEventMonitorManagerImpl(); - static constexpr uint32_t MAX_EVENT_NUM = 3; + static constexpr uint32_t MAX_EVENT_NUM = 4; int32_t OnImeShow(const ImeWindowInfo &info); int32_t OnImeHide(const ImeWindowInfo &info); std::set> GetListeners(uint32_t eventMask); std::mutex lock_; std::map>> listeners_{}; + bool isInputStart_{ false }; + uint32_t callingWindow_{ 0 }; }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_controller/include/input_client_proxy.h b/frameworks/native/inputmethod_controller/include/input_client_proxy.h index 6b7483d9..12aa6a49 100644 --- a/frameworks/native/inputmethod_controller/include/input_client_proxy.h +++ b/frameworks/native/inputmethod_controller/include/input_client_proxy.h @@ -38,6 +38,8 @@ public: int32_t OnInputStop(bool isStopInactiveClient) override; int32_t OnSwitchInput(const Property &property, const SubProperty &subProperty) override; int32_t OnPanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info) override; + int32_t NotifyInputStart(uint32_t callingWndId) override; + int32_t NotifyInputStop() override; void DeactivateClient() override; private: diff --git a/frameworks/native/inputmethod_controller/include/input_client_stub.h b/frameworks/native/inputmethod_controller/include/input_client_stub.h index a3d9aa8d..0a7874ec 100644 --- a/frameworks/native/inputmethod_controller/include/input_client_stub.h +++ b/frameworks/native/inputmethod_controller/include/input_client_stub.h @@ -40,6 +40,8 @@ public: int32_t OnInputStop(bool isStopInactiveClient) override; int32_t OnSwitchInput(const Property &property, const SubProperty &subProperty) override; int32_t OnPanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info) override; + int32_t NotifyInputStart(uint32_t callingWndId) override; + int32_t NotifyInputStop() override; void DeactivateClient() override; private: @@ -48,6 +50,8 @@ private: int32_t OnSwitchInputOnRemote(MessageParcel &data, MessageParcel &reply); int32_t OnPanelStatusChangeOnRemote(MessageParcel &data, MessageParcel &reply); int32_t DeactivateClientOnRemote(MessageParcel &data, MessageParcel &reply); + int32_t NotifyInputStartOnRemote(MessageParcel &data, MessageParcel &reply); + int32_t NotifyInputStopOnRemote(MessageParcel &data, MessageParcel &reply); }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_controller/include/input_method_system_ability_proxy.h b/frameworks/native/inputmethod_controller/include/input_method_system_ability_proxy.h index 2fbe1652..bc2c0b15 100644 --- a/frameworks/native/inputmethod_controller/include/input_method_system_ability_proxy.h +++ b/frameworks/native/inputmethod_controller/include/input_method_system_ability_proxy.h @@ -81,6 +81,8 @@ public: int32_t ShowCurrentInputDeprecated() override; bool IsDefaultImeSet() override; bool EnableIme(const std::string &bundleName) override; + // make app client know calling IMF window + int32_t SetCallingWindow(uint32_t windowId, sptr client) override; private: static inline BrokerDelegator delegator_; diff --git a/frameworks/native/inputmethod_controller/src/ime_event_monitor_manager_impl.cpp b/frameworks/native/inputmethod_controller/src/ime_event_monitor_manager_impl.cpp index 675c34b3..cfb02381 100644 --- a/frameworks/native/inputmethod_controller/src/ime_event_monitor_manager_impl.cpp +++ b/frameworks/native/inputmethod_controller/src/ime_event_monitor_manager_impl.cpp @@ -61,6 +61,9 @@ int32_t ImeEventMonitorManagerImpl::RegisterImeEventListener(uint32_t eventFlag, } it->second.insert(listener); } + if (isInputStart_ && EventStatusManager::IsInputStatusChangedOn(eventFlag)) { + listener->OnInputStart(callingWindow_); + } return ErrorCode::NO_ERROR; } @@ -121,6 +124,32 @@ int32_t ImeEventMonitorManagerImpl::OnPanelStatusChange(const InputWindowStatus return ErrorCode::ERROR_BAD_PARAMETERS; } +int32_t ImeEventMonitorManagerImpl::OnInputStart(uint32_t callingWndId) +{ + isInputStart_ = true; + callingWindow_ = callingWndId; + auto listeners = GetListeners(EVENT_INPUT_STATUS_CHANGED_MASK); + for (const auto &listener : listeners) { + if (listener != nullptr) { + IMSA_HILOGD("listener start to callback, callingWndId: %{public}u", callingWndId); + listener->OnInputStart(callingWndId); + } + } + return ErrorCode::NO_ERROR; +} + +int32_t ImeEventMonitorManagerImpl::OnInputStop() +{ + isInputStart_ = false; + auto listeners = GetListeners(EVENT_INPUT_STATUS_CHANGED_MASK); + for (const auto &listener : listeners) { + if (listener != nullptr) { + listener->OnInputStop(); + } + } + return ErrorCode::NO_ERROR; +} + int32_t ImeEventMonitorManagerImpl::OnImeShow(const ImeWindowInfo &info) { auto listeners = GetListeners(EVENT_IME_SHOW_MASK); diff --git a/frameworks/native/inputmethod_controller/src/input_client_proxy.cpp b/frameworks/native/inputmethod_controller/src/input_client_proxy.cpp index d60aef28..80179786 100644 --- a/frameworks/native/inputmethod_controller/src/input_client_proxy.cpp +++ b/frameworks/native/inputmethod_controller/src/input_client_proxy.cpp @@ -51,6 +51,19 @@ int32_t InputClientProxy::OnPanelStatusChange(const InputWindowStatus &status, c }); } +int32_t InputClientProxy::NotifyInputStart(uint32_t callingWndId) +{ + IMSA_HILOGD("InputClientProxy::NotifyInputStart"); + return SendRequest(ON_NOTIFY_INPUT_START, [callingWndId](MessageParcel &data) { + return ITypesUtil::Marshal(data, callingWndId); + }); +} + +int32_t InputClientProxy::NotifyInputStop() +{ + IMSA_HILOGD("InputClientProxy::NotifyInputStop"); + return SendRequest(ON_NOTIFY_INPUT_STOP, nullptr); +} void InputClientProxy::DeactivateClient() { SendRequest(DEACTIVATE_CLIENT, nullptr, nullptr, MessageOption::TF_ASYNC); diff --git a/frameworks/native/inputmethod_controller/src/input_client_stub.cpp b/frameworks/native/inputmethod_controller/src/input_client_stub.cpp index f1c17961..f2ea4b6f 100644 --- a/frameworks/native/inputmethod_controller/src/input_client_stub.cpp +++ b/frameworks/native/inputmethod_controller/src/input_client_stub.cpp @@ -61,6 +61,12 @@ int32_t InputClientStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Mes case DEACTIVATE_CLIENT: { return DeactivateClientOnRemote(data, reply); } + case ON_NOTIFY_INPUT_START: { + return NotifyInputStartOnRemote(data, reply); + } + case ON_NOTIFY_INPUT_STOP: { + return NotifyInputStopOnRemote(data, reply); + } default: return IPCObjectStub::OnRemoteRequest(code, data, reply, option); } @@ -115,6 +121,22 @@ int32_t InputClientStub::DeactivateClientOnRemote(MessageParcel &data, MessagePa return reply.WriteInt32(ErrorCode::NO_ERROR) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE; } +int32_t InputClientStub::NotifyInputStartOnRemote(MessageParcel &data, MessageParcel &reply) +{ + uint32_t callingWndId = 0; + if (!ITypesUtil::Unmarshal(data, callingWndId)) { + IMSA_HILOGE("read message parcel failed!"); + return ErrorCode::ERROR_EX_PARCELABLE; + } + return reply.WriteInt32(NotifyInputStart(callingWndId)) ? + ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE; +} + +int32_t InputClientStub::NotifyInputStopOnRemote(MessageParcel &data, MessageParcel &reply) +{ + return reply.WriteInt32(NotifyInputStop()) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE; +} + int32_t InputClientStub::OnInputReady(const sptr &agent) { return ErrorCode::NO_ERROR; @@ -136,6 +158,16 @@ int32_t InputClientStub::OnPanelStatusChange(const InputWindowStatus &status, co return ImeEventMonitorManagerImpl::GetInstance().OnPanelStatusChange(status, info); } +int32_t InputClientStub::NotifyInputStart(uint32_t callingWndId) +{ + return ImeEventMonitorManagerImpl::GetInstance().OnInputStart(callingWndId); +} + +int32_t InputClientStub::NotifyInputStop() +{ + return ImeEventMonitorManagerImpl::GetInstance().OnInputStop(); +} + void InputClientStub::DeactivateClient() { InputMethodController::GetInstance()->DeactivateClient(); diff --git a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp index 86df7622..b1455da4 100644 --- a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp +++ b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp @@ -34,6 +34,7 @@ #include "sys/prctl.h" #include "system_ability_definition.h" #include "system_cmd_channel_stub.h" +#include "ime_event_monitor_manager_impl.h" namespace OHOS { namespace MiscServices { @@ -556,6 +557,8 @@ int32_t InputMethodController::HideInput(sptr &client) void InputMethodController::OnRemoteSaDied(const wptr &remote) { IMSA_HILOGI("input method service death."); + // imf sa died, current client callback inputStop + ImeEventMonitorManagerImpl::GetInstance().OnInputStop(); auto textListener = GetTextListener(); if (textListener != nullptr && textConfig_.inputAttribute.isTextPreviewSupported) { IMSA_HILOGD("finish text preview."); @@ -900,6 +903,10 @@ int32_t InputMethodController::SetCallingWindow(uint32_t windowId) } IMSA_HILOGI("windowId: %{public}d.", windowId); agent->SetCallingWindow(windowId); + auto proxy = GetSystemAbilityProxy(); + if (proxy != nullptr) { + proxy->SetCallingWindow(windowId, clientInfo_.client); + } return ErrorCode::NO_ERROR; } diff --git a/frameworks/native/inputmethod_controller/src/input_method_system_ability_proxy.cpp b/frameworks/native/inputmethod_controller/src/input_method_system_ability_proxy.cpp index 7e290e5d..d104dc17 100644 --- a/frameworks/native/inputmethod_controller/src/input_method_system_ability_proxy.cpp +++ b/frameworks/native/inputmethod_controller/src/input_method_system_ability_proxy.cpp @@ -185,6 +185,17 @@ bool InputMethodSystemAbilityProxy::EnableIme(const std::string &bundleName) return enableIme; } +int32_t InputMethodSystemAbilityProxy::SetCallingWindow(uint32_t windowId, sptr client) +{ + IMSA_HILOGI("proxy setCallingWindow enter"); + if (client == nullptr) { + IMSA_HILOGE("nullptr client"); + return ErrorCode::ERROR_EX_NULL_POINTER; + } + return SendRequest(static_cast(InputMethodInterfaceCode::SET_CALLING_WINDOW), + [windowId, client](MessageParcel &data) { return ITypesUtil::Marshal(data, windowId, client->AsObject()); }); +} + int32_t InputMethodSystemAbilityProxy::ListInputMethod(InputMethodStatus status, std::vector &props) { return SendRequest( diff --git a/interfaces/inner_api/inputmethod_controller/include/ime_event_listener.h b/interfaces/inner_api/inputmethod_controller/include/ime_event_listener.h index 7e32b67b..86f00c1c 100644 --- a/interfaces/inner_api/inputmethod_controller/include/ime_event_listener.h +++ b/interfaces/inner_api/inputmethod_controller/include/ime_event_listener.h @@ -24,12 +24,15 @@ namespace MiscServices { constexpr uint32_t EVENT_IME_CHANGE_MASK = 1u; constexpr uint32_t EVENT_IME_SHOW_MASK = 1u << 1u; constexpr uint32_t EVENT_IME_HIDE_MASK = 1u << 2u; +constexpr uint32_t EVENT_INPUT_STATUS_CHANGED_MASK = 1u << 3u; // OnInputStart and OnInputStop class ImeEventListener { public: virtual ~ImeEventListener() = default; virtual void OnImeChange(const Property &property, const SubProperty &subProperty){}; virtual void OnImeShow(const ImeWindowInfo &info){}; virtual void OnImeHide(const ImeWindowInfo &info){}; + virtual void OnInputStart(uint32_t callingWndId) {}; + virtual void OnInputStop() {}; }; } // namespace MiscServices } // namespace OHOS diff --git a/interfaces/inner_api/inputmethod_controller/include/ime_event_monitor_manager.h b/interfaces/inner_api/inputmethod_controller/include/ime_event_monitor_manager.h index 1bd9348e..0e58b3f0 100644 --- a/interfaces/inner_api/inputmethod_controller/include/ime_event_monitor_manager.h +++ b/interfaces/inner_api/inputmethod_controller/include/ime_event_monitor_manager.h @@ -38,7 +38,8 @@ public: /** * @brief Register Ime Event Listener. * - * This function is used to Register Ime Event Listener, only IME_SHOW and IME_HIDE supported at present + * This function is used to Register Ime Event Listener, only IME_SHOW, IME_HIDE, + * INPUT_STATUS_CHANGED supported at present * * @param eventFlag Indicates the flag of the ime event to be registered * @param listener Indicates the the listener to be registered. @@ -50,7 +51,8 @@ public: /** * @brief UnRegister Ime Event Listener. * - * This function is used to UnRegister Ime Event Listener, only IME_SHOW and IME_HIDE supported at present + * This function is used to UnRegister Ime Event Listener, only IME_SHOW and IME_HIDE, + * INPUT_STATUS_CHANGED supported at present * * @param types Indicates the flag of the ime event to be unRegistered * @param listener Indicates the the listener to be unregistered. @@ -60,7 +62,8 @@ public: IMF_API int32_t UnRegisterImeEventListener(uint32_t eventFlag, const std::shared_ptr &listener); private: - static constexpr uint32_t ALL_EVENT_MASK = EVENT_IME_SHOW_MASK | EVENT_IME_HIDE_MASK; + static constexpr uint32_t ALL_EVENT_MASK = EVENT_IME_SHOW_MASK | EVENT_IME_HIDE_MASK | + EVENT_INPUT_STATUS_CHANGED_MASK; ImeEventMonitorManager(); ~ImeEventMonitorManager(); bool IsParamValid(uint32_t eventFlag, const std::shared_ptr &listener); diff --git a/services/include/i_input_method_system_ability.h b/services/include/i_input_method_system_ability.h index f9be4622..550a9030 100644 --- a/services/include/i_input_method_system_ability.h +++ b/services/include/i_input_method_system_ability.h @@ -81,6 +81,8 @@ public: // Deprecated because of no permission check, and keep for compatibility virtual int32_t HideCurrentInputDeprecated() = 0; virtual int32_t ShowCurrentInputDeprecated() = 0; + + virtual int32_t SetCallingWindow(uint32_t windowId, sptr client) = 0; }; } // namespace MiscServices } // namespace OHOS diff --git a/services/include/input_method_system_ability.h b/services/include/input_method_system_ability.h index 99c66699..4df05e84 100644 --- a/services/include/input_method_system_ability.h +++ b/services/include/input_method_system_ability.h @@ -74,6 +74,7 @@ public: int32_t UnRegisteredProxyIme(UnRegisteredType type, const sptr &core) override; int32_t PanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info) override; int32_t UpdateListenEventFlag(InputClientInfo &clientInfo, uint32_t eventFlag) override; + int32_t SetCallingWindow(uint32_t windowId, sptr client) override; bool IsCurrentIme() override; bool IsInputTypeSupported(InputType type) override; bool IsCurrentImeByPid(int32_t pid) override; diff --git a/services/include/input_method_system_ability_stub.h b/services/include/input_method_system_ability_stub.h index 90de6a0d..9bb8b0b7 100644 --- a/services/include/input_method_system_ability_stub.h +++ b/services/include/input_method_system_ability_stub.h @@ -109,6 +109,8 @@ private: int32_t InitConnectOnRemote(MessageParcel &data, MessageParcel &reply); + int32_t SetCallingWindowOnRemote(MessageParcel &data, MessageParcel &reply); + using RequestHandler = int32_t (InputMethodSystemAbilityStub::*)(MessageParcel &, MessageParcel &); static inline constexpr RequestHandler HANDLERS[static_cast(InputMethodInterfaceCode::IMS_CMD_END)] = { &InputMethodSystemAbilityStub::InvalidRequest, @@ -184,6 +186,8 @@ private: &InputMethodSystemAbilityStub::IsDefaultImeSetOnRemote, [static_cast(InputMethodInterfaceCode::ENABLE_IME)] = &InputMethodSystemAbilityStub::EnableImeOnRemote, + [static_cast(InputMethodInterfaceCode::SET_CALLING_WINDOW)] = + &InputMethodSystemAbilityStub::SetCallingWindowOnRemote, }; }; } // namespace OHOS::MiscServices diff --git a/services/include/inputmethod_service_ipc_interface_code.h b/services/include/inputmethod_service_ipc_interface_code.h index d9c70d61..cddd920f 100644 --- a/services/include/inputmethod_service_ipc_interface_code.h +++ b/services/include/inputmethod_service_ipc_interface_code.h @@ -57,6 +57,8 @@ enum class InputMethodInterfaceCode { INIT_CONNECT, IS_DEFAULT_IME_SET, ENABLE_IME, + SET_CALLING_WINDOW, + IMS_CMD_END, }; } // namespace MiscServices diff --git a/services/include/peruser_session.h b/services/include/peruser_session.h index 4790743f..5fd73872 100644 --- a/services/include/peruser_session.h +++ b/services/include/peruser_session.h @@ -147,6 +147,7 @@ public: int32_t SetInputType(); std::shared_ptr GetImeNativeCfg(int32_t userId, const std::string &bundleName, const std::string &subName); + int32_t OnSetCallingWindow(uint32_t callingWindowId, sptr client); private: struct ResetManager { @@ -242,6 +243,10 @@ private: bool HandleFirstStart(const std::shared_ptr &ime, bool isStopCurrentIme); bool HandleStartImeTimeout(const std::shared_ptr &ime); bool GetInputTypeToStart(std::shared_ptr &imeToStart); + // from service notify clients input start and stop + int32_t NotifyInputStartToClients(uint32_t callingWndId); + int32_t NotifyInputStopToClients(); + bool IsNotifyInputStop(const sptr &client); std::mutex imeStartLock_; BlockData isImeStarted_{ MAX_IME_START_TIME, false }; diff --git a/services/src/input_method_system_ability.cpp b/services/src/input_method_system_ability.cpp index 231d4eed..50169d73 100644 --- a/services/src/input_method_system_ability.cpp +++ b/services/src/input_method_system_ability.cpp @@ -539,7 +539,8 @@ int32_t InputMethodSystemAbility::PanelStatusChange(const InputWindowStatus &sta int32_t InputMethodSystemAbility::UpdateListenEventFlag(InputClientInfo &clientInfo, uint32_t eventFlag) { IMSA_HILOGI("finalEventFlag: %{public}u, eventFlag: %{public}u.", clientInfo.eventFlag, eventFlag); - if (EventStatusManager::IsImeHideOn(eventFlag) || EventStatusManager::IsImeShowOn(eventFlag)) { + if (EventStatusManager::IsImeHideOn(eventFlag) || EventStatusManager::IsImeShowOn(eventFlag) || + EventStatusManager::IsInputStatusChangedOn(eventFlag)) { if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()) && !identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) { IMSA_HILOGE("not system application!"); @@ -559,6 +560,18 @@ int32_t InputMethodSystemAbility::UpdateListenEventFlag(InputClientInfo &clientI return session->OnUpdateListenEventFlag(clientInfo); } +int32_t InputMethodSystemAbility::SetCallingWindow(uint32_t windowId, sptr client) +{ + IMSA_HILOGD("IMF SA setCallingWindow enter"); + auto callingUserId = GetCallingUserId(); + auto session = UserSessionManager::GetInstance().GetUserSession(callingUserId); + if (session == nullptr) { + IMSA_HILOGE("%{public}d session is nullptr!", callingUserId); + return ErrorCode::ERROR_NULL_POINTER; + } + return session->OnSetCallingWindow(windowId, client); +} + bool InputMethodSystemAbility::IsCurrentIme() { return IsCurrentIme(GetCallingUserId()); diff --git a/services/src/input_method_system_ability_stub.cpp b/services/src/input_method_system_ability_stub.cpp index 4769d874..40f08645 100644 --- a/services/src/input_method_system_ability_stub.cpp +++ b/services/src/input_method_system_ability_stub.cpp @@ -328,6 +328,22 @@ int32_t InputMethodSystemAbilityStub::UpdateListenEventFlagOnRemote(MessageParce return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE; } +int32_t InputMethodSystemAbilityStub::SetCallingWindowOnRemote(MessageParcel &data, MessageParcel &reply) +{ + auto clientObject = data.ReadRemoteObject(); + if (clientObject == nullptr) { + IMSA_HILOGE("clientObject is nullptr!"); + return ErrorCode::ERROR_EX_PARCELABLE; + } + uint32_t windowId = 0; + if (!ITypesUtil::Unmarshal(data, windowId)) { + IMSA_HILOGE("unmarshal failed!"); + return ErrorCode::ERROR_EX_PARCELABLE; + } + return ITypesUtil::Marshal(reply, SetCallingWindow(windowId, iface_cast(clientObject))) ? + ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE; +} + int32_t InputMethodSystemAbilityStub::ShowCurrentInputOnRemoteDeprecated(MessageParcel &data, MessageParcel &reply) { int32_t ret = ShowCurrentInputDeprecated(); diff --git a/services/src/peruser_session.cpp b/services/src/peruser_session.cpp index 73062265..b6a0f61d 100644 --- a/services/src/peruser_session.cpp +++ b/services/src/peruser_session.cpp @@ -232,6 +232,11 @@ int32_t PerUserSession::ShowKeyboard(const sptr ¤tClient) */ void PerUserSession::OnClientDied(sptr remote) { + IMSA_HILOGD("vkbtest onClientDied start."); + if (IsNotifyInputStop(remote)) { + IMSA_HILOGD("vkbtest ClientDie notify input stop"); + NotifyInputStopToClients(); + } if (remote == nullptr) { return; } @@ -280,6 +285,8 @@ void PerUserSession::OnImeDied(const sptr &remote, ImeType typ auto client = GetCurrentClient(); auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr; if (clientInfo != nullptr && clientInfo->bindImeType == type) { + IMSA_HILOGD("vkbtest imeDied notify input stop"); + NotifyInputStopToClients(); StopClientInput(clientInfo); if (type == ImeType::IME) { StartImeInImeDied(); @@ -419,6 +426,8 @@ int32_t PerUserSession::OnRequestHideInput() RemoveClient(inactiveClient, false, true); } RestoreCurrentImeSubType(); + IMSA_HILOGD("vkbtest end requestHideInput"); + NotifyInputStopToClients(); return ErrorCode::NO_ERROR; } @@ -468,7 +477,17 @@ int32_t PerUserSession::OnPrepareInput(const InputClientInfo &clientInfo) int32_t PerUserSession::OnReleaseInput(const sptr &client) { IMSA_HILOGD("PerUserSession::OnReleaseInput start"); - return RemoveClient(client, true); + bool isReady = IsNotifyInputStop(client); + int32_t ret = RemoveClient(client, true); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("vkbtest remove client failed"); + return ret; + } + if (isReady) { + IMSA_HILOGD("vkbtest notify input stop to clients"); + NotifyInputStopToClients(); + } + return ErrorCode::NO_ERROR; } int32_t PerUserSession::RemoveClient(const sptr &client, bool isUnbindFromClient, bool isInactiveClient) @@ -602,6 +621,8 @@ int32_t PerUserSession::BindClientWithIme(const std::shared_ptr { { UpdateFlag::BINDIMETYPE, type }, { UpdateFlag::ISSHOWKEYBOARD, clientInfo->isShowKeyboard }, { UpdateFlag::STATE, ClientState::ACTIVE } }); ReplaceCurrentClient(clientInfo->client); + int32_t errorCode = NotifyInputStartToClients(clientInfo->config.windowId); + IMSA_HILOGD("vkbtest bind notify ret: %{public}d.", errorCode); return ErrorCode::NO_ERROR; } @@ -683,6 +704,13 @@ int32_t PerUserSession::OnSetCoreAndAgent(const sptr &core, co } bool isStarted = true; isImeStarted_.SetValue(isStarted); + // if client exist, execute notify input start callback + if (client != nullptr && clientInfo != nullptr) { + ret = NotifyInputStartToClients(clientInfo->config.windowId); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("notifyInputStartToClients failed, ret: %{public}d.", ret); + } + } return ErrorCode::NO_ERROR; } @@ -1160,6 +1188,82 @@ int32_t PerUserSession::OnUpdateListenEventFlag(const InputClientInfo &clientInf return ErrorCode::NO_ERROR; } +int32_t PerUserSession::OnSetCallingWindow(uint32_t callingWindowId, sptr client) +{ + IMSA_HILOGD("OnSetCallingWindow enter"); + if (!IsSameClient(client, GetCurrentClient())) { + IMSA_HILOGE("client is not current client!"); + return ErrorCode::ERROR_CLIENT_NOT_FOCUSED; + } + if (client == nullptr) { + IMSA_HILOGE("nullptr client!"); + return ErrorCode::ERROR_CLIENT_NULL_POINTER; + } + auto clientInfo = GetClientInfo(client->AsObject()); + if (clientInfo == nullptr) { + IMSA_HILOGE("nullptr clientInfo!"); + return ErrorCode::ERROR_CLIENT_NULL_POINTER; + } + // if windowId change, refresh windowId info and notify clients input start; + if (clientInfo->config.windowId != callingWindowId) { + IMSA_HILOGD("windowId changed, refresh windowId info and notify clients input start."); + clientInfo->config.windowId = callingWindowId; + return NotifyInputStartToClients(callingWindowId); + } + return ErrorCode::NO_ERROR; +} + +int32_t PerUserSession::NotifyInputStartToClients(uint32_t callingWndId) +{ + IMSA_HILOGD("NotifyInputStartToClients enter"); + auto clientMap = GetClientMap(); + for (const auto &client : clientMap) { + auto clientInfo = client.second; + if (clientInfo == nullptr || clientInfo->client == nullptr || + !EventStatusManager::IsInputStatusChangedOn(clientInfo->eventFlag)) { + IMSA_HILOGE("nullptr clientInfo or no need to notify"); + continue; + } + int32_t ret = clientInfo->client->NotifyInputStart(callingWndId); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to notify OnInputStart, errorCode: %{public}d", ret); + continue; + } + } + return ErrorCode::NO_ERROR; +} + +int32_t PerUserSession::NotifyInputStopToClients() +{ + IMSA_HILOGD("NotifyInputStopToClients enter"); + auto clientMap = GetClientMap(); + for (const auto &client : clientMap) { + auto clientInfo = client.second; + if (clientInfo == nullptr || clientInfo->client == nullptr || + !EventStatusManager::IsInputStatusChangedOn(clientInfo->eventFlag)) { + IMSA_HILOGE("nullptr clientInfo or no need to notify"); + continue; + } + int32_t ret = clientInfo->client->NotifyInputStop(); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to notify OnInputStop, errorCode: %{public}d", ret); + continue; + } + } + return ErrorCode::NO_ERROR; +} + +bool PerUserSession::IsNotifyInputStop(const sptr &client) +{ + if (IsSameClient(client, GetCurrentClient())) { + return true; + } + if (IsSameClient(client, GetInactiveClient()) && GetCurrentClient() == nullptr) { + return true; + } + return false; +} + bool PerUserSession::IsImeStartInBind(ImeType bindImeType, ImeType startImeType) { return startImeType == ImeType::IME && bindImeType == ImeType::IME; @@ -1340,6 +1444,8 @@ int32_t PerUserSession::RemoveCurrentClient() IMSA_HILOGE("currentClient is nullptr!"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; } + IMSA_HILOGD("vkbtest abnormal remove current client"); + NotifyInputStopToClients(); return RemoveClient(currentClient, false); } diff --git a/test/unittest/cpp_test/src/ime_event_monitor_manager_test.cpp b/test/unittest/cpp_test/src/ime_event_monitor_manager_test.cpp index 8d441915..15145671 100644 --- a/test/unittest/cpp_test/src/ime_event_monitor_manager_test.cpp +++ b/test/unittest/cpp_test/src/ime_event_monitor_manager_test.cpp @@ -102,7 +102,7 @@ HWTEST_F(ImeEventMonitorManagerTest, testRegisterImeEventListener_003, TestSize. auto listener = std::make_shared(); auto ret = ImeEventMonitorManager::GetInstance().RegisterImeEventListener(15, listener); EXPECT_EQ(ret, ErrorCode::NO_ERROR); - EXPECT_EQ(ImeEventMonitorManagerImpl::GetInstance().listeners_.size(), 2); + EXPECT_EQ(ImeEventMonitorManagerImpl::GetInstance().listeners_.size(), 3); auto it = ImeEventMonitorManagerImpl::GetInstance().listeners_.find(EVENT_IME_HIDE_MASK); ASSERT_NE(it, ImeEventMonitorManagerImpl::GetInstance().listeners_.end()); it = ImeEventMonitorManagerImpl::GetInstance().listeners_.find(EVENT_IME_SHOW_MASK); @@ -462,6 +462,52 @@ HWTEST_F(ImeEventMonitorManagerTest, testUnRegisterImeEventListener_019, TestSiz iter = it->second.find(listener1); EXPECT_NE(iter, it->second.end()); } + +/** +* @tc.name: testInputStatusChangedListener +* @tc.desc: register and unregister EVENT_INPUT_STATUS_CHANGED_MASK, +* there is no effect on EVENT_IME_SHOW_MASK and EVENT_HIDE_SHOW_MASK +* @tc.type: FUNC +*/ +HWTEST_F(ImeEventMonitorManagerTest, testInputStatusChangedListener, TestSize.Level0) +{ + IMSA_HILOGI("testInputStatusChangedListener start."); + auto listener = std::make_shared(); + auto listener1 = std::make_shared(); + auto ret = ImeEventMonitorManager::GetInstance().RegisterImeEventListener( + EVENT_IME_SHOW_MASK | EVENT_IME_HIDE_MASK, listener); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + EXPECT_EQ(InputMethodController::GetInstance()->clientInfo_.eventFlag, 6); + + ret = ImeEventMonitorManager::GetInstance().RegisterImeEventListener(EVENT_INPUT_STATUS_CHANGED_MASK, listener); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + EXPECT_EQ(InputMethodController::GetInstance()->clientInfo_.eventFlag, 14); + + ret = ImeEventMonitorManager::GetInstance().UnRegisterImeEventListener(EVENT_INPUT_STATUS_CHANGED_MASK, listener); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + EXPECT_EQ(InputMethodController::GetInstance()->clientInfo_.eventFlag, 6); + auto it = ImeEventMonitorManagerImpl::GetInstance().listeners_.find(EVENT_IME_HIDE_MASK); + ASSERT_NE(it, ImeEventMonitorManagerImpl::GetInstance().listeners_.end()); + ASSERT_EQ(it->second.size(), 1); + auto iter = it->second.find(listener); + + ret = ImeEventMonitorManager::GetInstance().RegisterImeEventListener(EVENT_INPUT_STATUS_CHANGED_MASK, listener1); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + EXPECT_EQ(InputMethodController::GetInstance()->clientInfo_.eventFlag, 14); + it = ImeEventMonitorManagerImpl::GetInstance().listeners_.find(EVENT_INPUT_STATUS_CHANGED_MASK); + ASSERT_NE(it, ImeEventMonitorManagerImpl::GetInstance().listeners_.end()); + ASSERT_EQ(it->second.size(), 1); + iter = it->second.find(listener1); + EXPECT_NE(iter, it->second.end()); + + ret = ImeEventMonitorManager::GetInstance().RegisterImeEventListener(EVENT_INPUT_STATUS_CHANGED_MASK, listener); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + EXPECT_EQ(InputMethodController::GetInstance()->clientInfo_.eventFlag, 14); + it = ImeEventMonitorManagerImpl::GetInstance().listeners_.find(EVENT_INPUT_STATUS_CHANGED_MASK); + ASSERT_NE(it, ImeEventMonitorManagerImpl::GetInstance().listeners_.end()); + ASSERT_EQ(it->second.size(), 2); +} + /********************************* all test is for innerkit above ***************************************************/ /** * @tc.name: testRegisterImeEventListener_020