From 2be9918390e5d5744c5958124804bcb456384611 Mon Sep 17 00:00:00 2001 From: hemenghao Date: Wed, 6 Aug 2025 11:20:08 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E8=B4=BE=E7=BB=B4=E6=96=AF=E9=9C=80?= =?UTF-8?q?=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hemenghao --- common/include/global.h | 1 + .../inputmethod_ability/IInputMethodCore.idl | 1 + .../include/input_method_ability.h | 1 + .../include/input_method_core_service_impl.h | 1 + .../inputmethod_ability/include/tasks/task.h | 3 +- .../include/tasks/task_imsa.h | 12 + .../src/input_method_ability.cpp | 15 + .../src/input_method_ability_interface.cpp | 5 + .../src/input_method_core_service_impl.cpp | 6 +- .../include/input_client_info.h | 2 + .../include/input_method_ability_interface.h | 1 + .../include/input_method_engine_listener.h | 2 + .../include/input_method_types.h | 2 +- services/include/client_group.h | 2 +- services/include/peruser_session.h | 45 +- services/src/client_group.cpp | 6 +- services/src/input_method_system_ability.cpp | 13 +- services/src/peruser_session.cpp | 471 +++++++++++++----- .../perusersession_fuzzer.cpp | 4 +- test/unittest/cpp_test/BUILD.gn | 7 +- test/unittest/cpp_test/src/ime_proxy_test.cpp | 30 +- .../src/input_method_controller_test.cpp | 2 +- .../src/input_method_private_member_test.cpp | 36 +- .../cpp_test/src/json_operate_test.cpp | 23 + 24 files changed, 507 insertions(+), 184 deletions(-) diff --git a/common/include/global.h b/common/include/global.h index 3748e1939..47d61bd7e 100644 --- a/common/include/global.h +++ b/common/include/global.h @@ -142,6 +142,7 @@ enum { ERROR_SA_POST_TASK_FAILED, ERROR_IME_HAS_STARTED, ERROR_OPERATION_NOT_ALLOWED, + ERROR_REQUEST_RATE_EXCEEDED, ERROR_IMSA_END, }; }; // namespace ErrorCode diff --git a/frameworks/native/inputmethod_ability/IInputMethodCore.idl b/frameworks/native/inputmethod_ability/IInputMethodCore.idl index aa7aef257..557ff1207 100644 --- a/frameworks/native/inputmethod_ability/IInputMethodCore.idl +++ b/frameworks/native/inputmethod_ability/IInputMethodCore.idl @@ -35,4 +35,5 @@ interface OHOS.MiscServices.IInputMethodCore { [oneway] void OnSetInputType([in] int inputType); void OnCallingDisplayIdChanged([in] unsigned long dispalyId); void OnSendPrivateData([in] Value value); + void NotifyPreemption(); } \ No newline at end of file diff --git a/frameworks/native/inputmethod_ability/include/input_method_ability.h b/frameworks/native/inputmethod_ability/include/input_method_ability.h index a94f600ae..643d74f85 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_ability.h +++ b/frameworks/native/inputmethod_ability/include/input_method_ability.h @@ -119,6 +119,7 @@ public: int32_t ShowKeyboard(int32_t requestKeyboardReason); int32_t HideKeyboard(); int32_t OnDiscardTypingText(); + int32_t OnNotifyPreemption(); void OnInitInputControlChannel(sptr channelObj); void OnSetSubtype(SubProperty subProperty); diff --git a/frameworks/native/inputmethod_ability/include/input_method_core_service_impl.h b/frameworks/native/inputmethod_ability/include/input_method_core_service_impl.h index dda07ef7a..049cec6ce 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_core_service_impl.h +++ b/frameworks/native/inputmethod_ability/include/input_method_core_service_impl.h @@ -47,6 +47,7 @@ public: ErrCode OnSetInputType(int32_t inputType) override; ErrCode OnCallingDisplayIdChanged(uint64_t dispalyId) override; ErrCode OnSendPrivateData(const Value &Value) override; + ErrCode NotifyPreemption() override; }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_ability/include/tasks/task.h b/frameworks/native/inputmethod_ability/include/tasks/task.h index 77f1afcf9..dd4a0a2cc 100644 --- a/frameworks/native/inputmethod_ability/include/tasks/task.h +++ b/frameworks/native/inputmethod_ability/include/tasks/task.h @@ -62,7 +62,8 @@ enum TaskType : uint32_t { TASK_TYPE_IMSA_SET_CORE_AND_AGENT, TASK_TYPE_IMSA_ADJUST_KEYBOARD, TASK_TYPE_IMSA_DISCARD_TYPING_TEXT, - TASK_TYPE_IMSA_END = TASK_TYPE_IMSA_DISCARD_TYPING_TEXT, + TASK_TYPE_IMSA_NOTIFY_PREEMPTION, + TASK_TYPE_IMSA_END = TASK_TYPE_IMSA_NOTIFY_PREEMPTION, // Task from inner TASK_TYPE_RESUME, diff --git a/frameworks/native/inputmethod_ability/include/tasks/task_imsa.h b/frameworks/native/inputmethod_ability/include/tasks/task_imsa.h index 819b623cd..eef3666b3 100644 --- a/frameworks/native/inputmethod_ability/include/tasks/task_imsa.h +++ b/frameworks/native/inputmethod_ability/include/tasks/task_imsa.h @@ -196,6 +196,18 @@ public: } ~TaskImsaSetCoreAndAgent() = default; }; + +class TaskImsaNotifyPreemption : public Task { +public: + explicit TaskImsaNotifyPreemption() : Task(TASK_TYPE_IMSA_NOTIFY_PREEMPTION) + { + auto func = []() { + InputMethodAbility::GetInstance().OnNotifyPreemption(); + }; + actions_.emplace_back(std::make_unique(func)); + } + ~TaskImsaNotifyPreemption() = default; +}; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp index 04a611eaf..82bf6e998 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp @@ -139,6 +139,7 @@ int32_t InputMethodAbility::InitConnect() int32_t InputMethodAbility::UnRegisteredProxyIme(UnRegisteredType type) { + IMSA_HILOGD("type %{public}d", type); isBound_.store(false); auto proxy = GetImsaProxy(); if (proxy == nullptr) { @@ -1884,5 +1885,19 @@ int32_t InputMethodAbility::IsCapacitySupport(int32_t capacity, bool &isSupport) return proxy->IsCapacitySupport(capacity, isSupport); } + +int32_t InputMethodAbility::OnNotifyPreemption() +{ + IMSA_HILOGD("start."); + StopInput(dataChannelObject_, 0); + isBound_.store(false); + auto imeListener = GetImeListener(); + if (imeListener == nullptr) { + return ErrorCode::ERROR_IME_NOT_STARTED; + } + IMSA_HILOGD("notify begin."); + imeListener->NotifyPreemption(); + return ErrorCode::NO_ERROR; +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/inputmethod_ability/src/input_method_ability_interface.cpp b/frameworks/native/inputmethod_ability/src/input_method_ability_interface.cpp index 9da345e6e..9813775fc 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_ability_interface.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_ability_interface.cpp @@ -87,5 +87,10 @@ void InputMethodAbilityInterface::SetKdListener(std::shared_ptr()); + return ERR_OK; +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/inputmethod_controller/include/input_client_info.h b/frameworks/native/inputmethod_controller/include/input_client_info.h index b35768952..f51f33eac 100644 --- a/frameworks/native/inputmethod_controller/include/input_client_info.h +++ b/frameworks/native/inputmethod_controller/include/input_client_info.h @@ -31,6 +31,7 @@ enum class UpdateFlag : uint32_t { TEXT_CONFIG, UIEXTENSION_TOKENID, CLIENT_TYPE, + BIND_IME_PID, }; enum class ImeType : int32_t { IME = 0, @@ -75,6 +76,7 @@ struct InputClientInfo { RequestKeyboardReason requestKeyboardReason { RequestKeyboardReason::NONE }; // show keyboard reason ClientType type{ INNER_KIT }; // for hiSysEvent std::string name; // for hiSysEvent, client name:SA/processName app/bundleName + pid_t bindImePid { -1 }; }; struct InputClientInfoInner : public Parcelable { diff --git a/interfaces/inner_api/inputmethod_ability/include/input_method_ability_interface.h b/interfaces/inner_api/inputmethod_ability/include/input_method_ability_interface.h index 59f240445..07c1e6271 100644 --- a/interfaces/inner_api/inputmethod_ability/include/input_method_ability_interface.h +++ b/interfaces/inner_api/inputmethod_ability/include/input_method_ability_interface.h @@ -59,6 +59,7 @@ public: int32_t SendFunctionKey(int32_t funcKey); void SetImeListener(std::shared_ptr imeListener); void SetKdListener(std::shared_ptr kdListener); + int32_t SelectByRange(int32_t start, int32_t end); private: InputMethodAbilityInterface() = default; diff --git a/interfaces/inner_api/inputmethod_ability/include/input_method_engine_listener.h b/interfaces/inner_api/inputmethod_ability/include/input_method_engine_listener.h index ffdb16f61..0b9b15b36 100644 --- a/interfaces/inner_api/inputmethod_ability/include/input_method_engine_listener.h +++ b/interfaces/inner_api/inputmethod_ability/include/input_method_engine_listener.h @@ -53,6 +53,8 @@ public: return false; } virtual void OnCallingDisplayIdChanged(uint64_t callingDisplayId) {}; + + virtual void NotifyPreemption() {}; }; } // namespace MiscServices } // namespace OHOS diff --git a/interfaces/inner_api/inputmethod_ability/include/input_method_types.h b/interfaces/inner_api/inputmethod_ability/include/input_method_types.h index a0860972e..b06e64629 100644 --- a/interfaces/inner_api/inputmethod_ability/include/input_method_types.h +++ b/interfaces/inner_api/inputmethod_ability/include/input_method_types.h @@ -20,7 +20,7 @@ #include "key_event.h" namespace OHOS { namespace MiscServices { -enum class UnRegisteredType : int32_t { REMOVE_PROXY_IME, SWITCH_PROXY_IME_TO_IME, NONE }; +enum class UnRegisteredType : int32_t { REMOVE_PROXY_IME, NONE }; } // namespace MiscServices } // namespace OHOS #endif // INPUTMETHOD_IMF_PROXY_IME_UNREGISTERED_TYPE_H diff --git a/services/include/client_group.h b/services/include/client_group.h index ad3918935..804e9c9a0 100644 --- a/services/include/client_group.h +++ b/services/include/client_group.h @@ -43,7 +43,7 @@ public: void RemoveClientInfo(const sptr &client, bool isClientDied = false); void UpdateClientInfo(const sptr &client, const std::unordered_map> &updateInfos); + std::variant> &updateInfos); std::shared_ptr GetClientInfo(sptr inputClient); std::shared_ptr GetClientInfo(pid_t pid); diff --git a/services/include/peruser_session.h b/services/include/peruser_session.h index cb36cbadc..5b01ec6fe 100644 --- a/services/include/peruser_session.h +++ b/services/include/peruser_session.h @@ -30,14 +30,16 @@ #include "inputmethod_sysevent.h" #include "want.h" #include "ime_state_manager.h" +#include "input_method_client_types.h" namespace OHOS { namespace Rosen { - struct CallingWindowInfo; +struct CallingWindowInfo; } } namespace OHOS { namespace MiscServices { +const std::string IME_MIRROR_NAME = "proxyIme_IME_MIRROR"; enum class ImeStatus : uint32_t { STARTING, READY, EXITING }; enum class ImeEvent : uint32_t { START_IME, @@ -74,6 +76,11 @@ struct ImeData { : core(std::move(core)), agent(std::move(agent)), deathRecipient(std::move(deathRecipient)), pid(imePid) { } + + bool IsImeMirror() const + { + return ime.first == IME_MIRROR_NAME; + } ImeExtendInfo imeExtendInfo; }; @@ -91,8 +98,8 @@ public: ~PerUserSession(); int32_t OnPrepareInput(const InputClientInfo &clientInfo); - int32_t OnStartInput( - const InputClientInfo &inputClientInfo, sptr &agent, std::pair &imeInfo); + int32_t OnStartInput(const InputClientInfo &inputClientInfo, std::vector> &agents, + std::vector &imeInfos); int32_t OnReleaseInput(const sptr &client, uint32_t sessionId); int32_t OnSetCoreAndAgent(const sptr &core, const sptr &agent); int32_t OnHideCurrentInput(uint64_t displayId); @@ -114,8 +121,10 @@ public: int64_t GetInactiveClientPid(uint64_t displayId); int32_t OnPanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info, uint64_t displayId); int32_t OnUpdateListenEventFlag(const InputClientInfo &clientInfo); - int32_t OnRegisterProxyIme(const sptr &core, const sptr &agent); - int32_t OnUnRegisteredProxyIme(UnRegisteredType type, const sptr &core); + int32_t OnRegisterProxyIme(const sptr &core, const sptr &agent, int32_t pid); + int32_t OnUnRegisteredProxyIme(UnRegisteredType type, const sptr &core, pid_t pid); + int32_t OnBindImeMirror(const sptr &core, const sptr &agent); + int32_t OnUnBindImeMirror(); int32_t UpdateLargeMemorySceneState(const int32_t memoryState); int32_t OnRegisterProxyIme( uint64_t displayId, const sptr &core, const sptr &agent); @@ -138,6 +147,7 @@ public: int32_t RemoveAllCurrentClient(); std::shared_ptr GetReadyImeData(ImeType type); std::shared_ptr GetImeData(ImeType type); + std::shared_ptr GetImeData(pid_t pid); BlockQueue& GetSwitchQueue(); bool IsWmsReady(); bool CheckPwdInputPatternConv(InputClientInfo &clientInfo, uint64_t displayId); @@ -176,6 +186,12 @@ private: uint32_t num{ 0 }; time_t last{}; }; + enum TimeLimitType : uint32_t { + IME_LIMIT, + PROXY_IME_LIMIT, + }; + using CoreMethod = std::function &)>; + int32_t userId_; // the id of the user to whom the object is linking #ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE static const int MAX_IME_START_TIME = 2000; @@ -184,7 +200,7 @@ private: #endif static const int MAX_NOTIFY_TIME = 20; std::mutex resetLock; - ResetManager manager; + std::map managers_; using IpcExec = std::function; PerUserSession(const PerUserSession &); @@ -196,7 +212,7 @@ private: BlockQueue switchQueue_{ MAX_WAIT_TIME }; void OnClientDied(sptr remote); - void OnImeDied(const sptr &remote, ImeType type); + void OnImeDied(const sptr &remote, ImeType type, pid_t pid); int AddClientInfo(sptr inputClient, const InputClientInfo &clientInfo, ClientAddEvent event); int32_t RemoveClient(const sptr &client, const std::shared_ptr &clientGroup, @@ -212,9 +228,9 @@ private: const std::shared_ptr &imeNativeCfg = nullptr); int32_t UpdateImeData(sptr core, sptr agent, pid_t pid); int32_t AddImeData(ImeType type, sptr core, sptr agent, pid_t pid); - void RemoveImeData(ImeType type, bool isImeDied); - int32_t RemoveIme(const sptr &core, ImeType type); - std::shared_ptr GetValidIme(ImeType type); + void RemoveImeData(ImeType type); + void RemoveImeData(pid_t pid); + int32_t RemoveIme(ImeType type, pid_t pid); int32_t BindClientWithIme(const std::shared_ptr &clientInfo, ImeType type, bool isBindFromClient = false, uint64_t displayId = DEFAULT_DISPLAY_ID); @@ -238,6 +254,8 @@ private: bool IsProxyImeStartInImeBind(ImeType bindImeType, ImeType startImeType); bool IsImeBindTypeChanged(ImeType bindImeType); int32_t RequestIme(const std::shared_ptr &data, RequestType type, const IpcExec &exec); + int32_t RequestAllIme(const std::shared_ptr data, RequestType reqType, const CoreMethod &method); + std::vector> GetAllReadyImeData(ImeType type); bool WaitForCurrentImeStop(); void NotifyImeStopFinished(); @@ -253,7 +271,7 @@ private: int32_t HandleFirstStart(const std::shared_ptr &ime, bool isStopCurrentIme); int32_t HandleStartImeTimeout(const std::shared_ptr &ime); bool GetInputTypeToStart(std::shared_ptr &imeToStart); - void HandleImeBindTypeChanged(InputClientInfo &newClientInfo, const std::shared_ptr &clientGroup); + void HandleBindImeChanged(InputClientInfo &newClientInfo, const std::shared_ptr &clientGroup); int32_t NotifyCallingDisplayChanged(uint64_t displayId); bool GetCallingWindowInfo(const InputClientInfo &clientInfo, Rosen::CallingWindowInfo &callingWindowInfo); int32_t SendPrivateData(const std::unordered_map &privateCommand); @@ -268,15 +286,18 @@ private: bool IsAttachFinished(); uint32_t GetScbStartCount(); void ResetRestartTasks(); + int32_t SendAllReadyImeToClient( + std::shared_ptr ImeDatas, const std::shared_ptr &clientInfo); void SetImeConnection(const sptr &connection); sptr GetImeConnection(); void ClearImeConnection(const sptr &connection); + int32_t IsRequestOverLimit(TimeLimitType timeLimit, int32_t resetTimeOut, int32_t restartNum); std::mutex imeStartLock_; BlockData isImeStarted_{ MAX_IME_START_TIME, false }; std::mutex imeDataLock_; - std::unordered_map> imeData_; + std::unordered_map>> imeData_; std::mutex focusedClientLock_; std::atomic isSwitching_ = false; diff --git a/services/src/client_group.cpp b/services/src/client_group.cpp index 3c8852eee..c3bdaa28f 100644 --- a/services/src/client_group.cpp +++ b/services/src/client_group.cpp @@ -99,7 +99,7 @@ void ClientGroup::RemoveClientInfo(const sptr &client, bool isCli } void ClientGroup::UpdateClientInfo(const sptr &client, const std::unordered_map> &updateInfos) + std::variant> &updateInfos) { if (client == nullptr) { IMSA_HILOGE("client is nullptr!"); @@ -141,6 +141,10 @@ void ClientGroup::UpdateClientInfo(const sptr &client, const std: VariantUtil::GetValue(updateInfo.second, it->second->type); break; } + case UpdateFlag::BIND_IME_PID: { + VariantUtil::GetValue(updateInfo.second, it->second->bindImePid); + break; + } default: break; } diff --git a/services/src/input_method_system_ability.cpp b/services/src/input_method_system_ability.cpp index caac6c8c6..676f2168d 100644 --- a/services/src/input_method_system_ability.cpp +++ b/services/src/input_method_system_ability.cpp @@ -829,6 +829,7 @@ ErrCode InputMethodSystemAbility::RequestHideInput(bool isFocusTriggered) ErrCode InputMethodSystemAbility::SetCoreAndAgent(const sptr &core, const sptr &agent) { IMSA_HILOGD("InputMethodSystemAbility start."); + auto pid = IPCSkeleton::GetCallingPid(); auto userId = GetCallingUserId(); auto session = UserSessionManager::GetInstance().GetUserSession(userId); if (session == nullptr) { @@ -836,7 +837,7 @@ ErrCode InputMethodSystemAbility::SetCoreAndAgent(const sptr & return ErrorCode::ERROR_NULL_POINTER; } if (identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) { - return session->OnRegisterProxyIme(core, agent); + return session->OnRegisterProxyIme(core, agent, pid); } if (!IsCurrentIme(userId)) { IMSA_HILOGE("not current ime, userId:%{public}d", userId); @@ -2124,6 +2125,7 @@ int32_t InputMethodSystemAbility::GetSecurityMode(int32_t &security) ErrCode InputMethodSystemAbility::UnRegisteredProxyIme(int32_t type, const sptr &core) { + pid_t pid = IPCSkeleton::GetCallingPid(); if (!identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) { IMSA_HILOGE("not native sa!"); return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; @@ -2134,14 +2136,7 @@ ErrCode InputMethodSystemAbility::UnRegisteredProxyIme(int32_t type, const sptr< IMSA_HILOGE("%{public}d session is nullptr!", userId); return ErrorCode::ERROR_NULL_POINTER; } - if (static_cast(type) == UnRegisteredType::SWITCH_PROXY_IME_TO_IME) { - int32_t ret = ErrorCode::NO_ERROR; - ret = session->StartCurrentIme(); - if (ret != ErrorCode::NO_ERROR) { - return ret; - } - } - return session->OnUnRegisteredProxyIme(static_cast(type), core); + return session->OnUnRegisteredProxyIme(static_cast(type), core, pid); } int32_t InputMethodSystemAbility::CheckEnableAndSwitchPermission() diff --git a/services/src/peruser_session.cpp b/services/src/peruser_session.cpp index 51cc5f8c7..bf4930a61 100644 --- a/services/src/peruser_session.cpp +++ b/services/src/peruser_session.cpp @@ -68,6 +68,8 @@ constexpr const char *UNDEFINED = "undefined"; constexpr int32_t WAIT_ATTACH_FINISH_DELAY = 50; constexpr int32_t WAIT_ATTACH_FINISH_MAX_TIMES = 20; constexpr uint32_t MAX_SCB_START_COUNT = 2; +constexpr uint32_t PROXY_REGISTERATION_TIME_INTERVAL = 1; // 1s +constexpr uint32_t MAX_REGISTRATIONS_NUM = 3; PerUserSession::PerUserSession(int userId) : userId_(userId) { } PerUserSession::PerUserSession(int32_t userId, const std::shared_ptr &eventHandler) @@ -124,7 +126,9 @@ int32_t PerUserSession::HideKeyboard( IMSA_HILOGE("ime: %{public}d is not exist!", clientInfo->bindImeType); return ErrorCode::ERROR_IME_NOT_STARTED; } - auto ret = RequestIme(data, RequestType::NORMAL, [&data] { return data->core->HideKeyboard(); }); + auto ret = RequestIme(data, RequestType::NORMAL, [&data] { + return data->core->HideKeyboard(); + }); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to hide keyboard, ret: %{public}d!", ret); return ErrorCode::ERROR_KBD_HIDE_FAILED; @@ -204,28 +208,28 @@ void PerUserSession::OnClientDied(sptr remote) * It's called when an ime died * @param the remote object handler of the ime who died. */ -void PerUserSession::OnImeDied(const sptr &remote, ImeType type) +void PerUserSession::OnImeDied(const sptr &remote, ImeType type, pid_t pid) { if (remote == nullptr) { return; } IMSA_HILOGI("type: %{public}d.", type); - auto imeData = GetImeData(type); + auto imeData = GetImeData(pid); if (imeData != nullptr && imeData->imeStatus == ImeStatus::EXITING) { - RemoveImeData(type, true); + RemoveImeData(pid); InputTypeManager::GetInstance().Set(false); NotifyImeStopFinished(); IMSA_HILOGI("%{public}d not current imeData.", type); return; } - RemoveImeData(type, true); + RemoveImeData(pid); if (!OsAccountAdapter::IsOsAccountForeground(userId_)) { IMSA_HILOGW("userId:%{public}d in background, no need to restart ime.", userId_); return; } auto clientGroup = GetClientGroup(type); auto clientInfo = clientGroup != nullptr ? clientGroup->GetCurrentClientInfo() : nullptr; - if (clientInfo != nullptr && clientInfo->bindImeType == type) { + if (clientInfo != nullptr && clientInfo->bindImeType == type && clientInfo->bindImePid == pid) { clientGroup->NotifyInputStopToClients(); StopClientInput(clientInfo); if (type == ImeType::IME) { @@ -252,22 +256,14 @@ void PerUserSession::OnImeDied(const sptr &remote, ImeType typ } } -int32_t PerUserSession::RemoveIme(const sptr &core, ImeType type) +int32_t PerUserSession::RemoveIme(ImeType type, pid_t pid) { - if (core == nullptr) { - return ErrorCode::ERROR_NULL_POINTER; - } - auto data = GetReadyImeData(type); - if (data == nullptr || data->core->AsObject() != core->AsObject()) { - return ErrorCode::ERROR_IME_NOT_STARTED; - } - auto clientGroup = GetClientGroup(type); auto clientInfo = clientGroup != nullptr ? clientGroup->GetCurrentClientInfo() : nullptr; - if (clientInfo != nullptr && clientInfo->bindImeType == type) { + if (clientInfo != nullptr && clientInfo->bindImeType == type && clientInfo->bindImePid == pid) { UnBindClientWithIme(clientInfo, { .sessionId = 0 }); } - RemoveImeData(type, true); + RemoveImeData(pid); return ErrorCode::NO_ERROR; } @@ -378,8 +374,8 @@ int32_t PerUserSession::OnRequestShowInput(uint64_t displayId) IMSA_HILOGE("failed to show keyboard, ret: %{public}d!", ret); return ErrorCode::ERROR_KBD_SHOW_FAILED; } - InputMethodSysEvent::GetInstance().ReportImeState(ImeState::BIND, data->pid, - ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName); + InputMethodSysEvent::GetInstance().ReportImeState( + ImeState::BIND, data->pid, ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName); Memory::MemMgrClient::GetInstance().SetCritical(getpid(), true, INPUT_METHOD_SYSTEM_ABILITY_ID); auto currentClient = clientGroup->GetCurrentClient(); if (currentClient != nullptr) { @@ -393,7 +389,9 @@ int32_t PerUserSession::OnRequestHideInput(int32_t callingPid, uint64_t displayI IMSA_HILOGD("PerUserSession::OnRequestHideInput start."); auto data = GetReadyImeData(GetImeType(displayId)); if (data != nullptr) { - auto ret = RequestIme(data, RequestType::REQUEST_HIDE, [&data] { return data->core->HideKeyboard(); }); + auto ret = RequestIme(data, RequestType::REQUEST_HIDE, [&data] { + return data->core->HideKeyboard(); + }); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to hide keyboard, ret: %{public}d!", ret); return ErrorCode::ERROR_KBD_HIDE_FAILED; @@ -508,12 +506,12 @@ void PerUserSession::DeactivateClient(const sptr &client) IMSA_HILOGE("ime %{public}d doesn't exist!", clientInfo->bindImeType); return; } - RequestIme(data, RequestType::NORMAL, [&data, &clientInfo] { - data->core->OnClientInactive(clientInfo->channel); + RequestAllIme(data, RequestType::NORMAL, [&clientInfo](const sptr &core) { + core->OnClientInactive(clientInfo->channel); return ErrorCode::NO_ERROR; }); - InputMethodSysEvent::GetInstance().ReportImeState(ImeState::UNBIND, data->pid, - ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName); + InputMethodSysEvent::GetInstance().ReportImeState( + ImeState::UNBIND, data->pid, ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName); Memory::MemMgrClient::GetInstance().SetCritical(getpid(), false, INPUT_METHOD_SYSTEM_ABILITY_ID); } @@ -528,8 +526,8 @@ bool PerUserSession::IsProxyImeEnable() return ret; } -int32_t PerUserSession::OnStartInput( - const InputClientInfo &inputClientInfo, sptr &agent, std::pair &imeInfo) +int32_t PerUserSession::OnStartInput(const InputClientInfo &inputClientInfo, std::vector> &agents, + std::vector &imeInfos) { const sptr &client = inputClientInfo.client; if (client == nullptr) { @@ -550,9 +548,16 @@ int32_t PerUserSession::OnStartInput( infoTemp.isNotifyInputStart = inputClientInfo.isNotifyInputStart; ImeType imeType = GetImeType(inputClientInfo.displayId); if (GetDisplayGroupId(inputClientInfo.displayId) == DEFAULT_DISPLAY_ID) { - HandleImeBindTypeChanged(infoTemp, clientGroup); imeType = IsProxyImeEnable() ? ImeType::PROXY_IME : ImeType::IME; } + auto data = GetReadyImeData(imeType); + if (data == nullptr || data->agent == nullptr) { + IMSA_HILOGE("data or agent is nullptr!"); + return ErrorCode::ERROR_IME_NOT_STARTED; + } + infoTemp.bindImePid = data->pid; + infoTemp.bindImeType = imeType; + HandleBindImeChanged(infoTemp, clientGroup); infoTemp.isShowKeyboard = inputClientInfo.isShowKeyboard; infoTemp.needHide = inputClientInfo.needHide; infoTemp.requestKeyboardReason = inputClientInfo.requestKeyboardReason; @@ -563,16 +568,57 @@ int32_t PerUserSession::OnStartInput( IMSA_HILOGE("bind failed, ret: %{public}d!", ret); return ret; } - auto data = GetReadyImeData(imeType); - if (data == nullptr || data->agent == nullptr) { - IMSA_HILOGE("data or agent is nullptr!"); + auto allData = GetAllReadyImeData(imeType); + if (allData.empty()) { + IMSA_HILOGE("allData is empty!"); return ErrorCode::ERROR_IME_NOT_STARTED; } - agent = data->agent; - imeInfo = { data->pid, data->ime.first }; + + for (auto &data : allData) { + if (data->agent == nullptr) { + IMSA_HILOGE("agent is nullptr!"); + return ErrorCode::ERROR_IME_NOT_STARTED; + } + agents.emplace_back(data->agent); + BindImeInfo imeInfo = { data->pid, data->ime.first }; + imeInfos.emplace_back(imeInfo); + } return ErrorCode::NO_ERROR; } +int32_t PerUserSession::SendAllReadyImeToClient( + std::shared_ptr data, const std::shared_ptr &clientInfo) +{ + if (data == nullptr) { + IMSA_HILOGW("no need to send"); + return ErrorCode::NO_ERROR; + } + + std::vector> imeDatas = { data }; + if (!data->IsImeMirror()) { + auto imeMirrorData = GetReadyImeData(ImeType::IME_MIRROR); + if (imeMirrorData != nullptr) { + imeDatas.push_back(imeMirrorData); + } + } + + int32_t finalResult = ErrorCode::NO_ERROR; + int32_t ret; + for (const auto &dataItem : imeDatas) { + BindImeInfo imeInfo; + imeInfo.pid = dataItem->pid; + imeInfo.bundleName = dataItem->ime.first; + ret = clientInfo->client->OnInputReady(dataItem->agent, imeInfo); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("OnInputReady failed, ret = %{public}d", ret); + } + if (!dataItem->IsImeMirror()) { + finalResult = ret; + } + } + return finalResult; +} + int32_t PerUserSession::BindClientWithIme( const std::shared_ptr &clientInfo, ImeType type, bool isBindFromClient, uint64_t displayId) { @@ -587,7 +633,7 @@ int32_t PerUserSession::BindClientWithIme( } IMSA_HILOGD("imeType: %{public}d, isShowKeyboard: %{public}d, isBindFromClient: %{public}d.", type, clientInfo->isShowKeyboard, isBindFromClient); - auto data = GetValidIme(type); + auto data = GetReadyImeData(type); if (data == nullptr) { return ErrorCode::ERROR_IME_NOT_STARTED; } @@ -598,30 +644,31 @@ int32_t PerUserSession::BindClientWithIme( return ret; } } - auto ret = RequestIme(data, RequestType::START_INPUT, - [&data, &clientInfo, isBindFromClient]() { - InputClientInfoInner inputClientInfoInner = - InputMethodTools::GetInstance().InputClientInfoToInner(const_cast(*clientInfo)); - return data->core->StartInput(inputClientInfoInner, isBindFromClient); - }); + InputClientInfoInner inputClientInfoInner = + InputMethodTools::GetInstance().InputClientInfoToInner(*clientInfo); + auto ret = RequestAllIme( + data, RequestType::START_INPUT, [&inputClientInfoInner, isBindFromClient](const sptr &core) { + return core->StartInput(inputClientInfoInner, isBindFromClient); + }); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("start input failed, ret: %{public}d!", ret); return ErrorCode::ERROR_IME_START_INPUT_FAILED; } if (type == ImeType::IME) { - InputMethodSysEvent::GetInstance().ReportImeState(ImeState::BIND, data->pid, - ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName); + InputMethodSysEvent::GetInstance().ReportImeState( + ImeState::BIND, data->pid, ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName); Memory::MemMgrClient::GetInstance().SetCritical(getpid(), true, INPUT_METHOD_SYSTEM_ABILITY_ID); } if (!isBindFromClient) { - ret = clientInfo->client->OnInputReady(data->agent, data->pid, data->ime.first); + ret = SendAllReadyImeToClient(data, clientInfo); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("start client input failed, ret: %{public}d!", ret); return ErrorCode::ERROR_IMSA_CLIENT_INPUT_READY_FAILED; } } clientGroup->UpdateClientInfo(clientInfo->client->AsObject(), { { UpdateFlag::BINDIMETYPE, type }, - { UpdateFlag::ISSHOWKEYBOARD, clientInfo->isShowKeyboard }, { UpdateFlag::STATE, ClientState::ACTIVE } }); + { UpdateFlag::ISSHOWKEYBOARD, clientInfo->isShowKeyboard }, { UpdateFlag::STATE, ClientState::ACTIVE }, + { UpdateFlag::BIND_IME_PID, data->pid} }); ReplaceCurrentClient(clientInfo->client, clientGroup); if (clientInfo->isShowKeyboard) { clientGroup->NotifyInputStartToClients( @@ -675,13 +722,14 @@ void PerUserSession::StopImeInput(ImeType currentType, const sptr if (data == nullptr) { return; } - auto ret = RequestIme(data, RequestType::STOP_INPUT, [&data, ¤tChannel, sessionId]() { - return data->core->StopInput(currentChannel, sessionId); - }); + auto ret = + RequestAllIme(data, RequestType::STOP_INPUT, [¤tChannel, sessionId](const sptr &core) { + return core->StopInput(currentChannel, sessionId); + }); IMSA_HILOGI("stop ime input, ret: %{public}d.", ret); if (ret == ErrorCode::NO_ERROR && currentType == ImeType::IME) { - InputMethodSysEvent::GetInstance().ReportImeState(ImeState::UNBIND, data->pid, - ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName); + InputMethodSysEvent::GetInstance().ReportImeState( + ImeState::UNBIND, data->pid, ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName); Memory::MemMgrClient::GetInstance().SetCritical(getpid(), false, INPUT_METHOD_SYSTEM_ABILITY_ID); } if (currentType == ImeType::IME) { @@ -696,8 +744,9 @@ void PerUserSession::OnSecurityChange(int32_t security) IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME); return; } - auto ret = - RequestIme(data, RequestType::NORMAL, [&data, security] { return data->core->OnSecurityChange(security); }); + auto ret = RequestIme(data, RequestType::NORMAL, [&data, security] { + return data->core->OnSecurityChange(security); + }); IMSA_HILOGD("on security change, ret: %{public}d.", ret); } @@ -729,11 +778,21 @@ int32_t PerUserSession::OnSetCoreAndAgent(const sptr &core, co return ErrorCode::NO_ERROR; } -int32_t PerUserSession::OnRegisterProxyIme(const sptr &core, const sptr &agent) +int32_t PerUserSession::OnRegisterProxyIme(const sptr &core, const sptr &agent, + int32_t pid) { IMSA_HILOGD("start."); + auto result = IsRequestOverLimit(TimeLimitType::PROXY_IME_LIMIT, PROXY_REGISTERATION_TIME_INTERVAL, MAX_REGISTRATIONS_NUM); + if (result != ErrorCode::NO_ERROR) { + IMSA_HILOGI("frequent calls, service is busy."); + return result; + } auto imeType = ImeType::PROXY_IME; - auto ret = AddImeData(imeType, core, agent, IPCSkeleton::GetCallingPid()); + auto lastImeData = GetImeData(imeType); + if (lastImeData != nullptr && lastImeData->core!=nullptr && lastImeData->core->AsObject() != core->AsObject()) { + lastImeData->core->NotifyPreemption(); + } + auto ret = AddImeData(imeType, core, agent, pid); if (ret != ErrorCode::NO_ERROR) { return ret; } @@ -800,7 +859,7 @@ int32_t PerUserSession::OnUnregisterProxyIme(uint64_t displayId) if (displayId != agentDisplayId_.load()) { return false; } - RemoveImeData(ImeType::PROXY_AGENT_IME, false); + RemoveImeData(ImeType::PROXY_AGENT_IME); { std::lock_guard lock(virtualDisplayLock_); virtualScreenDisplayId_.erase(displayId); @@ -814,32 +873,54 @@ int32_t PerUserSession::OnUnregisterProxyIme(uint64_t displayId) return ErrorCode::NO_ERROR; } -int32_t PerUserSession::OnUnRegisteredProxyIme(UnRegisteredType type, const sptr &core) +int32_t PerUserSession::OnUnRegisteredProxyIme(UnRegisteredType type, const sptr &core, pid_t pid) { IMSA_HILOGD("proxy unregister type: %{public}d.", type); // 0: stop proxy 1: switch to ima if (type == UnRegisteredType::REMOVE_PROXY_IME) { - RemoveIme(core, ImeType::PROXY_IME); + RemoveIme(ImeType::PROXY_IME, pid); return ErrorCode::NO_ERROR; } - if (type == UnRegisteredType::SWITCH_PROXY_IME_TO_IME) { - auto clientInfo = GetCurrentClientInfo(); - if (clientInfo == nullptr) { - IMSA_HILOGE("not found current client!"); - return ErrorCode::ERROR_CLIENT_NOT_BOUND; - } - if (clientInfo->bindImeType == ImeType::PROXY_IME) { - UnBindClientWithIme(clientInfo, { .sessionId = 0 }); - } - InputClientInfo infoTemp; - infoTemp.isShowKeyboard = true; - infoTemp.client = clientInfo->client; - infoTemp.channel = clientInfo->channel; - return BindClientWithIme(std::make_shared(infoTemp), ImeType::IME); - } return ErrorCode::ERROR_BAD_PARAMETERS; } +int32_t PerUserSession::OnBindImeMirror(const sptr &core, const sptr &agent) +{ + IMSA_HILOGI("[ImeMirrorTag]star"); + auto imeType = ImeType::IME_MIRROR; + auto ret = AddImeData(imeType, core, agent, IPCSkeleton::GetCallingPid()); + if (ret != ErrorCode::NO_ERROR) { + return ret; + } + + auto clientInfo = GetCurrentClientInfo(); + if (clientInfo != nullptr) { + BindClientWithIme(clientInfo, imeType); + } + return ErrorCode::NO_ERROR; +} +int32_t PerUserSession::OnUnBindImeMirror() +{ + IMSA_HILOGD("[ImeMirrorTag]start"); + auto clientInfo = GetCurrentClientInfo(); + if (clientInfo == nullptr) { + RemoveImeData(ImeType::IME_MIRROR); + IMSA_HILOGD("[ImeMirrorTag]no current client"); + return ErrorCode::NO_ERROR; + } + + auto data = GetReadyImeData(ImeType::IME_MIRROR); + if (data == nullptr) { + IMSA_HILOGD("[ImeMirrorTag]no ime mirror"); + return ErrorCode::NO_ERROR; + } + + clientInfo->client->OnImeMirrorStop(data->agent); + StopImeInput(ImeType::IME_MIRROR, clientInfo->channel, 0); + RemoveImeData(ImeType::IME_MIRROR); + return ErrorCode::NO_ERROR; +} + int32_t PerUserSession::InitInputControlChannel() { IMSA_HILOGD("PerUserSession::InitInputControlChannel start."); @@ -853,8 +934,9 @@ int32_t PerUserSession::InitInputControlChannel() IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME); return ErrorCode::ERROR_IME_NOT_STARTED; } - return RequestIme(data, RequestType::NORMAL, - [&data, &inputControlChannel] { return data->core->InitInputControlChannel(inputControlChannel); }); + return RequestIme(data, RequestType::NORMAL, [&data, &inputControlChannel] { + return data->core->InitInputControlChannel(inputControlChannel); + }); } bool PerUserSession::IsLargeMemoryStateNeed() @@ -872,12 +954,8 @@ void PerUserSession::StartImeInImeDied() IMSA_HILOGD("StartImeInImeDied."); { std::lock_guard lock(resetLock); - auto now = time(nullptr); - if (difftime(now, manager.last) > IME_RESET_TIME_OUT) { - manager = { 0, now }; - } - ++manager.num; - if (manager.num > MAX_RESTART_NUM) { + auto result = IsRequestOverLimit(TimeLimitType::IME_LIMIT, IME_RESET_TIME_OUT, MAX_RESTART_NUM); + if (result != ErrorCode::NO_ERROR) { return; } } @@ -953,18 +1031,31 @@ int32_t PerUserSession::AddImeData(ImeType type, sptr core, sp IMSA_HILOGE("core or agent is nullptr!"); return ErrorCode::ERROR_NULL_POINTER; } + std::lock_guard lock(imeDataLock_); + auto &imeDataList = imeData_[type]; + auto iter = std::find_if( + imeDataList.begin(), imeDataList.end(), [&core, this](const std::shared_ptr &existingImeData) { + return existingImeData != nullptr && core->AsObject() == existingImeData->core->AsObject(); + }); + if (iter != imeDataList.end()) { + auto imeData = *iter; + imeDataList.erase(iter); + IMSA_HILOGI("%{public}s preempt again!", imeData->ime.first.c_str()); + imeDataList.push_back(imeData); + return ErrorCode::NO_ERROR; + } sptr deathRecipient = new (std::nothrow) InputDeathRecipient(); if (deathRecipient == nullptr) { IMSA_HILOGE("failed to new deathRecipient!"); return ErrorCode::ERROR_NULL_POINTER; } - deathRecipient->SetDeathRecipient([this, core, type](const wptr &) { this->OnImeDied(core, type); }); + deathRecipient->SetDeathRecipient( + [this, core, type, pid](const wptr &) { this->OnImeDied(core, type, pid); }); auto coreObject = core->AsObject(); if (coreObject == nullptr || (coreObject->IsProxyObject() && !coreObject->AddDeathRecipient(deathRecipient))) { IMSA_HILOGE("failed to add death recipient!"); return ErrorCode::ERROR_ADD_DEATH_RECIPIENT_FAILED; } - std::lock_guard lock(imeDataLock_); auto imeData = std::make_shared(core, agent, deathRecipient, pid); imeData->imeStatus = ImeStatus::READY; imeData->ime.first = "proxyIme"; @@ -976,36 +1067,61 @@ int32_t PerUserSession::AddImeData(ImeType type, sptr core, sp } else if (type == ImeType::PROXY_AGENT_IME) { imeData->ime.first.append(GET_NAME(_PROXY_AGENT_IME)); } - imeData_.insert_or_assign(type, imeData); + imeDataList.push_back(imeData); IMSA_HILOGI("add imeData with type: %{public}d name: %{public}s end", type, imeData->ime.first.c_str()); return ErrorCode::NO_ERROR; } std::shared_ptr PerUserSession::GetReadyImeData(ImeType type) { - std::lock_guard lock(imeDataLock_); - auto it = imeData_.find(type); - if (it == imeData_.end()) { + auto data = GetImeData(type); + if (data == nullptr || data->imeStatus != ImeStatus::READY) { return nullptr; } - if (it->second->imeStatus != ImeStatus::READY) { - return nullptr; + return data; +} + +std::vector> PerUserSession::GetAllReadyImeData(ImeType type) +{ + auto typeData = GetReadyImeData(type); + if (typeData == nullptr) { + return {}; } - return it->second; + + if (type == ImeType::IME_MIRROR) { + return { typeData }; + } + + auto imeMirrorData = GetReadyImeData(ImeType::IME_MIRROR); + if (imeMirrorData == nullptr) { + return { typeData }; + } + + return { typeData, imeMirrorData }; } -std::shared_ptr PerUserSession::GetValidIme(ImeType type) +void PerUserSession::RemoveImeData(pid_t pid) { - auto data = GetReadyImeData(type); - if (data != nullptr || type != ImeType::IME) { - return data; + std::lock_guard lock(imeDataLock_); + for (auto itType = imeData_.begin(); itType != imeData_.end(); ++itType) { + auto &imeDataList = itType->second; + auto iter = std::find_if(imeDataList.begin(), imeDataList.end(), [pid](const std::shared_ptr& imeDataTmp) { + return imeDataTmp != nullptr && imeDataTmp->pid == pid; + }); + if (iter != imeDataList.end()) { + if ((*iter)->core != nullptr && (*iter)->core->AsObject() != nullptr) { + (*iter)->core->AsObject()->RemoveDeathRecipient((*iter)->deathRecipient); + } + imeDataList.erase(iter); + } + if (imeDataList.empty()) { + imeData_.erase(itType); + break; + } } - IMSA_HILOGI("current ime is empty, try to restart it."); - StartCurrentIme(); - return GetReadyImeData(type); } -void PerUserSession::RemoveImeData(ImeType type, bool isImeDied) +void PerUserSession::RemoveImeData(ImeType type) { std::lock_guard lock(imeDataLock_); auto it = imeData_.find(type); @@ -1013,8 +1129,12 @@ void PerUserSession::RemoveImeData(ImeType type, bool isImeDied) IMSA_HILOGD("imeData not found."); return; } - auto data = it->second; - if (isImeDied && data->core != nullptr && data->core->AsObject() != nullptr) { + auto& dataList = it->second; + if (dataList.empty() || dataList.back() == nullptr) { + return; + } + for (auto iter = dataList.begin(); iter != dataList.end(); ++iter) { + const auto& data = *iter; data->core->AsObject()->RemoveDeathRecipient(data->deathRecipient); } imeData_.erase(type); @@ -1473,12 +1593,14 @@ bool PerUserSession::IsImeBindTypeChanged(ImeType bindImeType) int32_t PerUserSession::SwitchSubtype(const SubProperty &subProperty) { - auto data = GetValidIme(ImeType::IME); - if (data == nullptr) { + auto data = GetReadyImeData(ImeType::IME); + if (data == nullptr || data->core == nullptr) { IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME); return ErrorCode::ERROR_IME_NOT_STARTED; } - return RequestIme(data, RequestType::NORMAL, [&data, &subProperty] { return data->core->SetSubtype(subProperty); }); + return RequestIme(data, RequestType::NORMAL, [&data, &subProperty] { + return data->core->SetSubtype(subProperty); + }); } int32_t PerUserSession::SwitchSubtypeWithoutStartIme(const SubProperty &subProperty) @@ -1488,20 +1610,22 @@ int32_t PerUserSession::SwitchSubtypeWithoutStartIme(const SubProperty &subPrope IMSA_HILOGE("ime: %{public}d is not exist, or core is nullptr.", ImeType::IME); return ErrorCode::ERROR_IME_NOT_STARTED; } - return RequestIme(data, RequestType::NORMAL, - [&data, &subProperty] { return data->core->SetSubtype(subProperty); }); + return RequestIme(data, RequestType::NORMAL, [&data, &subProperty] { + return data->core->SetSubtype(subProperty); + }); } int32_t PerUserSession::SetInputType() { InputType inputType = InputTypeManager::GetInstance().GetCurrentInputType(); - auto data = GetValidIme(ImeType::IME); + auto data = GetReadyImeData(ImeType::IME); if (data == nullptr) { IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME); return ErrorCode::ERROR_IME_NOT_STARTED; } - return RequestIme(data, RequestType::NORMAL, - [&data, &inputType] { return data->core->OnSetInputType(static_cast(inputType)); }); + return RequestIme(data, RequestType::NORMAL, [&data, &inputType] { + return data->core->OnSetInputType(static_cast(inputType)); + }); } bool PerUserSession::IsBoundToClient(uint64_t displayId) @@ -1574,8 +1698,9 @@ int32_t PerUserSession::IsPanelShown(const PanelInfo &panelInfo, bool &isShown) IMSA_HILOGE("ime not started!"); return ErrorCode::ERROR_IME_NOT_STARTED; } - return RequestIme(ime, RequestType::NORMAL, - [&ime, &panelInfo, &isShown] { return ime->core->IsPanelShown(panelInfo, isShown); }); + return RequestIme(ime, RequestType::NORMAL, [&ime, &panelInfo, &isShown] { + return ime->core->IsPanelShown(panelInfo, isShown); + }); } bool PerUserSession::CheckSecurityMode() @@ -1589,7 +1714,7 @@ bool PerUserSession::CheckSecurityMode() int32_t PerUserSession::RequestIme(const std::shared_ptr &data, RequestType type, const IpcExec &exec) { - if (IsProxyImeEnable()) { + if (IsProxyImeEnable() || data->IsImeMirror()) { IMSA_HILOGD("proxy enable."); return exec(); } @@ -1607,6 +1732,40 @@ int32_t PerUserSession::RequestIme(const std::shared_ptr &data, Request return ret; } +int32_t PerUserSession::RequestAllIme( + const std::shared_ptr data, RequestType reqType, const CoreMethod &method) +{ + if (data == nullptr) { + IMSA_HILOGW("no need to request, type:%{public}d}", reqType); + return ErrorCode::NO_ERROR; + } + + std::vector> dataArray = { data }; + + if (!data->IsImeMirror()) { + auto imeMirrorData = GetReadyImeData(ImeType::IME_MIRROR); + if (imeMirrorData != nullptr) { + dataArray.push_back(imeMirrorData); + } + } + + int32_t finalResult = ErrorCode::NO_ERROR; + for (const auto &dataItem : dataArray) { + int32_t ret = RequestIme(dataItem, reqType, [&dataItem, &method]() { + return method(dataItem->core); // Execute the specified core method + }); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE( + "request ime failed, ret: %{public}d, IsImeMirror:%{public}d", ret, dataItem->IsImeMirror()); + } + // IME_MIRROR not effect overall result + if (!dataItem->IsImeMirror()) { + finalResult = ret; + } + } + return finalResult; +} + int32_t PerUserSession::OnConnectSystemCmd(const sptr &channel, sptr &agent) { auto data = GetReadyImeData(ImeType::IME); @@ -1614,8 +1773,9 @@ int32_t PerUserSession::OnConnectSystemCmd(const sptr &channel, s IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME); return ErrorCode::ERROR_IME_NOT_STARTED; } - auto ret = RequestIme(data, RequestType::NORMAL, - [&data, &channel, &agent] { return data->core->OnConnectSystemCmd(channel, agent); }); + auto ret = RequestIme(data, RequestType::NORMAL, [&data, &channel, &agent] { + return data->core->OnConnectSystemCmd(channel, agent); + }); IMSA_HILOGD("on connect systemCmd, ret: %{public}d.", ret); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("bind failed, ret: %{public}d!", ret); @@ -1795,7 +1955,7 @@ int32_t PerUserSession::InitImeData( if (imeNativeCfg != nullptr && !imeNativeCfg->imeExtendInfo.privateCommand.empty()) { imeData->imeExtendInfo.privateCommand = imeNativeCfg->imeExtendInfo.privateCommand; } - imeData_.insert({ ImeType::IME, imeData }); + imeData_.insert_or_assign(ImeType::IME, std::vector>{imeData}); return ErrorCode::NO_ERROR; } @@ -1810,10 +1970,14 @@ int32_t PerUserSession::UpdateImeData(sptr core, sptrsecond->core = core; - it->second->agent = agent; - it->second->pid = pid; - it->second->imeStateManager = ImeStateManagerFactory::GetInstance().CreateImeStateManager(pid, [this] { + auto& dataList = it->second; + if (dataList.empty() || dataList.back() == nullptr) { + return ErrorCode::ERROR_NULL_POINTER; + } + dataList.back()->core = core; + dataList.back()->agent = agent; + dataList.back()->pid = pid; + dataList.back()->imeStateManager = ImeStateManagerFactory::GetInstance().CreateImeStateManager(pid, [this] { StopCurrentIme(); }); sptr deathRecipient = new (std::nothrow) InputDeathRecipient(); @@ -1822,13 +1986,14 @@ int32_t PerUserSession::UpdateImeData(sptr core, sptrSetDeathRecipient([this, core, type](const wptr &) { this->OnImeDied(core, type); }); + deathRecipient->SetDeathRecipient( + [this, core, type, pid](const wptr &) { this->OnImeDied(core, type, pid); }); auto coreObject = core->AsObject(); if (coreObject == nullptr || (coreObject->IsProxyObject() && !coreObject->AddDeathRecipient(deathRecipient))) { IMSA_HILOGE("failed to add death recipient!"); return ErrorCode::ERROR_ADD_DEATH_RECIPIENT_FAILED; } - it->second->deathRecipient = deathRecipient; + dataList.back()->deathRecipient = deathRecipient; return ErrorCode::NO_ERROR; } @@ -1839,7 +2004,11 @@ int32_t PerUserSession::InitConnect(pid_t pid) if (it == imeData_.end()) { return ErrorCode::ERROR_NULL_POINTER; } - it->second->pid = pid; + auto& dataList = it->second; + if (dataList.empty() || dataList.back() == nullptr) { + return ErrorCode::ERROR_NULL_POINTER; + } + dataList.back()->pid = pid; return ErrorCode::NO_ERROR; } @@ -1850,7 +2019,25 @@ std::shared_ptr PerUserSession::GetImeData(ImeType type) if (it == imeData_.end()) { return nullptr; } - return it->second; + auto& dataList = it->second; + if (dataList.empty() || dataList.back() == nullptr) { + return nullptr; + } + return dataList.back(); +} + +std::shared_ptr PerUserSession::GetImeData(pid_t pid) +{ + std::lock_guard lock(imeDataLock_); + for (const auto &[imeType, imeDataList] : imeData_) { + auto iter = std::find_if(imeDataList.begin(), imeDataList.end(), [pid](const std::shared_ptr& imeDataTmp) { + return imeDataTmp != nullptr && imeDataTmp->pid == pid; + }); + if (iter != imeDataList.end()) { + return *iter; + } + } + return nullptr; } int32_t PerUserSession::StartIme(const std::shared_ptr &ime, bool isStopCurrentIme) @@ -1884,12 +2071,16 @@ ImeAction PerUserSession::GetImeAction(ImeEvent action) if (it == imeData_.end()) { return ImeAction::DO_ACTION_IN_NULL_IME_DATA; } - auto iter = imeEventConverter_.find({ it->second->imeStatus, action }); + auto& dataList = it->second; + if (dataList.empty() || dataList.back() == nullptr) { + return ImeAction::DO_ACTION_IN_NULL_IME_DATA; + } + auto iter = imeEventConverter_.find({ dataList.back()->imeStatus, action }); if (iter == imeEventConverter_.end()) { IMSA_HILOGE("abnormal!"); return ImeAction::DO_ACTION_IN_IME_EVENT_CONVERT_FAILED; } - it->second->imeStatus = iter->second.first; + dataList.back()->imeStatus = iter->second.first; return iter->second.second; } @@ -1987,9 +2178,9 @@ int32_t PerUserSession::StopReadyCurrentIme() IMSA_HILOGE("core is nullptr!"); return ForceStopCurrentIme(); } - auto ret = RequestIme(imeData, RequestType::NORMAL, [&imeData] { + auto ret = RequestAllIme(imeData, RequestType::NORMAL, [](const sptr &core) { // failed when register onInputStop after SetCoreAndAgent - return imeData->core->StopInputService(true); + return core->StopInputService(true); }); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("StopInputService failed."); @@ -2010,7 +2201,7 @@ int32_t PerUserSession::ForceStopCurrentIme(bool isNeedWait) } if (!ImeInfoInquirer::GetInstance().IsRunningIme(userId_, imeData->ime.first)) { IMSA_HILOGW("[%{public}s, %{public}s] already stop.", imeData->ime.first.c_str(), imeData->ime.second.c_str()); - RemoveImeData(ImeType::IME, true); + RemoveImeData(ImeType::IME); return ErrorCode::NO_ERROR; } auto clientInfo = GetCurrentClientInfo(); @@ -2035,7 +2226,7 @@ int32_t PerUserSession::ForceStopCurrentIme(bool isNeedWait) IMSA_HILOGW("stop [%{public}s, %{public}s] timeout.", imeData->ime.first.c_str(), imeData->ime.second.c_str()); return ErrorCode::ERROR_IMSA_FORCE_STOP_IME_TIMEOUT; } - RemoveImeData(ImeType::IME, true); + RemoveImeData(ImeType::IME); return ErrorCode::NO_ERROR; } @@ -2138,7 +2329,7 @@ bool PerUserSession::GetInputTypeToStart(std::shared_ptr &imeToSta return true; } -void PerUserSession::HandleImeBindTypeChanged( +void PerUserSession::HandleBindImeChanged( InputClientInfo &newClientInfo, const std::shared_ptr &clientGroup) { /* isClientInactive: true: represent the oldClientInfo is inactiveClient's @@ -2162,6 +2353,9 @@ void PerUserSession::HandleImeBindTypeChanged( if (oldClientInfo == nullptr) { return; } + if (IsSameClient(newClientInfo.client, oldClientInfo->client) && newClientInfo.pid != oldClientInfo->pid) { + newClientInfo.isNotifyInputStart = true; + } if (!IsImeBindTypeChanged(oldClientInfo->bindImeType)) { return; } @@ -2174,9 +2368,6 @@ void PerUserSession::HandleImeBindTypeChanged( } } IMSA_HILOGD("isClientInactive: %{public}d!", isClientInactive); - if (IsSameClient(newClientInfo.client, oldClientInfo->client)) { - newClientInfo.isNotifyInputStart = true; - } if (isClientInactive) { StopImeInput(oldClientInfo->bindImeType, oldClientInfo->channel, 0); return; @@ -2244,7 +2435,7 @@ std::shared_ptr PerUserSession::GetClientGroup(sptr std::shared_ptr PerUserSession::GetClientGroup(ImeType type) { - if (type == ImeType::IME || type == ImeType::PROXY_IME) { + if (type == ImeType::IME || type == ImeType::PROXY_IME || type == ImeType::IME_MIRROR) { return GetClientGroup(DEFAULT_DISPLAY_ID); } auto agentDisplayId = agentDisplayId_.load(); @@ -2301,7 +2492,7 @@ int32_t PerUserSession::NotifyCallingDisplayChanged(uint64_t displayId) IMSA_HILOGD("not default display"); return ErrorCode::NO_ERROR; } - auto data = GetValidIme(ImeType::IME); + auto data = GetReadyImeData(ImeType::IME); if (data == nullptr) { IMSA_HILOGE("ime is nullptr!"); return ErrorCode::ERROR_IME_NOT_STARTED; @@ -2414,8 +2605,7 @@ int32_t PerUserSession::SendPrivateData(const std::unordered_mapcore->OnSendPrivateData(value); }); @@ -2630,5 +2820,20 @@ void PerUserSession::ClearImeConnection(const sptr &c IMSA_HILOGI("clear imeConnection."); connection_ = nullptr; } + +int32_t PerUserSession::IsRequestOverLimit(TimeLimitType timeLimitType, int32_t resetTimeOut, int32_t restartNum) +{ + std::lock_guard lock(resetLock); + auto now = time(nullptr); + auto& manager = managers_[timeLimitType]; + if (difftime(now, manager.last) > resetTimeOut) { + manager = {0, now}; + } + ++manager.num; + if (manager.num > restartNum) { + return ErrorCode::ERROR_REQUEST_RATE_EXCEEDED; + } + return ErrorCode::NO_ERROR; +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/test/fuzztest/perusersession_fuzzer/perusersession_fuzzer.cpp b/test/fuzztest/perusersession_fuzzer/perusersession_fuzzer.cpp index 61e21da48..cc2e54622 100644 --- a/test/fuzztest/perusersession_fuzzer/perusersession_fuzzer.cpp +++ b/test/fuzztest/perusersession_fuzzer/perusersession_fuzzer.cpp @@ -93,10 +93,10 @@ bool FuzzPerUserSession(const uint8_t *rawData, size_t size) auto agent = iface_cast(agentStub); static std::shared_ptr userSessions = std::make_shared(MAIN_USER_ID); - userSessions->OnRegisterProxyIme(core, agent->AsObject()); + userSessions->OnRegisterProxyIme(core, agent->AsObject(), -1); FuzzedDataProvider provider(rawData, size); int32_t type = provider.ConsumeIntegral(); - userSessions->OnUnRegisteredProxyIme(static_cast(type), core); + userSessions->OnUnRegisteredProxyIme(static_cast(type), core, -1); userSessions->IsProxyImeEnable(); userSessions->OnPrepareInput(clientInfo); diff --git a/test/unittest/cpp_test/BUILD.gn b/test/unittest/cpp_test/BUILD.gn index 22231f939..26b76b8c1 100644 --- a/test/unittest/cpp_test/BUILD.gn +++ b/test/unittest/cpp_test/BUILD.gn @@ -932,7 +932,9 @@ ohos_unittest("ImeProxyTest") { "${inputmethod_path}/interfaces/inner_api/inputmethod_controller:input_client_stub", "${inputmethod_path}/interfaces/inner_api/inputmethod_controller:input_method_agent_proxy", "${inputmethod_path}/interfaces/inner_api/inputmethod_controller:inputmethod_client_static", - "${inputmethod_path}/services:inputmethod_service", + "${inputmethod_path}/services/adapter/settings_data_provider:settings_data_static", + "${inputmethod_path}/services:inputmethod_service_static", + "${inputmethod_path}/services/json:imf_json_static", "${inputmethod_path}/test/common:inputmethod_test_common", "${inputmethod_path}/test/unittest/cpp_test/common:inputmethod_tdd_util", "${inputmethod_path}/test/unittest/resource/bundle_dependencies/editorBox:editorBox", @@ -948,6 +950,9 @@ ohos_unittest("ImeProxyTest") { "access_token:libaccesstoken_sdk", "bundle_framework:appexecfwk_core", "c_utils:utils", + "cJSON:cjson", + "data_share:datashare_common", + "data_share:datashare_consumer", "googletest:gtest_main", "graphic_2d:librender_service_client", "graphic_2d:window_animation", diff --git a/test/unittest/cpp_test/src/ime_proxy_test.cpp b/test/unittest/cpp_test/src/ime_proxy_test.cpp index 72cfb645b..4fc0092ee 100644 --- a/test/unittest/cpp_test/src/ime_proxy_test.cpp +++ b/test/unittest/cpp_test/src/ime_proxy_test.cpp @@ -14,8 +14,10 @@ */ #define private public +#define protected public #include "input_method_ability.h" #include "task_manager.h" +#include "ime_info_inquirer.h" #undef private #include @@ -380,8 +382,6 @@ HWTEST_F(ImeProxyTest, UnRegisteredProxyNotInBind_switch_009, TestSize.Level1) InputMethodEngineListenerImpl::isEnable_ = true; auto ret = InputMethodAbilityInterface::GetInstance().RegisteredProxy(); EXPECT_EQ(ret, ErrorCode::NO_ERROR); - ret = InputMethodAbilityInterface::GetInstance().UnRegisteredProxy(UnRegisteredType::SWITCH_PROXY_IME_TO_IME); - EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_BOUND); } /** @@ -405,10 +405,6 @@ HWTEST_F(ImeProxyTest, UnRegisteredProxyInProxyBind_switch_010, TestSize.Level1) ImeSettingListenerTestImpl::ResetParam(); InputMethodEngineListenerImpl::ResetParam(); - ret = InputMethodAbilityInterface::GetInstance().UnRegisteredProxy(UnRegisteredType::SWITCH_PROXY_IME_TO_IME); - EXPECT_EQ(ret, ErrorCode::NO_ERROR); - EXPECT_TRUE(InputMethodEngineListenerImpl::WaitInputFinish()); - EXPECT_TRUE(ImeSettingListenerTestImpl::WaitPanelShow()); Close(false); TddUtil::GetUnfocused(); } @@ -674,14 +670,32 @@ HWTEST_F(ImeProxyTest, DiscardTypingTextTest, TestSize.Level0) * @tc.desc: Test RegisterProxyIme * @tc.type: FUNC */ -HWTEST_F(ImeProxyTest, RegisterProxyImeTest, TestSize.Level0) +HWTEST_F(ImeProxyTest, RegisterProxyImeTest001, TestSize.Level0) { - IMSA_HILOGI("ImeProxyTest::TestRegisterProxyImeTest"); + IMSA_HILOGI("ImeProxyTest::TestRegisterProxyImeTest001 start"); uint64_t displayId = -1; auto ret = InputMethodAbilityInterface::GetInstance().RegisterProxyIme(displayId); EXPECT_NE(ret, ErrorCode::NO_ERROR); ret = InputMethodAbilityInterface::GetInstance().UnregisterProxyIme(displayId); EXPECT_NE(ret, ErrorCode::NO_ERROR); } + +/** + * @tc.name: TestRegisterProxyIme + * @tc.desc: Test RegisterProxyIme failed + * @tc.type: FUNC + */ +HWTEST_F(ImeProxyTest, RegisterProxyImeTest002, TestSize.Level0) +{ + IMSA_HILOGI("ImeProxyTest::RegisterProxyImeTest002 start"); + uint64_t displayId = 0; + auto ret = InputMethodAbilityInterface::GetInstance().RegisterProxyIme(displayId); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + std::shared_ptr property = imc_->GetCurrentInputMethod(); + ASSERT_TRUE(property != nullptr); + EXPECT_EQ(property->name, "com.example.testIme"); + ret = InputMethodAbilityInterface::GetInstance().UnregisterProxyIme(displayId); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); +} } // namespace MiscServices } // namespace OHOS diff --git a/test/unittest/cpp_test/src/input_method_controller_test.cpp b/test/unittest/cpp_test/src/input_method_controller_test.cpp index ec1ed4cfc..465c6733f 100644 --- a/test/unittest/cpp_test/src/input_method_controller_test.cpp +++ b/test/unittest/cpp_test/src/input_method_controller_test.cpp @@ -2158,7 +2158,7 @@ HWTEST_F(InputMethodControllerTest, TestClientNullptr, TestSize.Level0) auto ret = sessionTemp->OnUpdateListenEventFlag(clientInfo); EXPECT_EQ(ret, ErrorCode::ERROR_NULL_POINTER); - sessionTemp->HandleImeBindTypeChanged(clientInfo, nullptr); + sessionTemp->HandleBindImeChanged(clientInfo, nullptr); std::shared_ptr ptr = nullptr; sessionTemp->ClearRequestKeyboardReason(ptr); auto info = std::make_shared(); diff --git a/test/unittest/cpp_test/src/input_method_private_member_test.cpp b/test/unittest/cpp_test/src/input_method_private_member_test.cpp index eceb33e34..a871a3c9b 100644 --- a/test/unittest/cpp_test/src/input_method_private_member_test.cpp +++ b/test/unittest/cpp_test/src/input_method_private_member_test.cpp @@ -369,10 +369,10 @@ HWTEST_F(InputMethodPrivateMemberTest, PerUserSessionParameterNullptr003, TestSi auto userSession = std::make_shared(MAIN_USER_ID); auto clientGroup = std::make_shared(DEFAULT_DISPLAY_ID, nullptr); userSession->OnClientDied(nullptr); - userSession->OnImeDied(nullptr, ImeType::IME); + userSession->OnImeDied(nullptr, ImeType::IME, IPCSkeleton::GetCallingPid()); bool isShowKeyboard = false; clientGroup->UpdateClientInfo(nullptr, { { UpdateFlag::ISSHOWKEYBOARD, isShowKeyboard } }); - int32_t ret = userSession->RemoveIme(nullptr, ImeType::IME); + int32_t ret = userSession->RemoveIme(ImeType::IME, IPCSkeleton::GetCallingPid()); EXPECT_EQ(ret, ErrorCode::ERROR_NULL_POINTER); } @@ -1173,11 +1173,8 @@ HWTEST_F(InputMethodPrivateMemberTest, TestOnUnRegisteredProxyIme, TestSize.Leve auto userSession = std::make_shared(MAIN_USER_ID); UnRegisteredType type = UnRegisteredType::REMOVE_PROXY_IME; const sptr core; - auto ret = userSession->OnUnRegisteredProxyIme(type, core); + auto ret = userSession->OnUnRegisteredProxyIme(type, core, IPCSkeleton::GetCallingPid()); EXPECT_EQ(ret, ErrorCode::NO_ERROR); - type = UnRegisteredType::SWITCH_PROXY_IME_TO_IME; - ret = userSession->OnUnRegisteredProxyIme(type, core); - EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_BOUND); userSession->clientGroupMap_.clear(); ret = userSession->RemoveAllCurrentClient(); EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NULL_POINTER); @@ -1748,7 +1745,9 @@ HWTEST_F(InputMethodPrivateMemberTest, SA_StartPreconfiguredDefaultIme, TestSize auto imeData1 = std::make_shared(nullptr, nullptr, nullptr, 100); imeData1->imeStatus = ImeStatus::READY; imeData1->ime = std::make_pair(bundleName, extName); - session.imeData_.insert_or_assign(ImeType::IME, imeData1); + std::vector> imeDataList; + imeDataList.push_back(imeData1); + session.imeData_.insert_or_assign(ImeType::IME, imeDataList); ImeInfoInquirer::GetInstance().systemConfig_.defaultInputMethod = bundleName + "/" + extName; auto [ret2, status2] = session.StartPreconfiguredDefaultIme(DEFAULT_DISPLAY_ID); EXPECT_EQ(status2, StartPreDefaultImeStatus::HAS_STARTED); @@ -1893,7 +1892,9 @@ HWTEST_F(InputMethodPrivateMemberTest, SA_SpecialSendPrivateData, TestSize.Level auto imeData1 = std::make_shared(nullptr, nullptr, nullptr, 100); imeData1->imeStatus = ImeStatus::READY; imeData1->ime = std::make_pair(bundleName, extName); - session.imeData_.insert_or_assign(ImeType::IME, imeData1); + std::vector> imeDataList; + imeDataList.push_back(imeData1); + session.imeData_.insert_or_assign(ImeType::IME, imeDataList); std::unordered_map privateCommand; // running ime same with pre default ime, send directly ImeInfoInquirer::GetInstance().systemConfig_.defaultInputMethod = bundleName + "/" + extName; @@ -1921,7 +1922,9 @@ HWTEST_F(InputMethodPrivateMemberTest, SA_CheckInputTypeOption, TestSize.Level0) auto imeData1 = std::make_shared(nullptr, nullptr, nullptr, 100); imeData1->imeStatus = ImeStatus::READY; imeData1->ime = std::make_pair(bundleName, extName); - session->imeData_.insert_or_assign(ImeType::IME, imeData1); + std::vector> imeDataList; + imeDataList.push_back(imeData1); + session->imeData_.insert_or_assign(ImeType::IME, imeDataList); UserSessionManager::GetInstance().userSessions_.insert_or_assign(MAIN_USER_ID, session); InputClientInfo info; // same textField, input type started @@ -2482,7 +2485,9 @@ HWTEST_F(InputMethodPrivateMemberTest, SA_RestoreCurrentImeSubType, TestSize.Lev auto imeData = std::make_shared(nullptr, nullptr, nullptr, 10); imeData->imeStatus = ImeStatus::READY; imeData->ime = std::make_pair(bundleName, extName); - session->imeData_.insert_or_assign(ImeType::IME, imeData); + std::vector> imeDataList; + imeDataList.push_back(imeData); + session->imeData_.insert_or_assign(ImeType::IME, imeDataList); ret = session->RestoreCurrentImeSubType(0); EXPECT_EQ(ret, ErrorCode::NO_ERROR); EXPECT_FALSE(InputTypeManager::GetInstance().isStarted_); @@ -2498,7 +2503,8 @@ HWTEST_F(InputMethodPrivateMemberTest, SA_RestoreCurrentImeSubType, TestSize.Lev InputTypeManager::GetInstance().isStarted_ = true; InputTypeManager::GetInstance().currentTypeIme_.bundleName = bundleName1; imeData->ime = std::make_pair(bundleName1, extName1); - session->imeData_.insert_or_assign(ImeType::IME, imeData); + imeDataList.push_back(imeData); + session->imeData_.insert_or_assign(ImeType::IME, imeDataList); ret = session->RestoreCurrentImeSubType(0); EXPECT_EQ(ret, ErrorCode::ERROR_IME_NOT_STARTED); EXPECT_FALSE(InputTypeManager::GetInstance().isStarted_); @@ -2598,7 +2604,9 @@ HWTEST_F(InputMethodPrivateMemberTest, SA_TryStartIme_001, TestSize.Level0) userSession->isBlockStartedByLowMem_ = true; auto imeData = std::make_shared(nullptr, nullptr, nullptr, 10); - userSession->imeData_.insert_or_assign(ImeType::IME, imeData); + std::vector> imeDataList; + imeDataList.push_back(imeData); + userSession->imeData_.insert_or_assign(ImeType::IME, imeDataList); ret = userSession->TryStartIme(); EXPECT_EQ(ret, ErrorCode::ERROR_IME_HAS_STARTED); @@ -2643,7 +2651,9 @@ HWTEST_F(InputMethodPrivateMemberTest, SA_TryDisconnectIme_001, TestSize.Level0) auto ret = userSession->TryDisconnectIme(); EXPECT_EQ(ret, ErrorCode::ERROR_IME_NOT_STARTED); auto imeData = std::make_shared(nullptr, nullptr, nullptr, 10); - userSession->imeData_.insert_or_assign(ImeType::IME, imeData); + std::vector> imeDataList; + imeDataList.push_back(imeData); + userSession->imeData_.insert_or_assign(ImeType::IME, imeDataList); userSession->attachingCount_ = 1; ret = userSession->TryDisconnectIme(); diff --git a/test/unittest/cpp_test/src/json_operate_test.cpp b/test/unittest/cpp_test/src/json_operate_test.cpp index bafd6b4a4..0d02043fd 100644 --- a/test/unittest/cpp_test/src/json_operate_test.cpp +++ b/test/unittest/cpp_test/src/json_operate_test.cpp @@ -411,5 +411,28 @@ HWTEST_F(JsonOperateTest, testIsDynamicStartIme, TestSize.Level1) instance.systemConfig_.dynamicStartImeValue = ""; instance.systemConfig_.dynamicStartImeSysParam = ""; } + +/** + * @tc.name: testImedataUidListParse + * @tc.desc: ImedataUidList Parse + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenyu + */ +HWTEST_F(JsonOperateTest, testImedataUidListParse, TestSize.Level1) +{ + IMSA_HILOGI("JsonOperateTest ImedataUidListParse START"); + ImeInfoInquirer::GetInstance().systemConfig_.proxyImeUidList.clear(); + ASSERT_EQ(ImeInfoInquirer::GetInstance().systemConfig_.proxyImeUidList.size(), 0); + auto ret = ImeInfoInquirer::GetInstance().IsVirtualProxyIme(0); + if (ImeInfoInquirer::GetInstance().systemConfig_.proxyImeUidList.size() != 0) { + ret = ImeInfoInquirer::GetInstance().IsVirtualProxyIme(0); + ASSERT_FALSE(ret); + ret = ImeInfoInquirer::GetInstance().IsVirtualProxyIme(5521); + ASSERT_TRUE(ret); + ret = ImeInfoInquirer::GetInstance().IsVirtualProxyIme(7101); + ASSERT_TRUE(ret); + } +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file -- Gitee From 13f6dccc7b79c3c480607d48064c2faa222bd412 Mon Sep 17 00:00:00 2001 From: hemenghao Date: Sun, 10 Aug 2025 15:15:25 +0800 Subject: [PATCH 2/2] =?UTF-8?q?daili=E5=A2=9E=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hemenghao --- .../include/tasks/task_imsa.h | 12 -- .../src/input_method_ability.cpp | 3 +- .../src/input_method_core_service_impl.cpp | 3 +- services/include/peruser_session.h | 2 + services/src/peruser_session.cpp | 97 ++++----- test/unittest/cpp_test/src/ime_proxy_test.cpp | 2 - .../src/input_method_private_member_test.cpp | 187 +++++++++++++++++- 7 files changed, 242 insertions(+), 64 deletions(-) diff --git a/frameworks/native/inputmethod_ability/include/tasks/task_imsa.h b/frameworks/native/inputmethod_ability/include/tasks/task_imsa.h index eef3666b3..819b623cd 100644 --- a/frameworks/native/inputmethod_ability/include/tasks/task_imsa.h +++ b/frameworks/native/inputmethod_ability/include/tasks/task_imsa.h @@ -196,18 +196,6 @@ public: } ~TaskImsaSetCoreAndAgent() = default; }; - -class TaskImsaNotifyPreemption : public Task { -public: - explicit TaskImsaNotifyPreemption() : Task(TASK_TYPE_IMSA_NOTIFY_PREEMPTION) - { - auto func = []() { - InputMethodAbility::GetInstance().OnNotifyPreemption(); - }; - actions_.emplace_back(std::make_unique(func)); - } - ~TaskImsaNotifyPreemption() = default; -}; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp index 82bf6e998..546c17786 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp @@ -594,6 +594,7 @@ int32_t InputMethodAbility::InvokeStartInputCallback(const TextTotalConfig &text InvokeAttachOptionsCallback(options, isNotifyInputStart || !isNotify_); if (isNotifyInputStart || !isNotify_) { isNotify_ = true; + IMSA_HILOGD("OnInputStart begin"); imeListener_->OnInputStart(); } if (TextConfig::IsPrivateCommandValid(textConfig.privateCommand) && IsDefaultIme()) { @@ -1895,7 +1896,7 @@ int32_t InputMethodAbility::OnNotifyPreemption() if (imeListener == nullptr) { return ErrorCode::ERROR_IME_NOT_STARTED; } - IMSA_HILOGD("notify begin."); + IMSA_HILOGD("notifyPreemption begin."); imeListener->NotifyPreemption(); return ErrorCode::NO_ERROR; } diff --git a/frameworks/native/inputmethod_ability/src/input_method_core_service_impl.cpp b/frameworks/native/inputmethod_ability/src/input_method_core_service_impl.cpp index 95f08b0a2..481fbc6ca 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_core_service_impl.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_core_service_impl.cpp @@ -134,8 +134,7 @@ ErrCode InputMethodCoreServiceImpl::OnSendPrivateData(const Value &Value) } ErrCode InputMethodCoreServiceImpl::NotifyPreemption() { - TaskManager::GetInstance().PostTask(std::make_shared()); - return ERR_OK; + return InputMethodAbility::GetInstance().OnNotifyPreemption(); } } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/services/include/peruser_session.h b/services/include/peruser_session.h index 5b01ec6fe..0ec863864 100644 --- a/services/include/peruser_session.h +++ b/services/include/peruser_session.h @@ -292,6 +292,8 @@ private: sptr GetImeConnection(); void ClearImeConnection(const sptr &connection); int32_t IsRequestOverLimit(TimeLimitType timeLimit, int32_t resetTimeOut, int32_t restartNum); + int32_t PrepareImeInfos(ImeType type, std::vector> &agents, + std::vector &imeInfos); std::mutex imeStartLock_; diff --git a/services/src/peruser_session.cpp b/services/src/peruser_session.cpp index bf4930a61..fa4701298 100644 --- a/services/src/peruser_session.cpp +++ b/services/src/peruser_session.cpp @@ -526,8 +526,8 @@ bool PerUserSession::IsProxyImeEnable() return ret; } -int32_t PerUserSession::OnStartInput(const InputClientInfo &inputClientInfo, std::vector> &agents, - std::vector &imeInfos) +int32_t PerUserSession::OnStartInput(const InputClientInfo &inputClientInfo, + std::vector> &agents, std::vector &imeInfos) { const sptr &client = inputClientInfo.client; if (client == nullptr) { @@ -568,22 +568,7 @@ int32_t PerUserSession::OnStartInput(const InputClientInfo &inputClientInfo, std IMSA_HILOGE("bind failed, ret: %{public}d!", ret); return ret; } - auto allData = GetAllReadyImeData(imeType); - if (allData.empty()) { - IMSA_HILOGE("allData is empty!"); - return ErrorCode::ERROR_IME_NOT_STARTED; - } - - for (auto &data : allData) { - if (data->agent == nullptr) { - IMSA_HILOGE("agent is nullptr!"); - return ErrorCode::ERROR_IME_NOT_STARTED; - } - agents.emplace_back(data->agent); - BindImeInfo imeInfo = { data->pid, data->ime.first }; - imeInfos.emplace_back(imeInfo); - } - return ErrorCode::NO_ERROR; + return PrepareImeInfos(imeType, agents, imeInfos); } int32_t PerUserSession::SendAllReadyImeToClient( @@ -782,14 +767,15 @@ int32_t PerUserSession::OnRegisterProxyIme(const sptr &core, c int32_t pid) { IMSA_HILOGD("start."); - auto result = IsRequestOverLimit(TimeLimitType::PROXY_IME_LIMIT, PROXY_REGISTERATION_TIME_INTERVAL, MAX_REGISTRATIONS_NUM); + auto result = IsRequestOverLimit(TimeLimitType::PROXY_IME_LIMIT, PROXY_REGISTERATION_TIME_INTERVAL, + MAX_REGISTRATIONS_NUM); if (result != ErrorCode::NO_ERROR) { IMSA_HILOGI("frequent calls, service is busy."); return result; } auto imeType = ImeType::PROXY_IME; auto lastImeData = GetImeData(imeType); - if (lastImeData != nullptr && lastImeData->core!=nullptr && lastImeData->core->AsObject() != core->AsObject()) { + if (lastImeData != nullptr && lastImeData->core != nullptr && lastImeData->core->AsObject() != core->AsObject()) { lastImeData->core->NotifyPreemption(); } auto ret = AddImeData(imeType, core, agent, pid); @@ -953,7 +939,6 @@ void PerUserSession::StartImeInImeDied() { IMSA_HILOGD("StartImeInImeDied."); { - std::lock_guard lock(resetLock); auto result = IsRequestOverLimit(TimeLimitType::IME_LIMIT, IME_RESET_TIME_OUT, MAX_RESTART_NUM); if (result != ErrorCode::NO_ERROR) { return; @@ -1066,6 +1051,8 @@ int32_t PerUserSession::AddImeData(ImeType type, sptr core, sp imeData->ime.first.append(GET_NAME(_PROXY_IME)); } else if (type == ImeType::PROXY_AGENT_IME) { imeData->ime.first.append(GET_NAME(_PROXY_AGENT_IME)); + } else if (type == ImeType::IME_MIRROR) { + imeData->ime.first.append(GET_NAME(_IME_MIRROR)); } imeDataList.push_back(imeData); IMSA_HILOGI("add imeData with type: %{public}d name: %{public}s end", type, imeData->ime.first.c_str()); @@ -1105,17 +1092,19 @@ void PerUserSession::RemoveImeData(pid_t pid) std::lock_guard lock(imeDataLock_); for (auto itType = imeData_.begin(); itType != imeData_.end(); ++itType) { auto &imeDataList = itType->second; - auto iter = std::find_if(imeDataList.begin(), imeDataList.end(), [pid](const std::shared_ptr& imeDataTmp) { - return imeDataTmp != nullptr && imeDataTmp->pid == pid; - }); + auto iter = + std::find_if(imeDataList.begin(), imeDataList.end(), [pid](const std::shared_ptr &imeDataTmp) { + return imeDataTmp != nullptr && imeDataTmp->pid == pid; + }); if (iter != imeDataList.end()) { - if ((*iter)->core != nullptr && (*iter)->core->AsObject() != nullptr) { - (*iter)->core->AsObject()->RemoveDeathRecipient((*iter)->deathRecipient); + auto imeData = *iter; + if (imeData != nullptr && imeData->core != nullptr && imeData->core->AsObject() != nullptr) { + imeData->core->AsObject()->RemoveDeathRecipient(imeData->deathRecipient); } imeDataList.erase(iter); - } - if (imeDataList.empty()) { - imeData_.erase(itType); + if (imeDataList.empty()) { + imeData_.erase(itType); + } break; } } @@ -1129,13 +1118,10 @@ void PerUserSession::RemoveImeData(ImeType type) IMSA_HILOGD("imeData not found."); return; } - auto& dataList = it->second; - if (dataList.empty() || dataList.back() == nullptr) { - return; - } - for (auto iter = dataList.begin(); iter != dataList.end(); ++iter) { - const auto& data = *iter; - data->core->AsObject()->RemoveDeathRecipient(data->deathRecipient); + for (auto imeData : it->second) { + if (imeData != nullptr && imeData->core != nullptr && imeData->core->AsObject() != nullptr) { + imeData->core->AsObject()->RemoveDeathRecipient(imeData->deathRecipient); + } } imeData_.erase(type); } @@ -1970,7 +1956,7 @@ int32_t PerUserSession::UpdateImeData(sptr core, sptrsecond; + auto &dataList = it->second; if (dataList.empty() || dataList.back() == nullptr) { return ErrorCode::ERROR_NULL_POINTER; } @@ -2004,7 +1990,7 @@ int32_t PerUserSession::InitConnect(pid_t pid) if (it == imeData_.end()) { return ErrorCode::ERROR_NULL_POINTER; } - auto& dataList = it->second; + auto &dataList = it->second; if (dataList.empty() || dataList.back() == nullptr) { return ErrorCode::ERROR_NULL_POINTER; } @@ -2019,7 +2005,7 @@ std::shared_ptr PerUserSession::GetImeData(ImeType type) if (it == imeData_.end()) { return nullptr; } - auto& dataList = it->second; + auto &dataList = it->second; if (dataList.empty() || dataList.back() == nullptr) { return nullptr; } @@ -2030,9 +2016,10 @@ std::shared_ptr PerUserSession::GetImeData(pid_t pid) { std::lock_guard lock(imeDataLock_); for (const auto &[imeType, imeDataList] : imeData_) { - auto iter = std::find_if(imeDataList.begin(), imeDataList.end(), [pid](const std::shared_ptr& imeDataTmp) { - return imeDataTmp != nullptr && imeDataTmp->pid == pid; - }); + auto iter = + std::find_if(imeDataList.begin(), imeDataList.end(), [pid](const std::shared_ptr &imeDataTmp) { + return imeDataTmp != nullptr && imeDataTmp->pid == pid; + }); if (iter != imeDataList.end()) { return *iter; } @@ -2071,7 +2058,7 @@ ImeAction PerUserSession::GetImeAction(ImeEvent action) if (it == imeData_.end()) { return ImeAction::DO_ACTION_IN_NULL_IME_DATA; } - auto& dataList = it->second; + auto &dataList = it->second; if (dataList.empty() || dataList.back() == nullptr) { return ImeAction::DO_ACTION_IN_NULL_IME_DATA; } @@ -2353,7 +2340,8 @@ void PerUserSession::HandleBindImeChanged( if (oldClientInfo == nullptr) { return; } - if (IsSameClient(newClientInfo.client, oldClientInfo->client) && newClientInfo.pid != oldClientInfo->pid) { + if (IsSameClient(newClientInfo.client, oldClientInfo->client) && + newClientInfo.bindImePid != oldClientInfo->bindImePid) { newClientInfo.isNotifyInputStart = true; } if (!IsImeBindTypeChanged(oldClientInfo->bindImeType)) { @@ -2835,5 +2823,26 @@ int32_t PerUserSession::IsRequestOverLimit(TimeLimitType timeLimitType, int32_t } return ErrorCode::NO_ERROR; } + +int32_t PerUserSession::PrepareImeInfos(ImeType type, std::vector> &agents, + std::vector &imeInfos) +{ + auto allData = GetAllReadyImeData(type); + if (allData.empty()) { + IMSA_HILOGE("allData is empty!"); + return ErrorCode::ERROR_IME_NOT_STARTED; + } + + for (auto &data : allData) { + if (data->agent == nullptr) { + IMSA_HILOGE("agent is nullptr!"); + return ErrorCode::ERROR_IME_NOT_STARTED; + } + agents.emplace_back(data->agent); + BindImeInfo imeInfo = { data->pid, data->ime.first }; + imeInfos.emplace_back(imeInfo); + } + return ErrorCode::NO_ERROR; +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/test/unittest/cpp_test/src/ime_proxy_test.cpp b/test/unittest/cpp_test/src/ime_proxy_test.cpp index 4fc0092ee..62a3494e1 100644 --- a/test/unittest/cpp_test/src/ime_proxy_test.cpp +++ b/test/unittest/cpp_test/src/ime_proxy_test.cpp @@ -694,8 +694,6 @@ HWTEST_F(ImeProxyTest, RegisterProxyImeTest002, TestSize.Level0) std::shared_ptr property = imc_->GetCurrentInputMethod(); ASSERT_TRUE(property != nullptr); EXPECT_EQ(property->name, "com.example.testIme"); - ret = InputMethodAbilityInterface::GetInstance().UnregisterProxyIme(displayId); - EXPECT_EQ(ret, ErrorCode::NO_ERROR); } } // namespace MiscServices } // namespace OHOS diff --git a/test/unittest/cpp_test/src/input_method_private_member_test.cpp b/test/unittest/cpp_test/src/input_method_private_member_test.cpp index a871a3c9b..1204c598c 100644 --- a/test/unittest/cpp_test/src/input_method_private_member_test.cpp +++ b/test/unittest/cpp_test/src/input_method_private_member_test.cpp @@ -343,11 +343,11 @@ HWTEST_F(InputMethodPrivateMemberTest, PerUserSessionParameterNullptr001, TestSi { IMSA_HILOGI("InputMethodPrivateMemberTest PerUserSessionParameterNullptr001 TEST START"); auto userSession = std::make_shared(MAIN_USER_ID); - sptr agent = nullptr; + std::vector> agents; InputClientInfo clientInfo; clientInfo.client = nullptr; - std::pair imeInfo; - int32_t ret = userSession->OnStartInput(clientInfo, agent, imeInfo); + std::vector imeInfo; + int32_t ret = userSession->OnStartInput(clientInfo, agents, imeInfo); EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NULL_POINTER); ret = userSession->OnReleaseInput(nullptr, 0); EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NULL_POINTER); @@ -2712,5 +2712,186 @@ HWTEST_F(InputMethodPrivateMemberTest, SA_TestClearImeConnection_001, TestSize.L userSession->ClearImeConnection(connection1); EXPECT_EQ(userSession->GetImeConnection(), connection); } + +/** + * @tc.name: PerUserSession_AddImeData_001 + * @tc.desc: PerUserSession_AddImeData_001 + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InputMethodPrivateMemberTest, PerUserSession_AddImeData_001, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodPrivateMemberTest::PerUserSession_AddImeData_001 start."); + auto userSession = std::make_shared(MAIN_USER_ID); + userSession->imeData_.clear(); + pid_t pid1 = 100; + sptr coreStub1 = new (std::nothrow) InputMethodCoreServiceImpl(); + sptr agentStub1 = new (std::nothrow) InputMethodAgentServiceImpl(); + auto ret = userSession->AddImeData(ImeType::PROXY_IME, coreStub1, agentStub1->AsObject(), pid1); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + auto it = userSession->imeData_.find(ImeType::PROXY_IME); + ASSERT_NE(it, userSession->imeData_.end()); + EXPECT_EQ(it->second.size(), 1); + + pid_t pid2 = 101; + sptr coreStub2 = new (std::nothrow) InputMethodCoreServiceImpl(); + sptr agentStub2 = new (std::nothrow) InputMethodAgentServiceImpl(); + ret = userSession->AddImeData(ImeType::PROXY_IME, coreStub2, agentStub2->AsObject(), pid2); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + it = userSession->imeData_.find(ImeType::PROXY_IME); + ASSERT_NE(it, userSession->imeData_.end()); + EXPECT_EQ(it->second.size(), 2); + + ret = userSession->AddImeData(ImeType::PROXY_IME, coreStub1, agentStub1->AsObject(), pid1); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + it = userSession->imeData_.find(ImeType::PROXY_IME); + ASSERT_NE(it, userSession->imeData_.end()); + ASSERT_EQ(it->second.size(), 2); + EXPECT_EQ(it->second[1]->pid, pid1); +} + +/** + * @tc.name: PerUserSession_GetImeData_001 + * @tc.desc: imeData_ info abnormal + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InputMethodPrivateMemberTest, PerUserSession_GetImeData_001, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodPrivateMemberTest::PerUserSession_GetImeData_001 start."); + auto userSession = std::make_shared(MAIN_USER_ID); + userSession->imeData_.clear(); + auto imeData = userSession->GetImeData(ImeType::PROXY_IME); + EXPECT_EQ(imeData, nullptr); + pid_t pid1 = 101; + imeData = userSession->GetImeData(pid1); + EXPECT_EQ(imeData, nullptr); + + userSession->imeData_.insert_or_assign(ImeType::IME, std::vector>{}); + imeData = userSession->GetImeData(ImeType::PROXY_IME); + EXPECT_EQ(imeData, nullptr); + imeData = userSession->GetImeData(pid1); + EXPECT_EQ(imeData, nullptr); + + userSession->imeData_.insert_or_assign(ImeType::PROXY_IME, std::vector>{}); + imeData = userSession->GetImeData(ImeType::PROXY_IME); + EXPECT_EQ(imeData, nullptr); + imeData = userSession->GetImeData(pid1); + EXPECT_EQ(imeData, nullptr); +} + +/** + * @tc.name: PerUserSession_GetImeData_002 + * @tc.desc: imeData_ normal + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InputMethodPrivateMemberTest, PerUserSession_GetImeData_002, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodPrivateMemberTest::PerUserSession_GetImeData_002 start."); + auto userSession = std::make_shared(MAIN_USER_ID); + userSession->imeData_.clear(); + pid_t pid1 = 101; + sptr coreStub1 = new (std::nothrow) InputMethodCoreServiceImpl(); + sptr agentStub1 = new (std::nothrow) InputMethodAgentServiceImpl(); + userSession->AddImeData(ImeType::PROXY_IME, coreStub1, agentStub1->AsObject(), pid1); + + pid_t pid2 = 102; + sptr coreStub2 = new (std::nothrow) InputMethodCoreServiceImpl(); + sptr agentStub2 = new (std::nothrow) InputMethodAgentServiceImpl(); + userSession->AddImeData(ImeType::PROXY_IME, coreStub2, agentStub2->AsObject(), pid2); + auto it = userSession->imeData_.find(ImeType::PROXY_IME); + ASSERT_NE(it, userSession->imeData_.end()); + EXPECT_EQ(it->second.size(), 2); + + auto imeData = userSession->GetImeData(ImeType::IME_MIRROR); + EXPECT_EQ(imeData, nullptr); + imeData = userSession->GetImeData(ImeType::PROXY_IME); + ASSERT_NE(imeData, nullptr); + EXPECT_EQ(imeData->pid, pid2); + + pid_t pid3 = 103; + imeData = userSession->GetImeData(pid3); + EXPECT_EQ(imeData, nullptr); + imeData = userSession->GetImeData(pid1); + ASSERT_NE(imeData, nullptr); + EXPECT_EQ(imeData->pid, pid1); +} + +/** + * @tc.name: PerUserSession_RemoveImeData_001 + * @tc.desc: Remove imeData by pid + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InputMethodPrivateMemberTest, PerUserSession_RemoveImeData_001, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodPrivateMemberTest::PerUserSession_RemoveImeData_001 start."); + auto userSession = std::make_shared(MAIN_USER_ID); + userSession->imeData_.clear(); + pid_t pid1 = 101; + sptr coreStub1 = new (std::nothrow) InputMethodCoreServiceImpl(); + sptr agentStub1 = new (std::nothrow) InputMethodAgentServiceImpl(); + userSession->AddImeData(ImeType::PROXY_IME, coreStub1, agentStub1->AsObject(), pid1); + + pid_t pid2 = 102; + sptr coreStub2 = new (std::nothrow) InputMethodCoreServiceImpl(); + sptr agentStub2 = new (std::nothrow) InputMethodAgentServiceImpl(); + userSession->AddImeData(ImeType::PROXY_IME, coreStub2, agentStub2->AsObject(), pid2); + auto it = userSession->imeData_.find(ImeType::PROXY_IME); + ASSERT_NE(it, userSession->imeData_.end()); + EXPECT_EQ(it->second.size(), 2); + + pid_t pid3 = 103; + userSession->RemoveImeData(pid3); + it = userSession->imeData_.find(ImeType::PROXY_IME); + ASSERT_NE(it, userSession->imeData_.end()); + EXPECT_EQ(it->second.size(), 2); + + userSession->RemoveImeData(pid2); + it = userSession->imeData_.find(ImeType::PROXY_IME); + ASSERT_NE(it, userSession->imeData_.end()); + ASSERT_EQ(it->second.size(), 1); + EXPECT_EQ(it->second[0]->pid, pid1); + + userSession->RemoveImeData(pid1); + it = userSession->imeData_.find(ImeType::PROXY_IME); + EXPECT_EQ(it, userSession->imeData_.end()); +} + +/** + * @tc.name: PerUserSession_RemoveImeData_002 + * @tc.desc: Remove imeData by imeType + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InputMethodPrivateMemberTest, PerUserSession_RemoveImeData_002, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodPrivateMemberTest::PerUserSession_RemoveImeData_002 start."); + auto userSession = std::make_shared(MAIN_USER_ID); + userSession->imeData_.clear(); + pid_t pid1 = 101; + sptr coreStub1 = new (std::nothrow) InputMethodCoreServiceImpl(); + sptr agentStub1 = new (std::nothrow) InputMethodAgentServiceImpl(); + userSession->AddImeData(ImeType::PROXY_IME, coreStub1, agentStub1->AsObject(), pid1); + + pid_t pid2 = 102; + sptr coreStub2 = new (std::nothrow) InputMethodCoreServiceImpl(); + sptr agentStub2 = new (std::nothrow) InputMethodAgentServiceImpl(); + userSession->AddImeData(ImeType::PROXY_IME, coreStub2, agentStub2->AsObject(), pid2); + auto it = userSession->imeData_.find(ImeType::PROXY_IME); + ASSERT_NE(it, userSession->imeData_.end()); + EXPECT_EQ(it->second.size(), 2); + + userSession->RemoveImeData(ImeType::IME_MIRROR); + it = userSession->imeData_.find(ImeType::PROXY_IME); + ASSERT_NE(it, userSession->imeData_.end()); + EXPECT_EQ(it->second.size(), 2); + + userSession->RemoveImeData(ImeType::PROXY_IME); + it = userSession->imeData_.find(ImeType::PROXY_IME); + EXPECT_EQ(it, userSession->imeData_.end()); +} + } // namespace MiscServices } // namespace OHOS \ No newline at end of file -- Gitee