1/*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "peruser_session.h"
17
18#include <chrono>
19#include <vector>
20
21#include "ability_manager_client.h"
22#include "app_mgr_client.h"
23#include "element_name.h"
24#include "identity_checker_impl.h"
25#include "ime_cfg_manager.h"
26#include "ime_connection.h"
27#include "ime_info_inquirer.h"
28#include "input_control_channel_stub.h"
29#include "input_type_manager.h"
30#include "ipc_skeleton.h"
31#include "iservice_registry.h"
32#include "mem_mgr_client.h"
33#include "message_parcel.h"
34#include "os_account_adapter.h"
35#include "parcel.h"
36#include "running_process_info.h"
37#include "scene_board_judgement.h"
38#include "security_mode_parser.h"
39#include "system_ability_definition.h"
40#include "unistd.h"
41#include "wms_connection_observer.h"
42
43namespace OHOS {
44namespace MiscServices {
45using namespace std::chrono;
46using namespace MessageID;
47using namespace OHOS::AppExecFwk;
48constexpr int64_t INVALID_PID = -1;
49constexpr uint32_t STOP_IME_TIME = 600;
50constexpr const char *STRICT_MODE = "strictMode";
51constexpr const char *ISOLATED_SANDBOX = "isolatedSandbox";
52constexpr uint32_t CHECK_IME_RUNNING_RETRY_INTERVAL = 60;
53constexpr uint32_t CHECK_IME_RUNNING_RETRY_TIMES = 10;
54PerUserSession::PerUserSession(int userId) : userId_(userId)
55{
56}
57
58PerUserSession::PerUserSession(int32_t userId, const std::shared_ptr<AppExecFwk::EventHandler> &eventHandler)
59    : userId_(userId), eventHandler_(eventHandler)
60{
61    auto bundleNames = ImeInfoInquirer::GetInstance().GetRunningIme(userId_);
62    if (!bundleNames.empty()) {
63        runningIme_ = bundleNames[0]; // one user only has one ime at present
64    }
65}
66
67PerUserSession::~PerUserSession()
68{
69}
70
71int PerUserSession::AddClientInfo(sptr<IRemoteObject> inputClient, const InputClientInfo &clientInfo,
72    ClientAddEvent event)
73{
74    IMSA_HILOGD("PerUserSession start.");
75    auto cacheInfo = GetClientInfo(inputClient);
76    if (cacheInfo != nullptr) {
77        IMSA_HILOGD("info is existed.");
78        if (cacheInfo->uiExtensionTokenId == IMF_INVALID_TOKENID &&
79            clientInfo.uiExtensionTokenId != IMF_INVALID_TOKENID) {
80            UpdateClientInfo(inputClient, { { UpdateFlag::UIEXTENSION_TOKENID, clientInfo.uiExtensionTokenId } });
81        }
82        UpdateClientInfo(inputClient, { { UpdateFlag::TEXT_CONFIG, clientInfo.config } });
83        if (event == START_LISTENING) {
84            UpdateClientInfo(inputClient, { { UpdateFlag::EVENTFLAG, clientInfo.eventFlag } });
85        }
86        return ErrorCode::NO_ERROR;
87    }
88    auto info = std::make_shared<InputClientInfo>(clientInfo);
89    std::weak_ptr<InputClientInfo> weakClientInfo = info;
90    info->deathRecipient->SetDeathRecipient([this, weakClientInfo](const wptr<IRemoteObject> &) {
91        auto clientInfo = weakClientInfo.lock();
92        if (clientInfo == nullptr) {
93            IMSA_HILOGD("clientInfo is nullptr.");
94            return;
95        }
96        this->OnClientDied(clientInfo->client);
97    });
98    auto obj = info->client->AsObject();
99    if (obj == nullptr) {
100        IMSA_HILOGE("client obj is nullptr!");
101        return ErrorCode::ERROR_CLIENT_NULL_POINTER;
102    }
103    if (obj->IsProxyObject() && !obj->AddDeathRecipient(info->deathRecipient)) {
104        IMSA_HILOGE("failed to add client death recipient!");
105        return ErrorCode::ERROR_CLIENT_ADD_FAILED;
106    }
107    std::lock_guard<std::recursive_mutex> lock(mtx);
108    mapClients_.insert({ inputClient, info });
109    IMSA_HILOGI("add client end.");
110    return ErrorCode::NO_ERROR;
111}
112
113void PerUserSession::RemoveClientInfo(const sptr<IRemoteObject> &client, bool isClientDied)
114{
115    std::lock_guard<std::recursive_mutex> lock(mtx);
116    auto clientInfo = GetClientInfo(client);
117    if (clientInfo == nullptr) {
118        IMSA_HILOGD("client already removed.");
119        return;
120    }
121    // if client is subscriber and the release is not because of the client died, do not remove
122    if (clientInfo->eventFlag != NO_EVENT_ON && !isClientDied) {
123        IMSA_HILOGD("is subscriber, do not remove.");
124        auto isShowKeyboard = false;
125        auto bindImeType = ImeType::NONE;
126        UpdateClientInfo(client,
127            { { UpdateFlag::BINDIMETYPE, bindImeType }, { UpdateFlag::ISSHOWKEYBOARD, isShowKeyboard } });
128        return;
129    }
130    if (clientInfo->deathRecipient != nullptr) {
131        IMSA_HILOGD("deathRecipient remove.");
132        client->RemoveDeathRecipient(clientInfo->deathRecipient);
133    }
134    mapClients_.erase(client);
135    IMSA_HILOGI("client[%{public}d] is removed.", clientInfo->pid);
136}
137
138void PerUserSession::UpdateClientInfo(const sptr<IRemoteObject> &client, const std::unordered_map<UpdateFlag,
139    std::variant<bool, uint32_t, ImeType, ClientState, TextTotalConfig>> &updateInfos)
140{
141    if (client == nullptr) {
142        IMSA_HILOGE("client is nullptr!");
143        return;
144    }
145    auto info = GetClientInfo(client);
146    if (info == nullptr) {
147        IMSA_HILOGE("client info is not exist!");
148        return;
149    }
150    for (const auto &updateInfo : updateInfos) {
151        switch (updateInfo.first) {
152            case UpdateFlag::EVENTFLAG: {
153                info->eventFlag = std::get<uint32_t>(updateInfo.second);
154                break;
155            }
156            case UpdateFlag::ISSHOWKEYBOARD: {
157                info->isShowKeyboard = std::get<bool>(updateInfo.second);
158                break;
159            }
160            case UpdateFlag::BINDIMETYPE: {
161                info->bindImeType = std::get<ImeType>(updateInfo.second);
162                break;
163            }
164            case UpdateFlag::STATE: {
165                info->state = std::get<ClientState>(updateInfo.second);
166                break;
167            }
168            case UpdateFlag::TEXT_CONFIG: {
169                info->config = std::get<TextTotalConfig>(updateInfo.second);
170                break;
171            }
172            case UpdateFlag::UIEXTENSION_TOKENID: {
173                info->uiExtensionTokenId = std::get<uint32_t>(updateInfo.second);
174                break;
175            }
176            default:
177                break;
178        }
179    }
180}
181
182int32_t PerUserSession::HideKeyboard(const sptr<IInputClient> &currentClient)
183{
184    IMSA_HILOGD("PerUserSession::HideKeyboard start.");
185    auto clientInfo = GetClientInfo(currentClient->AsObject());
186    if (clientInfo == nullptr) {
187        IMSA_HILOGE("client info is nullptr!");
188        return ErrorCode::ERROR_CLIENT_NOT_FOUND;
189    }
190    auto data = GetReadyImeData(clientInfo->bindImeType);
191    if (data == nullptr) {
192        IMSA_HILOGE("ime: %{public}d is not exist!", clientInfo->bindImeType);
193        return ErrorCode::ERROR_IME_NOT_STARTED;
194    }
195    auto ret = RequestIme(data, RequestType::NORMAL, [&data] { return data->core->HideKeyboard(false); });
196    if (ret != ErrorCode::NO_ERROR) {
197        IMSA_HILOGE("failed to hide keyboard, ret: %{public}d!", ret);
198        return ErrorCode::ERROR_KBD_HIDE_FAILED;
199    }
200    bool isShowKeyboard = false;
201    UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, isShowKeyboard } });
202    RestoreCurrentImeSubType();
203    return ErrorCode::NO_ERROR;
204}
205
206int32_t PerUserSession::ShowKeyboard(const sptr<IInputClient> &currentClient)
207{
208    IMSA_HILOGD("PerUserSession::ShowKeyboard start.");
209    auto clientInfo = GetClientInfo(currentClient->AsObject());
210    if (clientInfo == nullptr) {
211        IMSA_HILOGE("client info is nullptr!");
212        return ErrorCode::ERROR_CLIENT_NOT_FOUND;
213    }
214    auto data = GetReadyImeData(clientInfo->bindImeType);
215    if (data == nullptr) {
216        IMSA_HILOGE("ime: %{public}d is not exist!", clientInfo->bindImeType);
217        return ErrorCode::ERROR_IME_NOT_STARTED;
218    }
219    auto ret = RequestIme(data, RequestType::REQUEST_SHOW, [&data] { return data->core->ShowKeyboard(); });
220    if (ret != ErrorCode::NO_ERROR) {
221        IMSA_HILOGE("failed to show keyboard, ret: %{public}d!", ret);
222        return ErrorCode::ERROR_KBD_SHOW_FAILED;
223    }
224    bool isShowKeyboard = true;
225    UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, isShowKeyboard } });
226    return ErrorCode::NO_ERROR;
227}
228
229/** Handle the situation a remote input client died.
230 * It's called when a remote input client died
231 * @param the remote object handler of the input client died.
232 */
233void PerUserSession::OnClientDied(sptr<IInputClient> remote)
234{
235    if (remote == nullptr) {
236        return;
237    }
238    auto clientInfo = GetClientInfo(remote->AsObject());
239    IMSA_HILOGI("userId: %{public}d.", userId_);
240    if (IsSameClient(remote, GetCurrentClient())) {
241        if (clientInfo != nullptr) {
242            StopImeInput(clientInfo->bindImeType, clientInfo->channel);
243        }
244        SetCurrentClient(nullptr);
245        RestoreCurrentImeSubType();
246    }
247    if (IsSameClient(remote, GetInactiveClient())) {
248        if (clientInfo != nullptr) {
249            StopImeInput(clientInfo->bindImeType, clientInfo->channel);
250        }
251        SetInactiveClient(nullptr);
252        RestoreCurrentImeSubType();
253    }
254    RemoveClientInfo(remote->AsObject(), true);
255}
256
257/** Handle the situation that an ime died
258 * It's called when an ime died
259 * @param the remote object handler of the ime who died.
260 */
261void PerUserSession::OnImeDied(const sptr<IInputMethodCore> &remote, ImeType type)
262{
263    if (remote == nullptr) {
264        return;
265    }
266    IMSA_HILOGI("type: %{public}d.", type);
267    auto imeData = GetImeData(type);
268    auto ime = InputTypeManager::GetInstance().GetCurrentIme();
269    if (ime.bundleName == imeData->ime.first) {
270        InputTypeManager::GetInstance().Set(false);
271    }
272    if (imeData != nullptr && imeData->imeStatus == ImeStatus::EXITING) {
273        RemoveImeData(type, true);
274        NotifyImeStopFinished();
275        IMSA_HILOGI("%{public}d not current imeData.", type);
276        return;
277    }
278    RemoveImeData(type, true);
279    if (!OsAccountAdapter::IsOsAccountForeground(userId_)) {
280        IMSA_HILOGW("userId:%{public}d in background, no need to restart ime.", userId_);
281        return;
282    }
283    auto client = GetCurrentClient();
284    auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
285    if (clientInfo != nullptr && clientInfo->bindImeType == type) {
286        StopClientInput(clientInfo);
287        if (type == ImeType::IME) {
288            StartImeInImeDied();
289        }
290        return;
291    }
292    auto currentImeInfo = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
293    if (currentImeInfo == nullptr) {
294        IMSA_HILOGE("currentImeInfo is nullptr!");
295        return;
296    }
297    auto defaultImeInfo = ImeInfoInquirer::GetInstance().GetDefaultImeCfgProp();
298    if (defaultImeInfo == nullptr) {
299        IMSA_HILOGE("defaultImeInfo is nullptr!");
300        return;
301    }
302    if (type == ImeType::IME && currentImeInfo->bundleName == defaultImeInfo->name) {
303        StartImeInImeDied();
304    }
305}
306
307int32_t PerUserSession::RemoveIme(const sptr<IInputMethodCore> &core, ImeType type)
308{
309    if (core == nullptr) {
310        return ErrorCode::ERROR_NULL_POINTER;
311    }
312    auto data = GetReadyImeData(type);
313    if (data == nullptr || data->core->AsObject() != core->AsObject()) {
314        return ErrorCode::ERROR_IME_NOT_STARTED;
315    }
316
317    auto client = GetCurrentClient();
318    auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
319    if (clientInfo != nullptr && clientInfo->bindImeType == type) {
320        UnBindClientWithIme(clientInfo);
321    }
322    RemoveImeData(type, true);
323    return ErrorCode::NO_ERROR;
324}
325
326int32_t PerUserSession::OnHideCurrentInput()
327{
328    sptr<IInputClient> client = GetCurrentClient();
329    if (client == nullptr) {
330        IMSA_HILOGE("current client is nullptr!");
331        return ErrorCode::ERROR_CLIENT_NOT_FOUND;
332    }
333    return HideKeyboard(client);
334}
335
336int32_t PerUserSession::OnShowCurrentInput()
337{
338    IMSA_HILOGD("PerUserSession::OnShowCurrentInput start.");
339    sptr<IInputClient> client = GetCurrentClient();
340    if (client == nullptr) {
341        IMSA_HILOGE("current client is nullptr!");
342        return ErrorCode::ERROR_CLIENT_NOT_FOUND;
343    }
344    return ShowKeyboard(client);
345}
346
347int32_t PerUserSession::OnHideInput(sptr<IInputClient> client)
348{
349    IMSA_HILOGD("PerUserSession::OnHideInput start.");
350    if (!IsSameClient(client, GetCurrentClient())) {
351        IMSA_HILOGE("client is not current client!");
352        return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
353    }
354    return HideKeyboard(client);
355}
356
357int32_t PerUserSession::OnShowInput(sptr<IInputClient> client)
358{
359    IMSA_HILOGD("PerUserSession::OnShowInput start.");
360    if (!IsSameClient(client, GetCurrentClient())) {
361        IMSA_HILOGE("client is not current client!");
362        return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
363    }
364    return ShowKeyboard(client);
365}
366
367void PerUserSession::OnHideSoftKeyBoardSelf()
368{
369    IMSA_HILOGD("PerUserSession::OnHideSoftKeyBoardSel start.");
370    sptr<IInputClient> client = GetCurrentClient();
371    if (client == nullptr) {
372        IMSA_HILOGE("current client is nullptr!");
373        return;
374    }
375    UpdateClientInfo(client->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, false } });
376    RestoreCurrentImeSubType();
377}
378
379int32_t PerUserSession::OnRequestShowInput()
380{
381    IMSA_HILOGD("PerUserSession::OnRequestShowInput start.");
382    auto data = GetReadyImeData(ImeType::IME);
383    if (data == nullptr) {
384        IMSA_HILOGE("ime: %{public}d doesn't exist!", ImeType::IME);
385        return ErrorCode::ERROR_IME_NOT_STARTED;
386    }
387    auto ret = RequestIme(data, RequestType::REQUEST_SHOW, [&data] { return data->core->ShowKeyboard(); });
388    if (ret != ErrorCode::NO_ERROR) {
389        IMSA_HILOGE("failed to show keyboard, ret: %{public}d!", ret);
390        return ErrorCode::ERROR_KBD_SHOW_FAILED;
391    }
392    InputMethodSysEvent::GetInstance().ReportImeState(ImeState::BIND, data->pid,
393        ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName);
394    Memory::MemMgrClient::GetInstance().SetCritical(getpid(), true, INPUT_METHOD_SYSTEM_ABILITY_ID);
395    auto currentClient = GetCurrentClient();
396    if (currentClient != nullptr) {
397        UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, true } });
398    }
399    return ErrorCode::NO_ERROR;
400}
401
402int32_t PerUserSession::OnRequestHideInput()
403{
404    IMSA_HILOGD("PerUserSession::OnRequestHideInput start.");
405    auto data = GetReadyImeData(ImeType::IME);
406    if (data == nullptr) {
407        IMSA_HILOGE("ime: %{public}d doesn't exist!", ImeType::IME);
408        return ErrorCode::ERROR_IME_NOT_STARTED;
409    }
410
411    bool isForce = false;
412    if (!data->freezeMgr->IsIpcNeeded(RequestType::REQUEST_HIDE)) {
413        IMSA_HILOGD("need to force hide");
414        isForce = true;
415    }
416    auto ret = RequestIme(data, RequestType::REQUEST_HIDE,
417        [&data, isForce] { return data->core->HideKeyboard(isForce); });
418    if (ret != ErrorCode::NO_ERROR) {
419        IMSA_HILOGE("failed to hide keyboard, ret: %{public}d!", ret);
420        return ErrorCode::ERROR_KBD_HIDE_FAILED;
421    }
422    auto currentClient = GetCurrentClient();
423    if (currentClient != nullptr) {
424        UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, false } });
425    }
426    auto inactiveClient = GetInactiveClient();
427    if (inactiveClient != nullptr) {
428        RemoveClient(inactiveClient, false, true);
429    }
430    RestoreCurrentImeSubType();
431    return ErrorCode::NO_ERROR;
432}
433
434/** Get ClientInfo
435 * @param inputClient the IRemoteObject remote handler of given input client
436 * @return a pointer of ClientInfo if client is found
437 *         null if client is not found
438 * @note the clientInfo pointer should not be freed by caller
439 */
440std::shared_ptr<InputClientInfo> PerUserSession::GetClientInfo(sptr<IRemoteObject> inputClient)
441{
442    if (inputClient == nullptr) {
443        IMSA_HILOGE("inputClient is nullptr!");
444        return nullptr;
445    }
446    std::lock_guard<std::recursive_mutex> lock(mtx);
447    auto it = mapClients_.find(inputClient);
448    if (it == mapClients_.end()) {
449        IMSA_HILOGD("client not found.");
450        return nullptr;
451    }
452    return it->second;
453}
454
455std::shared_ptr<InputClientInfo> PerUserSession::GetClientInfo(pid_t pid)
456{
457    std::lock_guard<std::recursive_mutex> lock(mtx);
458    auto iter = std::find_if(mapClients_.begin(), mapClients_.end(),
459        [pid](const auto &mapClient) { return mapClient.second->pid == pid; });
460    if (iter == mapClients_.end()) {
461        IMSA_HILOGD("not found.");
462        return nullptr;
463    }
464    return iter->second;
465}
466
467int32_t PerUserSession::OnPrepareInput(const InputClientInfo &clientInfo)
468{
469    IMSA_HILOGD("PerUserSession::OnPrepareInput start");
470    return AddClientInfo(clientInfo.client->AsObject(), clientInfo, PREPARE_INPUT);
471}
472
473/** Release input. Called by an input client.Run in work thread of this user
474 * @param the parameters from remote client
475 * @return ErrorCode
476 */
477int32_t PerUserSession::OnReleaseInput(const sptr<IInputClient> &client)
478{
479    IMSA_HILOGD("PerUserSession::OnReleaseInput start");
480    return RemoveClient(client, true);
481}
482
483int32_t PerUserSession::RemoveClient(const sptr<IInputClient> &client, bool isUnbindFromClient, bool isInactiveClient)
484{
485    if (client == nullptr) {
486        return ErrorCode::ERROR_CLIENT_NULL_POINTER;
487    }
488    // if client is current client, unbind firstly
489    auto clientInfo = GetClientInfo(client->AsObject());
490    if (IsSameClient(client, GetCurrentClient())) {
491        UnBindClientWithIme(clientInfo, isUnbindFromClient);
492        SetCurrentClient(nullptr);
493        RestoreCurrentImeSubType();
494        StopClientInput(clientInfo);
495    }
496    if (IsSameClient(client, GetInactiveClient())) {
497        SetInactiveClient(nullptr);
498        StopClientInput(clientInfo, isInactiveClient);
499    }
500    RemoveClientInfo(client->AsObject());
501    return ErrorCode::NO_ERROR;
502}
503
504void PerUserSession::DeactivateClient(const sptr<IInputClient> &client)
505{
506    if (client == nullptr) {
507        IMSA_HILOGD("client is nullptr.");
508        return;
509    }
510    auto clientInfo = GetClientInfo(client->AsObject());
511    if (clientInfo == nullptr) {
512        return;
513    }
514    IMSA_HILOGI("deactivate client[%{public}d].", clientInfo->pid);
515    UpdateClientInfo(client->AsObject(), { { UpdateFlag::STATE, ClientState::INACTIVE } });
516    if (IsSameClient(client, GetCurrentClient())) {
517        SetCurrentClient(nullptr);
518    }
519    SetInactiveClient(client);
520    client->DeactivateClient();
521    if (InputTypeManager::GetInstance().IsStarted()) {
522        RestoreCurrentImeSubType();
523        return;
524    }
525    auto data = GetReadyImeData(clientInfo->bindImeType);
526    if (data == nullptr) {
527        IMSA_HILOGE("ime %{public}d doesn't exist!", clientInfo->bindImeType);
528        return;
529    }
530    RequestIme(data, RequestType::NORMAL, [&data, &clientInfo] {
531        data->core->OnClientInactive(clientInfo->channel);
532        return ErrorCode::NO_ERROR;
533    });
534    InputMethodSysEvent::GetInstance().ReportImeState(ImeState::UNBIND, data->pid,
535        ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName);
536    Memory::MemMgrClient::GetInstance().SetCritical(getpid(), false, INPUT_METHOD_SYSTEM_ABILITY_ID);
537}
538
539bool PerUserSession::IsProxyImeEnable()
540{
541    auto data = GetReadyImeData(ImeType::PROXY_IME);
542    return data != nullptr && data->core != nullptr && data->core->IsEnable();
543}
544
545int32_t PerUserSession::OnStartInput(const InputClientInfo &inputClientInfo, sptr<IRemoteObject> &agent)
546{
547    const sptr<IInputClient> &client = inputClientInfo.client;
548    if (client == nullptr) {
549        IMSA_HILOGE("client is nullptr!");
550        return ErrorCode::ERROR_CLIENT_NULL_POINTER;
551    }
552    auto clientInfo = GetClientInfo(client->AsObject());
553    if (clientInfo == nullptr) {
554        return ErrorCode::ERROR_CLIENT_NOT_FOUND;
555    }
556    IMSA_HILOGD("start input with keyboard[%{public}d].", inputClientInfo.isShowKeyboard);
557    if (IsSameClient(client, GetCurrentClient()) && IsImeBindChanged(clientInfo->bindImeType)) {
558        UnBindClientWithIme(clientInfo);
559    }
560    InputClientInfo infoTemp = *clientInfo;
561    infoTemp.isShowKeyboard = inputClientInfo.isShowKeyboard;
562    infoTemp.isNotifyInputStart = inputClientInfo.isNotifyInputStart;
563    infoTemp.needHide = inputClientInfo.needHide;
564    auto imeType = IsProxyImeEnable() ? ImeType::PROXY_IME : ImeType::IME;
565    int32_t ret = BindClientWithIme(std::make_shared<InputClientInfo>(infoTemp), imeType, true);
566    if (ret != ErrorCode::NO_ERROR) {
567        IMSA_HILOGE("bind failed, ret: %{public}d!", ret);
568        return ret;
569    }
570    auto data = GetReadyImeData(imeType);
571    if (data == nullptr || data->agent == nullptr) {
572        IMSA_HILOGE("data or agent is nullptr!");
573        return ErrorCode::ERROR_IME_NOT_STARTED;
574    }
575    agent = data->agent;
576    return ErrorCode::NO_ERROR;
577}
578
579int32_t PerUserSession::BindClientWithIme(const std::shared_ptr<InputClientInfo> &clientInfo, ImeType type,
580    bool isBindFromClient)
581{
582    if (clientInfo == nullptr) {
583        IMSA_HILOGE("clientInfo is nullptr!");
584        return ErrorCode::ERROR_NULL_POINTER;
585    }
586    IMSA_HILOGD("imeType: %{public}d, isShowKeyboard: %{public}d, isBindFromClient: %{public}d.", type,
587        clientInfo->isShowKeyboard, isBindFromClient);
588    auto data = GetValidIme(type);
589    if (data == nullptr) {
590        return ErrorCode::ERROR_IME_NOT_STARTED;
591    }
592    auto ret = RequestIme(data, RequestType::START_INPUT,
593        [&data, &clientInfo, isBindFromClient]() { return data->core->StartInput(*clientInfo, isBindFromClient); });
594    if (ret != ErrorCode::NO_ERROR) {
595        IMSA_HILOGE("start input failed, ret: %{public}d!", ret);
596        return ErrorCode::ERROR_IME_START_INPUT_FAILED;
597    }
598    if (type == ImeType::IME) {
599        InputMethodSysEvent::GetInstance().ReportImeState(ImeState::BIND, data->pid,
600            ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName);
601        Memory::MemMgrClient::GetInstance().SetCritical(getpid(), true, INPUT_METHOD_SYSTEM_ABILITY_ID);
602    }
603    if (!isBindFromClient && clientInfo->client->OnInputReady(data->agent) != ErrorCode::NO_ERROR) {
604        IMSA_HILOGE("start client input failed, ret: %{public}d!", ret);
605        return ErrorCode::ERROR_EX_PARCELABLE;
606    }
607    UpdateClientInfo(clientInfo->client->AsObject(),
608        { { UpdateFlag::BINDIMETYPE, type }, { UpdateFlag::ISSHOWKEYBOARD, clientInfo->isShowKeyboard },
609            { UpdateFlag::STATE, ClientState::ACTIVE } });
610    ReplaceCurrentClient(clientInfo->client);
611    return ErrorCode::NO_ERROR;
612}
613
614void PerUserSession::UnBindClientWithIme(const std::shared_ptr<InputClientInfo> &currentClientInfo,
615    bool isUnbindFromClient)
616{
617    if (currentClientInfo == nullptr) {
618        return;
619    }
620    if (!isUnbindFromClient) {
621        IMSA_HILOGD("unbind from service.");
622        StopClientInput(currentClientInfo);
623    }
624    StopImeInput(currentClientInfo->bindImeType, currentClientInfo->channel);
625}
626
627void PerUserSession::StopClientInput(const std::shared_ptr<InputClientInfo> &clientInfo, bool isStopInactiveClient)
628{
629    if (clientInfo == nullptr || clientInfo->client == nullptr) {
630        return;
631    }
632    auto ret = clientInfo->client->OnInputStop(isStopInactiveClient);
633    IMSA_HILOGI("isStopInactiveClient: %{public}d, client pid: %{public}d, ret: %{public}d.", isStopInactiveClient,
634        clientInfo->pid, ret);
635}
636
637void PerUserSession::StopImeInput(ImeType currentType, const sptr<IRemoteObject> &currentChannel)
638{
639    auto data = GetReadyImeData(currentType);
640    if (data == nullptr) {
641        return;
642    }
643    auto ret = RequestIme(data, RequestType::STOP_INPUT,
644        [&data, &currentChannel]() { return data->core->StopInput(currentChannel); });
645    IMSA_HILOGI("stop ime input, ret: %{public}d.", ret);
646    if (ret == ErrorCode::NO_ERROR && currentType == ImeType::IME) {
647        InputMethodSysEvent::GetInstance().ReportImeState(ImeState::UNBIND, data->pid,
648            ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName);
649        Memory::MemMgrClient::GetInstance().SetCritical(getpid(), false, INPUT_METHOD_SYSTEM_ABILITY_ID);
650    }
651    if (currentType == ImeType::IME) {
652        RestoreCurrentImeSubType();
653    }
654}
655
656void PerUserSession::OnSecurityChange(int32_t security)
657{
658    auto data = GetReadyImeData(ImeType::IME);
659    if (data == nullptr) {
660        IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME);
661        return;
662    }
663    auto ret =
664        RequestIme(data, RequestType::NORMAL, [&data, security] { return data->core->OnSecurityChange(security); });
665    IMSA_HILOGD("on security change, ret: %{public}d.", ret);
666}
667
668int32_t PerUserSession::OnSetCoreAndAgent(const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent)
669{
670    IMSA_HILOGI("start.");
671    auto ret = UpdateImeData(core, agent, IPCSkeleton::GetCallingPid());
672    if (ret != ErrorCode::NO_ERROR) {
673        return ret;
674    }
675    auto action = GetImeAction(ImeEvent::SET_CORE_AND_AGENT);
676    if (action == ImeAction::DO_NOTHING) {
677        return ErrorCode::NO_ERROR;
678    }
679    if (action != ImeAction::DO_SET_CORE_AND_AGENT) {
680        return ErrorCode::ERROR_IME;
681    }
682    ret = InitInputControlChannel();
683    IMSA_HILOGI("init input control channel ret: %{public}d.", ret);
684    auto imeType = ImeType::IME;
685    auto client = GetCurrentClient();
686    auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
687    if (clientInfo != nullptr && IsImeStartInBind(clientInfo->bindImeType, imeType)) {
688        BindClientWithIme(clientInfo, imeType);
689    }
690    bool isStarted = true;
691    isImeStarted_.SetValue(isStarted);
692    return ErrorCode::NO_ERROR;
693}
694
695int32_t PerUserSession::OnRegisterProxyIme(const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent)
696{
697    IMSA_HILOGD("start.");
698    auto imeType = ImeType::PROXY_IME;
699    auto ret = AddImeData(imeType, core, agent, IPCSkeleton::GetCallingPid());
700    if (ret != ErrorCode::NO_ERROR) {
701        return ret;
702    }
703    auto client = GetCurrentClient();
704    auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
705    if (clientInfo != nullptr) {
706        if (IsProxyImeStartInBind(clientInfo->bindImeType, imeType)) {
707            BindClientWithIme(clientInfo, imeType);
708        }
709        if (IsProxyImeStartInImeBind(clientInfo->bindImeType, imeType)) {
710            UnBindClientWithIme(clientInfo);
711            BindClientWithIme(clientInfo, imeType);
712        }
713    }
714    return ErrorCode::NO_ERROR;
715}
716
717int32_t PerUserSession::OnUnRegisteredProxyIme(UnRegisteredType type, const sptr<IInputMethodCore> &core)
718{
719    IMSA_HILOGD("proxy unregister type: %{public}d.", type);
720    // 0: stop proxy  1: switch to ima
721    if (type == UnRegisteredType::REMOVE_PROXY_IME) {
722        RemoveIme(core, ImeType::PROXY_IME);
723        return ErrorCode::NO_ERROR;
724    }
725    if (type == UnRegisteredType::SWITCH_PROXY_IME_TO_IME) {
726        auto client = GetCurrentClient();
727        auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
728        if (clientInfo == nullptr) {
729            IMSA_HILOGE("not found current client!");
730            return ErrorCode::ERROR_CLIENT_NOT_BOUND;
731        }
732        if (clientInfo->bindImeType == ImeType::PROXY_IME) {
733            UnBindClientWithIme(clientInfo);
734        }
735        InputClientInfo infoTemp = { .isShowKeyboard = true,
736            .client = clientInfo->client,
737            .channel = clientInfo->channel };
738        return BindClientWithIme(std::make_shared<InputClientInfo>(infoTemp), ImeType::IME);
739    }
740    return ErrorCode::ERROR_BAD_PARAMETERS;
741}
742
743int32_t PerUserSession::InitInputControlChannel()
744{
745    IMSA_HILOGD("PerUserSession::InitInputControlChannel start.");
746    sptr<IInputControlChannel> inputControlChannel = new InputControlChannelStub(userId_);
747    auto data = GetReadyImeData(ImeType::IME);
748    if (data == nullptr) {
749        IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME);
750        return ErrorCode::ERROR_IME_NOT_STARTED;
751    }
752    return RequestIme(data, RequestType::NORMAL,
753        [&data, &inputControlChannel] { return data->core->InitInputControlChannel(inputControlChannel); });
754}
755
756void PerUserSession::StartImeInImeDied()
757{
758    IMSA_HILOGD("StartImeInImeDied.");
759    {
760        std::lock_guard<std::mutex> lock(resetLock);
761        auto now = time(nullptr);
762        if (difftime(now, manager.last) > IME_RESET_TIME_OUT) {
763            manager = { 0, now };
764        }
765        ++manager.num;
766        if (manager.num > MAX_RESTART_NUM) {
767            return;
768        }
769    }
770    if (!IsWmsReady()) {
771        IMSA_HILOGW("not ready to start ime.");
772        return;
773    }
774    StartCurrentIme();
775}
776
777void PerUserSession::SetCurrentClient(sptr<IInputClient> client)
778{
779    IMSA_HILOGD("set current client.");
780    std::lock_guard<std::mutex> lock(clientLock_);
781    currentClient_ = client;
782}
783
784sptr<IInputClient> PerUserSession::GetCurrentClient()
785{
786    IMSA_HILOGD("get current client.");
787    std::lock_guard<std::mutex> lock(clientLock_);
788    return currentClient_;
789}
790
791void PerUserSession::ReplaceCurrentClient(const sptr<IInputClient> &client)
792{
793    std::lock_guard<std::mutex> lock(focusedClientLock_);
794    if (client == nullptr) {
795        return;
796    }
797    auto clientInfo = GetClientInfo(client->AsObject());
798    if (clientInfo == nullptr) {
799        return;
800    }
801    auto replacedClient = GetCurrentClient();
802    SetCurrentClient(client);
803    if (replacedClient != nullptr) {
804        auto replacedClientInfo = GetClientInfo(replacedClient->AsObject());
805        if (replacedClientInfo != nullptr && replacedClientInfo->pid != clientInfo->pid) {
806            IMSA_HILOGI("remove replaced client: [%{public}d]", replacedClientInfo->pid);
807            RemoveClient(replacedClient);
808        }
809    }
810    auto inactiveClient = GetInactiveClient();
811    if (inactiveClient != nullptr) {
812        auto inactiveClientInfo = GetClientInfo(inactiveClient->AsObject());
813        if (inactiveClientInfo != nullptr && inactiveClientInfo->pid != clientInfo->pid) {
814            IMSA_HILOGI("remove inactive client: [%{public}d]", inactiveClientInfo->pid);
815            RemoveClient(inactiveClient, false);
816        }
817    }
818}
819
820void PerUserSession::SetInactiveClient(sptr<IInputClient> client)
821{
822    IMSA_HILOGD("set inactive client.");
823    std::lock_guard<std::mutex> lock(inactiveClientLock_);
824    inactiveClient_ = client;
825}
826
827sptr<IInputClient> PerUserSession::GetInactiveClient()
828{
829    std::lock_guard<std::mutex> lock(inactiveClientLock_);
830    return inactiveClient_;
831}
832
833void PerUserSession::NotifyImeChangeToClients(const Property &property, const SubProperty &subProperty)
834{
835    IMSA_HILOGD("start.");
836    std::lock_guard<std::recursive_mutex> lock(mtx);
837    for (const auto &client : mapClients_) {
838        auto clientInfo = client.second;
839        if (clientInfo == nullptr || !EventStatusManager::IsImeChangeOn(clientInfo->eventFlag)) {
840            IMSA_HILOGD("client nullptr or no need to notify.");
841            continue;
842        }
843        IMSA_HILOGD("notify client: [%{public}d]", static_cast<int32_t>(clientInfo->pid));
844        int32_t ret = clientInfo->client->OnSwitchInput(property, subProperty);
845        if (ret != ErrorCode::NO_ERROR) {
846            IMSA_HILOGE("notify failed, ret: %{public}d, uid: %{public}d!", ret, static_cast<int32_t>(clientInfo->uid));
847            continue;
848        }
849    }
850}
851
852int32_t PerUserSession::AddImeData(ImeType type, sptr<IInputMethodCore> core, sptr<IRemoteObject> agent, pid_t pid)
853{
854    if (core == nullptr || agent == nullptr) {
855        IMSA_HILOGE("core or agent is nullptr!");
856        return ErrorCode::ERROR_NULL_POINTER;
857    }
858    sptr<InputDeathRecipient> deathRecipient = new (std::nothrow) InputDeathRecipient();
859    if (deathRecipient == nullptr) {
860        IMSA_HILOGE("failed to new deathRecipient!");
861        return ErrorCode::ERROR_NULL_POINTER;
862    }
863    deathRecipient->SetDeathRecipient([this, core, type](const wptr<IRemoteObject> &) { this->OnImeDied(core, type); });
864    auto coreObject = core->AsObject();
865    if (coreObject == nullptr || (coreObject->IsProxyObject() && !coreObject->AddDeathRecipient(deathRecipient))) {
866        IMSA_HILOGE("failed to add death recipient!");
867        return ErrorCode::ERROR_ADD_DEATH_RECIPIENT_FAILED;
868    }
869    std::lock_guard<std::mutex> lock(imeDataLock_);
870    auto imeData = std::make_shared<ImeData>(core, agent, deathRecipient, pid);
871    imeData->imeStatus = ImeStatus::READY;
872    imeData_.insert_or_assign(type, imeData);
873    return ErrorCode::NO_ERROR;
874}
875
876std::shared_ptr<ImeData> PerUserSession::GetReadyImeData(ImeType type)
877{
878    std::lock_guard<std::mutex> lock(imeDataLock_);
879    auto it = imeData_.find(type);
880    if (it == imeData_.end()) {
881        return nullptr;
882    }
883    if (it->second->imeStatus != ImeStatus::READY) {
884        return nullptr;
885    }
886    return it->second;
887}
888
889std::shared_ptr<ImeData> PerUserSession::GetValidIme(ImeType type)
890{
891    auto data = GetReadyImeData(type);
892    if (data != nullptr || type != ImeType::IME) {
893        return data;
894    }
895    IMSA_HILOGI("current ime is empty, try to restart it.");
896    StartCurrentIme();
897    return GetReadyImeData(type);
898}
899
900void PerUserSession::RemoveImeData(ImeType type, bool isImeDied)
901{
902    std::lock_guard<std::mutex> lock(imeDataLock_);
903    auto it = imeData_.find(type);
904    if (it == imeData_.end()) {
905        IMSA_HILOGD("imeData not found.");
906        return;
907    }
908    auto data = it->second;
909    if (isImeDied && data->core != nullptr && data->core->AsObject() != nullptr) {
910        data->core->AsObject()->RemoveDeathRecipient(data->deathRecipient);
911    }
912    imeData_.erase(type);
913}
914
915void PerUserSession::OnFocused(int32_t pid, int32_t uid)
916{
917    std::lock_guard<std::mutex> lock(focusedClientLock_);
918    auto client = GetCurrentClient();
919    if (client == nullptr) {
920        return;
921    }
922    if (IsCurClientFocused(pid, uid)) {
923        IMSA_HILOGD("current client focused, focusedPid: %{public}d", pid);
924        return;
925    }
926    if (!OHOS::Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
927        IMSA_HILOGI("focus shifts to pid: %{public}d, remove current client.", pid);
928        RemoveClient(client);
929        InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNFOCUSED);
930        return;
931    }
932    IMSA_HILOGI("focus shifts to pid: %{public}d, deactivate current client.", pid);
933    DeactivateClient(client);
934}
935
936void PerUserSession::OnUnfocused(int32_t pid, int32_t uid)
937{
938    if (GetCurrentClient() == nullptr) {
939        return;
940    }
941    if (IsCurClientUnFocused(pid, uid)) {
942        IMSA_HILOGD("current client Unfocused, unFocusedPid: %{public}d", pid);
943        return;
944    }
945    auto clientInfo = GetClientInfo(pid);
946    if (clientInfo == nullptr) {
947        return;
948    }
949    RemoveClient(clientInfo->client);
950    InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNFOCUSED);
951}
952
953std::shared_ptr<InputClientInfo> PerUserSession::GetCurClientInfo()
954{
955    auto client = GetCurrentClient();
956    if (client == nullptr) {
957        IMSA_HILOGD("no client in bound state.");
958        return nullptr;
959    }
960    return GetClientInfo(client->AsObject());
961}
962
963bool PerUserSession::IsCurClientFocused(int32_t pid, int32_t uid)
964{
965    auto clientInfo = GetCurClientInfo();
966    if (clientInfo == nullptr) {
967        IMSA_HILOGE("failed to get cur client info!");
968        return false;
969    }
970    auto identityChecker = std::make_shared<IdentityCheckerImpl>();
971    if (clientInfo->uiExtensionTokenId != IMF_INVALID_TOKENID &&
972        identityChecker->IsFocusedUIExtension(clientInfo->uiExtensionTokenId)) {
973        IMSA_HILOGI("UIExtension focused");
974        return true;
975    }
976    return clientInfo->pid == pid && clientInfo->uid == uid;
977}
978
979bool PerUserSession::IsCurClientUnFocused(int32_t pid, int32_t uid)
980{
981    auto clientInfo = GetCurClientInfo();
982    if (clientInfo == nullptr) {
983        IMSA_HILOGE("failed to get cur client info!");
984        return false;
985    }
986    auto identityChecker = std::make_shared<IdentityCheckerImpl>();
987    if (clientInfo->uiExtensionTokenId != IMF_INVALID_TOKENID &&
988        !identityChecker->IsFocusedUIExtension(clientInfo->uiExtensionTokenId)) {
989        IMSA_HILOGI("UIExtension UnFocused.");
990        return true;
991    }
992    return clientInfo->pid == pid && clientInfo->uid == uid;
993}
994
995bool PerUserSession::IsSameClient(sptr<IInputClient> source, sptr<IInputClient> dest)
996{
997    return source != nullptr && dest != nullptr && source->AsObject() == dest->AsObject();
998}
999
1000bool PerUserSession::StartCurrentIme(bool isStopCurrentIme)
1001{
1002    auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
1003    auto imeToStart = ImeInfoInquirer::GetInstance().GetImeToStart(userId_);
1004    IMSA_HILOGD("currentIme: %{public}s, imeToStart: %{public}s.", currentIme->imeId.c_str(),
1005        imeToStart->imeId.c_str());
1006    if (!StartIme(imeToStart, isStopCurrentIme)) {
1007        IMSA_HILOGE("failed to start ime!");
1008        InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ErrorCode::ERROR_IME_START_FAILED,
1009            imeToStart->imeId, "start ime failed!");
1010        return false;
1011    }
1012    IMSA_HILOGI("current ime changed to %{public}s.", imeToStart->imeId.c_str());
1013    auto currentImeInfo =
1014        ImeInfoInquirer::GetInstance().GetImeInfo(userId_, imeToStart->bundleName, imeToStart->subName);
1015    if (currentImeInfo != nullptr) {
1016        NotifyImeChangeToClients(currentImeInfo->prop, currentImeInfo->subProp);
1017        SwitchSubtype(currentImeInfo->subProp);
1018    }
1019    return true;
1020}
1021
1022bool PerUserSession::GetCurrentUsingImeId(ImeIdentification &imeId)
1023{
1024    if (InputTypeManager::GetInstance().IsStarted()) {
1025        IMSA_HILOGI("get right click on state current ime.");
1026        auto currentIme = InputTypeManager::GetInstance().GetCurrentIme();
1027        imeId = currentIme;
1028        return true;
1029    }
1030    auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
1031    if (currentImeCfg == nullptr) {
1032        IMSA_HILOGE("currentImeCfg is nullptr!");
1033        return false;
1034    }
1035    imeId.bundleName = currentImeCfg->bundleName;
1036    imeId.subName = currentImeCfg->extName;
1037    return true;
1038}
1039
1040AAFwk::Want PerUserSession::GetWant(const std::shared_ptr<ImeNativeCfg> &ime)
1041{
1042    SecurityMode mode;
1043    bool isolatedSandBox = true;
1044    if (SecurityModeParser::GetInstance()->IsDefaultFullMode(ime->bundleName, userId_)) {
1045        mode = SecurityMode::FULL;
1046        isolatedSandBox = false;
1047    } else if (ImeInfoInquirer::GetInstance().IsEnableSecurityMode()) {
1048        mode = SecurityModeParser::GetInstance()->GetSecurityMode(ime->bundleName, userId_);
1049    } else {
1050        mode = SecurityMode::FULL;
1051    }
1052    AAFwk::Want want;
1053    want.SetElementName(ime->bundleName, ime->extName);
1054    want.SetParam(STRICT_MODE, !(mode == SecurityMode::FULL));
1055    want.SetParam(ISOLATED_SANDBOX, isolatedSandBox);
1056    IMSA_HILOGI("userId: %{public}d, ime: %{public}s, mode: %{public}d, isolatedSandbox: %{public}d", userId_,
1057        ime->imeId.c_str(), static_cast<int32_t>(mode), isolatedSandBox);
1058    return want;
1059}
1060
1061bool PerUserSession::StartInputService(const std::shared_ptr<ImeNativeCfg> &ime)
1062{
1063    if (ime == nullptr) {
1064        return false;
1065    }
1066    isImeStarted_.Clear(false);
1067    sptr<AAFwk::IAbilityConnection> connection = new (std::nothrow) ImeConnection();
1068    if (connection == nullptr) {
1069        IMSA_HILOGE("failed to create connection!");
1070        return false;
1071    }
1072    auto want = GetWant(ime);
1073    auto ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectExtensionAbility(want, connection, userId_);
1074    if (ret != ErrorCode::NO_ERROR) {
1075        IMSA_HILOGE("connect %{public}s failed, ret: %{public}d!", ime->imeId.c_str(), ret);
1076        InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ErrorCode::ERROR_IME_START_FAILED, ime->imeId,
1077            "failed to start ability.");
1078        return false;
1079    }
1080    InitImeData({ ime->bundleName, ime->extName });
1081    if (!isImeStarted_.GetValue()) {
1082        IMSA_HILOGE("start %{public}s timeout!", ime->imeId.c_str());
1083        return false;
1084    }
1085    IMSA_HILOGI("%{public}s started successfully.", ime->imeId.c_str());
1086    InputMethodSysEvent::GetInstance().RecordEvent(IMEBehaviour::START_IME);
1087    return true;
1088}
1089
1090int64_t PerUserSession::GetCurrentClientPid()
1091{
1092    auto client = GetCurrentClient();
1093    if (client == nullptr) {
1094        return INVALID_PID;
1095    }
1096    auto clientInfo = GetClientInfo(client->AsObject());
1097    if (clientInfo == nullptr) {
1098        return INVALID_PID;
1099    }
1100    return clientInfo->pid;
1101}
1102
1103int64_t PerUserSession::GetInactiveClientPid()
1104{
1105    auto client = GetInactiveClient();
1106    if (client == nullptr) {
1107        return INVALID_PID;
1108    }
1109    auto clientInfo = GetClientInfo(client->AsObject());
1110    if (clientInfo == nullptr) {
1111        return INVALID_PID;
1112    }
1113    return clientInfo->pid;
1114}
1115
1116int32_t PerUserSession::OnPanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info)
1117{
1118    auto clientMap = GetClientMap();
1119    for (const auto &client : clientMap) {
1120        auto clientInfo = client.second;
1121        if (clientInfo == nullptr) {
1122            IMSA_HILOGD("client nullptr or no need to notify.");
1123            continue;
1124        }
1125        if (status == InputWindowStatus::SHOW && !EventStatusManager::IsImeShowOn(clientInfo->eventFlag)) {
1126            IMSA_HILOGD("has not imeShow callback");
1127            continue;
1128        }
1129        if (status == InputWindowStatus::HIDE && !EventStatusManager::IsImeHideOn(clientInfo->eventFlag)) {
1130            IMSA_HILOGD("has not imeHide callback");
1131            continue;
1132        }
1133        int32_t ret = clientInfo->client->OnPanelStatusChange(status, info);
1134        if (ret != ErrorCode::NO_ERROR) {
1135            IMSA_HILOGE("failed to OnPanelStatusChange, ret: %{public}d", ret);
1136            continue;
1137        }
1138    }
1139    return ErrorCode::NO_ERROR;
1140}
1141
1142int32_t PerUserSession::OnUpdateListenEventFlag(const InputClientInfo &clientInfo)
1143{
1144    auto remoteClient = clientInfo.client->AsObject();
1145    auto ret = AddClientInfo(remoteClient, clientInfo, START_LISTENING);
1146    if (ret != ErrorCode::NO_ERROR) {
1147        IMSA_HILOGE("failed to AddClientInfo!");
1148        return ret;
1149    }
1150    auto info = GetClientInfo(remoteClient);
1151    if (info == nullptr) {
1152        IMSA_HILOGE("info is nullptr!");
1153        return ErrorCode::ERROR_CLIENT_NOT_FOUND;
1154    }
1155    if (info->eventFlag == NO_EVENT_ON && info->bindImeType == ImeType::NONE) {
1156        RemoveClientInfo(remoteClient, false);
1157    }
1158    return ErrorCode::NO_ERROR;
1159}
1160
1161bool PerUserSession::IsImeStartInBind(ImeType bindImeType, ImeType startImeType)
1162{
1163    return startImeType == ImeType::IME && bindImeType == ImeType::IME;
1164}
1165
1166bool PerUserSession::IsProxyImeStartInBind(ImeType bindImeType, ImeType startImeType)
1167{
1168    return startImeType == ImeType::PROXY_IME && bindImeType == ImeType::PROXY_IME;
1169}
1170
1171bool PerUserSession::IsProxyImeStartInImeBind(ImeType bindImeType, ImeType startImeType)
1172{
1173    return startImeType == ImeType::PROXY_IME && bindImeType == ImeType::IME;
1174}
1175
1176bool PerUserSession::IsImeBindChanged(ImeType bindImeType)
1177{
1178    return (bindImeType == ImeType::IME && IsProxyImeEnable()) ||
1179           (bindImeType == ImeType::PROXY_IME && !IsProxyImeEnable());
1180}
1181
1182int32_t PerUserSession::SwitchSubtype(const SubProperty &subProperty)
1183{
1184    auto data = GetValidIme(ImeType::IME);
1185    if (data == nullptr) {
1186        IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME);
1187        return ErrorCode::ERROR_IME_NOT_STARTED;
1188    }
1189    return RequestIme(data, RequestType::NORMAL, [&data, &subProperty] { return data->core->SetSubtype(subProperty); });
1190}
1191
1192int32_t PerUserSession::SetInputType()
1193{
1194    InputType inputType = InputTypeManager::GetInstance().GetCurrentInputType();
1195    auto data = GetValidIme(ImeType::IME);
1196    if (data == nullptr) {
1197        IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME);
1198        return ErrorCode::ERROR_IME_NOT_STARTED;
1199    }
1200    return RequestIme(data, RequestType::NORMAL, [&data, &inputType] { return data->core->OnSetInputType(inputType); });
1201}
1202
1203bool PerUserSession::IsBoundToClient()
1204{
1205    if (GetCurrentClient() == nullptr) {
1206        IMSA_HILOGE("not in bound state!");
1207        return false;
1208    }
1209    return true;
1210}
1211
1212int32_t PerUserSession::RestoreCurrentImeSubType()
1213{
1214    if (!InputTypeManager::GetInstance().IsStarted()) {
1215        IMSA_HILOGD("already exit.");
1216        return ErrorCode::NO_ERROR;
1217    }
1218    auto typeIme = InputTypeManager::GetInstance().GetCurrentIme();
1219    auto cfgIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
1220    if (cfgIme->bundleName != typeIme.bundleName) {
1221        IMSA_HILOGD("diff ime, not deal, restore ime when attach.");
1222        return ErrorCode::NO_ERROR;
1223    }
1224    auto imeData = GetReadyImeData(ImeType::IME);
1225    InputTypeManager::GetInstance().Set(false);
1226    if (imeData == nullptr || imeData->ime.first != cfgIme->bundleName || imeData->ime.second != cfgIme->extName) {
1227        return ErrorCode::NO_ERROR;
1228    }
1229    SubProperty subProp = { .name = cfgIme->bundleName, .id = cfgIme->subName };
1230    auto subPropTemp = ImeInfoInquirer::GetInstance().GetCurrentSubtype(userId_);
1231    if (subPropTemp != nullptr) {
1232        subProp = *subPropTemp;
1233    }
1234    IMSA_HILOGD("same ime, restore subtype: %{public}s.", cfgIme->subName.c_str());
1235    return SwitchSubtype(subProp);
1236}
1237
1238bool PerUserSession::IsCurrentImeByPid(int32_t pid)
1239{
1240    auto imeData = GetImeData(ImeType::IME);
1241    if (imeData == nullptr) {
1242        IMSA_HILOGE("ime not started!");
1243        return false;
1244    }
1245    IMSA_HILOGD("userId: %{public}d, pid: %{public}d, current pid: %{public}d.", userId_, pid, imeData->pid);
1246    return imeData->pid == pid;
1247}
1248
1249int32_t PerUserSession::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
1250{
1251    if (GetCurrentClient() == nullptr) {
1252        IMSA_HILOGD("not in bound state.");
1253        isShown = false;
1254        return ErrorCode::NO_ERROR;
1255    }
1256    auto ime = GetReadyImeData(ImeType::IME);
1257    if (ime == nullptr) {
1258        IMSA_HILOGE("ime not started!");
1259        return ErrorCode::ERROR_IME_NOT_STARTED;
1260    }
1261    return RequestIme(ime, RequestType::NORMAL,
1262        [&ime, &panelInfo, &isShown] { return ime->core->IsPanelShown(panelInfo, isShown); });
1263}
1264
1265bool PerUserSession::CheckSecurityMode()
1266{
1267    auto client = GetCurrentClient();
1268    auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
1269    if (clientInfo != nullptr) {
1270        return clientInfo->config.inputAttribute.GetSecurityFlag();
1271    }
1272    return false;
1273}
1274
1275std::map<sptr<IRemoteObject>, std::shared_ptr<InputClientInfo>> PerUserSession::GetClientMap()
1276{
1277    std::lock_guard<std::recursive_mutex> lock(mtx);
1278    return mapClients_;
1279}
1280
1281int32_t PerUserSession::RequestIme(const std::shared_ptr<ImeData> &data, RequestType type, const IpcExec &exec)
1282{
1283    if (IsProxyImeEnable()) {
1284        IMSA_HILOGD("proxy enable.");
1285        return exec();
1286    }
1287    if (data == nullptr || data->freezeMgr == nullptr) {
1288        IMSA_HILOGE("data is nullptr!");
1289        return ErrorCode::NO_ERROR;
1290    }
1291    data->freezeMgr->BeforeIpc(type);
1292    auto ret = exec();
1293    data->freezeMgr->AfterIpc(type, ret == ErrorCode::NO_ERROR);
1294    return ret;
1295}
1296
1297int32_t PerUserSession::OnConnectSystemCmd(const sptr<IRemoteObject> &channel, sptr<IRemoteObject> &agent)
1298{
1299    auto data = GetReadyImeData(ImeType::IME);
1300    if (data == nullptr) {
1301        IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME);
1302        return ErrorCode::ERROR_IME_NOT_STARTED;
1303    }
1304    auto ret = RequestIme(data, RequestType::NORMAL,
1305        [&data, &channel, &agent] { return data->core->OnConnectSystemCmd(channel, agent); });
1306    IMSA_HILOGD("on connect systemCmd, ret: %{public}d.", ret);
1307    if (ret != ErrorCode::NO_ERROR) {
1308        IMSA_HILOGE("bind failed, ret: %{public}d!", ret);
1309        return ret;
1310    }
1311    return ErrorCode::NO_ERROR;
1312}
1313
1314bool PerUserSession::WaitForCurrentImeStop()
1315{
1316    IMSA_HILOGI("start.");
1317    std::unique_lock<std::mutex> lock(imeStopMutex_);
1318    isSwitching_.store(true);
1319    return imeStopCv_.wait_for(lock, std::chrono::milliseconds(STOP_IME_TIME), [this]() { return !isSwitching_; });
1320}
1321
1322void PerUserSession::NotifyImeStopFinished()
1323{
1324    IMSA_HILOGI("start.");
1325    std::unique_lock<std::mutex> lock(imeStopMutex_);
1326    isSwitching_.store(false);
1327    imeStopCv_.notify_one();
1328}
1329
1330int32_t PerUserSession::RemoveCurrentClient()
1331{
1332    auto currentClient = GetCurrentClient();
1333    if (currentClient == nullptr) {
1334        IMSA_HILOGE("currentClient is nullptr!");
1335        return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1336    }
1337    return RemoveClient(currentClient, false);
1338}
1339
1340bool PerUserSession::IsWmsReady()
1341{
1342    if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
1343        IMSA_HILOGD("scb enable");
1344        return WmsConnectionObserver::IsWmsConnected(userId_);
1345    }
1346    return IsReady(WINDOW_MANAGER_SERVICE_ID);
1347}
1348
1349bool PerUserSession::IsReady(int32_t saId)
1350{
1351    auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1352    if (saMgr == nullptr) {
1353        IMSA_HILOGE("get saMgr failed!");
1354        return false;
1355    }
1356    if (saMgr->CheckSystemAbility(saId) == nullptr) {
1357        IMSA_HILOGE("sa:%{public}d not ready!", saId);
1358        return false;
1359    }
1360    return true;
1361}
1362
1363void PerUserSession::AddRestartIme()
1364{
1365    int32_t tasks = 0;
1366    {
1367        std::lock_guard<std::mutex> lock(restartMutex_);
1368        if (restartTasks_ >= MAX_RESTART_TASKS) {
1369            return;
1370        }
1371        restartTasks_ = std::max(restartTasks_, 0);
1372        tasks = ++restartTasks_;
1373    }
1374    if (tasks == 1 && !RestartIme()) {
1375        std::lock_guard<std::mutex> lock(restartMutex_);
1376        restartTasks_ = 0;
1377    }
1378}
1379
1380bool PerUserSession::RestartIme()
1381{
1382    auto task = [this]() {
1383        if (IsReady(MEMORY_MANAGER_SA_ID) && IsWmsReady() && runningIme_.empty()) {
1384            auto ret = StartCurrentIme(true);
1385            if (!ret) {
1386                IMSA_HILOGE("start ime failed!");
1387            }
1388        }
1389        int32_t tasks = 0;
1390        {
1391            std::lock_guard<std::mutex> lock(restartMutex_);
1392            tasks = --restartTasks_;
1393        }
1394        if (tasks > 0 && !RestartIme()) {
1395            std::lock_guard<std::mutex> lock(restartMutex_);
1396            restartTasks_ = 0;
1397        }
1398    };
1399    if (eventHandler_ == nullptr) {
1400        IMSA_HILOGE("eventHandler_ is nullptr!");
1401        return false;
1402    }
1403    return eventHandler_->PostTask(task, "RestartCurrentImeTask", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
1404}
1405
1406BlockQueue<SwitchInfo>& PerUserSession::GetSwitchQueue()
1407{
1408    return switchQueue_;
1409}
1410
1411int32_t PerUserSession::InitImeData(const std::pair<std::string, std::string> &ime)
1412{
1413    std::lock_guard<std::mutex> lock(imeDataLock_);
1414    auto it = imeData_.find(ImeType::IME);
1415    if (it != imeData_.end()) {
1416        return ErrorCode::NO_ERROR;
1417    }
1418    auto imeData = std::make_shared<ImeData>(nullptr, nullptr, nullptr, -1);
1419    imeData->startTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1420    imeData->ime = ime;
1421    imeData_.insert({ ImeType::IME, imeData });
1422    return ErrorCode::NO_ERROR;
1423}
1424
1425int32_t PerUserSession::UpdateImeData(sptr<IInputMethodCore> core, sptr<IRemoteObject> agent, pid_t pid)
1426{
1427    if (core == nullptr || agent == nullptr) {
1428        IMSA_HILOGE("core or agent is nullptr!");
1429        return ErrorCode::ERROR_NULL_POINTER;
1430    }
1431    std::lock_guard<std::mutex> lock(imeDataLock_);
1432    auto it = imeData_.find(ImeType::IME);
1433    if (it == imeData_.end()) {
1434        return ErrorCode::ERROR_NULL_POINTER;
1435    }
1436    it->second->core = core;
1437    it->second->agent = agent;
1438    it->second->pid = pid;
1439    it->second->freezeMgr = std::make_shared<FreezeManager>(pid);
1440    sptr<InputDeathRecipient> deathRecipient = new (std::nothrow) InputDeathRecipient();
1441    if (deathRecipient == nullptr) {
1442        IMSA_HILOGE("failed to new deathRecipient!");
1443        return ErrorCode::ERROR_NULL_POINTER;
1444    }
1445    auto type = ImeType::IME;
1446    deathRecipient->SetDeathRecipient([this, core, type](const wptr<IRemoteObject> &) { this->OnImeDied(core, type); });
1447    auto coreObject = core->AsObject();
1448    if (coreObject == nullptr || (coreObject->IsProxyObject() && !coreObject->AddDeathRecipient(deathRecipient))) {
1449        IMSA_HILOGE("failed to add death recipient!");
1450        return ErrorCode::ERROR_ADD_DEATH_RECIPIENT_FAILED;
1451    }
1452    it->second->deathRecipient = deathRecipient;
1453    return ErrorCode::NO_ERROR;
1454}
1455
1456int32_t PerUserSession::InitConnect(pid_t pid)
1457{
1458    std::lock_guard<std::mutex> lock(imeDataLock_);
1459    auto it = imeData_.find(ImeType::IME);
1460    if (it == imeData_.end()) {
1461        return ErrorCode::ERROR_NULL_POINTER;
1462    }
1463    it->second->pid = pid;
1464    return ErrorCode::NO_ERROR;
1465}
1466
1467std::shared_ptr<ImeData> PerUserSession::GetImeData(ImeType type)
1468{
1469    std::lock_guard<std::mutex> lock(imeDataLock_);
1470    auto it = imeData_.find(type);
1471    if (it == imeData_.end()) {
1472        return nullptr;
1473    }
1474    return it->second;
1475}
1476
1477bool PerUserSession::StartIme(const std::shared_ptr<ImeNativeCfg> &ime, bool isStopCurrentIme)
1478{
1479    std::lock_guard<std::mutex> lock(imeStartLock_);
1480    if (ime == nullptr) {
1481        return false;
1482    }
1483    auto imeData = GetImeData(ImeType::IME);
1484    if (imeData == nullptr) {
1485        return HandleFirstStart(ime, isStopCurrentIme);
1486    }
1487    if (imeData->ime.first == ime->bundleName && imeData->ime.second == ime->extName) {
1488        if (isStopCurrentIme) {
1489            return StartNewIme(ime);
1490        }
1491        return StartCurrentIme(ime);
1492    }
1493    return StartNewIme(ime);
1494}
1495
1496ImeAction PerUserSession::GetImeAction(ImeEvent action)
1497{
1498    std::lock_guard<std::mutex> lock(imeDataLock_);
1499    auto it = imeData_.find(ImeType::IME);
1500    if (it == imeData_.end()) {
1501        return ImeAction::DO_ACTION_IN_NULL_IME_DATA;
1502    }
1503    auto iter = imeEventConverter_.find({ it->second->imeStatus, action });
1504    if (iter == imeEventConverter_.end()) {
1505        IMSA_HILOGE("abnormal!");
1506        return ImeAction::DO_ACTION_IN_IME_EVENT_CONVERT_FAILED;
1507    }
1508    it->second->imeStatus = iter->second.first;
1509    return iter->second.second;
1510}
1511
1512bool PerUserSession::StartCurrentIme(const std::shared_ptr<ImeNativeCfg> &ime)
1513{
1514    auto imeData = GetImeData(ImeType::IME);
1515    if (imeData == nullptr) {
1516        return StartInputService(ime);
1517    }
1518    auto action = GetImeAction(ImeEvent::START_IME);
1519    if (action == ImeAction::DO_ACTION_IN_IME_EVENT_CONVERT_FAILED) {
1520        return false;
1521    }
1522    if (action == ImeAction::DO_ACTION_IN_NULL_IME_DATA) {
1523        return StartInputService(ime);
1524    }
1525    if (action == ImeAction::DO_NOTHING) {
1526        return true;
1527    }
1528    if (action == ImeAction::HANDLE_STARTING_IME) {
1529        int64_t time = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1530        if (time - imeData->startTime > ImeData::START_TIME_OUT) {
1531            IMSA_HILOGE("[%{public}s, %{public}s] start abnormal, more than eight second!", imeData->ime.first.c_str(),
1532                imeData->ime.second.c_str());
1533            return HandleStartImeTimeout(ime);
1534        }
1535        return StartInputService(ime);
1536    }
1537    if (!StopExitingCurrentIme()) {
1538        return false;
1539    }
1540    return StartInputService(ime);
1541}
1542
1543bool PerUserSession::HandleStartImeTimeout(const std::shared_ptr<ImeNativeCfg> &ime)
1544{
1545    auto action = GetImeAction(ImeEvent::START_IME_TIMEOUT);
1546    if (action == ImeAction::DO_ACTION_IN_NULL_IME_DATA) {
1547        return StartInputService(ime);
1548    }
1549    if (action == ImeAction::DO_ACTION_IN_IME_EVENT_CONVERT_FAILED) {
1550        return false;
1551    }
1552    if (action == ImeAction::DO_NOTHING) {
1553        IMSA_HILOGW("ready when timeout");
1554        return true;
1555    }
1556    ForceStopCurrentIme(false);
1557    return false;
1558}
1559
1560bool PerUserSession::StartNewIme(const std::shared_ptr<ImeNativeCfg> &ime)
1561{
1562    if (!StopCurrentIme()) {
1563        return false;
1564    }
1565    return StartInputService(ime);
1566}
1567
1568bool PerUserSession::StopCurrentIme()
1569{
1570    auto action = GetImeAction(ImeEvent::STOP_IME);
1571    if (action == ImeAction::DO_ACTION_IN_NULL_IME_DATA) {
1572        return true;
1573    }
1574    if (action == ImeAction::DO_ACTION_IN_IME_EVENT_CONVERT_FAILED) {
1575        return false;
1576    }
1577    if (action == ImeAction::STOP_READY_IME) {
1578        return StopReadyCurrentIme();
1579    }
1580    if (action == ImeAction::STOP_STARTING_IME) {
1581        return ForceStopCurrentIme();
1582    }
1583    return StopExitingCurrentIme();
1584}
1585
1586bool PerUserSession::StopReadyCurrentIme()
1587{
1588    auto client = GetCurrentClient();
1589    auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
1590    if (clientInfo != nullptr && clientInfo->bindImeType == ImeType::IME) {
1591        StopClientInput(clientInfo);
1592    }
1593    auto imeData = GetImeData(ImeType::IME);
1594    if (imeData == nullptr) {
1595        return true;
1596    }
1597    if (imeData->core == nullptr) {
1598        IMSA_HILOGE("core is nullptr!");
1599        return ForceStopCurrentIme();
1600    }
1601    auto ret = RequestIme(imeData, RequestType::NORMAL, [&imeData] {
1602        // failed when register onInputStop after SetCoreAndAgent
1603        return imeData->core->StopInputService(true);
1604    });
1605    if (ret != ErrorCode::NO_ERROR) {
1606        IMSA_HILOGE("StopInputService failed.");
1607        return ForceStopCurrentIme();
1608    }
1609    if (!WaitForCurrentImeStop()) {
1610        IMSA_HILOGI("stop timeout.");
1611        return ForceStopCurrentIme();
1612    }
1613    return true;
1614}
1615
1616bool PerUserSession::StopExitingCurrentIme()
1617{
1618    auto imeData = GetImeData(ImeType::IME);
1619    if (imeData == nullptr) {
1620        return true;
1621    }
1622    if (!ImeInfoInquirer::GetInstance().IsRunningIme(userId_, imeData->ime.first)) {
1623        IMSA_HILOGD("already stop!");
1624        RemoveImeData(ImeType::IME, true);
1625        return true;
1626    }
1627    return ForceStopCurrentIme();
1628}
1629
1630bool PerUserSession::ForceStopCurrentIme(bool isNeedWait)
1631{
1632    auto client = GetCurrentClient();
1633    auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
1634    if (clientInfo != nullptr && clientInfo->bindImeType == ImeType::IME) {
1635        StopClientInput(clientInfo);
1636    }
1637    auto imeData = GetImeData(ImeType::IME);
1638    if (imeData == nullptr) {
1639        return true;
1640    }
1641    AAFwk::Want want;
1642    want.SetElementName(imeData->ime.first, imeData->ime.second);
1643    auto ret = AAFwk::AbilityManagerClient::GetInstance()->StopExtensionAbility(
1644        want, nullptr, userId_, AppExecFwk::ExtensionAbilityType::INPUTMETHOD);
1645    if (ret != ErrorCode::NO_ERROR) {
1646        IMSA_HILOGE("StopExtensionAbility [%{public}s, %{public}s] failed, ret: %{public}d!",
1647            imeData->ime.first.c_str(), imeData->ime.second.c_str(), ret);
1648        return false;
1649    }
1650    if (!isNeedWait) {
1651        return true;
1652    }
1653    WaitForCurrentImeStop();
1654    if (ImeInfoInquirer::GetInstance().IsRunningIme(userId_, imeData->ime.first)) {
1655        IMSA_HILOGW("stop [%{public}s, %{public}s] timeout.", imeData->ime.first.c_str(), imeData->ime.second.c_str());
1656        return false;
1657    }
1658    RemoveImeData(ImeType::IME, true);
1659    return true;
1660}
1661
1662bool PerUserSession::HandleFirstStart(const std::shared_ptr<ImeNativeCfg> &ime, bool isStopCurrentIme)
1663{
1664    if (runningIme_.empty()) {
1665        return StartInputService(ime);
1666    }
1667    IMSA_HILOGW("imsa abnormal restore.");
1668    if (isStopCurrentIme) {
1669        return true;
1670    }
1671    if (BlockRetry(CHECK_IME_RUNNING_RETRY_INTERVAL, CHECK_IME_RUNNING_RETRY_TIMES,
1672                   [this]() -> bool { return !ImeInfoInquirer::GetInstance().IsRunningIme(userId_, runningIme_); })) {
1673        IMSA_HILOGI("[%{public}d, %{public}s] stop completely", userId_, runningIme_.c_str());
1674        runningIme_.clear();
1675        return StartInputService(ime);
1676    }
1677    IMSA_HILOGW("[%{public}d, %{public}s] stop timeout", userId_, runningIme_.c_str());
1678    return false;
1679}
1680
1681int32_t PerUserSession::RestoreCurrentIme()
1682{
1683    InputTypeManager::GetInstance().Set(false);
1684    auto cfgIme = ImeInfoInquirer::GetInstance().GetImeToStart(userId_);
1685    auto imeData = GetReadyImeData(ImeType::IME);
1686    if (imeData != nullptr && imeData->ime.first == cfgIme->bundleName && imeData->ime.second == cfgIme->extName) {
1687        return ErrorCode::NO_ERROR;
1688    }
1689    IMSA_HILOGD("need restore!");
1690    if (!StartIme(cfgIme)) {
1691        IMSA_HILOGE("start ime failed!");
1692        return ErrorCode::ERROR_IME_START_FAILED;
1693    }
1694    SubProperty subProp = { .name = cfgIme->bundleName, .id = cfgIme->subName };
1695    auto subPropTemp = ImeInfoInquirer::GetInstance().GetCurrentSubtype(userId_);
1696    if (subPropTemp != nullptr) {
1697        subProp = *subPropTemp;
1698    }
1699    SwitchSubtype(subProp);
1700    return ErrorCode::NO_ERROR;
1701}
1702
1703bool PerUserSession::CheckPwdInputPatternConv(InputClientInfo &newClientInfo)
1704{
1705    auto exClient = GetCurrentClient();
1706    if (exClient == nullptr) {
1707        exClient = GetInactiveClient();
1708    }
1709    auto exClientInfo = exClient != nullptr ? GetClientInfo(exClient->AsObject()) : nullptr;
1710    if (exClientInfo == nullptr) {
1711        IMSA_HILOGE("exClientInfo is nullptr!");
1712        return false;
1713    }
1714    // if current input pattern differ from previous in pwd and normal, need hide panel first.
1715    if (newClientInfo.config.inputAttribute.GetSecurityFlag()) {
1716        IMSA_HILOGI("new input pattern is pwd.");
1717        return !exClientInfo->config.inputAttribute.GetSecurityFlag();
1718    }
1719    IMSA_HILOGI("new input pattern is normal.");
1720    return exClientInfo->config.inputAttribute.GetSecurityFlag();
1721}
1722} // namespace MiscServices
1723} // namespace OHOS