122736c2fSopenharmony_ci/*
222736c2fSopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd.
322736c2fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
422736c2fSopenharmony_ci * you may not use this file except in compliance with the License.
522736c2fSopenharmony_ci * You may obtain a copy of the License at
622736c2fSopenharmony_ci *
722736c2fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
822736c2fSopenharmony_ci *
922736c2fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1022736c2fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1122736c2fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1222736c2fSopenharmony_ci * See the License for the specific language governing permissions and
1322736c2fSopenharmony_ci * limitations under the License.
1422736c2fSopenharmony_ci */
1522736c2fSopenharmony_ci
1622736c2fSopenharmony_ci#include "peruser_session.h"
1722736c2fSopenharmony_ci
1822736c2fSopenharmony_ci#include <chrono>
1922736c2fSopenharmony_ci#include <vector>
2022736c2fSopenharmony_ci
2122736c2fSopenharmony_ci#include "ability_manager_client.h"
2222736c2fSopenharmony_ci#include "app_mgr_client.h"
2322736c2fSopenharmony_ci#include "element_name.h"
2422736c2fSopenharmony_ci#include "identity_checker_impl.h"
2522736c2fSopenharmony_ci#include "ime_cfg_manager.h"
2622736c2fSopenharmony_ci#include "ime_connection.h"
2722736c2fSopenharmony_ci#include "ime_info_inquirer.h"
2822736c2fSopenharmony_ci#include "input_control_channel_stub.h"
2922736c2fSopenharmony_ci#include "input_type_manager.h"
3022736c2fSopenharmony_ci#include "ipc_skeleton.h"
3122736c2fSopenharmony_ci#include "iservice_registry.h"
3222736c2fSopenharmony_ci#include "mem_mgr_client.h"
3322736c2fSopenharmony_ci#include "message_parcel.h"
3422736c2fSopenharmony_ci#include "os_account_adapter.h"
3522736c2fSopenharmony_ci#include "parcel.h"
3622736c2fSopenharmony_ci#include "running_process_info.h"
3722736c2fSopenharmony_ci#include "scene_board_judgement.h"
3822736c2fSopenharmony_ci#include "security_mode_parser.h"
3922736c2fSopenharmony_ci#include "system_ability_definition.h"
4022736c2fSopenharmony_ci#include "unistd.h"
4122736c2fSopenharmony_ci#include "wms_connection_observer.h"
4222736c2fSopenharmony_ci
4322736c2fSopenharmony_cinamespace OHOS {
4422736c2fSopenharmony_cinamespace MiscServices {
4522736c2fSopenharmony_ciusing namespace std::chrono;
4622736c2fSopenharmony_ciusing namespace MessageID;
4722736c2fSopenharmony_ciusing namespace OHOS::AppExecFwk;
4822736c2fSopenharmony_ciconstexpr int64_t INVALID_PID = -1;
4922736c2fSopenharmony_ciconstexpr uint32_t STOP_IME_TIME = 600;
5022736c2fSopenharmony_ciconstexpr const char *STRICT_MODE = "strictMode";
5122736c2fSopenharmony_ciconstexpr const char *ISOLATED_SANDBOX = "isolatedSandbox";
5222736c2fSopenharmony_ciconstexpr uint32_t CHECK_IME_RUNNING_RETRY_INTERVAL = 60;
5322736c2fSopenharmony_ciconstexpr uint32_t CHECK_IME_RUNNING_RETRY_TIMES = 10;
5422736c2fSopenharmony_ciPerUserSession::PerUserSession(int userId) : userId_(userId)
5522736c2fSopenharmony_ci{
5622736c2fSopenharmony_ci}
5722736c2fSopenharmony_ci
5822736c2fSopenharmony_ciPerUserSession::PerUserSession(int32_t userId, const std::shared_ptr<AppExecFwk::EventHandler> &eventHandler)
5922736c2fSopenharmony_ci    : userId_(userId), eventHandler_(eventHandler)
6022736c2fSopenharmony_ci{
6122736c2fSopenharmony_ci    auto bundleNames = ImeInfoInquirer::GetInstance().GetRunningIme(userId_);
6222736c2fSopenharmony_ci    if (!bundleNames.empty()) {
6322736c2fSopenharmony_ci        runningIme_ = bundleNames[0]; // one user only has one ime at present
6422736c2fSopenharmony_ci    }
6522736c2fSopenharmony_ci}
6622736c2fSopenharmony_ci
6722736c2fSopenharmony_ciPerUserSession::~PerUserSession()
6822736c2fSopenharmony_ci{
6922736c2fSopenharmony_ci}
7022736c2fSopenharmony_ci
7122736c2fSopenharmony_ciint PerUserSession::AddClientInfo(sptr<IRemoteObject> inputClient, const InputClientInfo &clientInfo,
7222736c2fSopenharmony_ci    ClientAddEvent event)
7322736c2fSopenharmony_ci{
7422736c2fSopenharmony_ci    IMSA_HILOGD("PerUserSession start.");
7522736c2fSopenharmony_ci    auto cacheInfo = GetClientInfo(inputClient);
7622736c2fSopenharmony_ci    if (cacheInfo != nullptr) {
7722736c2fSopenharmony_ci        IMSA_HILOGD("info is existed.");
7822736c2fSopenharmony_ci        if (cacheInfo->uiExtensionTokenId == IMF_INVALID_TOKENID &&
7922736c2fSopenharmony_ci            clientInfo.uiExtensionTokenId != IMF_INVALID_TOKENID) {
8022736c2fSopenharmony_ci            UpdateClientInfo(inputClient, { { UpdateFlag::UIEXTENSION_TOKENID, clientInfo.uiExtensionTokenId } });
8122736c2fSopenharmony_ci        }
8222736c2fSopenharmony_ci        UpdateClientInfo(inputClient, { { UpdateFlag::TEXT_CONFIG, clientInfo.config } });
8322736c2fSopenharmony_ci        if (event == START_LISTENING) {
8422736c2fSopenharmony_ci            UpdateClientInfo(inputClient, { { UpdateFlag::EVENTFLAG, clientInfo.eventFlag } });
8522736c2fSopenharmony_ci        }
8622736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
8722736c2fSopenharmony_ci    }
8822736c2fSopenharmony_ci    auto info = std::make_shared<InputClientInfo>(clientInfo);
8922736c2fSopenharmony_ci    std::weak_ptr<InputClientInfo> weakClientInfo = info;
9022736c2fSopenharmony_ci    info->deathRecipient->SetDeathRecipient([this, weakClientInfo](const wptr<IRemoteObject> &) {
9122736c2fSopenharmony_ci        auto clientInfo = weakClientInfo.lock();
9222736c2fSopenharmony_ci        if (clientInfo == nullptr) {
9322736c2fSopenharmony_ci            IMSA_HILOGD("clientInfo is nullptr.");
9422736c2fSopenharmony_ci            return;
9522736c2fSopenharmony_ci        }
9622736c2fSopenharmony_ci        this->OnClientDied(clientInfo->client);
9722736c2fSopenharmony_ci    });
9822736c2fSopenharmony_ci    auto obj = info->client->AsObject();
9922736c2fSopenharmony_ci    if (obj == nullptr) {
10022736c2fSopenharmony_ci        IMSA_HILOGE("client obj is nullptr!");
10122736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NULL_POINTER;
10222736c2fSopenharmony_ci    }
10322736c2fSopenharmony_ci    if (obj->IsProxyObject() && !obj->AddDeathRecipient(info->deathRecipient)) {
10422736c2fSopenharmony_ci        IMSA_HILOGE("failed to add client death recipient!");
10522736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_ADD_FAILED;
10622736c2fSopenharmony_ci    }
10722736c2fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mtx);
10822736c2fSopenharmony_ci    mapClients_.insert({ inputClient, info });
10922736c2fSopenharmony_ci    IMSA_HILOGI("add client end.");
11022736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
11122736c2fSopenharmony_ci}
11222736c2fSopenharmony_ci
11322736c2fSopenharmony_civoid PerUserSession::RemoveClientInfo(const sptr<IRemoteObject> &client, bool isClientDied)
11422736c2fSopenharmony_ci{
11522736c2fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mtx);
11622736c2fSopenharmony_ci    auto clientInfo = GetClientInfo(client);
11722736c2fSopenharmony_ci    if (clientInfo == nullptr) {
11822736c2fSopenharmony_ci        IMSA_HILOGD("client already removed.");
11922736c2fSopenharmony_ci        return;
12022736c2fSopenharmony_ci    }
12122736c2fSopenharmony_ci    // if client is subscriber and the release is not because of the client died, do not remove
12222736c2fSopenharmony_ci    if (clientInfo->eventFlag != NO_EVENT_ON && !isClientDied) {
12322736c2fSopenharmony_ci        IMSA_HILOGD("is subscriber, do not remove.");
12422736c2fSopenharmony_ci        auto isShowKeyboard = false;
12522736c2fSopenharmony_ci        auto bindImeType = ImeType::NONE;
12622736c2fSopenharmony_ci        UpdateClientInfo(client,
12722736c2fSopenharmony_ci            { { UpdateFlag::BINDIMETYPE, bindImeType }, { UpdateFlag::ISSHOWKEYBOARD, isShowKeyboard } });
12822736c2fSopenharmony_ci        return;
12922736c2fSopenharmony_ci    }
13022736c2fSopenharmony_ci    if (clientInfo->deathRecipient != nullptr) {
13122736c2fSopenharmony_ci        IMSA_HILOGD("deathRecipient remove.");
13222736c2fSopenharmony_ci        client->RemoveDeathRecipient(clientInfo->deathRecipient);
13322736c2fSopenharmony_ci    }
13422736c2fSopenharmony_ci    mapClients_.erase(client);
13522736c2fSopenharmony_ci    IMSA_HILOGI("client[%{public}d] is removed.", clientInfo->pid);
13622736c2fSopenharmony_ci}
13722736c2fSopenharmony_ci
13822736c2fSopenharmony_civoid PerUserSession::UpdateClientInfo(const sptr<IRemoteObject> &client, const std::unordered_map<UpdateFlag,
13922736c2fSopenharmony_ci    std::variant<bool, uint32_t, ImeType, ClientState, TextTotalConfig>> &updateInfos)
14022736c2fSopenharmony_ci{
14122736c2fSopenharmony_ci    if (client == nullptr) {
14222736c2fSopenharmony_ci        IMSA_HILOGE("client is nullptr!");
14322736c2fSopenharmony_ci        return;
14422736c2fSopenharmony_ci    }
14522736c2fSopenharmony_ci    auto info = GetClientInfo(client);
14622736c2fSopenharmony_ci    if (info == nullptr) {
14722736c2fSopenharmony_ci        IMSA_HILOGE("client info is not exist!");
14822736c2fSopenharmony_ci        return;
14922736c2fSopenharmony_ci    }
15022736c2fSopenharmony_ci    for (const auto &updateInfo : updateInfos) {
15122736c2fSopenharmony_ci        switch (updateInfo.first) {
15222736c2fSopenharmony_ci            case UpdateFlag::EVENTFLAG: {
15322736c2fSopenharmony_ci                info->eventFlag = std::get<uint32_t>(updateInfo.second);
15422736c2fSopenharmony_ci                break;
15522736c2fSopenharmony_ci            }
15622736c2fSopenharmony_ci            case UpdateFlag::ISSHOWKEYBOARD: {
15722736c2fSopenharmony_ci                info->isShowKeyboard = std::get<bool>(updateInfo.second);
15822736c2fSopenharmony_ci                break;
15922736c2fSopenharmony_ci            }
16022736c2fSopenharmony_ci            case UpdateFlag::BINDIMETYPE: {
16122736c2fSopenharmony_ci                info->bindImeType = std::get<ImeType>(updateInfo.second);
16222736c2fSopenharmony_ci                break;
16322736c2fSopenharmony_ci            }
16422736c2fSopenharmony_ci            case UpdateFlag::STATE: {
16522736c2fSopenharmony_ci                info->state = std::get<ClientState>(updateInfo.second);
16622736c2fSopenharmony_ci                break;
16722736c2fSopenharmony_ci            }
16822736c2fSopenharmony_ci            case UpdateFlag::TEXT_CONFIG: {
16922736c2fSopenharmony_ci                info->config = std::get<TextTotalConfig>(updateInfo.second);
17022736c2fSopenharmony_ci                break;
17122736c2fSopenharmony_ci            }
17222736c2fSopenharmony_ci            case UpdateFlag::UIEXTENSION_TOKENID: {
17322736c2fSopenharmony_ci                info->uiExtensionTokenId = std::get<uint32_t>(updateInfo.second);
17422736c2fSopenharmony_ci                break;
17522736c2fSopenharmony_ci            }
17622736c2fSopenharmony_ci            default:
17722736c2fSopenharmony_ci                break;
17822736c2fSopenharmony_ci        }
17922736c2fSopenharmony_ci    }
18022736c2fSopenharmony_ci}
18122736c2fSopenharmony_ci
18222736c2fSopenharmony_ciint32_t PerUserSession::HideKeyboard(const sptr<IInputClient> &currentClient)
18322736c2fSopenharmony_ci{
18422736c2fSopenharmony_ci    IMSA_HILOGD("PerUserSession::HideKeyboard start.");
18522736c2fSopenharmony_ci    auto clientInfo = GetClientInfo(currentClient->AsObject());
18622736c2fSopenharmony_ci    if (clientInfo == nullptr) {
18722736c2fSopenharmony_ci        IMSA_HILOGE("client info is nullptr!");
18822736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NOT_FOUND;
18922736c2fSopenharmony_ci    }
19022736c2fSopenharmony_ci    auto data = GetReadyImeData(clientInfo->bindImeType);
19122736c2fSopenharmony_ci    if (data == nullptr) {
19222736c2fSopenharmony_ci        IMSA_HILOGE("ime: %{public}d is not exist!", clientInfo->bindImeType);
19322736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_NOT_STARTED;
19422736c2fSopenharmony_ci    }
19522736c2fSopenharmony_ci    auto ret = RequestIme(data, RequestType::NORMAL, [&data] { return data->core->HideKeyboard(false); });
19622736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
19722736c2fSopenharmony_ci        IMSA_HILOGE("failed to hide keyboard, ret: %{public}d!", ret);
19822736c2fSopenharmony_ci        return ErrorCode::ERROR_KBD_HIDE_FAILED;
19922736c2fSopenharmony_ci    }
20022736c2fSopenharmony_ci    bool isShowKeyboard = false;
20122736c2fSopenharmony_ci    UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, isShowKeyboard } });
20222736c2fSopenharmony_ci    RestoreCurrentImeSubType();
20322736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
20422736c2fSopenharmony_ci}
20522736c2fSopenharmony_ci
20622736c2fSopenharmony_ciint32_t PerUserSession::ShowKeyboard(const sptr<IInputClient> &currentClient)
20722736c2fSopenharmony_ci{
20822736c2fSopenharmony_ci    IMSA_HILOGD("PerUserSession::ShowKeyboard start.");
20922736c2fSopenharmony_ci    auto clientInfo = GetClientInfo(currentClient->AsObject());
21022736c2fSopenharmony_ci    if (clientInfo == nullptr) {
21122736c2fSopenharmony_ci        IMSA_HILOGE("client info is nullptr!");
21222736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NOT_FOUND;
21322736c2fSopenharmony_ci    }
21422736c2fSopenharmony_ci    auto data = GetReadyImeData(clientInfo->bindImeType);
21522736c2fSopenharmony_ci    if (data == nullptr) {
21622736c2fSopenharmony_ci        IMSA_HILOGE("ime: %{public}d is not exist!", clientInfo->bindImeType);
21722736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_NOT_STARTED;
21822736c2fSopenharmony_ci    }
21922736c2fSopenharmony_ci    auto ret = RequestIme(data, RequestType::REQUEST_SHOW, [&data] { return data->core->ShowKeyboard(); });
22022736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
22122736c2fSopenharmony_ci        IMSA_HILOGE("failed to show keyboard, ret: %{public}d!", ret);
22222736c2fSopenharmony_ci        return ErrorCode::ERROR_KBD_SHOW_FAILED;
22322736c2fSopenharmony_ci    }
22422736c2fSopenharmony_ci    bool isShowKeyboard = true;
22522736c2fSopenharmony_ci    UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, isShowKeyboard } });
22622736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
22722736c2fSopenharmony_ci}
22822736c2fSopenharmony_ci
22922736c2fSopenharmony_ci/** Handle the situation a remote input client died.
23022736c2fSopenharmony_ci * It's called when a remote input client died
23122736c2fSopenharmony_ci * @param the remote object handler of the input client died.
23222736c2fSopenharmony_ci */
23322736c2fSopenharmony_civoid PerUserSession::OnClientDied(sptr<IInputClient> remote)
23422736c2fSopenharmony_ci{
23522736c2fSopenharmony_ci    if (remote == nullptr) {
23622736c2fSopenharmony_ci        return;
23722736c2fSopenharmony_ci    }
23822736c2fSopenharmony_ci    auto clientInfo = GetClientInfo(remote->AsObject());
23922736c2fSopenharmony_ci    IMSA_HILOGI("userId: %{public}d.", userId_);
24022736c2fSopenharmony_ci    if (IsSameClient(remote, GetCurrentClient())) {
24122736c2fSopenharmony_ci        if (clientInfo != nullptr) {
24222736c2fSopenharmony_ci            StopImeInput(clientInfo->bindImeType, clientInfo->channel);
24322736c2fSopenharmony_ci        }
24422736c2fSopenharmony_ci        SetCurrentClient(nullptr);
24522736c2fSopenharmony_ci        RestoreCurrentImeSubType();
24622736c2fSopenharmony_ci    }
24722736c2fSopenharmony_ci    if (IsSameClient(remote, GetInactiveClient())) {
24822736c2fSopenharmony_ci        if (clientInfo != nullptr) {
24922736c2fSopenharmony_ci            StopImeInput(clientInfo->bindImeType, clientInfo->channel);
25022736c2fSopenharmony_ci        }
25122736c2fSopenharmony_ci        SetInactiveClient(nullptr);
25222736c2fSopenharmony_ci        RestoreCurrentImeSubType();
25322736c2fSopenharmony_ci    }
25422736c2fSopenharmony_ci    RemoveClientInfo(remote->AsObject(), true);
25522736c2fSopenharmony_ci}
25622736c2fSopenharmony_ci
25722736c2fSopenharmony_ci/** Handle the situation that an ime died
25822736c2fSopenharmony_ci * It's called when an ime died
25922736c2fSopenharmony_ci * @param the remote object handler of the ime who died.
26022736c2fSopenharmony_ci */
26122736c2fSopenharmony_civoid PerUserSession::OnImeDied(const sptr<IInputMethodCore> &remote, ImeType type)
26222736c2fSopenharmony_ci{
26322736c2fSopenharmony_ci    if (remote == nullptr) {
26422736c2fSopenharmony_ci        return;
26522736c2fSopenharmony_ci    }
26622736c2fSopenharmony_ci    IMSA_HILOGI("type: %{public}d.", type);
26722736c2fSopenharmony_ci    auto imeData = GetImeData(type);
26822736c2fSopenharmony_ci    auto ime = InputTypeManager::GetInstance().GetCurrentIme();
26922736c2fSopenharmony_ci    if (ime.bundleName == imeData->ime.first) {
27022736c2fSopenharmony_ci        InputTypeManager::GetInstance().Set(false);
27122736c2fSopenharmony_ci    }
27222736c2fSopenharmony_ci    if (imeData != nullptr && imeData->imeStatus == ImeStatus::EXITING) {
27322736c2fSopenharmony_ci        RemoveImeData(type, true);
27422736c2fSopenharmony_ci        NotifyImeStopFinished();
27522736c2fSopenharmony_ci        IMSA_HILOGI("%{public}d not current imeData.", type);
27622736c2fSopenharmony_ci        return;
27722736c2fSopenharmony_ci    }
27822736c2fSopenharmony_ci    RemoveImeData(type, true);
27922736c2fSopenharmony_ci    if (!OsAccountAdapter::IsOsAccountForeground(userId_)) {
28022736c2fSopenharmony_ci        IMSA_HILOGW("userId:%{public}d in background, no need to restart ime.", userId_);
28122736c2fSopenharmony_ci        return;
28222736c2fSopenharmony_ci    }
28322736c2fSopenharmony_ci    auto client = GetCurrentClient();
28422736c2fSopenharmony_ci    auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
28522736c2fSopenharmony_ci    if (clientInfo != nullptr && clientInfo->bindImeType == type) {
28622736c2fSopenharmony_ci        StopClientInput(clientInfo);
28722736c2fSopenharmony_ci        if (type == ImeType::IME) {
28822736c2fSopenharmony_ci            StartImeInImeDied();
28922736c2fSopenharmony_ci        }
29022736c2fSopenharmony_ci        return;
29122736c2fSopenharmony_ci    }
29222736c2fSopenharmony_ci    auto currentImeInfo = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
29322736c2fSopenharmony_ci    if (currentImeInfo == nullptr) {
29422736c2fSopenharmony_ci        IMSA_HILOGE("currentImeInfo is nullptr!");
29522736c2fSopenharmony_ci        return;
29622736c2fSopenharmony_ci    }
29722736c2fSopenharmony_ci    auto defaultImeInfo = ImeInfoInquirer::GetInstance().GetDefaultImeCfgProp();
29822736c2fSopenharmony_ci    if (defaultImeInfo == nullptr) {
29922736c2fSopenharmony_ci        IMSA_HILOGE("defaultImeInfo is nullptr!");
30022736c2fSopenharmony_ci        return;
30122736c2fSopenharmony_ci    }
30222736c2fSopenharmony_ci    if (type == ImeType::IME && currentImeInfo->bundleName == defaultImeInfo->name) {
30322736c2fSopenharmony_ci        StartImeInImeDied();
30422736c2fSopenharmony_ci    }
30522736c2fSopenharmony_ci}
30622736c2fSopenharmony_ci
30722736c2fSopenharmony_ciint32_t PerUserSession::RemoveIme(const sptr<IInputMethodCore> &core, ImeType type)
30822736c2fSopenharmony_ci{
30922736c2fSopenharmony_ci    if (core == nullptr) {
31022736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
31122736c2fSopenharmony_ci    }
31222736c2fSopenharmony_ci    auto data = GetReadyImeData(type);
31322736c2fSopenharmony_ci    if (data == nullptr || data->core->AsObject() != core->AsObject()) {
31422736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_NOT_STARTED;
31522736c2fSopenharmony_ci    }
31622736c2fSopenharmony_ci
31722736c2fSopenharmony_ci    auto client = GetCurrentClient();
31822736c2fSopenharmony_ci    auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
31922736c2fSopenharmony_ci    if (clientInfo != nullptr && clientInfo->bindImeType == type) {
32022736c2fSopenharmony_ci        UnBindClientWithIme(clientInfo);
32122736c2fSopenharmony_ci    }
32222736c2fSopenharmony_ci    RemoveImeData(type, true);
32322736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
32422736c2fSopenharmony_ci}
32522736c2fSopenharmony_ci
32622736c2fSopenharmony_ciint32_t PerUserSession::OnHideCurrentInput()
32722736c2fSopenharmony_ci{
32822736c2fSopenharmony_ci    sptr<IInputClient> client = GetCurrentClient();
32922736c2fSopenharmony_ci    if (client == nullptr) {
33022736c2fSopenharmony_ci        IMSA_HILOGE("current client is nullptr!");
33122736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NOT_FOUND;
33222736c2fSopenharmony_ci    }
33322736c2fSopenharmony_ci    return HideKeyboard(client);
33422736c2fSopenharmony_ci}
33522736c2fSopenharmony_ci
33622736c2fSopenharmony_ciint32_t PerUserSession::OnShowCurrentInput()
33722736c2fSopenharmony_ci{
33822736c2fSopenharmony_ci    IMSA_HILOGD("PerUserSession::OnShowCurrentInput start.");
33922736c2fSopenharmony_ci    sptr<IInputClient> client = GetCurrentClient();
34022736c2fSopenharmony_ci    if (client == nullptr) {
34122736c2fSopenharmony_ci        IMSA_HILOGE("current client is nullptr!");
34222736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NOT_FOUND;
34322736c2fSopenharmony_ci    }
34422736c2fSopenharmony_ci    return ShowKeyboard(client);
34522736c2fSopenharmony_ci}
34622736c2fSopenharmony_ci
34722736c2fSopenharmony_ciint32_t PerUserSession::OnHideInput(sptr<IInputClient> client)
34822736c2fSopenharmony_ci{
34922736c2fSopenharmony_ci    IMSA_HILOGD("PerUserSession::OnHideInput start.");
35022736c2fSopenharmony_ci    if (!IsSameClient(client, GetCurrentClient())) {
35122736c2fSopenharmony_ci        IMSA_HILOGE("client is not current client!");
35222736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
35322736c2fSopenharmony_ci    }
35422736c2fSopenharmony_ci    return HideKeyboard(client);
35522736c2fSopenharmony_ci}
35622736c2fSopenharmony_ci
35722736c2fSopenharmony_ciint32_t PerUserSession::OnShowInput(sptr<IInputClient> client)
35822736c2fSopenharmony_ci{
35922736c2fSopenharmony_ci    IMSA_HILOGD("PerUserSession::OnShowInput start.");
36022736c2fSopenharmony_ci    if (!IsSameClient(client, GetCurrentClient())) {
36122736c2fSopenharmony_ci        IMSA_HILOGE("client is not current client!");
36222736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
36322736c2fSopenharmony_ci    }
36422736c2fSopenharmony_ci    return ShowKeyboard(client);
36522736c2fSopenharmony_ci}
36622736c2fSopenharmony_ci
36722736c2fSopenharmony_civoid PerUserSession::OnHideSoftKeyBoardSelf()
36822736c2fSopenharmony_ci{
36922736c2fSopenharmony_ci    IMSA_HILOGD("PerUserSession::OnHideSoftKeyBoardSel start.");
37022736c2fSopenharmony_ci    sptr<IInputClient> client = GetCurrentClient();
37122736c2fSopenharmony_ci    if (client == nullptr) {
37222736c2fSopenharmony_ci        IMSA_HILOGE("current client is nullptr!");
37322736c2fSopenharmony_ci        return;
37422736c2fSopenharmony_ci    }
37522736c2fSopenharmony_ci    UpdateClientInfo(client->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, false } });
37622736c2fSopenharmony_ci    RestoreCurrentImeSubType();
37722736c2fSopenharmony_ci}
37822736c2fSopenharmony_ci
37922736c2fSopenharmony_ciint32_t PerUserSession::OnRequestShowInput()
38022736c2fSopenharmony_ci{
38122736c2fSopenharmony_ci    IMSA_HILOGD("PerUserSession::OnRequestShowInput start.");
38222736c2fSopenharmony_ci    auto data = GetReadyImeData(ImeType::IME);
38322736c2fSopenharmony_ci    if (data == nullptr) {
38422736c2fSopenharmony_ci        IMSA_HILOGE("ime: %{public}d doesn't exist!", ImeType::IME);
38522736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_NOT_STARTED;
38622736c2fSopenharmony_ci    }
38722736c2fSopenharmony_ci    auto ret = RequestIme(data, RequestType::REQUEST_SHOW, [&data] { return data->core->ShowKeyboard(); });
38822736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
38922736c2fSopenharmony_ci        IMSA_HILOGE("failed to show keyboard, ret: %{public}d!", ret);
39022736c2fSopenharmony_ci        return ErrorCode::ERROR_KBD_SHOW_FAILED;
39122736c2fSopenharmony_ci    }
39222736c2fSopenharmony_ci    InputMethodSysEvent::GetInstance().ReportImeState(ImeState::BIND, data->pid,
39322736c2fSopenharmony_ci        ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName);
39422736c2fSopenharmony_ci    Memory::MemMgrClient::GetInstance().SetCritical(getpid(), true, INPUT_METHOD_SYSTEM_ABILITY_ID);
39522736c2fSopenharmony_ci    auto currentClient = GetCurrentClient();
39622736c2fSopenharmony_ci    if (currentClient != nullptr) {
39722736c2fSopenharmony_ci        UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, true } });
39822736c2fSopenharmony_ci    }
39922736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
40022736c2fSopenharmony_ci}
40122736c2fSopenharmony_ci
40222736c2fSopenharmony_ciint32_t PerUserSession::OnRequestHideInput()
40322736c2fSopenharmony_ci{
40422736c2fSopenharmony_ci    IMSA_HILOGD("PerUserSession::OnRequestHideInput start.");
40522736c2fSopenharmony_ci    auto data = GetReadyImeData(ImeType::IME);
40622736c2fSopenharmony_ci    if (data == nullptr) {
40722736c2fSopenharmony_ci        IMSA_HILOGE("ime: %{public}d doesn't exist!", ImeType::IME);
40822736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_NOT_STARTED;
40922736c2fSopenharmony_ci    }
41022736c2fSopenharmony_ci
41122736c2fSopenharmony_ci    bool isForce = false;
41222736c2fSopenharmony_ci    if (!data->freezeMgr->IsIpcNeeded(RequestType::REQUEST_HIDE)) {
41322736c2fSopenharmony_ci        IMSA_HILOGD("need to force hide");
41422736c2fSopenharmony_ci        isForce = true;
41522736c2fSopenharmony_ci    }
41622736c2fSopenharmony_ci    auto ret = RequestIme(data, RequestType::REQUEST_HIDE,
41722736c2fSopenharmony_ci        [&data, isForce] { return data->core->HideKeyboard(isForce); });
41822736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
41922736c2fSopenharmony_ci        IMSA_HILOGE("failed to hide keyboard, ret: %{public}d!", ret);
42022736c2fSopenharmony_ci        return ErrorCode::ERROR_KBD_HIDE_FAILED;
42122736c2fSopenharmony_ci    }
42222736c2fSopenharmony_ci    auto currentClient = GetCurrentClient();
42322736c2fSopenharmony_ci    if (currentClient != nullptr) {
42422736c2fSopenharmony_ci        UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, false } });
42522736c2fSopenharmony_ci    }
42622736c2fSopenharmony_ci    auto inactiveClient = GetInactiveClient();
42722736c2fSopenharmony_ci    if (inactiveClient != nullptr) {
42822736c2fSopenharmony_ci        RemoveClient(inactiveClient, false, true);
42922736c2fSopenharmony_ci    }
43022736c2fSopenharmony_ci    RestoreCurrentImeSubType();
43122736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
43222736c2fSopenharmony_ci}
43322736c2fSopenharmony_ci
43422736c2fSopenharmony_ci/** Get ClientInfo
43522736c2fSopenharmony_ci * @param inputClient the IRemoteObject remote handler of given input client
43622736c2fSopenharmony_ci * @return a pointer of ClientInfo if client is found
43722736c2fSopenharmony_ci *         null if client is not found
43822736c2fSopenharmony_ci * @note the clientInfo pointer should not be freed by caller
43922736c2fSopenharmony_ci */
44022736c2fSopenharmony_cistd::shared_ptr<InputClientInfo> PerUserSession::GetClientInfo(sptr<IRemoteObject> inputClient)
44122736c2fSopenharmony_ci{
44222736c2fSopenharmony_ci    if (inputClient == nullptr) {
44322736c2fSopenharmony_ci        IMSA_HILOGE("inputClient is nullptr!");
44422736c2fSopenharmony_ci        return nullptr;
44522736c2fSopenharmony_ci    }
44622736c2fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mtx);
44722736c2fSopenharmony_ci    auto it = mapClients_.find(inputClient);
44822736c2fSopenharmony_ci    if (it == mapClients_.end()) {
44922736c2fSopenharmony_ci        IMSA_HILOGD("client not found.");
45022736c2fSopenharmony_ci        return nullptr;
45122736c2fSopenharmony_ci    }
45222736c2fSopenharmony_ci    return it->second;
45322736c2fSopenharmony_ci}
45422736c2fSopenharmony_ci
45522736c2fSopenharmony_cistd::shared_ptr<InputClientInfo> PerUserSession::GetClientInfo(pid_t pid)
45622736c2fSopenharmony_ci{
45722736c2fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mtx);
45822736c2fSopenharmony_ci    auto iter = std::find_if(mapClients_.begin(), mapClients_.end(),
45922736c2fSopenharmony_ci        [pid](const auto &mapClient) { return mapClient.second->pid == pid; });
46022736c2fSopenharmony_ci    if (iter == mapClients_.end()) {
46122736c2fSopenharmony_ci        IMSA_HILOGD("not found.");
46222736c2fSopenharmony_ci        return nullptr;
46322736c2fSopenharmony_ci    }
46422736c2fSopenharmony_ci    return iter->second;
46522736c2fSopenharmony_ci}
46622736c2fSopenharmony_ci
46722736c2fSopenharmony_ciint32_t PerUserSession::OnPrepareInput(const InputClientInfo &clientInfo)
46822736c2fSopenharmony_ci{
46922736c2fSopenharmony_ci    IMSA_HILOGD("PerUserSession::OnPrepareInput start");
47022736c2fSopenharmony_ci    return AddClientInfo(clientInfo.client->AsObject(), clientInfo, PREPARE_INPUT);
47122736c2fSopenharmony_ci}
47222736c2fSopenharmony_ci
47322736c2fSopenharmony_ci/** Release input. Called by an input client.Run in work thread of this user
47422736c2fSopenharmony_ci * @param the parameters from remote client
47522736c2fSopenharmony_ci * @return ErrorCode
47622736c2fSopenharmony_ci */
47722736c2fSopenharmony_ciint32_t PerUserSession::OnReleaseInput(const sptr<IInputClient> &client)
47822736c2fSopenharmony_ci{
47922736c2fSopenharmony_ci    IMSA_HILOGD("PerUserSession::OnReleaseInput start");
48022736c2fSopenharmony_ci    return RemoveClient(client, true);
48122736c2fSopenharmony_ci}
48222736c2fSopenharmony_ci
48322736c2fSopenharmony_ciint32_t PerUserSession::RemoveClient(const sptr<IInputClient> &client, bool isUnbindFromClient, bool isInactiveClient)
48422736c2fSopenharmony_ci{
48522736c2fSopenharmony_ci    if (client == nullptr) {
48622736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NULL_POINTER;
48722736c2fSopenharmony_ci    }
48822736c2fSopenharmony_ci    // if client is current client, unbind firstly
48922736c2fSopenharmony_ci    auto clientInfo = GetClientInfo(client->AsObject());
49022736c2fSopenharmony_ci    if (IsSameClient(client, GetCurrentClient())) {
49122736c2fSopenharmony_ci        UnBindClientWithIme(clientInfo, isUnbindFromClient);
49222736c2fSopenharmony_ci        SetCurrentClient(nullptr);
49322736c2fSopenharmony_ci        RestoreCurrentImeSubType();
49422736c2fSopenharmony_ci        StopClientInput(clientInfo);
49522736c2fSopenharmony_ci    }
49622736c2fSopenharmony_ci    if (IsSameClient(client, GetInactiveClient())) {
49722736c2fSopenharmony_ci        SetInactiveClient(nullptr);
49822736c2fSopenharmony_ci        StopClientInput(clientInfo, isInactiveClient);
49922736c2fSopenharmony_ci    }
50022736c2fSopenharmony_ci    RemoveClientInfo(client->AsObject());
50122736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
50222736c2fSopenharmony_ci}
50322736c2fSopenharmony_ci
50422736c2fSopenharmony_civoid PerUserSession::DeactivateClient(const sptr<IInputClient> &client)
50522736c2fSopenharmony_ci{
50622736c2fSopenharmony_ci    if (client == nullptr) {
50722736c2fSopenharmony_ci        IMSA_HILOGD("client is nullptr.");
50822736c2fSopenharmony_ci        return;
50922736c2fSopenharmony_ci    }
51022736c2fSopenharmony_ci    auto clientInfo = GetClientInfo(client->AsObject());
51122736c2fSopenharmony_ci    if (clientInfo == nullptr) {
51222736c2fSopenharmony_ci        return;
51322736c2fSopenharmony_ci    }
51422736c2fSopenharmony_ci    IMSA_HILOGI("deactivate client[%{public}d].", clientInfo->pid);
51522736c2fSopenharmony_ci    UpdateClientInfo(client->AsObject(), { { UpdateFlag::STATE, ClientState::INACTIVE } });
51622736c2fSopenharmony_ci    if (IsSameClient(client, GetCurrentClient())) {
51722736c2fSopenharmony_ci        SetCurrentClient(nullptr);
51822736c2fSopenharmony_ci    }
51922736c2fSopenharmony_ci    SetInactiveClient(client);
52022736c2fSopenharmony_ci    client->DeactivateClient();
52122736c2fSopenharmony_ci    if (InputTypeManager::GetInstance().IsStarted()) {
52222736c2fSopenharmony_ci        RestoreCurrentImeSubType();
52322736c2fSopenharmony_ci        return;
52422736c2fSopenharmony_ci    }
52522736c2fSopenharmony_ci    auto data = GetReadyImeData(clientInfo->bindImeType);
52622736c2fSopenharmony_ci    if (data == nullptr) {
52722736c2fSopenharmony_ci        IMSA_HILOGE("ime %{public}d doesn't exist!", clientInfo->bindImeType);
52822736c2fSopenharmony_ci        return;
52922736c2fSopenharmony_ci    }
53022736c2fSopenharmony_ci    RequestIme(data, RequestType::NORMAL, [&data, &clientInfo] {
53122736c2fSopenharmony_ci        data->core->OnClientInactive(clientInfo->channel);
53222736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
53322736c2fSopenharmony_ci    });
53422736c2fSopenharmony_ci    InputMethodSysEvent::GetInstance().ReportImeState(ImeState::UNBIND, data->pid,
53522736c2fSopenharmony_ci        ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName);
53622736c2fSopenharmony_ci    Memory::MemMgrClient::GetInstance().SetCritical(getpid(), false, INPUT_METHOD_SYSTEM_ABILITY_ID);
53722736c2fSopenharmony_ci}
53822736c2fSopenharmony_ci
53922736c2fSopenharmony_cibool PerUserSession::IsProxyImeEnable()
54022736c2fSopenharmony_ci{
54122736c2fSopenharmony_ci    auto data = GetReadyImeData(ImeType::PROXY_IME);
54222736c2fSopenharmony_ci    return data != nullptr && data->core != nullptr && data->core->IsEnable();
54322736c2fSopenharmony_ci}
54422736c2fSopenharmony_ci
54522736c2fSopenharmony_ciint32_t PerUserSession::OnStartInput(const InputClientInfo &inputClientInfo, sptr<IRemoteObject> &agent)
54622736c2fSopenharmony_ci{
54722736c2fSopenharmony_ci    const sptr<IInputClient> &client = inputClientInfo.client;
54822736c2fSopenharmony_ci    if (client == nullptr) {
54922736c2fSopenharmony_ci        IMSA_HILOGE("client is nullptr!");
55022736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NULL_POINTER;
55122736c2fSopenharmony_ci    }
55222736c2fSopenharmony_ci    auto clientInfo = GetClientInfo(client->AsObject());
55322736c2fSopenharmony_ci    if (clientInfo == nullptr) {
55422736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NOT_FOUND;
55522736c2fSopenharmony_ci    }
55622736c2fSopenharmony_ci    IMSA_HILOGD("start input with keyboard[%{public}d].", inputClientInfo.isShowKeyboard);
55722736c2fSopenharmony_ci    if (IsSameClient(client, GetCurrentClient()) && IsImeBindChanged(clientInfo->bindImeType)) {
55822736c2fSopenharmony_ci        UnBindClientWithIme(clientInfo);
55922736c2fSopenharmony_ci    }
56022736c2fSopenharmony_ci    InputClientInfo infoTemp = *clientInfo;
56122736c2fSopenharmony_ci    infoTemp.isShowKeyboard = inputClientInfo.isShowKeyboard;
56222736c2fSopenharmony_ci    infoTemp.isNotifyInputStart = inputClientInfo.isNotifyInputStart;
56322736c2fSopenharmony_ci    infoTemp.needHide = inputClientInfo.needHide;
56422736c2fSopenharmony_ci    auto imeType = IsProxyImeEnable() ? ImeType::PROXY_IME : ImeType::IME;
56522736c2fSopenharmony_ci    int32_t ret = BindClientWithIme(std::make_shared<InputClientInfo>(infoTemp), imeType, true);
56622736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
56722736c2fSopenharmony_ci        IMSA_HILOGE("bind failed, ret: %{public}d!", ret);
56822736c2fSopenharmony_ci        return ret;
56922736c2fSopenharmony_ci    }
57022736c2fSopenharmony_ci    auto data = GetReadyImeData(imeType);
57122736c2fSopenharmony_ci    if (data == nullptr || data->agent == nullptr) {
57222736c2fSopenharmony_ci        IMSA_HILOGE("data or agent is nullptr!");
57322736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_NOT_STARTED;
57422736c2fSopenharmony_ci    }
57522736c2fSopenharmony_ci    agent = data->agent;
57622736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
57722736c2fSopenharmony_ci}
57822736c2fSopenharmony_ci
57922736c2fSopenharmony_ciint32_t PerUserSession::BindClientWithIme(const std::shared_ptr<InputClientInfo> &clientInfo, ImeType type,
58022736c2fSopenharmony_ci    bool isBindFromClient)
58122736c2fSopenharmony_ci{
58222736c2fSopenharmony_ci    if (clientInfo == nullptr) {
58322736c2fSopenharmony_ci        IMSA_HILOGE("clientInfo is nullptr!");
58422736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
58522736c2fSopenharmony_ci    }
58622736c2fSopenharmony_ci    IMSA_HILOGD("imeType: %{public}d, isShowKeyboard: %{public}d, isBindFromClient: %{public}d.", type,
58722736c2fSopenharmony_ci        clientInfo->isShowKeyboard, isBindFromClient);
58822736c2fSopenharmony_ci    auto data = GetValidIme(type);
58922736c2fSopenharmony_ci    if (data == nullptr) {
59022736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_NOT_STARTED;
59122736c2fSopenharmony_ci    }
59222736c2fSopenharmony_ci    auto ret = RequestIme(data, RequestType::START_INPUT,
59322736c2fSopenharmony_ci        [&data, &clientInfo, isBindFromClient]() { return data->core->StartInput(*clientInfo, isBindFromClient); });
59422736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
59522736c2fSopenharmony_ci        IMSA_HILOGE("start input failed, ret: %{public}d!", ret);
59622736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_START_INPUT_FAILED;
59722736c2fSopenharmony_ci    }
59822736c2fSopenharmony_ci    if (type == ImeType::IME) {
59922736c2fSopenharmony_ci        InputMethodSysEvent::GetInstance().ReportImeState(ImeState::BIND, data->pid,
60022736c2fSopenharmony_ci            ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName);
60122736c2fSopenharmony_ci        Memory::MemMgrClient::GetInstance().SetCritical(getpid(), true, INPUT_METHOD_SYSTEM_ABILITY_ID);
60222736c2fSopenharmony_ci    }
60322736c2fSopenharmony_ci    if (!isBindFromClient && clientInfo->client->OnInputReady(data->agent) != ErrorCode::NO_ERROR) {
60422736c2fSopenharmony_ci        IMSA_HILOGE("start client input failed, ret: %{public}d!", ret);
60522736c2fSopenharmony_ci        return ErrorCode::ERROR_EX_PARCELABLE;
60622736c2fSopenharmony_ci    }
60722736c2fSopenharmony_ci    UpdateClientInfo(clientInfo->client->AsObject(),
60822736c2fSopenharmony_ci        { { UpdateFlag::BINDIMETYPE, type }, { UpdateFlag::ISSHOWKEYBOARD, clientInfo->isShowKeyboard },
60922736c2fSopenharmony_ci            { UpdateFlag::STATE, ClientState::ACTIVE } });
61022736c2fSopenharmony_ci    ReplaceCurrentClient(clientInfo->client);
61122736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
61222736c2fSopenharmony_ci}
61322736c2fSopenharmony_ci
61422736c2fSopenharmony_civoid PerUserSession::UnBindClientWithIme(const std::shared_ptr<InputClientInfo> &currentClientInfo,
61522736c2fSopenharmony_ci    bool isUnbindFromClient)
61622736c2fSopenharmony_ci{
61722736c2fSopenharmony_ci    if (currentClientInfo == nullptr) {
61822736c2fSopenharmony_ci        return;
61922736c2fSopenharmony_ci    }
62022736c2fSopenharmony_ci    if (!isUnbindFromClient) {
62122736c2fSopenharmony_ci        IMSA_HILOGD("unbind from service.");
62222736c2fSopenharmony_ci        StopClientInput(currentClientInfo);
62322736c2fSopenharmony_ci    }
62422736c2fSopenharmony_ci    StopImeInput(currentClientInfo->bindImeType, currentClientInfo->channel);
62522736c2fSopenharmony_ci}
62622736c2fSopenharmony_ci
62722736c2fSopenharmony_civoid PerUserSession::StopClientInput(const std::shared_ptr<InputClientInfo> &clientInfo, bool isStopInactiveClient)
62822736c2fSopenharmony_ci{
62922736c2fSopenharmony_ci    if (clientInfo == nullptr || clientInfo->client == nullptr) {
63022736c2fSopenharmony_ci        return;
63122736c2fSopenharmony_ci    }
63222736c2fSopenharmony_ci    auto ret = clientInfo->client->OnInputStop(isStopInactiveClient);
63322736c2fSopenharmony_ci    IMSA_HILOGI("isStopInactiveClient: %{public}d, client pid: %{public}d, ret: %{public}d.", isStopInactiveClient,
63422736c2fSopenharmony_ci        clientInfo->pid, ret);
63522736c2fSopenharmony_ci}
63622736c2fSopenharmony_ci
63722736c2fSopenharmony_civoid PerUserSession::StopImeInput(ImeType currentType, const sptr<IRemoteObject> &currentChannel)
63822736c2fSopenharmony_ci{
63922736c2fSopenharmony_ci    auto data = GetReadyImeData(currentType);
64022736c2fSopenharmony_ci    if (data == nullptr) {
64122736c2fSopenharmony_ci        return;
64222736c2fSopenharmony_ci    }
64322736c2fSopenharmony_ci    auto ret = RequestIme(data, RequestType::STOP_INPUT,
64422736c2fSopenharmony_ci        [&data, &currentChannel]() { return data->core->StopInput(currentChannel); });
64522736c2fSopenharmony_ci    IMSA_HILOGI("stop ime input, ret: %{public}d.", ret);
64622736c2fSopenharmony_ci    if (ret == ErrorCode::NO_ERROR && currentType == ImeType::IME) {
64722736c2fSopenharmony_ci        InputMethodSysEvent::GetInstance().ReportImeState(ImeState::UNBIND, data->pid,
64822736c2fSopenharmony_ci            ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName);
64922736c2fSopenharmony_ci        Memory::MemMgrClient::GetInstance().SetCritical(getpid(), false, INPUT_METHOD_SYSTEM_ABILITY_ID);
65022736c2fSopenharmony_ci    }
65122736c2fSopenharmony_ci    if (currentType == ImeType::IME) {
65222736c2fSopenharmony_ci        RestoreCurrentImeSubType();
65322736c2fSopenharmony_ci    }
65422736c2fSopenharmony_ci}
65522736c2fSopenharmony_ci
65622736c2fSopenharmony_civoid PerUserSession::OnSecurityChange(int32_t security)
65722736c2fSopenharmony_ci{
65822736c2fSopenharmony_ci    auto data = GetReadyImeData(ImeType::IME);
65922736c2fSopenharmony_ci    if (data == nullptr) {
66022736c2fSopenharmony_ci        IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME);
66122736c2fSopenharmony_ci        return;
66222736c2fSopenharmony_ci    }
66322736c2fSopenharmony_ci    auto ret =
66422736c2fSopenharmony_ci        RequestIme(data, RequestType::NORMAL, [&data, security] { return data->core->OnSecurityChange(security); });
66522736c2fSopenharmony_ci    IMSA_HILOGD("on security change, ret: %{public}d.", ret);
66622736c2fSopenharmony_ci}
66722736c2fSopenharmony_ci
66822736c2fSopenharmony_ciint32_t PerUserSession::OnSetCoreAndAgent(const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent)
66922736c2fSopenharmony_ci{
67022736c2fSopenharmony_ci    IMSA_HILOGI("start.");
67122736c2fSopenharmony_ci    auto ret = UpdateImeData(core, agent, IPCSkeleton::GetCallingPid());
67222736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
67322736c2fSopenharmony_ci        return ret;
67422736c2fSopenharmony_ci    }
67522736c2fSopenharmony_ci    auto action = GetImeAction(ImeEvent::SET_CORE_AND_AGENT);
67622736c2fSopenharmony_ci    if (action == ImeAction::DO_NOTHING) {
67722736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
67822736c2fSopenharmony_ci    }
67922736c2fSopenharmony_ci    if (action != ImeAction::DO_SET_CORE_AND_AGENT) {
68022736c2fSopenharmony_ci        return ErrorCode::ERROR_IME;
68122736c2fSopenharmony_ci    }
68222736c2fSopenharmony_ci    ret = InitInputControlChannel();
68322736c2fSopenharmony_ci    IMSA_HILOGI("init input control channel ret: %{public}d.", ret);
68422736c2fSopenharmony_ci    auto imeType = ImeType::IME;
68522736c2fSopenharmony_ci    auto client = GetCurrentClient();
68622736c2fSopenharmony_ci    auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
68722736c2fSopenharmony_ci    if (clientInfo != nullptr && IsImeStartInBind(clientInfo->bindImeType, imeType)) {
68822736c2fSopenharmony_ci        BindClientWithIme(clientInfo, imeType);
68922736c2fSopenharmony_ci    }
69022736c2fSopenharmony_ci    bool isStarted = true;
69122736c2fSopenharmony_ci    isImeStarted_.SetValue(isStarted);
69222736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
69322736c2fSopenharmony_ci}
69422736c2fSopenharmony_ci
69522736c2fSopenharmony_ciint32_t PerUserSession::OnRegisterProxyIme(const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent)
69622736c2fSopenharmony_ci{
69722736c2fSopenharmony_ci    IMSA_HILOGD("start.");
69822736c2fSopenharmony_ci    auto imeType = ImeType::PROXY_IME;
69922736c2fSopenharmony_ci    auto ret = AddImeData(imeType, core, agent, IPCSkeleton::GetCallingPid());
70022736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
70122736c2fSopenharmony_ci        return ret;
70222736c2fSopenharmony_ci    }
70322736c2fSopenharmony_ci    auto client = GetCurrentClient();
70422736c2fSopenharmony_ci    auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
70522736c2fSopenharmony_ci    if (clientInfo != nullptr) {
70622736c2fSopenharmony_ci        if (IsProxyImeStartInBind(clientInfo->bindImeType, imeType)) {
70722736c2fSopenharmony_ci            BindClientWithIme(clientInfo, imeType);
70822736c2fSopenharmony_ci        }
70922736c2fSopenharmony_ci        if (IsProxyImeStartInImeBind(clientInfo->bindImeType, imeType)) {
71022736c2fSopenharmony_ci            UnBindClientWithIme(clientInfo);
71122736c2fSopenharmony_ci            BindClientWithIme(clientInfo, imeType);
71222736c2fSopenharmony_ci        }
71322736c2fSopenharmony_ci    }
71422736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
71522736c2fSopenharmony_ci}
71622736c2fSopenharmony_ci
71722736c2fSopenharmony_ciint32_t PerUserSession::OnUnRegisteredProxyIme(UnRegisteredType type, const sptr<IInputMethodCore> &core)
71822736c2fSopenharmony_ci{
71922736c2fSopenharmony_ci    IMSA_HILOGD("proxy unregister type: %{public}d.", type);
72022736c2fSopenharmony_ci    // 0: stop proxy  1: switch to ima
72122736c2fSopenharmony_ci    if (type == UnRegisteredType::REMOVE_PROXY_IME) {
72222736c2fSopenharmony_ci        RemoveIme(core, ImeType::PROXY_IME);
72322736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
72422736c2fSopenharmony_ci    }
72522736c2fSopenharmony_ci    if (type == UnRegisteredType::SWITCH_PROXY_IME_TO_IME) {
72622736c2fSopenharmony_ci        auto client = GetCurrentClient();
72722736c2fSopenharmony_ci        auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
72822736c2fSopenharmony_ci        if (clientInfo == nullptr) {
72922736c2fSopenharmony_ci            IMSA_HILOGE("not found current client!");
73022736c2fSopenharmony_ci            return ErrorCode::ERROR_CLIENT_NOT_BOUND;
73122736c2fSopenharmony_ci        }
73222736c2fSopenharmony_ci        if (clientInfo->bindImeType == ImeType::PROXY_IME) {
73322736c2fSopenharmony_ci            UnBindClientWithIme(clientInfo);
73422736c2fSopenharmony_ci        }
73522736c2fSopenharmony_ci        InputClientInfo infoTemp = { .isShowKeyboard = true,
73622736c2fSopenharmony_ci            .client = clientInfo->client,
73722736c2fSopenharmony_ci            .channel = clientInfo->channel };
73822736c2fSopenharmony_ci        return BindClientWithIme(std::make_shared<InputClientInfo>(infoTemp), ImeType::IME);
73922736c2fSopenharmony_ci    }
74022736c2fSopenharmony_ci    return ErrorCode::ERROR_BAD_PARAMETERS;
74122736c2fSopenharmony_ci}
74222736c2fSopenharmony_ci
74322736c2fSopenharmony_ciint32_t PerUserSession::InitInputControlChannel()
74422736c2fSopenharmony_ci{
74522736c2fSopenharmony_ci    IMSA_HILOGD("PerUserSession::InitInputControlChannel start.");
74622736c2fSopenharmony_ci    sptr<IInputControlChannel> inputControlChannel = new InputControlChannelStub(userId_);
74722736c2fSopenharmony_ci    auto data = GetReadyImeData(ImeType::IME);
74822736c2fSopenharmony_ci    if (data == nullptr) {
74922736c2fSopenharmony_ci        IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME);
75022736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_NOT_STARTED;
75122736c2fSopenharmony_ci    }
75222736c2fSopenharmony_ci    return RequestIme(data, RequestType::NORMAL,
75322736c2fSopenharmony_ci        [&data, &inputControlChannel] { return data->core->InitInputControlChannel(inputControlChannel); });
75422736c2fSopenharmony_ci}
75522736c2fSopenharmony_ci
75622736c2fSopenharmony_civoid PerUserSession::StartImeInImeDied()
75722736c2fSopenharmony_ci{
75822736c2fSopenharmony_ci    IMSA_HILOGD("StartImeInImeDied.");
75922736c2fSopenharmony_ci    {
76022736c2fSopenharmony_ci        std::lock_guard<std::mutex> lock(resetLock);
76122736c2fSopenharmony_ci        auto now = time(nullptr);
76222736c2fSopenharmony_ci        if (difftime(now, manager.last) > IME_RESET_TIME_OUT) {
76322736c2fSopenharmony_ci            manager = { 0, now };
76422736c2fSopenharmony_ci        }
76522736c2fSopenharmony_ci        ++manager.num;
76622736c2fSopenharmony_ci        if (manager.num > MAX_RESTART_NUM) {
76722736c2fSopenharmony_ci            return;
76822736c2fSopenharmony_ci        }
76922736c2fSopenharmony_ci    }
77022736c2fSopenharmony_ci    if (!IsWmsReady()) {
77122736c2fSopenharmony_ci        IMSA_HILOGW("not ready to start ime.");
77222736c2fSopenharmony_ci        return;
77322736c2fSopenharmony_ci    }
77422736c2fSopenharmony_ci    StartCurrentIme();
77522736c2fSopenharmony_ci}
77622736c2fSopenharmony_ci
77722736c2fSopenharmony_civoid PerUserSession::SetCurrentClient(sptr<IInputClient> client)
77822736c2fSopenharmony_ci{
77922736c2fSopenharmony_ci    IMSA_HILOGD("set current client.");
78022736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(clientLock_);
78122736c2fSopenharmony_ci    currentClient_ = client;
78222736c2fSopenharmony_ci}
78322736c2fSopenharmony_ci
78422736c2fSopenharmony_cisptr<IInputClient> PerUserSession::GetCurrentClient()
78522736c2fSopenharmony_ci{
78622736c2fSopenharmony_ci    IMSA_HILOGD("get current client.");
78722736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(clientLock_);
78822736c2fSopenharmony_ci    return currentClient_;
78922736c2fSopenharmony_ci}
79022736c2fSopenharmony_ci
79122736c2fSopenharmony_civoid PerUserSession::ReplaceCurrentClient(const sptr<IInputClient> &client)
79222736c2fSopenharmony_ci{
79322736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(focusedClientLock_);
79422736c2fSopenharmony_ci    if (client == nullptr) {
79522736c2fSopenharmony_ci        return;
79622736c2fSopenharmony_ci    }
79722736c2fSopenharmony_ci    auto clientInfo = GetClientInfo(client->AsObject());
79822736c2fSopenharmony_ci    if (clientInfo == nullptr) {
79922736c2fSopenharmony_ci        return;
80022736c2fSopenharmony_ci    }
80122736c2fSopenharmony_ci    auto replacedClient = GetCurrentClient();
80222736c2fSopenharmony_ci    SetCurrentClient(client);
80322736c2fSopenharmony_ci    if (replacedClient != nullptr) {
80422736c2fSopenharmony_ci        auto replacedClientInfo = GetClientInfo(replacedClient->AsObject());
80522736c2fSopenharmony_ci        if (replacedClientInfo != nullptr && replacedClientInfo->pid != clientInfo->pid) {
80622736c2fSopenharmony_ci            IMSA_HILOGI("remove replaced client: [%{public}d]", replacedClientInfo->pid);
80722736c2fSopenharmony_ci            RemoveClient(replacedClient);
80822736c2fSopenharmony_ci        }
80922736c2fSopenharmony_ci    }
81022736c2fSopenharmony_ci    auto inactiveClient = GetInactiveClient();
81122736c2fSopenharmony_ci    if (inactiveClient != nullptr) {
81222736c2fSopenharmony_ci        auto inactiveClientInfo = GetClientInfo(inactiveClient->AsObject());
81322736c2fSopenharmony_ci        if (inactiveClientInfo != nullptr && inactiveClientInfo->pid != clientInfo->pid) {
81422736c2fSopenharmony_ci            IMSA_HILOGI("remove inactive client: [%{public}d]", inactiveClientInfo->pid);
81522736c2fSopenharmony_ci            RemoveClient(inactiveClient, false);
81622736c2fSopenharmony_ci        }
81722736c2fSopenharmony_ci    }
81822736c2fSopenharmony_ci}
81922736c2fSopenharmony_ci
82022736c2fSopenharmony_civoid PerUserSession::SetInactiveClient(sptr<IInputClient> client)
82122736c2fSopenharmony_ci{
82222736c2fSopenharmony_ci    IMSA_HILOGD("set inactive client.");
82322736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(inactiveClientLock_);
82422736c2fSopenharmony_ci    inactiveClient_ = client;
82522736c2fSopenharmony_ci}
82622736c2fSopenharmony_ci
82722736c2fSopenharmony_cisptr<IInputClient> PerUserSession::GetInactiveClient()
82822736c2fSopenharmony_ci{
82922736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(inactiveClientLock_);
83022736c2fSopenharmony_ci    return inactiveClient_;
83122736c2fSopenharmony_ci}
83222736c2fSopenharmony_ci
83322736c2fSopenharmony_civoid PerUserSession::NotifyImeChangeToClients(const Property &property, const SubProperty &subProperty)
83422736c2fSopenharmony_ci{
83522736c2fSopenharmony_ci    IMSA_HILOGD("start.");
83622736c2fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mtx);
83722736c2fSopenharmony_ci    for (const auto &client : mapClients_) {
83822736c2fSopenharmony_ci        auto clientInfo = client.second;
83922736c2fSopenharmony_ci        if (clientInfo == nullptr || !EventStatusManager::IsImeChangeOn(clientInfo->eventFlag)) {
84022736c2fSopenharmony_ci            IMSA_HILOGD("client nullptr or no need to notify.");
84122736c2fSopenharmony_ci            continue;
84222736c2fSopenharmony_ci        }
84322736c2fSopenharmony_ci        IMSA_HILOGD("notify client: [%{public}d]", static_cast<int32_t>(clientInfo->pid));
84422736c2fSopenharmony_ci        int32_t ret = clientInfo->client->OnSwitchInput(property, subProperty);
84522736c2fSopenharmony_ci        if (ret != ErrorCode::NO_ERROR) {
84622736c2fSopenharmony_ci            IMSA_HILOGE("notify failed, ret: %{public}d, uid: %{public}d!", ret, static_cast<int32_t>(clientInfo->uid));
84722736c2fSopenharmony_ci            continue;
84822736c2fSopenharmony_ci        }
84922736c2fSopenharmony_ci    }
85022736c2fSopenharmony_ci}
85122736c2fSopenharmony_ci
85222736c2fSopenharmony_ciint32_t PerUserSession::AddImeData(ImeType type, sptr<IInputMethodCore> core, sptr<IRemoteObject> agent, pid_t pid)
85322736c2fSopenharmony_ci{
85422736c2fSopenharmony_ci    if (core == nullptr || agent == nullptr) {
85522736c2fSopenharmony_ci        IMSA_HILOGE("core or agent is nullptr!");
85622736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
85722736c2fSopenharmony_ci    }
85822736c2fSopenharmony_ci    sptr<InputDeathRecipient> deathRecipient = new (std::nothrow) InputDeathRecipient();
85922736c2fSopenharmony_ci    if (deathRecipient == nullptr) {
86022736c2fSopenharmony_ci        IMSA_HILOGE("failed to new deathRecipient!");
86122736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
86222736c2fSopenharmony_ci    }
86322736c2fSopenharmony_ci    deathRecipient->SetDeathRecipient([this, core, type](const wptr<IRemoteObject> &) { this->OnImeDied(core, type); });
86422736c2fSopenharmony_ci    auto coreObject = core->AsObject();
86522736c2fSopenharmony_ci    if (coreObject == nullptr || (coreObject->IsProxyObject() && !coreObject->AddDeathRecipient(deathRecipient))) {
86622736c2fSopenharmony_ci        IMSA_HILOGE("failed to add death recipient!");
86722736c2fSopenharmony_ci        return ErrorCode::ERROR_ADD_DEATH_RECIPIENT_FAILED;
86822736c2fSopenharmony_ci    }
86922736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(imeDataLock_);
87022736c2fSopenharmony_ci    auto imeData = std::make_shared<ImeData>(core, agent, deathRecipient, pid);
87122736c2fSopenharmony_ci    imeData->imeStatus = ImeStatus::READY;
87222736c2fSopenharmony_ci    imeData_.insert_or_assign(type, imeData);
87322736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
87422736c2fSopenharmony_ci}
87522736c2fSopenharmony_ci
87622736c2fSopenharmony_cistd::shared_ptr<ImeData> PerUserSession::GetReadyImeData(ImeType type)
87722736c2fSopenharmony_ci{
87822736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(imeDataLock_);
87922736c2fSopenharmony_ci    auto it = imeData_.find(type);
88022736c2fSopenharmony_ci    if (it == imeData_.end()) {
88122736c2fSopenharmony_ci        return nullptr;
88222736c2fSopenharmony_ci    }
88322736c2fSopenharmony_ci    if (it->second->imeStatus != ImeStatus::READY) {
88422736c2fSopenharmony_ci        return nullptr;
88522736c2fSopenharmony_ci    }
88622736c2fSopenharmony_ci    return it->second;
88722736c2fSopenharmony_ci}
88822736c2fSopenharmony_ci
88922736c2fSopenharmony_cistd::shared_ptr<ImeData> PerUserSession::GetValidIme(ImeType type)
89022736c2fSopenharmony_ci{
89122736c2fSopenharmony_ci    auto data = GetReadyImeData(type);
89222736c2fSopenharmony_ci    if (data != nullptr || type != ImeType::IME) {
89322736c2fSopenharmony_ci        return data;
89422736c2fSopenharmony_ci    }
89522736c2fSopenharmony_ci    IMSA_HILOGI("current ime is empty, try to restart it.");
89622736c2fSopenharmony_ci    StartCurrentIme();
89722736c2fSopenharmony_ci    return GetReadyImeData(type);
89822736c2fSopenharmony_ci}
89922736c2fSopenharmony_ci
90022736c2fSopenharmony_civoid PerUserSession::RemoveImeData(ImeType type, bool isImeDied)
90122736c2fSopenharmony_ci{
90222736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(imeDataLock_);
90322736c2fSopenharmony_ci    auto it = imeData_.find(type);
90422736c2fSopenharmony_ci    if (it == imeData_.end()) {
90522736c2fSopenharmony_ci        IMSA_HILOGD("imeData not found.");
90622736c2fSopenharmony_ci        return;
90722736c2fSopenharmony_ci    }
90822736c2fSopenharmony_ci    auto data = it->second;
90922736c2fSopenharmony_ci    if (isImeDied && data->core != nullptr && data->core->AsObject() != nullptr) {
91022736c2fSopenharmony_ci        data->core->AsObject()->RemoveDeathRecipient(data->deathRecipient);
91122736c2fSopenharmony_ci    }
91222736c2fSopenharmony_ci    imeData_.erase(type);
91322736c2fSopenharmony_ci}
91422736c2fSopenharmony_ci
91522736c2fSopenharmony_civoid PerUserSession::OnFocused(int32_t pid, int32_t uid)
91622736c2fSopenharmony_ci{
91722736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(focusedClientLock_);
91822736c2fSopenharmony_ci    auto client = GetCurrentClient();
91922736c2fSopenharmony_ci    if (client == nullptr) {
92022736c2fSopenharmony_ci        return;
92122736c2fSopenharmony_ci    }
92222736c2fSopenharmony_ci    if (IsCurClientFocused(pid, uid)) {
92322736c2fSopenharmony_ci        IMSA_HILOGD("current client focused, focusedPid: %{public}d", pid);
92422736c2fSopenharmony_ci        return;
92522736c2fSopenharmony_ci    }
92622736c2fSopenharmony_ci    if (!OHOS::Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
92722736c2fSopenharmony_ci        IMSA_HILOGI("focus shifts to pid: %{public}d, remove current client.", pid);
92822736c2fSopenharmony_ci        RemoveClient(client);
92922736c2fSopenharmony_ci        InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNFOCUSED);
93022736c2fSopenharmony_ci        return;
93122736c2fSopenharmony_ci    }
93222736c2fSopenharmony_ci    IMSA_HILOGI("focus shifts to pid: %{public}d, deactivate current client.", pid);
93322736c2fSopenharmony_ci    DeactivateClient(client);
93422736c2fSopenharmony_ci}
93522736c2fSopenharmony_ci
93622736c2fSopenharmony_civoid PerUserSession::OnUnfocused(int32_t pid, int32_t uid)
93722736c2fSopenharmony_ci{
93822736c2fSopenharmony_ci    if (GetCurrentClient() == nullptr) {
93922736c2fSopenharmony_ci        return;
94022736c2fSopenharmony_ci    }
94122736c2fSopenharmony_ci    if (IsCurClientUnFocused(pid, uid)) {
94222736c2fSopenharmony_ci        IMSA_HILOGD("current client Unfocused, unFocusedPid: %{public}d", pid);
94322736c2fSopenharmony_ci        return;
94422736c2fSopenharmony_ci    }
94522736c2fSopenharmony_ci    auto clientInfo = GetClientInfo(pid);
94622736c2fSopenharmony_ci    if (clientInfo == nullptr) {
94722736c2fSopenharmony_ci        return;
94822736c2fSopenharmony_ci    }
94922736c2fSopenharmony_ci    RemoveClient(clientInfo->client);
95022736c2fSopenharmony_ci    InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNFOCUSED);
95122736c2fSopenharmony_ci}
95222736c2fSopenharmony_ci
95322736c2fSopenharmony_cistd::shared_ptr<InputClientInfo> PerUserSession::GetCurClientInfo()
95422736c2fSopenharmony_ci{
95522736c2fSopenharmony_ci    auto client = GetCurrentClient();
95622736c2fSopenharmony_ci    if (client == nullptr) {
95722736c2fSopenharmony_ci        IMSA_HILOGD("no client in bound state.");
95822736c2fSopenharmony_ci        return nullptr;
95922736c2fSopenharmony_ci    }
96022736c2fSopenharmony_ci    return GetClientInfo(client->AsObject());
96122736c2fSopenharmony_ci}
96222736c2fSopenharmony_ci
96322736c2fSopenharmony_cibool PerUserSession::IsCurClientFocused(int32_t pid, int32_t uid)
96422736c2fSopenharmony_ci{
96522736c2fSopenharmony_ci    auto clientInfo = GetCurClientInfo();
96622736c2fSopenharmony_ci    if (clientInfo == nullptr) {
96722736c2fSopenharmony_ci        IMSA_HILOGE("failed to get cur client info!");
96822736c2fSopenharmony_ci        return false;
96922736c2fSopenharmony_ci    }
97022736c2fSopenharmony_ci    auto identityChecker = std::make_shared<IdentityCheckerImpl>();
97122736c2fSopenharmony_ci    if (clientInfo->uiExtensionTokenId != IMF_INVALID_TOKENID &&
97222736c2fSopenharmony_ci        identityChecker->IsFocusedUIExtension(clientInfo->uiExtensionTokenId)) {
97322736c2fSopenharmony_ci        IMSA_HILOGI("UIExtension focused");
97422736c2fSopenharmony_ci        return true;
97522736c2fSopenharmony_ci    }
97622736c2fSopenharmony_ci    return clientInfo->pid == pid && clientInfo->uid == uid;
97722736c2fSopenharmony_ci}
97822736c2fSopenharmony_ci
97922736c2fSopenharmony_cibool PerUserSession::IsCurClientUnFocused(int32_t pid, int32_t uid)
98022736c2fSopenharmony_ci{
98122736c2fSopenharmony_ci    auto clientInfo = GetCurClientInfo();
98222736c2fSopenharmony_ci    if (clientInfo == nullptr) {
98322736c2fSopenharmony_ci        IMSA_HILOGE("failed to get cur client info!");
98422736c2fSopenharmony_ci        return false;
98522736c2fSopenharmony_ci    }
98622736c2fSopenharmony_ci    auto identityChecker = std::make_shared<IdentityCheckerImpl>();
98722736c2fSopenharmony_ci    if (clientInfo->uiExtensionTokenId != IMF_INVALID_TOKENID &&
98822736c2fSopenharmony_ci        !identityChecker->IsFocusedUIExtension(clientInfo->uiExtensionTokenId)) {
98922736c2fSopenharmony_ci        IMSA_HILOGI("UIExtension UnFocused.");
99022736c2fSopenharmony_ci        return true;
99122736c2fSopenharmony_ci    }
99222736c2fSopenharmony_ci    return clientInfo->pid == pid && clientInfo->uid == uid;
99322736c2fSopenharmony_ci}
99422736c2fSopenharmony_ci
99522736c2fSopenharmony_cibool PerUserSession::IsSameClient(sptr<IInputClient> source, sptr<IInputClient> dest)
99622736c2fSopenharmony_ci{
99722736c2fSopenharmony_ci    return source != nullptr && dest != nullptr && source->AsObject() == dest->AsObject();
99822736c2fSopenharmony_ci}
99922736c2fSopenharmony_ci
100022736c2fSopenharmony_cibool PerUserSession::StartCurrentIme(bool isStopCurrentIme)
100122736c2fSopenharmony_ci{
100222736c2fSopenharmony_ci    auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
100322736c2fSopenharmony_ci    auto imeToStart = ImeInfoInquirer::GetInstance().GetImeToStart(userId_);
100422736c2fSopenharmony_ci    IMSA_HILOGD("currentIme: %{public}s, imeToStart: %{public}s.", currentIme->imeId.c_str(),
100522736c2fSopenharmony_ci        imeToStart->imeId.c_str());
100622736c2fSopenharmony_ci    if (!StartIme(imeToStart, isStopCurrentIme)) {
100722736c2fSopenharmony_ci        IMSA_HILOGE("failed to start ime!");
100822736c2fSopenharmony_ci        InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ErrorCode::ERROR_IME_START_FAILED,
100922736c2fSopenharmony_ci            imeToStart->imeId, "start ime failed!");
101022736c2fSopenharmony_ci        return false;
101122736c2fSopenharmony_ci    }
101222736c2fSopenharmony_ci    IMSA_HILOGI("current ime changed to %{public}s.", imeToStart->imeId.c_str());
101322736c2fSopenharmony_ci    auto currentImeInfo =
101422736c2fSopenharmony_ci        ImeInfoInquirer::GetInstance().GetImeInfo(userId_, imeToStart->bundleName, imeToStart->subName);
101522736c2fSopenharmony_ci    if (currentImeInfo != nullptr) {
101622736c2fSopenharmony_ci        NotifyImeChangeToClients(currentImeInfo->prop, currentImeInfo->subProp);
101722736c2fSopenharmony_ci        SwitchSubtype(currentImeInfo->subProp);
101822736c2fSopenharmony_ci    }
101922736c2fSopenharmony_ci    return true;
102022736c2fSopenharmony_ci}
102122736c2fSopenharmony_ci
102222736c2fSopenharmony_cibool PerUserSession::GetCurrentUsingImeId(ImeIdentification &imeId)
102322736c2fSopenharmony_ci{
102422736c2fSopenharmony_ci    if (InputTypeManager::GetInstance().IsStarted()) {
102522736c2fSopenharmony_ci        IMSA_HILOGI("get right click on state current ime.");
102622736c2fSopenharmony_ci        auto currentIme = InputTypeManager::GetInstance().GetCurrentIme();
102722736c2fSopenharmony_ci        imeId = currentIme;
102822736c2fSopenharmony_ci        return true;
102922736c2fSopenharmony_ci    }
103022736c2fSopenharmony_ci    auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
103122736c2fSopenharmony_ci    if (currentImeCfg == nullptr) {
103222736c2fSopenharmony_ci        IMSA_HILOGE("currentImeCfg is nullptr!");
103322736c2fSopenharmony_ci        return false;
103422736c2fSopenharmony_ci    }
103522736c2fSopenharmony_ci    imeId.bundleName = currentImeCfg->bundleName;
103622736c2fSopenharmony_ci    imeId.subName = currentImeCfg->extName;
103722736c2fSopenharmony_ci    return true;
103822736c2fSopenharmony_ci}
103922736c2fSopenharmony_ci
104022736c2fSopenharmony_ciAAFwk::Want PerUserSession::GetWant(const std::shared_ptr<ImeNativeCfg> &ime)
104122736c2fSopenharmony_ci{
104222736c2fSopenharmony_ci    SecurityMode mode;
104322736c2fSopenharmony_ci    bool isolatedSandBox = true;
104422736c2fSopenharmony_ci    if (SecurityModeParser::GetInstance()->IsDefaultFullMode(ime->bundleName, userId_)) {
104522736c2fSopenharmony_ci        mode = SecurityMode::FULL;
104622736c2fSopenharmony_ci        isolatedSandBox = false;
104722736c2fSopenharmony_ci    } else if (ImeInfoInquirer::GetInstance().IsEnableSecurityMode()) {
104822736c2fSopenharmony_ci        mode = SecurityModeParser::GetInstance()->GetSecurityMode(ime->bundleName, userId_);
104922736c2fSopenharmony_ci    } else {
105022736c2fSopenharmony_ci        mode = SecurityMode::FULL;
105122736c2fSopenharmony_ci    }
105222736c2fSopenharmony_ci    AAFwk::Want want;
105322736c2fSopenharmony_ci    want.SetElementName(ime->bundleName, ime->extName);
105422736c2fSopenharmony_ci    want.SetParam(STRICT_MODE, !(mode == SecurityMode::FULL));
105522736c2fSopenharmony_ci    want.SetParam(ISOLATED_SANDBOX, isolatedSandBox);
105622736c2fSopenharmony_ci    IMSA_HILOGI("userId: %{public}d, ime: %{public}s, mode: %{public}d, isolatedSandbox: %{public}d", userId_,
105722736c2fSopenharmony_ci        ime->imeId.c_str(), static_cast<int32_t>(mode), isolatedSandBox);
105822736c2fSopenharmony_ci    return want;
105922736c2fSopenharmony_ci}
106022736c2fSopenharmony_ci
106122736c2fSopenharmony_cibool PerUserSession::StartInputService(const std::shared_ptr<ImeNativeCfg> &ime)
106222736c2fSopenharmony_ci{
106322736c2fSopenharmony_ci    if (ime == nullptr) {
106422736c2fSopenharmony_ci        return false;
106522736c2fSopenharmony_ci    }
106622736c2fSopenharmony_ci    isImeStarted_.Clear(false);
106722736c2fSopenharmony_ci    sptr<AAFwk::IAbilityConnection> connection = new (std::nothrow) ImeConnection();
106822736c2fSopenharmony_ci    if (connection == nullptr) {
106922736c2fSopenharmony_ci        IMSA_HILOGE("failed to create connection!");
107022736c2fSopenharmony_ci        return false;
107122736c2fSopenharmony_ci    }
107222736c2fSopenharmony_ci    auto want = GetWant(ime);
107322736c2fSopenharmony_ci    auto ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectExtensionAbility(want, connection, userId_);
107422736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
107522736c2fSopenharmony_ci        IMSA_HILOGE("connect %{public}s failed, ret: %{public}d!", ime->imeId.c_str(), ret);
107622736c2fSopenharmony_ci        InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ErrorCode::ERROR_IME_START_FAILED, ime->imeId,
107722736c2fSopenharmony_ci            "failed to start ability.");
107822736c2fSopenharmony_ci        return false;
107922736c2fSopenharmony_ci    }
108022736c2fSopenharmony_ci    InitImeData({ ime->bundleName, ime->extName });
108122736c2fSopenharmony_ci    if (!isImeStarted_.GetValue()) {
108222736c2fSopenharmony_ci        IMSA_HILOGE("start %{public}s timeout!", ime->imeId.c_str());
108322736c2fSopenharmony_ci        return false;
108422736c2fSopenharmony_ci    }
108522736c2fSopenharmony_ci    IMSA_HILOGI("%{public}s started successfully.", ime->imeId.c_str());
108622736c2fSopenharmony_ci    InputMethodSysEvent::GetInstance().RecordEvent(IMEBehaviour::START_IME);
108722736c2fSopenharmony_ci    return true;
108822736c2fSopenharmony_ci}
108922736c2fSopenharmony_ci
109022736c2fSopenharmony_ciint64_t PerUserSession::GetCurrentClientPid()
109122736c2fSopenharmony_ci{
109222736c2fSopenharmony_ci    auto client = GetCurrentClient();
109322736c2fSopenharmony_ci    if (client == nullptr) {
109422736c2fSopenharmony_ci        return INVALID_PID;
109522736c2fSopenharmony_ci    }
109622736c2fSopenharmony_ci    auto clientInfo = GetClientInfo(client->AsObject());
109722736c2fSopenharmony_ci    if (clientInfo == nullptr) {
109822736c2fSopenharmony_ci        return INVALID_PID;
109922736c2fSopenharmony_ci    }
110022736c2fSopenharmony_ci    return clientInfo->pid;
110122736c2fSopenharmony_ci}
110222736c2fSopenharmony_ci
110322736c2fSopenharmony_ciint64_t PerUserSession::GetInactiveClientPid()
110422736c2fSopenharmony_ci{
110522736c2fSopenharmony_ci    auto client = GetInactiveClient();
110622736c2fSopenharmony_ci    if (client == nullptr) {
110722736c2fSopenharmony_ci        return INVALID_PID;
110822736c2fSopenharmony_ci    }
110922736c2fSopenharmony_ci    auto clientInfo = GetClientInfo(client->AsObject());
111022736c2fSopenharmony_ci    if (clientInfo == nullptr) {
111122736c2fSopenharmony_ci        return INVALID_PID;
111222736c2fSopenharmony_ci    }
111322736c2fSopenharmony_ci    return clientInfo->pid;
111422736c2fSopenharmony_ci}
111522736c2fSopenharmony_ci
111622736c2fSopenharmony_ciint32_t PerUserSession::OnPanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info)
111722736c2fSopenharmony_ci{
111822736c2fSopenharmony_ci    auto clientMap = GetClientMap();
111922736c2fSopenharmony_ci    for (const auto &client : clientMap) {
112022736c2fSopenharmony_ci        auto clientInfo = client.second;
112122736c2fSopenharmony_ci        if (clientInfo == nullptr) {
112222736c2fSopenharmony_ci            IMSA_HILOGD("client nullptr or no need to notify.");
112322736c2fSopenharmony_ci            continue;
112422736c2fSopenharmony_ci        }
112522736c2fSopenharmony_ci        if (status == InputWindowStatus::SHOW && !EventStatusManager::IsImeShowOn(clientInfo->eventFlag)) {
112622736c2fSopenharmony_ci            IMSA_HILOGD("has not imeShow callback");
112722736c2fSopenharmony_ci            continue;
112822736c2fSopenharmony_ci        }
112922736c2fSopenharmony_ci        if (status == InputWindowStatus::HIDE && !EventStatusManager::IsImeHideOn(clientInfo->eventFlag)) {
113022736c2fSopenharmony_ci            IMSA_HILOGD("has not imeHide callback");
113122736c2fSopenharmony_ci            continue;
113222736c2fSopenharmony_ci        }
113322736c2fSopenharmony_ci        int32_t ret = clientInfo->client->OnPanelStatusChange(status, info);
113422736c2fSopenharmony_ci        if (ret != ErrorCode::NO_ERROR) {
113522736c2fSopenharmony_ci            IMSA_HILOGE("failed to OnPanelStatusChange, ret: %{public}d", ret);
113622736c2fSopenharmony_ci            continue;
113722736c2fSopenharmony_ci        }
113822736c2fSopenharmony_ci    }
113922736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
114022736c2fSopenharmony_ci}
114122736c2fSopenharmony_ci
114222736c2fSopenharmony_ciint32_t PerUserSession::OnUpdateListenEventFlag(const InputClientInfo &clientInfo)
114322736c2fSopenharmony_ci{
114422736c2fSopenharmony_ci    auto remoteClient = clientInfo.client->AsObject();
114522736c2fSopenharmony_ci    auto ret = AddClientInfo(remoteClient, clientInfo, START_LISTENING);
114622736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
114722736c2fSopenharmony_ci        IMSA_HILOGE("failed to AddClientInfo!");
114822736c2fSopenharmony_ci        return ret;
114922736c2fSopenharmony_ci    }
115022736c2fSopenharmony_ci    auto info = GetClientInfo(remoteClient);
115122736c2fSopenharmony_ci    if (info == nullptr) {
115222736c2fSopenharmony_ci        IMSA_HILOGE("info is nullptr!");
115322736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NOT_FOUND;
115422736c2fSopenharmony_ci    }
115522736c2fSopenharmony_ci    if (info->eventFlag == NO_EVENT_ON && info->bindImeType == ImeType::NONE) {
115622736c2fSopenharmony_ci        RemoveClientInfo(remoteClient, false);
115722736c2fSopenharmony_ci    }
115822736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
115922736c2fSopenharmony_ci}
116022736c2fSopenharmony_ci
116122736c2fSopenharmony_cibool PerUserSession::IsImeStartInBind(ImeType bindImeType, ImeType startImeType)
116222736c2fSopenharmony_ci{
116322736c2fSopenharmony_ci    return startImeType == ImeType::IME && bindImeType == ImeType::IME;
116422736c2fSopenharmony_ci}
116522736c2fSopenharmony_ci
116622736c2fSopenharmony_cibool PerUserSession::IsProxyImeStartInBind(ImeType bindImeType, ImeType startImeType)
116722736c2fSopenharmony_ci{
116822736c2fSopenharmony_ci    return startImeType == ImeType::PROXY_IME && bindImeType == ImeType::PROXY_IME;
116922736c2fSopenharmony_ci}
117022736c2fSopenharmony_ci
117122736c2fSopenharmony_cibool PerUserSession::IsProxyImeStartInImeBind(ImeType bindImeType, ImeType startImeType)
117222736c2fSopenharmony_ci{
117322736c2fSopenharmony_ci    return startImeType == ImeType::PROXY_IME && bindImeType == ImeType::IME;
117422736c2fSopenharmony_ci}
117522736c2fSopenharmony_ci
117622736c2fSopenharmony_cibool PerUserSession::IsImeBindChanged(ImeType bindImeType)
117722736c2fSopenharmony_ci{
117822736c2fSopenharmony_ci    return (bindImeType == ImeType::IME && IsProxyImeEnable()) ||
117922736c2fSopenharmony_ci           (bindImeType == ImeType::PROXY_IME && !IsProxyImeEnable());
118022736c2fSopenharmony_ci}
118122736c2fSopenharmony_ci
118222736c2fSopenharmony_ciint32_t PerUserSession::SwitchSubtype(const SubProperty &subProperty)
118322736c2fSopenharmony_ci{
118422736c2fSopenharmony_ci    auto data = GetValidIme(ImeType::IME);
118522736c2fSopenharmony_ci    if (data == nullptr) {
118622736c2fSopenharmony_ci        IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME);
118722736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_NOT_STARTED;
118822736c2fSopenharmony_ci    }
118922736c2fSopenharmony_ci    return RequestIme(data, RequestType::NORMAL, [&data, &subProperty] { return data->core->SetSubtype(subProperty); });
119022736c2fSopenharmony_ci}
119122736c2fSopenharmony_ci
119222736c2fSopenharmony_ciint32_t PerUserSession::SetInputType()
119322736c2fSopenharmony_ci{
119422736c2fSopenharmony_ci    InputType inputType = InputTypeManager::GetInstance().GetCurrentInputType();
119522736c2fSopenharmony_ci    auto data = GetValidIme(ImeType::IME);
119622736c2fSopenharmony_ci    if (data == nullptr) {
119722736c2fSopenharmony_ci        IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME);
119822736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_NOT_STARTED;
119922736c2fSopenharmony_ci    }
120022736c2fSopenharmony_ci    return RequestIme(data, RequestType::NORMAL, [&data, &inputType] { return data->core->OnSetInputType(inputType); });
120122736c2fSopenharmony_ci}
120222736c2fSopenharmony_ci
120322736c2fSopenharmony_cibool PerUserSession::IsBoundToClient()
120422736c2fSopenharmony_ci{
120522736c2fSopenharmony_ci    if (GetCurrentClient() == nullptr) {
120622736c2fSopenharmony_ci        IMSA_HILOGE("not in bound state!");
120722736c2fSopenharmony_ci        return false;
120822736c2fSopenharmony_ci    }
120922736c2fSopenharmony_ci    return true;
121022736c2fSopenharmony_ci}
121122736c2fSopenharmony_ci
121222736c2fSopenharmony_ciint32_t PerUserSession::RestoreCurrentImeSubType()
121322736c2fSopenharmony_ci{
121422736c2fSopenharmony_ci    if (!InputTypeManager::GetInstance().IsStarted()) {
121522736c2fSopenharmony_ci        IMSA_HILOGD("already exit.");
121622736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
121722736c2fSopenharmony_ci    }
121822736c2fSopenharmony_ci    auto typeIme = InputTypeManager::GetInstance().GetCurrentIme();
121922736c2fSopenharmony_ci    auto cfgIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
122022736c2fSopenharmony_ci    if (cfgIme->bundleName != typeIme.bundleName) {
122122736c2fSopenharmony_ci        IMSA_HILOGD("diff ime, not deal, restore ime when attach.");
122222736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
122322736c2fSopenharmony_ci    }
122422736c2fSopenharmony_ci    auto imeData = GetReadyImeData(ImeType::IME);
122522736c2fSopenharmony_ci    InputTypeManager::GetInstance().Set(false);
122622736c2fSopenharmony_ci    if (imeData == nullptr || imeData->ime.first != cfgIme->bundleName || imeData->ime.second != cfgIme->extName) {
122722736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
122822736c2fSopenharmony_ci    }
122922736c2fSopenharmony_ci    SubProperty subProp = { .name = cfgIme->bundleName, .id = cfgIme->subName };
123022736c2fSopenharmony_ci    auto subPropTemp = ImeInfoInquirer::GetInstance().GetCurrentSubtype(userId_);
123122736c2fSopenharmony_ci    if (subPropTemp != nullptr) {
123222736c2fSopenharmony_ci        subProp = *subPropTemp;
123322736c2fSopenharmony_ci    }
123422736c2fSopenharmony_ci    IMSA_HILOGD("same ime, restore subtype: %{public}s.", cfgIme->subName.c_str());
123522736c2fSopenharmony_ci    return SwitchSubtype(subProp);
123622736c2fSopenharmony_ci}
123722736c2fSopenharmony_ci
123822736c2fSopenharmony_cibool PerUserSession::IsCurrentImeByPid(int32_t pid)
123922736c2fSopenharmony_ci{
124022736c2fSopenharmony_ci    auto imeData = GetImeData(ImeType::IME);
124122736c2fSopenharmony_ci    if (imeData == nullptr) {
124222736c2fSopenharmony_ci        IMSA_HILOGE("ime not started!");
124322736c2fSopenharmony_ci        return false;
124422736c2fSopenharmony_ci    }
124522736c2fSopenharmony_ci    IMSA_HILOGD("userId: %{public}d, pid: %{public}d, current pid: %{public}d.", userId_, pid, imeData->pid);
124622736c2fSopenharmony_ci    return imeData->pid == pid;
124722736c2fSopenharmony_ci}
124822736c2fSopenharmony_ci
124922736c2fSopenharmony_ciint32_t PerUserSession::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
125022736c2fSopenharmony_ci{
125122736c2fSopenharmony_ci    if (GetCurrentClient() == nullptr) {
125222736c2fSopenharmony_ci        IMSA_HILOGD("not in bound state.");
125322736c2fSopenharmony_ci        isShown = false;
125422736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
125522736c2fSopenharmony_ci    }
125622736c2fSopenharmony_ci    auto ime = GetReadyImeData(ImeType::IME);
125722736c2fSopenharmony_ci    if (ime == nullptr) {
125822736c2fSopenharmony_ci        IMSA_HILOGE("ime not started!");
125922736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_NOT_STARTED;
126022736c2fSopenharmony_ci    }
126122736c2fSopenharmony_ci    return RequestIme(ime, RequestType::NORMAL,
126222736c2fSopenharmony_ci        [&ime, &panelInfo, &isShown] { return ime->core->IsPanelShown(panelInfo, isShown); });
126322736c2fSopenharmony_ci}
126422736c2fSopenharmony_ci
126522736c2fSopenharmony_cibool PerUserSession::CheckSecurityMode()
126622736c2fSopenharmony_ci{
126722736c2fSopenharmony_ci    auto client = GetCurrentClient();
126822736c2fSopenharmony_ci    auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
126922736c2fSopenharmony_ci    if (clientInfo != nullptr) {
127022736c2fSopenharmony_ci        return clientInfo->config.inputAttribute.GetSecurityFlag();
127122736c2fSopenharmony_ci    }
127222736c2fSopenharmony_ci    return false;
127322736c2fSopenharmony_ci}
127422736c2fSopenharmony_ci
127522736c2fSopenharmony_cistd::map<sptr<IRemoteObject>, std::shared_ptr<InputClientInfo>> PerUserSession::GetClientMap()
127622736c2fSopenharmony_ci{
127722736c2fSopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mtx);
127822736c2fSopenharmony_ci    return mapClients_;
127922736c2fSopenharmony_ci}
128022736c2fSopenharmony_ci
128122736c2fSopenharmony_ciint32_t PerUserSession::RequestIme(const std::shared_ptr<ImeData> &data, RequestType type, const IpcExec &exec)
128222736c2fSopenharmony_ci{
128322736c2fSopenharmony_ci    if (IsProxyImeEnable()) {
128422736c2fSopenharmony_ci        IMSA_HILOGD("proxy enable.");
128522736c2fSopenharmony_ci        return exec();
128622736c2fSopenharmony_ci    }
128722736c2fSopenharmony_ci    if (data == nullptr || data->freezeMgr == nullptr) {
128822736c2fSopenharmony_ci        IMSA_HILOGE("data is nullptr!");
128922736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
129022736c2fSopenharmony_ci    }
129122736c2fSopenharmony_ci    data->freezeMgr->BeforeIpc(type);
129222736c2fSopenharmony_ci    auto ret = exec();
129322736c2fSopenharmony_ci    data->freezeMgr->AfterIpc(type, ret == ErrorCode::NO_ERROR);
129422736c2fSopenharmony_ci    return ret;
129522736c2fSopenharmony_ci}
129622736c2fSopenharmony_ci
129722736c2fSopenharmony_ciint32_t PerUserSession::OnConnectSystemCmd(const sptr<IRemoteObject> &channel, sptr<IRemoteObject> &agent)
129822736c2fSopenharmony_ci{
129922736c2fSopenharmony_ci    auto data = GetReadyImeData(ImeType::IME);
130022736c2fSopenharmony_ci    if (data == nullptr) {
130122736c2fSopenharmony_ci        IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME);
130222736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_NOT_STARTED;
130322736c2fSopenharmony_ci    }
130422736c2fSopenharmony_ci    auto ret = RequestIme(data, RequestType::NORMAL,
130522736c2fSopenharmony_ci        [&data, &channel, &agent] { return data->core->OnConnectSystemCmd(channel, agent); });
130622736c2fSopenharmony_ci    IMSA_HILOGD("on connect systemCmd, ret: %{public}d.", ret);
130722736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
130822736c2fSopenharmony_ci        IMSA_HILOGE("bind failed, ret: %{public}d!", ret);
130922736c2fSopenharmony_ci        return ret;
131022736c2fSopenharmony_ci    }
131122736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
131222736c2fSopenharmony_ci}
131322736c2fSopenharmony_ci
131422736c2fSopenharmony_cibool PerUserSession::WaitForCurrentImeStop()
131522736c2fSopenharmony_ci{
131622736c2fSopenharmony_ci    IMSA_HILOGI("start.");
131722736c2fSopenharmony_ci    std::unique_lock<std::mutex> lock(imeStopMutex_);
131822736c2fSopenharmony_ci    isSwitching_.store(true);
131922736c2fSopenharmony_ci    return imeStopCv_.wait_for(lock, std::chrono::milliseconds(STOP_IME_TIME), [this]() { return !isSwitching_; });
132022736c2fSopenharmony_ci}
132122736c2fSopenharmony_ci
132222736c2fSopenharmony_civoid PerUserSession::NotifyImeStopFinished()
132322736c2fSopenharmony_ci{
132422736c2fSopenharmony_ci    IMSA_HILOGI("start.");
132522736c2fSopenharmony_ci    std::unique_lock<std::mutex> lock(imeStopMutex_);
132622736c2fSopenharmony_ci    isSwitching_.store(false);
132722736c2fSopenharmony_ci    imeStopCv_.notify_one();
132822736c2fSopenharmony_ci}
132922736c2fSopenharmony_ci
133022736c2fSopenharmony_ciint32_t PerUserSession::RemoveCurrentClient()
133122736c2fSopenharmony_ci{
133222736c2fSopenharmony_ci    auto currentClient = GetCurrentClient();
133322736c2fSopenharmony_ci    if (currentClient == nullptr) {
133422736c2fSopenharmony_ci        IMSA_HILOGE("currentClient is nullptr!");
133522736c2fSopenharmony_ci        return ErrorCode::ERROR_CLIENT_NULL_POINTER;
133622736c2fSopenharmony_ci    }
133722736c2fSopenharmony_ci    return RemoveClient(currentClient, false);
133822736c2fSopenharmony_ci}
133922736c2fSopenharmony_ci
134022736c2fSopenharmony_cibool PerUserSession::IsWmsReady()
134122736c2fSopenharmony_ci{
134222736c2fSopenharmony_ci    if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
134322736c2fSopenharmony_ci        IMSA_HILOGD("scb enable");
134422736c2fSopenharmony_ci        return WmsConnectionObserver::IsWmsConnected(userId_);
134522736c2fSopenharmony_ci    }
134622736c2fSopenharmony_ci    return IsReady(WINDOW_MANAGER_SERVICE_ID);
134722736c2fSopenharmony_ci}
134822736c2fSopenharmony_ci
134922736c2fSopenharmony_cibool PerUserSession::IsReady(int32_t saId)
135022736c2fSopenharmony_ci{
135122736c2fSopenharmony_ci    auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
135222736c2fSopenharmony_ci    if (saMgr == nullptr) {
135322736c2fSopenharmony_ci        IMSA_HILOGE("get saMgr failed!");
135422736c2fSopenharmony_ci        return false;
135522736c2fSopenharmony_ci    }
135622736c2fSopenharmony_ci    if (saMgr->CheckSystemAbility(saId) == nullptr) {
135722736c2fSopenharmony_ci        IMSA_HILOGE("sa:%{public}d not ready!", saId);
135822736c2fSopenharmony_ci        return false;
135922736c2fSopenharmony_ci    }
136022736c2fSopenharmony_ci    return true;
136122736c2fSopenharmony_ci}
136222736c2fSopenharmony_ci
136322736c2fSopenharmony_civoid PerUserSession::AddRestartIme()
136422736c2fSopenharmony_ci{
136522736c2fSopenharmony_ci    int32_t tasks = 0;
136622736c2fSopenharmony_ci    {
136722736c2fSopenharmony_ci        std::lock_guard<std::mutex> lock(restartMutex_);
136822736c2fSopenharmony_ci        if (restartTasks_ >= MAX_RESTART_TASKS) {
136922736c2fSopenharmony_ci            return;
137022736c2fSopenharmony_ci        }
137122736c2fSopenharmony_ci        restartTasks_ = std::max(restartTasks_, 0);
137222736c2fSopenharmony_ci        tasks = ++restartTasks_;
137322736c2fSopenharmony_ci    }
137422736c2fSopenharmony_ci    if (tasks == 1 && !RestartIme()) {
137522736c2fSopenharmony_ci        std::lock_guard<std::mutex> lock(restartMutex_);
137622736c2fSopenharmony_ci        restartTasks_ = 0;
137722736c2fSopenharmony_ci    }
137822736c2fSopenharmony_ci}
137922736c2fSopenharmony_ci
138022736c2fSopenharmony_cibool PerUserSession::RestartIme()
138122736c2fSopenharmony_ci{
138222736c2fSopenharmony_ci    auto task = [this]() {
138322736c2fSopenharmony_ci        if (IsReady(MEMORY_MANAGER_SA_ID) && IsWmsReady() && runningIme_.empty()) {
138422736c2fSopenharmony_ci            auto ret = StartCurrentIme(true);
138522736c2fSopenharmony_ci            if (!ret) {
138622736c2fSopenharmony_ci                IMSA_HILOGE("start ime failed!");
138722736c2fSopenharmony_ci            }
138822736c2fSopenharmony_ci        }
138922736c2fSopenharmony_ci        int32_t tasks = 0;
139022736c2fSopenharmony_ci        {
139122736c2fSopenharmony_ci            std::lock_guard<std::mutex> lock(restartMutex_);
139222736c2fSopenharmony_ci            tasks = --restartTasks_;
139322736c2fSopenharmony_ci        }
139422736c2fSopenharmony_ci        if (tasks > 0 && !RestartIme()) {
139522736c2fSopenharmony_ci            std::lock_guard<std::mutex> lock(restartMutex_);
139622736c2fSopenharmony_ci            restartTasks_ = 0;
139722736c2fSopenharmony_ci        }
139822736c2fSopenharmony_ci    };
139922736c2fSopenharmony_ci    if (eventHandler_ == nullptr) {
140022736c2fSopenharmony_ci        IMSA_HILOGE("eventHandler_ is nullptr!");
140122736c2fSopenharmony_ci        return false;
140222736c2fSopenharmony_ci    }
140322736c2fSopenharmony_ci    return eventHandler_->PostTask(task, "RestartCurrentImeTask", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
140422736c2fSopenharmony_ci}
140522736c2fSopenharmony_ci
140622736c2fSopenharmony_ciBlockQueue<SwitchInfo>& PerUserSession::GetSwitchQueue()
140722736c2fSopenharmony_ci{
140822736c2fSopenharmony_ci    return switchQueue_;
140922736c2fSopenharmony_ci}
141022736c2fSopenharmony_ci
141122736c2fSopenharmony_ciint32_t PerUserSession::InitImeData(const std::pair<std::string, std::string> &ime)
141222736c2fSopenharmony_ci{
141322736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(imeDataLock_);
141422736c2fSopenharmony_ci    auto it = imeData_.find(ImeType::IME);
141522736c2fSopenharmony_ci    if (it != imeData_.end()) {
141622736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
141722736c2fSopenharmony_ci    }
141822736c2fSopenharmony_ci    auto imeData = std::make_shared<ImeData>(nullptr, nullptr, nullptr, -1);
141922736c2fSopenharmony_ci    imeData->startTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
142022736c2fSopenharmony_ci    imeData->ime = ime;
142122736c2fSopenharmony_ci    imeData_.insert({ ImeType::IME, imeData });
142222736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
142322736c2fSopenharmony_ci}
142422736c2fSopenharmony_ci
142522736c2fSopenharmony_ciint32_t PerUserSession::UpdateImeData(sptr<IInputMethodCore> core, sptr<IRemoteObject> agent, pid_t pid)
142622736c2fSopenharmony_ci{
142722736c2fSopenharmony_ci    if (core == nullptr || agent == nullptr) {
142822736c2fSopenharmony_ci        IMSA_HILOGE("core or agent is nullptr!");
142922736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
143022736c2fSopenharmony_ci    }
143122736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(imeDataLock_);
143222736c2fSopenharmony_ci    auto it = imeData_.find(ImeType::IME);
143322736c2fSopenharmony_ci    if (it == imeData_.end()) {
143422736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
143522736c2fSopenharmony_ci    }
143622736c2fSopenharmony_ci    it->second->core = core;
143722736c2fSopenharmony_ci    it->second->agent = agent;
143822736c2fSopenharmony_ci    it->second->pid = pid;
143922736c2fSopenharmony_ci    it->second->freezeMgr = std::make_shared<FreezeManager>(pid);
144022736c2fSopenharmony_ci    sptr<InputDeathRecipient> deathRecipient = new (std::nothrow) InputDeathRecipient();
144122736c2fSopenharmony_ci    if (deathRecipient == nullptr) {
144222736c2fSopenharmony_ci        IMSA_HILOGE("failed to new deathRecipient!");
144322736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
144422736c2fSopenharmony_ci    }
144522736c2fSopenharmony_ci    auto type = ImeType::IME;
144622736c2fSopenharmony_ci    deathRecipient->SetDeathRecipient([this, core, type](const wptr<IRemoteObject> &) { this->OnImeDied(core, type); });
144722736c2fSopenharmony_ci    auto coreObject = core->AsObject();
144822736c2fSopenharmony_ci    if (coreObject == nullptr || (coreObject->IsProxyObject() && !coreObject->AddDeathRecipient(deathRecipient))) {
144922736c2fSopenharmony_ci        IMSA_HILOGE("failed to add death recipient!");
145022736c2fSopenharmony_ci        return ErrorCode::ERROR_ADD_DEATH_RECIPIENT_FAILED;
145122736c2fSopenharmony_ci    }
145222736c2fSopenharmony_ci    it->second->deathRecipient = deathRecipient;
145322736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
145422736c2fSopenharmony_ci}
145522736c2fSopenharmony_ci
145622736c2fSopenharmony_ciint32_t PerUserSession::InitConnect(pid_t pid)
145722736c2fSopenharmony_ci{
145822736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(imeDataLock_);
145922736c2fSopenharmony_ci    auto it = imeData_.find(ImeType::IME);
146022736c2fSopenharmony_ci    if (it == imeData_.end()) {
146122736c2fSopenharmony_ci        return ErrorCode::ERROR_NULL_POINTER;
146222736c2fSopenharmony_ci    }
146322736c2fSopenharmony_ci    it->second->pid = pid;
146422736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
146522736c2fSopenharmony_ci}
146622736c2fSopenharmony_ci
146722736c2fSopenharmony_cistd::shared_ptr<ImeData> PerUserSession::GetImeData(ImeType type)
146822736c2fSopenharmony_ci{
146922736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(imeDataLock_);
147022736c2fSopenharmony_ci    auto it = imeData_.find(type);
147122736c2fSopenharmony_ci    if (it == imeData_.end()) {
147222736c2fSopenharmony_ci        return nullptr;
147322736c2fSopenharmony_ci    }
147422736c2fSopenharmony_ci    return it->second;
147522736c2fSopenharmony_ci}
147622736c2fSopenharmony_ci
147722736c2fSopenharmony_cibool PerUserSession::StartIme(const std::shared_ptr<ImeNativeCfg> &ime, bool isStopCurrentIme)
147822736c2fSopenharmony_ci{
147922736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(imeStartLock_);
148022736c2fSopenharmony_ci    if (ime == nullptr) {
148122736c2fSopenharmony_ci        return false;
148222736c2fSopenharmony_ci    }
148322736c2fSopenharmony_ci    auto imeData = GetImeData(ImeType::IME);
148422736c2fSopenharmony_ci    if (imeData == nullptr) {
148522736c2fSopenharmony_ci        return HandleFirstStart(ime, isStopCurrentIme);
148622736c2fSopenharmony_ci    }
148722736c2fSopenharmony_ci    if (imeData->ime.first == ime->bundleName && imeData->ime.second == ime->extName) {
148822736c2fSopenharmony_ci        if (isStopCurrentIme) {
148922736c2fSopenharmony_ci            return StartNewIme(ime);
149022736c2fSopenharmony_ci        }
149122736c2fSopenharmony_ci        return StartCurrentIme(ime);
149222736c2fSopenharmony_ci    }
149322736c2fSopenharmony_ci    return StartNewIme(ime);
149422736c2fSopenharmony_ci}
149522736c2fSopenharmony_ci
149622736c2fSopenharmony_ciImeAction PerUserSession::GetImeAction(ImeEvent action)
149722736c2fSopenharmony_ci{
149822736c2fSopenharmony_ci    std::lock_guard<std::mutex> lock(imeDataLock_);
149922736c2fSopenharmony_ci    auto it = imeData_.find(ImeType::IME);
150022736c2fSopenharmony_ci    if (it == imeData_.end()) {
150122736c2fSopenharmony_ci        return ImeAction::DO_ACTION_IN_NULL_IME_DATA;
150222736c2fSopenharmony_ci    }
150322736c2fSopenharmony_ci    auto iter = imeEventConverter_.find({ it->second->imeStatus, action });
150422736c2fSopenharmony_ci    if (iter == imeEventConverter_.end()) {
150522736c2fSopenharmony_ci        IMSA_HILOGE("abnormal!");
150622736c2fSopenharmony_ci        return ImeAction::DO_ACTION_IN_IME_EVENT_CONVERT_FAILED;
150722736c2fSopenharmony_ci    }
150822736c2fSopenharmony_ci    it->second->imeStatus = iter->second.first;
150922736c2fSopenharmony_ci    return iter->second.second;
151022736c2fSopenharmony_ci}
151122736c2fSopenharmony_ci
151222736c2fSopenharmony_cibool PerUserSession::StartCurrentIme(const std::shared_ptr<ImeNativeCfg> &ime)
151322736c2fSopenharmony_ci{
151422736c2fSopenharmony_ci    auto imeData = GetImeData(ImeType::IME);
151522736c2fSopenharmony_ci    if (imeData == nullptr) {
151622736c2fSopenharmony_ci        return StartInputService(ime);
151722736c2fSopenharmony_ci    }
151822736c2fSopenharmony_ci    auto action = GetImeAction(ImeEvent::START_IME);
151922736c2fSopenharmony_ci    if (action == ImeAction::DO_ACTION_IN_IME_EVENT_CONVERT_FAILED) {
152022736c2fSopenharmony_ci        return false;
152122736c2fSopenharmony_ci    }
152222736c2fSopenharmony_ci    if (action == ImeAction::DO_ACTION_IN_NULL_IME_DATA) {
152322736c2fSopenharmony_ci        return StartInputService(ime);
152422736c2fSopenharmony_ci    }
152522736c2fSopenharmony_ci    if (action == ImeAction::DO_NOTHING) {
152622736c2fSopenharmony_ci        return true;
152722736c2fSopenharmony_ci    }
152822736c2fSopenharmony_ci    if (action == ImeAction::HANDLE_STARTING_IME) {
152922736c2fSopenharmony_ci        int64_t time = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
153022736c2fSopenharmony_ci        if (time - imeData->startTime > ImeData::START_TIME_OUT) {
153122736c2fSopenharmony_ci            IMSA_HILOGE("[%{public}s, %{public}s] start abnormal, more than eight second!", imeData->ime.first.c_str(),
153222736c2fSopenharmony_ci                imeData->ime.second.c_str());
153322736c2fSopenharmony_ci            return HandleStartImeTimeout(ime);
153422736c2fSopenharmony_ci        }
153522736c2fSopenharmony_ci        return StartInputService(ime);
153622736c2fSopenharmony_ci    }
153722736c2fSopenharmony_ci    if (!StopExitingCurrentIme()) {
153822736c2fSopenharmony_ci        return false;
153922736c2fSopenharmony_ci    }
154022736c2fSopenharmony_ci    return StartInputService(ime);
154122736c2fSopenharmony_ci}
154222736c2fSopenharmony_ci
154322736c2fSopenharmony_cibool PerUserSession::HandleStartImeTimeout(const std::shared_ptr<ImeNativeCfg> &ime)
154422736c2fSopenharmony_ci{
154522736c2fSopenharmony_ci    auto action = GetImeAction(ImeEvent::START_IME_TIMEOUT);
154622736c2fSopenharmony_ci    if (action == ImeAction::DO_ACTION_IN_NULL_IME_DATA) {
154722736c2fSopenharmony_ci        return StartInputService(ime);
154822736c2fSopenharmony_ci    }
154922736c2fSopenharmony_ci    if (action == ImeAction::DO_ACTION_IN_IME_EVENT_CONVERT_FAILED) {
155022736c2fSopenharmony_ci        return false;
155122736c2fSopenharmony_ci    }
155222736c2fSopenharmony_ci    if (action == ImeAction::DO_NOTHING) {
155322736c2fSopenharmony_ci        IMSA_HILOGW("ready when timeout");
155422736c2fSopenharmony_ci        return true;
155522736c2fSopenharmony_ci    }
155622736c2fSopenharmony_ci    ForceStopCurrentIme(false);
155722736c2fSopenharmony_ci    return false;
155822736c2fSopenharmony_ci}
155922736c2fSopenharmony_ci
156022736c2fSopenharmony_cibool PerUserSession::StartNewIme(const std::shared_ptr<ImeNativeCfg> &ime)
156122736c2fSopenharmony_ci{
156222736c2fSopenharmony_ci    if (!StopCurrentIme()) {
156322736c2fSopenharmony_ci        return false;
156422736c2fSopenharmony_ci    }
156522736c2fSopenharmony_ci    return StartInputService(ime);
156622736c2fSopenharmony_ci}
156722736c2fSopenharmony_ci
156822736c2fSopenharmony_cibool PerUserSession::StopCurrentIme()
156922736c2fSopenharmony_ci{
157022736c2fSopenharmony_ci    auto action = GetImeAction(ImeEvent::STOP_IME);
157122736c2fSopenharmony_ci    if (action == ImeAction::DO_ACTION_IN_NULL_IME_DATA) {
157222736c2fSopenharmony_ci        return true;
157322736c2fSopenharmony_ci    }
157422736c2fSopenharmony_ci    if (action == ImeAction::DO_ACTION_IN_IME_EVENT_CONVERT_FAILED) {
157522736c2fSopenharmony_ci        return false;
157622736c2fSopenharmony_ci    }
157722736c2fSopenharmony_ci    if (action == ImeAction::STOP_READY_IME) {
157822736c2fSopenharmony_ci        return StopReadyCurrentIme();
157922736c2fSopenharmony_ci    }
158022736c2fSopenharmony_ci    if (action == ImeAction::STOP_STARTING_IME) {
158122736c2fSopenharmony_ci        return ForceStopCurrentIme();
158222736c2fSopenharmony_ci    }
158322736c2fSopenharmony_ci    return StopExitingCurrentIme();
158422736c2fSopenharmony_ci}
158522736c2fSopenharmony_ci
158622736c2fSopenharmony_cibool PerUserSession::StopReadyCurrentIme()
158722736c2fSopenharmony_ci{
158822736c2fSopenharmony_ci    auto client = GetCurrentClient();
158922736c2fSopenharmony_ci    auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
159022736c2fSopenharmony_ci    if (clientInfo != nullptr && clientInfo->bindImeType == ImeType::IME) {
159122736c2fSopenharmony_ci        StopClientInput(clientInfo);
159222736c2fSopenharmony_ci    }
159322736c2fSopenharmony_ci    auto imeData = GetImeData(ImeType::IME);
159422736c2fSopenharmony_ci    if (imeData == nullptr) {
159522736c2fSopenharmony_ci        return true;
159622736c2fSopenharmony_ci    }
159722736c2fSopenharmony_ci    if (imeData->core == nullptr) {
159822736c2fSopenharmony_ci        IMSA_HILOGE("core is nullptr!");
159922736c2fSopenharmony_ci        return ForceStopCurrentIme();
160022736c2fSopenharmony_ci    }
160122736c2fSopenharmony_ci    auto ret = RequestIme(imeData, RequestType::NORMAL, [&imeData] {
160222736c2fSopenharmony_ci        // failed when register onInputStop after SetCoreAndAgent
160322736c2fSopenharmony_ci        return imeData->core->StopInputService(true);
160422736c2fSopenharmony_ci    });
160522736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
160622736c2fSopenharmony_ci        IMSA_HILOGE("StopInputService failed.");
160722736c2fSopenharmony_ci        return ForceStopCurrentIme();
160822736c2fSopenharmony_ci    }
160922736c2fSopenharmony_ci    if (!WaitForCurrentImeStop()) {
161022736c2fSopenharmony_ci        IMSA_HILOGI("stop timeout.");
161122736c2fSopenharmony_ci        return ForceStopCurrentIme();
161222736c2fSopenharmony_ci    }
161322736c2fSopenharmony_ci    return true;
161422736c2fSopenharmony_ci}
161522736c2fSopenharmony_ci
161622736c2fSopenharmony_cibool PerUserSession::StopExitingCurrentIme()
161722736c2fSopenharmony_ci{
161822736c2fSopenharmony_ci    auto imeData = GetImeData(ImeType::IME);
161922736c2fSopenharmony_ci    if (imeData == nullptr) {
162022736c2fSopenharmony_ci        return true;
162122736c2fSopenharmony_ci    }
162222736c2fSopenharmony_ci    if (!ImeInfoInquirer::GetInstance().IsRunningIme(userId_, imeData->ime.first)) {
162322736c2fSopenharmony_ci        IMSA_HILOGD("already stop!");
162422736c2fSopenharmony_ci        RemoveImeData(ImeType::IME, true);
162522736c2fSopenharmony_ci        return true;
162622736c2fSopenharmony_ci    }
162722736c2fSopenharmony_ci    return ForceStopCurrentIme();
162822736c2fSopenharmony_ci}
162922736c2fSopenharmony_ci
163022736c2fSopenharmony_cibool PerUserSession::ForceStopCurrentIme(bool isNeedWait)
163122736c2fSopenharmony_ci{
163222736c2fSopenharmony_ci    auto client = GetCurrentClient();
163322736c2fSopenharmony_ci    auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
163422736c2fSopenharmony_ci    if (clientInfo != nullptr && clientInfo->bindImeType == ImeType::IME) {
163522736c2fSopenharmony_ci        StopClientInput(clientInfo);
163622736c2fSopenharmony_ci    }
163722736c2fSopenharmony_ci    auto imeData = GetImeData(ImeType::IME);
163822736c2fSopenharmony_ci    if (imeData == nullptr) {
163922736c2fSopenharmony_ci        return true;
164022736c2fSopenharmony_ci    }
164122736c2fSopenharmony_ci    AAFwk::Want want;
164222736c2fSopenharmony_ci    want.SetElementName(imeData->ime.first, imeData->ime.second);
164322736c2fSopenharmony_ci    auto ret = AAFwk::AbilityManagerClient::GetInstance()->StopExtensionAbility(
164422736c2fSopenharmony_ci        want, nullptr, userId_, AppExecFwk::ExtensionAbilityType::INPUTMETHOD);
164522736c2fSopenharmony_ci    if (ret != ErrorCode::NO_ERROR) {
164622736c2fSopenharmony_ci        IMSA_HILOGE("StopExtensionAbility [%{public}s, %{public}s] failed, ret: %{public}d!",
164722736c2fSopenharmony_ci            imeData->ime.first.c_str(), imeData->ime.second.c_str(), ret);
164822736c2fSopenharmony_ci        return false;
164922736c2fSopenharmony_ci    }
165022736c2fSopenharmony_ci    if (!isNeedWait) {
165122736c2fSopenharmony_ci        return true;
165222736c2fSopenharmony_ci    }
165322736c2fSopenharmony_ci    WaitForCurrentImeStop();
165422736c2fSopenharmony_ci    if (ImeInfoInquirer::GetInstance().IsRunningIme(userId_, imeData->ime.first)) {
165522736c2fSopenharmony_ci        IMSA_HILOGW("stop [%{public}s, %{public}s] timeout.", imeData->ime.first.c_str(), imeData->ime.second.c_str());
165622736c2fSopenharmony_ci        return false;
165722736c2fSopenharmony_ci    }
165822736c2fSopenharmony_ci    RemoveImeData(ImeType::IME, true);
165922736c2fSopenharmony_ci    return true;
166022736c2fSopenharmony_ci}
166122736c2fSopenharmony_ci
166222736c2fSopenharmony_cibool PerUserSession::HandleFirstStart(const std::shared_ptr<ImeNativeCfg> &ime, bool isStopCurrentIme)
166322736c2fSopenharmony_ci{
166422736c2fSopenharmony_ci    if (runningIme_.empty()) {
166522736c2fSopenharmony_ci        return StartInputService(ime);
166622736c2fSopenharmony_ci    }
166722736c2fSopenharmony_ci    IMSA_HILOGW("imsa abnormal restore.");
166822736c2fSopenharmony_ci    if (isStopCurrentIme) {
166922736c2fSopenharmony_ci        return true;
167022736c2fSopenharmony_ci    }
167122736c2fSopenharmony_ci    if (BlockRetry(CHECK_IME_RUNNING_RETRY_INTERVAL, CHECK_IME_RUNNING_RETRY_TIMES,
167222736c2fSopenharmony_ci                   [this]() -> bool { return !ImeInfoInquirer::GetInstance().IsRunningIme(userId_, runningIme_); })) {
167322736c2fSopenharmony_ci        IMSA_HILOGI("[%{public}d, %{public}s] stop completely", userId_, runningIme_.c_str());
167422736c2fSopenharmony_ci        runningIme_.clear();
167522736c2fSopenharmony_ci        return StartInputService(ime);
167622736c2fSopenharmony_ci    }
167722736c2fSopenharmony_ci    IMSA_HILOGW("[%{public}d, %{public}s] stop timeout", userId_, runningIme_.c_str());
167822736c2fSopenharmony_ci    return false;
167922736c2fSopenharmony_ci}
168022736c2fSopenharmony_ci
168122736c2fSopenharmony_ciint32_t PerUserSession::RestoreCurrentIme()
168222736c2fSopenharmony_ci{
168322736c2fSopenharmony_ci    InputTypeManager::GetInstance().Set(false);
168422736c2fSopenharmony_ci    auto cfgIme = ImeInfoInquirer::GetInstance().GetImeToStart(userId_);
168522736c2fSopenharmony_ci    auto imeData = GetReadyImeData(ImeType::IME);
168622736c2fSopenharmony_ci    if (imeData != nullptr && imeData->ime.first == cfgIme->bundleName && imeData->ime.second == cfgIme->extName) {
168722736c2fSopenharmony_ci        return ErrorCode::NO_ERROR;
168822736c2fSopenharmony_ci    }
168922736c2fSopenharmony_ci    IMSA_HILOGD("need restore!");
169022736c2fSopenharmony_ci    if (!StartIme(cfgIme)) {
169122736c2fSopenharmony_ci        IMSA_HILOGE("start ime failed!");
169222736c2fSopenharmony_ci        return ErrorCode::ERROR_IME_START_FAILED;
169322736c2fSopenharmony_ci    }
169422736c2fSopenharmony_ci    SubProperty subProp = { .name = cfgIme->bundleName, .id = cfgIme->subName };
169522736c2fSopenharmony_ci    auto subPropTemp = ImeInfoInquirer::GetInstance().GetCurrentSubtype(userId_);
169622736c2fSopenharmony_ci    if (subPropTemp != nullptr) {
169722736c2fSopenharmony_ci        subProp = *subPropTemp;
169822736c2fSopenharmony_ci    }
169922736c2fSopenharmony_ci    SwitchSubtype(subProp);
170022736c2fSopenharmony_ci    return ErrorCode::NO_ERROR;
170122736c2fSopenharmony_ci}
170222736c2fSopenharmony_ci
170322736c2fSopenharmony_cibool PerUserSession::CheckPwdInputPatternConv(InputClientInfo &newClientInfo)
170422736c2fSopenharmony_ci{
170522736c2fSopenharmony_ci    auto exClient = GetCurrentClient();
170622736c2fSopenharmony_ci    if (exClient == nullptr) {
170722736c2fSopenharmony_ci        exClient = GetInactiveClient();
170822736c2fSopenharmony_ci    }
170922736c2fSopenharmony_ci    auto exClientInfo = exClient != nullptr ? GetClientInfo(exClient->AsObject()) : nullptr;
171022736c2fSopenharmony_ci    if (exClientInfo == nullptr) {
171122736c2fSopenharmony_ci        IMSA_HILOGE("exClientInfo is nullptr!");
171222736c2fSopenharmony_ci        return false;
171322736c2fSopenharmony_ci    }
171422736c2fSopenharmony_ci    // if current input pattern differ from previous in pwd and normal, need hide panel first.
171522736c2fSopenharmony_ci    if (newClientInfo.config.inputAttribute.GetSecurityFlag()) {
171622736c2fSopenharmony_ci        IMSA_HILOGI("new input pattern is pwd.");
171722736c2fSopenharmony_ci        return !exClientInfo->config.inputAttribute.GetSecurityFlag();
171822736c2fSopenharmony_ci    }
171922736c2fSopenharmony_ci    IMSA_HILOGI("new input pattern is normal.");
172022736c2fSopenharmony_ci    return exClientInfo->config.inputAttribute.GetSecurityFlag();
172122736c2fSopenharmony_ci}
172222736c2fSopenharmony_ci} // namespace MiscServices
172322736c2fSopenharmony_ci} // namespace OHOS